Merge from Chromium at DEPS revision r216972
This commit was generated by merge_to_master.py.
Change-Id: I01cb28d94e3fcf99e3624d75cafa50d929787ddd
diff --git a/.DEPS.git b/.DEPS.git
index acce559..a1071d8 100644
--- a/.DEPS.git
+++ b/.DEPS.git
@@ -11,7 +11,7 @@
'git_url':
'https://chromium.googlesource.com',
'webkit_rev':
- '@88c9a95505973e4bc340d847a42caaae3e709774'
+ '@2384839ebef90ff82cbfc837374243a8b7985dc0'
}
deps = {
@@ -25,10 +25,10 @@
Var('git_url') + '/chromium/frame_rate/content.git@c10272c88463efeef6bb19c9ec07c42bc8fe22b9',
'src/chrome/test/data/perf/third_party/octane':
Var('git_url') + '/external/octane-benchmark.git@9ac27bfd9e0bc73663db0c0551440215d8b20d09',
- 'src/googleurl':
- Var('git_url') + '/external/google-url.git@ca8c31644137b3b46021ee37973c8749aae5c3bf',
+ 'src/media/cdm/ppapi/api':
+ Var('git_url') + '/chromium/cdm.git@c2b192a02546916d28233cfd8b7717ffcdcc8347',
'src/native_client':
- Var('git_url') + '/native_client/src/native_client.git@f87ee6e69c38cec1acdabf4d2d608ea8f0510253',
+ Var('git_url') + '/native_client/src/native_client.git@3a9cf2a60e4c3f54564de368d540c556efaa9289',
'src/sdch/open-vcdiff':
Var('git_url') + '/external/open-vcdiff.git@438f2a5be6d809bc21611a94cd37bfc8c28ceb33',
'src/testing/gmock':
@@ -64,7 +64,7 @@
'src/third_party/libexif/sources':
Var('git_url') + '/chromium/deps/libexif/sources.git@d815c325bab0d1871d4c7e70600ecdfdab07db9e',
'src/third_party/libjingle/source/talk':
- Var('git_url') + '/external/webrtc/stable/talk.git@c237f0ad875cde990bf9d89f41424b18809cc345',
+ Var('git_url') + '/external/webrtc/stable/talk.git@7bf94f9c4ab08aa82f78018d8ba363b5b60b05ed',
'src/third_party/libjpeg_turbo':
Var('git_url') + '/chromium/deps/libjpeg_turbo.git@82ce8a6d4ebe12a177c0c3597192f2b4f09e81c3',
'src/third_party/libphonenumber/src/phonenumbers':
@@ -98,11 +98,11 @@
'src/third_party/sfntly/cpp/src':
Var('git_url') + '/external/sfntly/cpp/src.git@cfb2f1743f0169ad8d01035458617bce97107539',
'src/third_party/skia/gyp':
- Var('git_url') + '/external/skia/gyp.git@dccf47acbdb65e21ed989fa3f45e638caffa6ce6',
+ Var('git_url') + '/external/skia/gyp.git@5afe400f473c747e2e5acb50b249fad1b8f2b0fc',
'src/third_party/skia/include':
- Var('git_url') + '/external/skia/include.git@970ef2af6ab2e1d6554207e3f66cce934cd091d5',
+ Var('git_url') + '/external/skia/include.git@9b8ab717a6bf3fdc5eaa0ef5845c8daa14e3604b',
'src/third_party/skia/src':
- Var('git_url') + '/external/skia/src.git@d2da8bcbed4791ae93c3070c50e89865b6398e10',
+ Var('git_url') + '/external/skia/src.git@06e8b2aa9249ff96559f7c08adffa83f4e855258',
'src/third_party/smhasher/src':
Var('git_url') + '/external/smhasher.git@6f63a4882e6b2cf87e8eec1a3ef8644e0d963283',
'src/third_party/snappy/src':
@@ -112,7 +112,7 @@
'src/third_party/swig/Lib':
Var('git_url') + '/chromium/deps/swig/Lib.git@549f0b084ad9c40ef42d111303d831eb8d91252e',
'src/third_party/trace-viewer':
- Var('git_url') + '/external/trace-viewer.git@a6a836af25bb1a05cb9b03e2a955a9c0c93254bc',
+ Var('git_url') + '/external/trace-viewer.git@105f1a5f16ef9ca378f8caf006cc7da2d09da57f',
'src/third_party/usrsctp/usrsctplib':
Var('git_url') + '/external/usrsctplib.git@9fde21ced28f3314e75a2d90e5dcc7867e2a6b75',
'src/third_party/webdriver/pylib':
@@ -122,7 +122,7 @@
'src/third_party/webpagereplay':
Var('git_url') + '/external/web-page-replay.git@ca269709e412d06b7b9f649dd47fb91f38f73852',
'src/third_party/webrtc':
- Var('git_url') + '/external/webrtc/stable/webrtc.git@dc26d5440b80f042dfc516116b2e15ce618a405d',
+ Var('git_url') + '/external/webrtc/stable/webrtc.git@2b8e89ebe8233d5faca71c5df3fc0259ca7fa784',
'src/third_party/yasm/source/patched-yasm':
Var('git_url') + '/chromium/deps/yasm/patched-yasm.git@c960eb11ccda80b10ed50be39df4f0663b371d1d',
'src/tools/deps2git':
@@ -136,16 +136,14 @@
'src/tools/swarm_client':
Var('git_url') + '/chromium/tools/swarm_client.git@86681e9a54c88972dba217b4f1007222dd8936a4',
'src/v8':
- Var('git_url') + '/external/v8.git@54d8a9855f2c6a6c3c33b5b66cbfbbac2cbcaa00',
- 'src/webkit/renderer/media/crypto/ppapi/cdm':
- Var('git_url') + '/chromium/cdm.git@c2b192a02546916d28233cfd8b7717ffcdcc8347',
+ Var('git_url') + '/external/v8.git@89acc0bef1acf051e807b057dbcbcd478a8ad301',
}
deps_os = {
'android':
{
'src/third_party/android_tools':
- Var('git_url') + '/android_tools.git@eda719cf5bf102f38b17fe4f583fbc5fde581be6',
+ Var('git_url') + '/android_tools.git@881586ca84f2fb8e82faa9c8d645416d175d0f01',
'src/third_party/aosp':
Var('git_url') + '/chromium/deps/aosp.git@bbafe5155dff86bbba1e92b42a073ffcfcfbf28c',
'src/third_party/apache-mime4j':
@@ -357,15 +355,13 @@
'+testing',
'+third_party/icu/source/common/unicode',
'+third_party/icu/source/i18n/unicode',
- '+url',
- '!googleurl'
+ '+url'
]
skip_child_includes = [
'breakpad',
'chrome_frame',
'delegate_execute',
- 'googleurl',
'metro_driver',
'native_client_sdk',
'o3d',
diff --git a/DEPS b/DEPS
index 7798439..01ca9de 100644
--- a/DEPS
+++ b/DEPS
@@ -8,12 +8,12 @@
"sourceforge_url": "http://svn.code.sf.net/p/%(repo)s/code",
"webkit_trunk": "http://src.chromium.org/blink/trunk",
"nacl_trunk": "http://src.chromium.org/native_client/trunk",
- "webkit_revision": "155688",
+ "webkit_revision": "155921",
"chromium_git": "https://chromium.googlesource.com",
"chromiumos_git": "https://chromium.googlesource.com/chromiumos",
"skia_git": "https://skia.googlesource.com",
"swig_revision": "69281",
- "nacl_revision": "11930",
+ "nacl_revision": "11988",
# After changing nacl_revision, run 'glient sync' and check native_client/DEPS
# to update other nacl_*_revision's.
"nacl_tools_revision": "11437", # native_client/DEPS: tools_rev
@@ -29,16 +29,16 @@
"ffmpeg_hash": "894e6f715645528e815aee2dad45b59704238dcd",
"sfntly_revision": "134",
- "skia_revision": "10602",
- "skia_hash": "6d04e64f56b658635eeb46fcdb02188ce54f1567",
+ "skia_revision": "10648",
+ "skia_hash": "a5b11fcd59d769450ac85a3b1e88d2e6eaca865e",
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling Skia
# and V8 without interference from each other.
- "v8_revision": "16104",
+ "v8_revision": "16142",
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling WebRTC
# and V8 without interference from each other.
- "webrtc_revision": "4490",
+ "webrtc_revision": "4520",
"jsoncpp_revision": "248",
"nss_revision": "209026",
# Three lines of non-changing comments so that
@@ -55,9 +55,6 @@
"src/breakpad/src":
(Var("googlecode_url") % "google-breakpad") + "/trunk/src@1199",
- "src/googleurl":
- (Var("googlecode_url") % "google-url") + "/trunk@185",
-
"src/sdch/open-vcdiff":
(Var("googlecode_url") % "open-vcdiff") + "/trunk@42",
@@ -72,7 +69,7 @@
"/external/angle.git@b93f84acdecd3eebf316750d8024b8b592c9012b",
"src/third_party/trace-viewer":
- (Var("googlecode_url") % "trace-viewer") + "/trunk@816",
+ (Var("googlecode_url") % "trace-viewer") + "/trunk@847",
"src/third_party/WebKit":
Var("webkit_trunk") + "@" + Var("webkit_revision"),
@@ -247,7 +244,7 @@
"src/third_party/accessibility-developer-tools":
Var("chromium_git") + "/external/accessibility-developer-tools.git@2e3c9c8e49277a0ca1eeba510271eb03f9486d8f",
- "src/webkit/renderer/media/crypto/ppapi/cdm":
+ "src/media/cdm/ppapi/api":
"/trunk/deps/cdm@181763",
"src/third_party/mesa/src":
@@ -456,7 +453,7 @@
"android": {
"src/third_party/android_tools":
Var("chromium_git") + "/android_tools.git" +
- "@eda719cf5bf102f38b17fe4f583fbc5fde581be6",
+ "@881586ca84f2fb8e82faa9c8d645416d175d0f01",
"src/third_party/aosp":
"/trunk/deps/third_party/aosp@148330",
@@ -513,8 +510,6 @@
"+third_party/icu/source/common/unicode",
"+third_party/icu/source/i18n/unicode",
"+url",
- # TODO(tfarina): Temporary, until we finish the migration to url. Remove this!
- "!googleurl",
]
@@ -523,7 +518,6 @@
"breakpad",
"chrome_frame",
"delegate_execute",
- "googleurl",
"metro_driver",
"native_client_sdk",
"o3d",
diff --git a/GypAndroid.darwin-arm.mk b/GypAndroid.darwin-arm.mk
index d4f87d0..85b5b60 100644
--- a/GypAndroid.darwin-arm.mk
+++ b/GypAndroid.darwin-arm.mk
@@ -85,8 +85,6 @@
include $(LOCAL_PATH)/net/net_jni_headers.target.darwin-arm.mk
include $(LOCAL_PATH)/net/net_resources.target.darwin-arm.mk
include $(LOCAL_PATH)/net/private_key_types_java.target.darwin-arm.mk
-include $(LOCAL_PATH)/ppapi/ppapi_c.target.darwin-arm.mk
-include $(LOCAL_PATH)/ppapi/ppapi_shared.target.darwin-arm.mk
include $(LOCAL_PATH)/printing/printing.target.darwin-arm.mk
include $(LOCAL_PATH)/sandbox/sandbox.target.darwin-arm.mk
include $(LOCAL_PATH)/sandbox/sandbox_services.target.darwin-arm.mk
@@ -150,6 +148,7 @@
include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf_config.target.darwin-arm.mk
include $(LOCAL_PATH)/third_party/WebKit/public/blink.target.darwin-arm.mk
include $(LOCAL_PATH)/third_party/WebKit/public/blink_minimal.target.darwin-arm.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_skia_config.target.darwin-arm.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/preprocessor.target.darwin-arm.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_common.target.darwin-arm.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_glsl.target.darwin-arm.mk
@@ -226,14 +225,12 @@
include $(LOCAL_PATH)/webkit/common/user_agent/user_agent.target.darwin-arm.mk
include $(LOCAL_PATH)/webkit/common/user_agent/webkit_version.target.darwin-arm.mk
include $(LOCAL_PATH)/webkit/common/webkit_common.target.darwin-arm.mk
-include $(LOCAL_PATH)/webkit/plugins/plugins_common.target.darwin-arm.mk
include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-arm.mk
include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-arm.mk
include $(LOCAL_PATH)/webkit/renderer/webkit_renderer.target.darwin-arm.mk
include $(LOCAL_PATH)/webkit/support/glue.target.darwin-arm.mk
include $(LOCAL_PATH)/webkit/support/glue_child.target.darwin-arm.mk
include $(LOCAL_PATH)/webkit/support/overscroller_jni_headers.target.darwin-arm.mk
-include $(LOCAL_PATH)/webkit/support/plugins.target.darwin-arm.mk
include $(LOCAL_PATH)/webkit/webkit_resources.target.darwin-arm.mk
include $(LOCAL_PATH)/webkit/webkit_storage_browser.target.darwin-arm.mk
include $(LOCAL_PATH)/webkit/webkit_storage_common.target.darwin-arm.mk
diff --git a/GypAndroid.darwin-mips.mk b/GypAndroid.darwin-mips.mk
index d870e25..5dc9a15 100644
--- a/GypAndroid.darwin-mips.mk
+++ b/GypAndroid.darwin-mips.mk
@@ -85,8 +85,6 @@
include $(LOCAL_PATH)/net/net_jni_headers.target.darwin-mips.mk
include $(LOCAL_PATH)/net/net_resources.target.darwin-mips.mk
include $(LOCAL_PATH)/net/private_key_types_java.target.darwin-mips.mk
-include $(LOCAL_PATH)/ppapi/ppapi_c.target.darwin-mips.mk
-include $(LOCAL_PATH)/ppapi/ppapi_shared.target.darwin-mips.mk
include $(LOCAL_PATH)/printing/printing.target.darwin-mips.mk
include $(LOCAL_PATH)/sandbox/sandbox.target.darwin-mips.mk
include $(LOCAL_PATH)/sandbox/sandbox_services.target.darwin-mips.mk
@@ -146,6 +144,7 @@
include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf_config.target.darwin-mips.mk
include $(LOCAL_PATH)/third_party/WebKit/public/blink.target.darwin-mips.mk
include $(LOCAL_PATH)/third_party/WebKit/public/blink_minimal.target.darwin-mips.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_skia_config.target.darwin-mips.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/preprocessor.target.darwin-mips.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_common.target.darwin-mips.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_glsl.target.darwin-mips.mk
@@ -222,14 +221,12 @@
include $(LOCAL_PATH)/webkit/common/user_agent/user_agent.target.darwin-mips.mk
include $(LOCAL_PATH)/webkit/common/user_agent/webkit_version.target.darwin-mips.mk
include $(LOCAL_PATH)/webkit/common/webkit_common.target.darwin-mips.mk
-include $(LOCAL_PATH)/webkit/plugins/plugins_common.target.darwin-mips.mk
include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-mips.mk
include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-mips.mk
include $(LOCAL_PATH)/webkit/renderer/webkit_renderer.target.darwin-mips.mk
include $(LOCAL_PATH)/webkit/support/glue.target.darwin-mips.mk
include $(LOCAL_PATH)/webkit/support/glue_child.target.darwin-mips.mk
include $(LOCAL_PATH)/webkit/support/overscroller_jni_headers.target.darwin-mips.mk
-include $(LOCAL_PATH)/webkit/support/plugins.target.darwin-mips.mk
include $(LOCAL_PATH)/webkit/webkit_resources.target.darwin-mips.mk
include $(LOCAL_PATH)/webkit/webkit_storage_browser.target.darwin-mips.mk
include $(LOCAL_PATH)/webkit/webkit_storage_common.target.darwin-mips.mk
diff --git a/GypAndroid.darwin-x86.mk b/GypAndroid.darwin-x86.mk
index 6ee10d3..f9ea4ce 100644
--- a/GypAndroid.darwin-x86.mk
+++ b/GypAndroid.darwin-x86.mk
@@ -90,8 +90,6 @@
include $(LOCAL_PATH)/net/net_jni_headers.target.darwin-x86.mk
include $(LOCAL_PATH)/net/net_resources.target.darwin-x86.mk
include $(LOCAL_PATH)/net/private_key_types_java.target.darwin-x86.mk
-include $(LOCAL_PATH)/ppapi/ppapi_c.target.darwin-x86.mk
-include $(LOCAL_PATH)/ppapi/ppapi_shared.target.darwin-x86.mk
include $(LOCAL_PATH)/printing/printing.target.darwin-x86.mk
include $(LOCAL_PATH)/sandbox/sandbox.target.darwin-x86.mk
include $(LOCAL_PATH)/sandbox/sandbox_services.target.darwin-x86.mk
@@ -154,6 +152,7 @@
include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf_config.target.darwin-x86.mk
include $(LOCAL_PATH)/third_party/WebKit/public/blink.target.darwin-x86.mk
include $(LOCAL_PATH)/third_party/WebKit/public/blink_minimal.target.darwin-x86.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_skia_config.target.darwin-x86.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/preprocessor.target.darwin-x86.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_common.target.darwin-x86.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_glsl.target.darwin-x86.mk
@@ -240,14 +239,12 @@
include $(LOCAL_PATH)/webkit/common/user_agent/user_agent.target.darwin-x86.mk
include $(LOCAL_PATH)/webkit/common/user_agent/webkit_version.target.darwin-x86.mk
include $(LOCAL_PATH)/webkit/common/webkit_common.target.darwin-x86.mk
-include $(LOCAL_PATH)/webkit/plugins/plugins_common.target.darwin-x86.mk
include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-x86.mk
include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-x86.mk
include $(LOCAL_PATH)/webkit/renderer/webkit_renderer.target.darwin-x86.mk
include $(LOCAL_PATH)/webkit/support/glue.target.darwin-x86.mk
include $(LOCAL_PATH)/webkit/support/glue_child.target.darwin-x86.mk
include $(LOCAL_PATH)/webkit/support/overscroller_jni_headers.target.darwin-x86.mk
-include $(LOCAL_PATH)/webkit/support/plugins.target.darwin-x86.mk
include $(LOCAL_PATH)/webkit/webkit_resources.target.darwin-x86.mk
include $(LOCAL_PATH)/webkit/webkit_storage_browser.target.darwin-x86.mk
include $(LOCAL_PATH)/webkit/webkit_storage_common.target.darwin-x86.mk
diff --git a/GypAndroid.linux-arm.mk b/GypAndroid.linux-arm.mk
index 0a2979b..673934c 100644
--- a/GypAndroid.linux-arm.mk
+++ b/GypAndroid.linux-arm.mk
@@ -85,8 +85,6 @@
include $(LOCAL_PATH)/net/net_jni_headers.target.linux-arm.mk
include $(LOCAL_PATH)/net/net_resources.target.linux-arm.mk
include $(LOCAL_PATH)/net/private_key_types_java.target.linux-arm.mk
-include $(LOCAL_PATH)/ppapi/ppapi_c.target.linux-arm.mk
-include $(LOCAL_PATH)/ppapi/ppapi_shared.target.linux-arm.mk
include $(LOCAL_PATH)/printing/printing.target.linux-arm.mk
include $(LOCAL_PATH)/sandbox/sandbox.target.linux-arm.mk
include $(LOCAL_PATH)/sandbox/sandbox_services.target.linux-arm.mk
@@ -150,6 +148,7 @@
include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf_config.target.linux-arm.mk
include $(LOCAL_PATH)/third_party/WebKit/public/blink.target.linux-arm.mk
include $(LOCAL_PATH)/third_party/WebKit/public/blink_minimal.target.linux-arm.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_skia_config.target.linux-arm.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/preprocessor.target.linux-arm.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_common.target.linux-arm.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_glsl.target.linux-arm.mk
@@ -226,14 +225,12 @@
include $(LOCAL_PATH)/webkit/common/user_agent/user_agent.target.linux-arm.mk
include $(LOCAL_PATH)/webkit/common/user_agent/webkit_version.target.linux-arm.mk
include $(LOCAL_PATH)/webkit/common/webkit_common.target.linux-arm.mk
-include $(LOCAL_PATH)/webkit/plugins/plugins_common.target.linux-arm.mk
include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-arm.mk
include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-arm.mk
include $(LOCAL_PATH)/webkit/renderer/webkit_renderer.target.linux-arm.mk
include $(LOCAL_PATH)/webkit/support/glue.target.linux-arm.mk
include $(LOCAL_PATH)/webkit/support/glue_child.target.linux-arm.mk
include $(LOCAL_PATH)/webkit/support/overscroller_jni_headers.target.linux-arm.mk
-include $(LOCAL_PATH)/webkit/support/plugins.target.linux-arm.mk
include $(LOCAL_PATH)/webkit/webkit_resources.target.linux-arm.mk
include $(LOCAL_PATH)/webkit/webkit_storage_browser.target.linux-arm.mk
include $(LOCAL_PATH)/webkit/webkit_storage_common.target.linux-arm.mk
diff --git a/GypAndroid.linux-mips.mk b/GypAndroid.linux-mips.mk
index 07ae768..d3e160f 100644
--- a/GypAndroid.linux-mips.mk
+++ b/GypAndroid.linux-mips.mk
@@ -85,8 +85,6 @@
include $(LOCAL_PATH)/net/net_jni_headers.target.linux-mips.mk
include $(LOCAL_PATH)/net/net_resources.target.linux-mips.mk
include $(LOCAL_PATH)/net/private_key_types_java.target.linux-mips.mk
-include $(LOCAL_PATH)/ppapi/ppapi_c.target.linux-mips.mk
-include $(LOCAL_PATH)/ppapi/ppapi_shared.target.linux-mips.mk
include $(LOCAL_PATH)/printing/printing.target.linux-mips.mk
include $(LOCAL_PATH)/sandbox/sandbox.target.linux-mips.mk
include $(LOCAL_PATH)/sandbox/sandbox_services.target.linux-mips.mk
@@ -146,6 +144,7 @@
include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf_config.target.linux-mips.mk
include $(LOCAL_PATH)/third_party/WebKit/public/blink.target.linux-mips.mk
include $(LOCAL_PATH)/third_party/WebKit/public/blink_minimal.target.linux-mips.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_skia_config.target.linux-mips.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/preprocessor.target.linux-mips.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_common.target.linux-mips.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_glsl.target.linux-mips.mk
@@ -222,14 +221,12 @@
include $(LOCAL_PATH)/webkit/common/user_agent/user_agent.target.linux-mips.mk
include $(LOCAL_PATH)/webkit/common/user_agent/webkit_version.target.linux-mips.mk
include $(LOCAL_PATH)/webkit/common/webkit_common.target.linux-mips.mk
-include $(LOCAL_PATH)/webkit/plugins/plugins_common.target.linux-mips.mk
include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-mips.mk
include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-mips.mk
include $(LOCAL_PATH)/webkit/renderer/webkit_renderer.target.linux-mips.mk
include $(LOCAL_PATH)/webkit/support/glue.target.linux-mips.mk
include $(LOCAL_PATH)/webkit/support/glue_child.target.linux-mips.mk
include $(LOCAL_PATH)/webkit/support/overscroller_jni_headers.target.linux-mips.mk
-include $(LOCAL_PATH)/webkit/support/plugins.target.linux-mips.mk
include $(LOCAL_PATH)/webkit/webkit_resources.target.linux-mips.mk
include $(LOCAL_PATH)/webkit/webkit_storage_browser.target.linux-mips.mk
include $(LOCAL_PATH)/webkit/webkit_storage_common.target.linux-mips.mk
diff --git a/GypAndroid.linux-x86.mk b/GypAndroid.linux-x86.mk
index 5ca8972..06bb9bf 100644
--- a/GypAndroid.linux-x86.mk
+++ b/GypAndroid.linux-x86.mk
@@ -90,8 +90,6 @@
include $(LOCAL_PATH)/net/net_jni_headers.target.linux-x86.mk
include $(LOCAL_PATH)/net/net_resources.target.linux-x86.mk
include $(LOCAL_PATH)/net/private_key_types_java.target.linux-x86.mk
-include $(LOCAL_PATH)/ppapi/ppapi_c.target.linux-x86.mk
-include $(LOCAL_PATH)/ppapi/ppapi_shared.target.linux-x86.mk
include $(LOCAL_PATH)/printing/printing.target.linux-x86.mk
include $(LOCAL_PATH)/sandbox/sandbox.target.linux-x86.mk
include $(LOCAL_PATH)/sandbox/sandbox_services.target.linux-x86.mk
@@ -154,6 +152,7 @@
include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf_config.target.linux-x86.mk
include $(LOCAL_PATH)/third_party/WebKit/public/blink.target.linux-x86.mk
include $(LOCAL_PATH)/third_party/WebKit/public/blink_minimal.target.linux-x86.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_skia_config.target.linux-x86.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/preprocessor.target.linux-x86.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_common.target.linux-x86.mk
include $(LOCAL_PATH)/third_party/angle_dx11/src/translator_glsl.target.linux-x86.mk
@@ -240,14 +239,12 @@
include $(LOCAL_PATH)/webkit/common/user_agent/user_agent.target.linux-x86.mk
include $(LOCAL_PATH)/webkit/common/user_agent/webkit_version.target.linux-x86.mk
include $(LOCAL_PATH)/webkit/common/webkit_common.target.linux-x86.mk
-include $(LOCAL_PATH)/webkit/plugins/plugins_common.target.linux-x86.mk
include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-x86.mk
include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-x86.mk
include $(LOCAL_PATH)/webkit/renderer/webkit_renderer.target.linux-x86.mk
include $(LOCAL_PATH)/webkit/support/glue.target.linux-x86.mk
include $(LOCAL_PATH)/webkit/support/glue_child.target.linux-x86.mk
include $(LOCAL_PATH)/webkit/support/overscroller_jni_headers.target.linux-x86.mk
-include $(LOCAL_PATH)/webkit/support/plugins.target.linux-x86.mk
include $(LOCAL_PATH)/webkit/webkit_resources.target.linux-x86.mk
include $(LOCAL_PATH)/webkit/webkit_storage_browser.target.linux-x86.mk
include $(LOCAL_PATH)/webkit/webkit_storage_common.target.linux-x86.mk
diff --git a/NOTICE b/NOTICE
index 2d19b86..3e42dcf 100644
--- a/NOTICE
+++ b/NOTICE
@@ -522,72 +522,6 @@
*
* ***** END LICENSE BLOCK ***** */
-Copyright 2007, Google Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
--------------------------------------------------------------------------------
-
-The file url_parse.cc is based on nsURLParsers.cc from Mozilla. This file is
-licensed separately as follows:
-
-The contents of this file are subject to the Mozilla Public License Version
-1.1 (the "License"); you may not use this file except in compliance with
-the License. You may obtain a copy of the License at
-http://www.mozilla.org/MPL/
-
-Software distributed under the License is distributed on an "AS IS" basis,
-WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-for the specific language governing rights and limitations under the
-License.
-
-The Original Code is mozilla.org code.
-
-The Initial Developer of the Original Code is
-Netscape Communications Corporation.
-Portions created by the Initial Developer are Copyright (C) 1998
-the Initial Developer. All Rights Reserved.
-
-Contributor(s):
- Darin Fisher (original author)
-
-Alternatively, the contents of this file may be used under the terms of
-either the GNU General Public License Version 2 or later (the "GPL"), or
-the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-in which case the provisions of the GPL or the LGPL are applicable instead
-of those above. If you wish to allow use of your version of this file only
-under the terms of either the GPL or the LGPL, and not to allow others to
-use your version of this file under the terms of the MPL, indicate your
-decision by deleting the provisions above and replace them with the notice
-and other provisions required by the GPL or the LGPL. If you do not delete
-the provisions above, a recipient may use your version of this file under
-the terms of any one of the MPL, the GPL or the LGPL.
-
Copyright 2011, The Chromium Authors
All rights reserved.
@@ -7997,6 +7931,138 @@
*/
+Copyright 2007, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------------------------------------------------------------------
+
+The file url_parse.cc is based on nsURLParsers.cc from Mozilla. This file is
+licensed separately as follows:
+
+The contents of this file are subject to the Mozilla Public License Version
+1.1 (the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+for the specific language governing rights and limitations under the
+License.
+
+The Original Code is mozilla.org code.
+
+The Initial Developer of the Original Code is
+Netscape Communications Corporation.
+Portions created by the Initial Developer are Copyright (C) 1998
+the Initial Developer. All Rights Reserved.
+
+Contributor(s):
+ Darin Fisher (original author)
+
+Alternatively, the contents of this file may be used under the terms of
+either the GNU General Public License Version 2 or later (the "GPL"), or
+the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+in which case the provisions of the GPL or the LGPL are applicable instead
+of those above. If you wish to allow use of your version of this file only
+under the terms of either the GPL or the LGPL, and not to allow others to
+use your version of this file under the terms of the MPL, indicate your
+decision by deleting the provisions above and replace them with the notice
+and other provisions required by the GPL or the LGPL. If you do not delete
+the provisions above, a recipient may use your version of this file under
+the terms of any one of the MPL, the GPL or the LGPL.
+
+Copyright 2007, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------------------------------------------------------------------
+
+The file url_parse.cc is based on nsURLParsers.cc from Mozilla. This file is
+licensed separately as follows:
+
+The contents of this file are subject to the Mozilla Public License Version
+1.1 (the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+for the specific language governing rights and limitations under the
+License.
+
+The Original Code is mozilla.org code.
+
+The Initial Developer of the Original Code is
+Netscape Communications Corporation.
+Portions created by the Initial Developer are Copyright (C) 1998
+the Initial Developer. All Rights Reserved.
+
+Contributor(s):
+ Darin Fisher (original author)
+
+Alternatively, the contents of this file may be used under the terms of
+either the GNU General Public License Version 2 or later (the "GPL"), or
+the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+in which case the provisions of the GPL or the LGPL are applicable instead
+of those above. If you wish to allow use of your version of this file only
+under the terms of either the GPL or the LGPL, and not to allow others to
+use your version of this file under the terms of the MPL, indicate your
+decision by deleting the provisions above and replace them with the notice
+and other provisions required by the GPL or the LGPL. If you do not delete
+the provisions above, a recipient may use your version of this file under
+the terms of any one of the MPL, the GPL or the LGPL.
+
This license applies to all parts of V8 that are not externally
maintained libraries. The externally maintained libraries used by V8
are:
diff --git a/WATCHLISTS b/WATCHLISTS
index 995f53c..b9c1b36 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -262,6 +262,14 @@
'fullscreen_controller': {
'filepath': 'fullscreen_controller',
},
+ 'geolocation': {
+ 'filepath': 'chrome/browser/geolocation/|'\
+ 'content/browser/geolocation|'\
+ 'content/public/common/geoposition.*|'\
+ 'content/public/browser/geolocation.*|'\
+ 'content/renderer/geolocation.*|'\
+ 'content/shell/geolocation/',
+ },
'gfx_image': {
'filepath': 'ui/gfx/image/',
},
@@ -676,6 +684,7 @@
'filebrowse': ['rginda+watch@chromium.org'],
'ftp': ['phajdan.jr@chromium.org'],
'fullscreen_controller': ['scheib+watch@chromium.org'],
+ 'geolocation': ['mvanouwerkerk@chromium.org'],
'gfx_geometry': ['cc-bugs@chromium.org'],
'gfx_image': ['rsesek+watch@chromium.org'],
'gpu': ['apatrick@chromium.org'],
diff --git a/android_webview/android_webview.gyp b/android_webview/android_webview.gyp
index 237712a..1653997 100644
--- a/android_webview/android_webview.gyp
+++ b/android_webview/android_webview.gyp
@@ -85,6 +85,7 @@
'../gpu/gpu.gyp:command_buffer_service',
'../gpu/gpu.gyp:gles2_implementation',
'../ui/gl/gl.gyp:gl',
+ '../ui/ui.gyp:shell_dialogs',
'../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu',
'android_webview_pak',
],
diff --git a/android_webview/android_webview_common.target.darwin-arm.mk b/android_webview/android_webview_common.target.darwin-arm.mk
index 5e3624e..b07ae11 100644
--- a/android_webview/android_webview_common.target.darwin-arm.mk
+++ b/android_webview/android_webview_common.target.darwin-arm.mk
@@ -124,6 +124,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -233,6 +234,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/android_webview_common.target.darwin-mips.mk b/android_webview/android_webview_common.target.darwin-mips.mk
index c775bc5..0f138a1 100644
--- a/android_webview/android_webview_common.target.darwin-mips.mk
+++ b/android_webview/android_webview_common.target.darwin-mips.mk
@@ -123,6 +123,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -231,6 +232,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/android_webview_common.target.darwin-x86.mk b/android_webview/android_webview_common.target.darwin-x86.mk
index 0044f93..7ee937e 100644
--- a/android_webview/android_webview_common.target.darwin-x86.mk
+++ b/android_webview/android_webview_common.target.darwin-x86.mk
@@ -126,6 +126,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -238,6 +239,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/android_webview_common.target.linux-arm.mk b/android_webview/android_webview_common.target.linux-arm.mk
index 5e3624e..b07ae11 100644
--- a/android_webview/android_webview_common.target.linux-arm.mk
+++ b/android_webview/android_webview_common.target.linux-arm.mk
@@ -124,6 +124,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -233,6 +234,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/android_webview_common.target.linux-mips.mk b/android_webview/android_webview_common.target.linux-mips.mk
index c775bc5..0f138a1 100644
--- a/android_webview/android_webview_common.target.linux-mips.mk
+++ b/android_webview/android_webview_common.target.linux-mips.mk
@@ -123,6 +123,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -231,6 +232,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/android_webview_common.target.linux-x86.mk b/android_webview/android_webview_common.target.linux-x86.mk
index 0044f93..7ee937e 100644
--- a/android_webview/android_webview_common.target.linux-x86.mk
+++ b/android_webview/android_webview_common.target.linux-x86.mk
@@ -126,6 +126,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -238,6 +239,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h
index 9e02959..78beb17 100644
--- a/android_webview/browser/browser_view_renderer.h
+++ b/android_webview/browser/browser_view_renderer.h
@@ -6,10 +6,12 @@
#define ANDROID_WEBVIEW_BROWSER_BROWSER_VIEW_RENDERER_H_
#include "base/android/scoped_java_ref.h"
+#include "skia/ext/refptr.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/vector2d_f.h"
+class SkPicture;
struct AwDrawGLInfo;
struct AwDrawSWFunctionTable;
@@ -84,7 +86,6 @@
// Global hookup methods.
static void SetAwDrawSWFunctionTable(AwDrawSWFunctionTable* table);
static AwDrawSWFunctionTable* GetAwDrawSWFunctionTable();
- static bool IsSkiaVersionCompatible();
// Rendering methods.
@@ -108,9 +109,7 @@
virtual void SetGlobalVisibleRect(const gfx::Rect& visible_rect) = 0;
// CapturePicture API methods.
- virtual base::android::ScopedJavaLocalRef<jobject> CapturePicture(
- int width,
- int height) = 0;
+ virtual skia::RefPtr<SkPicture> CapturePicture(int width, int height) = 0;
virtual void EnableOnNewPicture(bool enabled) = 0;
// View update notifications.
diff --git a/android_webview/browser/in_process_view_renderer.cc b/android_webview/browser/in_process_view_renderer.cc
index 3e25680..39614d3 100644
--- a/android_webview/browser/in_process_view_renderer.cc
+++ b/android_webview/browser/in_process_view_renderer.cc
@@ -22,7 +22,6 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "gpu/command_buffer/service/in_process_command_buffer.h"
-#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkDevice.h"
@@ -64,13 +63,11 @@
InProcessViewRenderer* instance_;
};
-typedef base::Callback<bool(SkCanvas*)> RenderMethod;
-
bool RasterizeIntoBitmap(JNIEnv* env,
const JavaRef<jobject>& jbitmap,
int scroll_x,
int scroll_y,
- const RenderMethod& renderer) {
+ const InProcessViewRenderer::RenderMethod& renderer) {
DCHECK(jbitmap.obj());
AndroidBitmapInfo bitmap_info;
@@ -113,6 +110,26 @@
return true;
}
+class ScopedPixelAccess {
+ public:
+ ScopedPixelAccess(JNIEnv* env, jobject java_canvas) {
+ AwDrawSWFunctionTable* sw_functions =
+ BrowserViewRenderer::GetAwDrawSWFunctionTable();
+ pixels_ = sw_functions ?
+ sw_functions->access_pixels(env, java_canvas) : NULL;
+ }
+ ~ScopedPixelAccess() {
+ if (pixels_)
+ BrowserViewRenderer::GetAwDrawSWFunctionTable()->release_pixels(pixels_);
+ }
+ AwPixelInfo* pixels() { return pixels_; }
+
+ private:
+ AwPixelInfo* pixels_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedPixelAccess);
+};
+
bool HardwareEnabled() {
static bool g_hw_enabled = !CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableWebViewGLMode);
@@ -123,13 +140,6 @@
// Allows preventing extra copies of data when rendering.
AwDrawSWFunctionTable* g_sw_draw_functions = NULL;
-// Tells if the Skia library versions in Android and Chromium are compatible.
-// If they are then it's possible to pass Skia objects like SkPictures to the
-// Android glue layer via the SW rendering functions.
-// If they are not, then additional copies and rasterizations are required
-// as a fallback mechanism, which will have an important performance impact.
-bool g_is_skia_version_compatible = false;
-
const int64 kFallbackTickTimeoutInMilliseconds = 20;
class ScopedAllowGL {
@@ -180,11 +190,6 @@
void BrowserViewRenderer::SetAwDrawSWFunctionTable(
AwDrawSWFunctionTable* table) {
g_sw_draw_functions = table;
- g_is_skia_version_compatible =
- g_sw_draw_functions->is_skia_version_compatible(&SkGraphics::GetVersion);
- LOG_IF(WARNING, !g_is_skia_version_compatible)
- << "Skia versions are not compatible, rendering performance will suffer.";
-
gpu::InProcessCommandBuffer::SetScheduleCallback(
base::Bind(&ScheduleGpuWork));
}
@@ -194,12 +199,6 @@
return g_sw_draw_functions;
}
-// static
-bool BrowserViewRenderer::IsSkiaVersionCompatible() {
- DCHECK(g_sw_draw_functions);
- return g_is_skia_version_compatible;
-}
-
InProcessViewRenderer::InProcessViewRenderer(
BrowserViewRenderer::Client* client,
JavaHelper* java_helper,
@@ -213,6 +212,7 @@
page_scale_factor_(1.0),
on_new_picture_enable_(false),
compositor_needs_continuous_invalidate_(false),
+ need_fast_invalidate_(false),
block_invalidates_(false),
width_(0),
height_(0),
@@ -305,7 +305,6 @@
void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) {
TRACE_EVENT0("android_webview", "InProcessViewRenderer::DrawGL");
- DCHECK(visible_);
manager_key_ = g_view_renderer_manager.Get().DidDrawGL(manager_key_, this);
@@ -330,8 +329,19 @@
}
}
- if (draw_info->mode == AwDrawGLInfo::kModeProcess)
+ if (draw_info->mode == AwDrawGLInfo::kModeProcess) {
+ TRACE_EVENT_INSTANT0(
+ "android_webview", "EarlyOut_ModeProcess", TRACE_EVENT_SCOPE_THREAD);
return;
+ }
+
+ UpdateCachedGlobalVisibleRect();
+ if (cached_global_visible_rect_.IsEmpty()) {
+ TRACE_EVENT_INSTANT0("android_webview",
+ "EarlyOut_EmptyVisibleRect",
+ TRACE_EVENT_SCOPE_THREAD);
+ return;
+ }
// DrawGL may be called without OnDraw, so cancel |fallback_tick_| here as
// well just to be safe.
@@ -361,6 +371,15 @@
draw_info->clip_top,
draw_info->clip_right - draw_info->clip_left,
draw_info->clip_bottom - draw_info->clip_top);
+
+ // Assume we always draw the full visible rect if we are drawing into a layer.
+ bool drew_full_visible_rect = true;
+
+ if (!draw_info->is_layer) {
+ clip_rect.Intersect(cached_global_visible_rect_);
+ drew_full_visible_rect = clip_rect.Contains(cached_global_visible_rect_);
+ }
+
block_invalidates_ = true;
// TODO(joth): Check return value.
compositor_->DemandDrawHw(gfx::Size(draw_info->width, draw_info->height),
@@ -370,8 +389,6 @@
block_invalidates_ = false;
gl_surface_->ResetBackingFrameBufferObject();
- UpdateCachedGlobalVisibleRect();
- bool drew_full_visible_rect = clip_rect.Contains(cached_global_visible_rect_);
EnsureContinuousInvalidation(draw_info, !drew_full_visible_rect);
}
@@ -382,7 +399,6 @@
bool InProcessViewRenderer::DrawSWInternal(jobject java_canvas,
const gfx::Rect& clip) {
- TRACE_EVENT0("android_webview", "InProcessViewRenderer::DrawSW");
fallback_tick_.Cancel();
if (clip.IsEmpty()) {
@@ -397,17 +413,57 @@
return false;
}
- JNIEnv* env = AttachCurrentThread();
+ return RenderViaAuxilaryBitmapIfNeeded(
+ java_canvas,
+ java_helper_,
+ scroll_at_start_of_frame_,
+ clip,
+ base::Bind(&InProcessViewRenderer::CompositeSW,
+ base::Unretained(this)),
+ web_contents_);
+}
- AwDrawSWFunctionTable* sw_functions = GetAwDrawSWFunctionTable();
- AwPixelInfo* pixels = sw_functions ?
- sw_functions->access_pixels(env, java_canvas) : NULL;
- // Render into an auxiliary bitmap if pixel info is not available.
- ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas);
- if (pixels == NULL) {
+// static
+bool InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded(
+ jobject java_canvas,
+ BrowserViewRenderer::JavaHelper* java_helper,
+ const gfx::Vector2d& scroll_correction,
+ const gfx::Rect& clip,
+ InProcessViewRenderer::RenderMethod render_source,
+ void* owner_key) {
+ TRACE_EVENT0("android_webview",
+ "InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded");
+
+ JNIEnv* env = AttachCurrentThread();
+ ScopedPixelAccess auto_release_pixels(env, java_canvas);
+ AwPixelInfo* pixels = auto_release_pixels.pixels();
+ SkMatrix matrix;
+ SkBitmap::Config config(SkBitmap::kNo_Config);
+ if (pixels) {
+ switch (pixels->config) {
+ case AwConfig_ARGB_8888:
+ config = SkBitmap::kARGB_8888_Config;
+ break;
+ case AwConfig_RGB_565:
+ config = SkBitmap::kRGB_565_Config;
+ break;
+ }
+
+ for (int i = 0; i < 9; i++) {
+ matrix.set(i, pixels->matrix[i]);
+ }
+ // Workaround for http://crbug.com/271096: SW draw only supports
+ // translate & scale transforms.
+ if (matrix.getType() & ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))
+ config = SkBitmap::kNo_Config;
+ }
+
+ if (config == SkBitmap::kNo_Config) {
+ // Render into an auxiliary bitmap if pixel info is not available.
+ ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas);
TRACE_EVENT0("android_webview", "RenderToAuxBitmap");
- ScopedJavaLocalRef<jobject> jbitmap(java_helper_->CreateBitmap(
- env, clip.width(), clip.height(), jcanvas, web_contents_));
+ ScopedJavaLocalRef<jobject> jbitmap(java_helper->CreateBitmap(
+ env, clip.width(), clip.height(), jcanvas, owner_key));
if (!jbitmap.obj()) {
TRACE_EVENT_INSTANT0("android_webview",
"EarlyOut_BitmapAllocFail",
@@ -416,68 +472,57 @@
}
if (!RasterizeIntoBitmap(env, jbitmap,
- clip.x() - scroll_at_start_of_frame_.x(),
- clip.y() - scroll_at_start_of_frame_.y(),
- base::Bind(&InProcessViewRenderer::CompositeSW,
- base::Unretained(this)))) {
+ clip.x() - scroll_correction.x(),
+ clip.y() - scroll_correction.y(),
+ render_source)) {
TRACE_EVENT_INSTANT0("android_webview",
"EarlyOut_RasterizeFail",
TRACE_EVENT_SCOPE_THREAD);
return false;
}
- java_helper_->DrawBitmapIntoCanvas(env, jbitmap, jcanvas,
- clip.x(), clip.y());
+ java_helper->DrawBitmapIntoCanvas(env, jbitmap, jcanvas,
+ clip.x(), clip.y());
return true;
}
// Draw in a SkCanvas built over the pixel information.
- bool succeeded = false;
- {
- SkBitmap bitmap;
- bitmap.setConfig(static_cast<SkBitmap::Config>(pixels->config),
- pixels->width,
- pixels->height,
- pixels->row_bytes);
- bitmap.setPixels(pixels->pixels);
- SkDevice device(bitmap);
- SkCanvas canvas(&device);
- SkMatrix matrix;
- for (int i = 0; i < 9; i++)
- matrix.set(i, pixels->matrix[i]);
- canvas.setMatrix(matrix);
+ SkBitmap bitmap;
+ bitmap.setConfig(config,
+ pixels->width,
+ pixels->height,
+ pixels->row_bytes);
+ bitmap.setPixels(pixels->pixels);
+ SkDevice device(bitmap);
+ SkCanvas canvas(&device);
+ canvas.setMatrix(matrix);
- if (pixels->clip_region_size) {
- SkRegion clip_region;
- size_t bytes_read = clip_region.readFromMemory(pixels->clip_region);
- DCHECK_EQ(pixels->clip_region_size, bytes_read);
- canvas.setClipRegion(clip_region);
- } else {
- canvas.clipRect(gfx::RectToSkRect(clip));
+ if (pixels->clip_rect_count) {
+ SkRegion clip;
+ for (int i = 0; i < pixels->clip_rect_count; ++i) {
+ clip.op(SkIRect::MakeXYWH(pixels->clip_rects[i + 0],
+ pixels->clip_rects[i + 1],
+ pixels->clip_rects[i + 2],
+ pixels->clip_rects[i + 3]),
+ SkRegion::kUnion_Op);
}
- canvas.translate(scroll_at_start_of_frame_.x(),
- scroll_at_start_of_frame_.y());
-
- succeeded = CompositeSW(&canvas);
+ canvas.setClipRegion(clip);
}
- sw_functions->release_pixels(pixels);
- return succeeded;
+ canvas.translate(scroll_correction.x(),
+ scroll_correction.y());
+
+ return render_source.Run(&canvas);
}
-base::android::ScopedJavaLocalRef<jobject>
-InProcessViewRenderer::CapturePicture(int width, int height) {
- if (!compositor_ || !GetAwDrawSWFunctionTable()) {
- TRACE_EVENT_INSTANT0(
- "android_webview", "EarlyOut_CapturePicture", TRACE_EVENT_SCOPE_THREAD);
- return ScopedJavaLocalRef<jobject>();
- }
+skia::RefPtr<SkPicture> InProcessViewRenderer::CapturePicture(int width,
+ int height) {
+ TRACE_EVENT0("android_webview", "InProcessViewRenderer::CapturePicture");
// Return empty Picture objects for empty SkPictures.
- JNIEnv* env = AttachCurrentThread();
+ skia::RefPtr<SkPicture> picture = skia::AdoptRef(new SkPicture);
if (width <= 0 || height <= 0) {
- return java_helper_->RecordBitmapIntoPicture(env,
- ScopedJavaLocalRef<jobject>());
+ return picture;
}
// Reset scroll back to the origin, will go back to the old
@@ -485,36 +530,11 @@
base::AutoReset<gfx::Vector2dF> scroll_reset(&scroll_offset_css_,
gfx::Vector2d());
- skia::RefPtr<SkPicture> picture = skia::AdoptRef(new SkPicture);
SkCanvas* rec_canvas = picture->beginRecording(width, height, 0);
- if (!CompositeSW(rec_canvas))
- return ScopedJavaLocalRef<jobject>();
+ if (compositor_)
+ CompositeSW(rec_canvas);
picture->endRecording();
-
- if (IsSkiaVersionCompatible()) {
- // Add a reference that the create_picture() will take ownership of.
- picture->ref();
- return ScopedJavaLocalRef<jobject>(env,
- GetAwDrawSWFunctionTable()->create_picture(env, picture.get()));
- }
-
- // If Skia versions are not compatible, workaround it by rasterizing the
- // picture into a bitmap and drawing it into a new Java picture. Pass null
- // for |canvas| as we don't have java canvas at this point (and it would be
- // software anyway).
- ScopedJavaLocalRef<jobject> jbitmap(java_helper_->CreateBitmap(
- env, picture->width(), picture->height(), ScopedJavaLocalRef<jobject>(),
- NULL));
- if (!jbitmap.obj())
- return ScopedJavaLocalRef<jobject>();
-
- if (!RasterizeIntoBitmap(env, jbitmap, 0, 0,
- base::Bind(&RenderPictureToCanvas,
- base::Unretained(picture.get())))) {
- return ScopedJavaLocalRef<jobject>();
- }
-
- return java_helper_->RecordBitmapIntoPicture(env, jbitmap);
+ return picture;
}
void InProcessViewRenderer::EnableOnNewPicture(bool enabled) {
@@ -620,6 +640,7 @@
"invalidate",
invalidate);
compositor_needs_continuous_invalidate_ = invalidate;
+ need_fast_invalidate_ = compositor_needs_continuous_invalidate_;
EnsureContinuousInvalidation(NULL, false);
}
@@ -726,11 +747,17 @@
// ticked. This can happen if this is reached because
// invalidate_ignore_compositor is true.
if (compositor_needs_continuous_invalidate_) {
+ int64 delay_in_ms = kFallbackTickTimeoutInMilliseconds;
+ if (need_fast_invalidate_) {
+ TRACE_EVENT_INSTANT0(
+ "android_webview", "FastFallbackTick", TRACE_EVENT_SCOPE_THREAD);
+ delay_in_ms = 0;
+ need_fast_invalidate_ = false;
+ }
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
fallback_tick_.callback(),
- base::TimeDelta::FromMilliseconds(
- kFallbackTickTimeoutInMilliseconds));
+ base::TimeDelta::FromMilliseconds(delay_in_ms));
}
}
}
diff --git a/android_webview/browser/in_process_view_renderer.h b/android_webview/browser/in_process_view_renderer.h
index 8bb2c60..e86796f 100644
--- a/android_webview/browser/in_process_view_renderer.h
+++ b/android_webview/browser/in_process_view_renderer.h
@@ -38,6 +38,16 @@
static InProcessViewRenderer* FromWebContents(
content::WebContents* contents);
+ // TODO(joth): consider extracting this to its own utility class.
+ typedef base::Callback<bool(SkCanvas*)> RenderMethod;
+ static bool RenderViaAuxilaryBitmapIfNeeded(
+ jobject java_canvas,
+ JavaHelper* java_helper,
+ const gfx::Vector2d& scroll_correction,
+ const gfx::Rect& clip,
+ RenderMethod render_source,
+ void* owner_key);
+
// BrowserViewRenderer overrides
virtual bool OnDraw(jobject java_canvas,
bool is_hardware_canvas,
@@ -45,9 +55,8 @@
const gfx::Rect& clip) OVERRIDE;
virtual void DrawGL(AwDrawGLInfo* draw_info) OVERRIDE;
virtual void SetGlobalVisibleRect(const gfx::Rect& visible_rect) OVERRIDE;
- virtual base::android::ScopedJavaLocalRef<jobject> CapturePicture(
- int width,
- int height) OVERRIDE;
+ virtual skia::RefPtr<SkPicture> CapturePicture(int width,
+ int height) OVERRIDE;
virtual void EnableOnNewPicture(bool enabled) OVERRIDE;
virtual void OnVisibilityChanged(bool visible) OVERRIDE;
virtual void OnSizeChanged(int width, int height) OVERRIDE;
@@ -117,6 +126,13 @@
// states.
bool compositor_needs_continuous_invalidate_;
+ // If this is true, then the fallback tick is posted with zero delay. This
+ // is to reduce the time in cases when blink main thread is blocked waiting.
+ // This is set when |compositor_needs_continuous_invalidate_| is set.
+ // Eventually, this should correspond to BeginFrame when BeginFrame and
+ // BeginFrameDeadline are separate functions.
+ bool need_fast_invalidate_;
+
// Used to block additional invalidates while one is already pending or before
// compositor draw which may switch continuous_invalidate on and off in the
// process.
diff --git a/android_webview/buildbot/deps_whitelist.py b/android_webview/buildbot/deps_whitelist.py
index 69c87be..105646f 100755
--- a/android_webview/buildbot/deps_whitelist.py
+++ b/android_webview/buildbot/deps_whitelist.py
@@ -32,7 +32,6 @@
# Dependencies that need to be merged into the Android tree.
self._snapshot_into_android_dependencies = [
- 'googleurl',
'sdch/open-vcdiff',
'testing/gtest',
'third_party/WebKit',
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 099a6e9..493e75b 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -11,6 +11,7 @@
import android.graphics.Color;
import android.graphics.Picture;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.net.http.SslCertificate;
import android.os.AsyncTask;
import android.os.Build;
@@ -124,6 +125,11 @@
void setMeasuredDimension(int measuredWidth, int measuredHeight);
/**
+ * @see View#getScrollBarStyle()
+ */
+ int super_getScrollBarStyle();
+
+ /**
* Requests a callback on the native DrawGL method (see getAwDrawGLFunction)
* if called from within onDraw, |canvas| will be non-null and hardware accelerated.
* otherwise, |canvas| will be null, and the container view itself will be hardware
@@ -500,6 +506,7 @@
new OverScroller(mContainerView.getContext()));
setOverScrollMode(mContainerView.getOverScrollMode());
+ setScrollBarStyle(mInternalAccessAdapter.super_getScrollBarStyle());
setNewAwContents(nativeInit(browserContext));
}
@@ -664,7 +671,10 @@
@CalledByNative
private void updateGlobalVisibleRect() {
- mContainerView.getGlobalVisibleRect(sLocalGlobalVisibleRect);
+ if (!mContainerView.getGlobalVisibleRect(sLocalGlobalVisibleRect)) {
+ sLocalGlobalVisibleRect.setEmpty();
+ }
+
nativeSetGlobalVisibleRect(mNativeAwContents, sLocalGlobalVisibleRect.left,
sLocalGlobalVisibleRect.top, sLocalGlobalVisibleRect.right,
sLocalGlobalVisibleRect.bottom);
@@ -714,9 +724,9 @@
}
public Picture capturePicture() {
- return nativeCapturePicture(mNativeAwContents,
- mScrollOffsetManager.computeHorizontalScrollRange(),
- mScrollOffsetManager.computeVerticalScrollRange());
+ return new AwPicture(nativeCapturePicture(mNativeAwContents,
+ mScrollOffsetManager.computeHorizontalScrollRange(),
+ mScrollOffsetManager.computeVerticalScrollRange()));
}
/**
@@ -889,6 +899,54 @@
}
}
+ // TODO(mkosiba): In WebViewClassic these appear in some of the scroll extent calculation
+ // methods but toggling them has no visiual effect on the content (in other words the scrolling
+ // code behaves as if the scrollbar-related padding is in place but the onDraw code doesn't
+ // take that into consideration).
+ // http://crbug.com/269032
+ private boolean mOverlayHorizontalScrollbar = true;
+ private boolean mOverlayVerticalScrollbar = false;
+
+ /**
+ * @see View#setScrollBarStyle(int)
+ */
+ public void setScrollBarStyle(int style) {
+ if (style == View.SCROLLBARS_INSIDE_OVERLAY
+ || style == View.SCROLLBARS_OUTSIDE_OVERLAY) {
+ mOverlayHorizontalScrollbar = mOverlayVerticalScrollbar = true;
+ } else {
+ mOverlayHorizontalScrollbar = mOverlayVerticalScrollbar = false;
+ }
+ }
+
+ /**
+ * @see View#setHorizontalScrollbarOverlay(boolean)
+ */
+ public void setHorizontalScrollbarOverlay(boolean overlay) {
+ mOverlayHorizontalScrollbar = overlay;
+ }
+
+ /**
+ * @see View#setVerticalScrollbarOverlay(boolean)
+ */
+ public void setVerticalScrollbarOverlay(boolean overlay) {
+ mOverlayVerticalScrollbar = overlay;
+ }
+
+ /**
+ * @see View#overlayHorizontalScrollbar()
+ */
+ public boolean overlayHorizontalScrollbar() {
+ return mOverlayVerticalScrollbar;
+ }
+
+ /**
+ * @see View#overlayVerticalScrollbar()
+ */
+ public boolean overlayVerticalScrollbar() {
+ return mOverlayVerticalScrollbar;
+ }
+
/**
* Called by the embedder when the scroll offset of the containing view has changed.
* @see View#onScrollChanged(int,int)
@@ -1811,7 +1869,7 @@
private native void nativeSetBackgroundColor(int nativeAwContents, int color);
private native int nativeGetAwDrawGLViewContext(int nativeAwContents);
- private native Picture nativeCapturePicture(int nativeAwContents, int width, int height);
+ private native int nativeCapturePicture(int nativeAwContents, int width, int height);
private native void nativeEnableOnNewPicture(int nativeAwContents, boolean enabled);
private native void nativeInvokeGeolocationCallback(
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
index f1c7f45..3f2245c 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
@@ -199,6 +199,14 @@
// WebView specific methods that map directly to WebViewClient / WebChromeClient
//--------------------------------------------------------------------------------------------
+ public static class FileChooserParams {
+ public int mode;
+ public String acceptTypes;
+ public String title;
+ public String defaultFilename;
+ public boolean capture;
+ }
+
public abstract void getVisitedHistory(ValueCallback<String[]> callback);
public abstract void doUpdateVisitedHistory(String url, boolean isReload);
@@ -229,6 +237,10 @@
public abstract void onDownloadStart(String url, String userAgent, String contentDisposition,
String mimeType, long contentLength);
+ // TODO(joth): Make abstract once this has rolled in downstream.
+ public /*abstract*/ void showFileChooser(ValueCallback<String[]> uploadFilePathsCallback,
+ FileChooserParams fileChooserParams) { }
+
public abstract void onGeolocationPermissionsShowPrompt(String origin,
GeolocationPermissions.Callback callback);
diff --git a/android_webview/java/src/org/chromium/android_webview/AwPicture.java b/android_webview/java/src/org/chromium/android_webview/AwPicture.java
new file mode 100644
index 0000000..30ec57b
--- /dev/null
+++ b/android_webview/java/src/org/chromium/android_webview/AwPicture.java
@@ -0,0 +1,95 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.android_webview;
+
+import android.graphics.Canvas;
+import android.graphics.Picture;
+import android.graphics.Rect;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+import org.chromium.content.common.CleanupReference;
+
+import java.io.OutputStream;
+
+// A simple wrapper around a SkPicture, that allows final rendering to be performed using the
+// chromium skia library.
+@JNINamespace("android_webview")
+class AwPicture extends Picture {
+
+ private int mNativeAwPicture;
+
+ // There is no explicit destroy method on Picture base-class, so cleanup is always
+ // handled via the CleanupReference.
+ private static final class DestroyRunnable implements Runnable {
+ private int mNativeAwPicture;
+ private DestroyRunnable(int nativeAwPicture) {
+ mNativeAwPicture = nativeAwPicture;
+ }
+ @Override
+ public void run() {
+ nativeDestroy(mNativeAwPicture);
+ }
+ }
+
+ private CleanupReference mCleanupReference;
+
+ /**
+ * @param nativeAwPicture is an instance of the AwPicture native class. Ownership is
+ * taken by this java instance.
+ */
+ AwPicture(int nativeAwPicture) {
+ mNativeAwPicture = nativeAwPicture;
+ mCleanupReference = new CleanupReference(this, new DestroyRunnable(nativeAwPicture));
+ }
+
+ @Override
+ public Canvas beginRecording(int width, int height) {
+ unsupportedOperation();
+ return null;
+ }
+
+ @Override
+ public void endRecording() {
+ // Intentional no-op. The native picture ended recording prior to java c'tor call.
+ }
+
+ @Override
+ public int getWidth() {
+ return nativeGetWidth(mNativeAwPicture);
+ }
+
+ @Override
+ public int getHeight() {
+ return nativeGetHeight(mNativeAwPicture);
+ }
+
+ // Effectively a local variable of draw(), but held as a member to avoid GC churn.
+ private Rect mClipBoundsTemporary = new Rect();
+
+ @Override
+ public void draw(Canvas canvas) {
+ canvas.getClipBounds(mClipBoundsTemporary);
+ nativeDraw(mNativeAwPicture, canvas,
+ mClipBoundsTemporary.left, mClipBoundsTemporary.top,
+ mClipBoundsTemporary.right, mClipBoundsTemporary.bottom);
+ }
+
+ @Override
+ public void writeToStream(OutputStream stream) {
+ unsupportedOperation();
+ }
+
+ private void unsupportedOperation() {
+ throw new IllegalStateException("Unsupported in AwPicture");
+ }
+
+ private static native void nativeDestroy(int nativeAwPicture);
+ private native int nativeGetWidth(int nativeAwPicture);
+ private native int nativeGetHeight(int nativeAwPicture);
+ private native void nativeDraw(int nativeAwPicture, Canvas canvas,
+ int left, int top, int right, int bottom);
+}
+
diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java
index 23f48eb..d26fd9a 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java
@@ -4,6 +4,8 @@
package org.chromium.android_webview;
+import com.google.common.annotations.VisibleForTesting;
+
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.components.web_contents_delegate_android.WebContentsDelegateAndroid;
@@ -14,8 +16,14 @@
* It should contain abstract WebContentsDelegate methods to be implemented by the embedder.
* These methods belong to WebView but are not shared with the Chromium Android port.
*/
+@VisibleForTesting
@JNINamespace("android_webview")
public abstract class AwWebContentsDelegate extends WebContentsDelegateAndroid {
+ // Callback filesSelectedInChooser() when done.
+ @CalledByNative
+ public abstract void runFileChooser(int processId, int renderId, int mode_flags,
+ String acceptTypes, String title, String defaultFilename, boolean capture);
+
@CalledByNative
public abstract boolean addNewContents(boolean isDialog, boolean isUserGesture);
@@ -33,4 +41,8 @@
@CalledByNative
public void updatePreferredSize(int widthCss, int heightCss) {
}
+
+ // Call in response to a prior runFileChooser call.
+ protected static native void nativeFilesSelectedInChooser(int processId, int renderId,
+ int mode_flags, String[] filePath);
}
diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
index f5eefe8..260ea96 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
@@ -11,6 +11,7 @@
import android.util.Log;
import android.view.KeyEvent;
import android.webkit.ConsoleMessage;
+import android.webkit.ValueCallback;
import org.chromium.content.browser.ContentViewCore;
@@ -86,14 +87,15 @@
@Override
public void openNewTab(String url, String extraHeaders, byte[] postData, int disposition) {
- // TODO: implement
+ // This is only called in chrome layers.
+ assert false;
}
@Override
public boolean addNewContents(int nativeSourceWebContents, int nativeWebContents,
int disposition, Rect initialPosition, boolean userGesture) {
- // TODO: implement
- return false;
+ // This is overridden native side; see the other addNewContents overload.
+ throw new RuntimeException("Impossible");
}
@Override
@@ -136,6 +138,29 @@
}
@Override
+ public void runFileChooser(final int processId, final int renderId, final int mode_flags,
+ String acceptTypes, String title, String defaultFilename, boolean capture) {
+ AwContentsClient.FileChooserParams params = new AwContentsClient.FileChooserParams();
+ params.mode = mode_flags;
+ params.acceptTypes = acceptTypes;
+ params.title = title;
+ params.defaultFilename = defaultFilename;
+ params.capture = capture;
+
+ mContentsClient.showFileChooser(new ValueCallback<String[]>() {
+ boolean completed = false;
+ @Override
+ public void onReceiveValue(String[] results) {
+ if (completed) {
+ throw new IllegalStateException("Duplicate showFileChooser result");
+ }
+ completed = true;
+ nativeFilesSelectedInChooser(processId, renderId, mode_flags, results);
+ }
+ }, params);
+ }
+
+ @Override
public boolean addNewContents(boolean isDialog, boolean isUserGesture) {
return mContentsClient.onCreateWindow(isDialog, isUserGesture);
}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwTargetDensityDpiTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwTargetDensityDpiTest.java
index 92dfb61..1a10196 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwTargetDensityDpiTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwTargetDensityDpiTest.java
@@ -38,8 +38,9 @@
int actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
assertEquals((float)deviceInfo.getDisplayWidth(), (float)actualWidth, 10f);
- float displayWidth = (float)(deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale());
- float deviceDpi = (float)(120f * deviceInfo.getDIPScale());
+ float displayWidth = (float)(deviceInfo.getDisplayWidth());
+ float deviceDpi = (float)(160f * deviceInfo.getDIPScale());
+
loadDataSync(awContents, onPageFinishedHelper, pageHighDpi, "text/html", false);
actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
assertEquals(displayWidth * (240f / deviceDpi), (float)actualWidth, 10f);
diff --git a/android_webview/libwebviewchromium.target.darwin-arm.mk b/android_webview/libwebviewchromium.target.darwin-arm.mk
index a634af8..fe7c5a0 100644
--- a/android_webview/libwebviewchromium.target.darwin-arm.mk
+++ b/android_webview/libwebviewchromium.target.darwin-arm.mk
@@ -38,6 +38,7 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_gyp)/skia_skia_opts_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_neon_gyp)/skia_skia_opts_neon_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_zlib_zlib_gyp)/third_party_zlib_zlib_gyp.a \
+ $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_freetype_ft2_gyp)/third_party_freetype_ft2_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a \
@@ -151,18 +152,10 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_modules_modules_gyp)/third_party_WebKit_Source_modules_modules_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,printing_printing_gyp)/printing_printing_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_plugins_plugins_common_gyp)/webkit_plugins_plugins_common_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_support_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_support_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_gpu_webkit_gpu_gyp)/webkit_common_gpu_webkit_gpu_gyp.a \
$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_plugins_gyp)/webkit_support_plugins_gyp.a \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ppapi_ppapi_shared_gyp)/ppapi_ppapi_shared_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_native_theme_native_theme_gyp)/ui_native_theme_native_theme_gyp.a \
- $(call intermediates-dir-for,GYP,webkit_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_common_aidl_gyp)/common_aidl.stamp \
@@ -179,6 +172,9 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,ui_snapshot_snapshot_gyp)/ui_snapshot_snapshot_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_child_gyp)/content_content_child_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_native_theme_native_theme_gyp)/ui_native_theme_native_theme_gyp.a \
+ $(call intermediates-dir-for,GYP,webkit_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -198,6 +194,7 @@
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_script_formatter_worker_js_gyp)/concatenated_script_formatter_worker_js.stamp \
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_css_gyp)/concatenated_devtools_css.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,net_http_server_gyp)/net_http_server_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
$(call intermediates-dir-for,GYP,sandbox_sandbox_gyp)/sandbox.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_sandbox_services_gyp)/sandbox_sandbox_services_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_seccomp_bpf_gyp)/sandbox_seccomp_bpf_gyp.a \
@@ -548,15 +545,9 @@
third_party_WebKit_Source_modules_modules_gyp \
webkit_support_glue_gyp \
printing_printing_gyp \
- webkit_plugins_plugins_common_gyp \
webkit_renderer_compositor_bindings_webkit_compositor_support_gyp \
webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp \
webkit_common_gpu_webkit_gpu_gyp \
- webkit_support_plugins_gyp \
- ppapi_ppapi_shared_gyp \
- ui_surface_surface_gyp \
- webkit_support_glue_child_gyp \
- ui_native_theme_native_theme_gyp \
components_encryptor_gyp \
components_user_prefs_gyp \
base_base_prefs_gyp \
@@ -568,8 +559,11 @@
ui_snapshot_snapshot_gyp \
content_content_gpu_gyp \
content_content_child_gyp \
+ webkit_support_glue_child_gyp \
+ ui_native_theme_native_theme_gyp \
content_content_utility_gyp \
net_http_server_gyp \
+ ui_surface_surface_gyp \
sandbox_sandbox_services_gyp \
sandbox_seccomp_bpf_gyp \
components_webdata_common_gyp \
diff --git a/android_webview/libwebviewchromium.target.darwin-mips.mk b/android_webview/libwebviewchromium.target.darwin-mips.mk
index a8686e5..f153051 100644
--- a/android_webview/libwebviewchromium.target.darwin-mips.mk
+++ b/android_webview/libwebviewchromium.target.darwin-mips.mk
@@ -37,6 +37,7 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_gyp)/skia_skia_opts_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_zlib_zlib_gyp)/third_party_zlib_zlib_gyp.a \
+ $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_freetype_ft2_gyp)/third_party_freetype_ft2_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a \
@@ -149,18 +150,10 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_modules_modules_gyp)/third_party_WebKit_Source_modules_modules_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,printing_printing_gyp)/printing_printing_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_plugins_plugins_common_gyp)/webkit_plugins_plugins_common_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_support_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_support_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_gpu_webkit_gpu_gyp)/webkit_common_gpu_webkit_gpu_gyp.a \
$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_plugins_gyp)/webkit_support_plugins_gyp.a \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ppapi_ppapi_shared_gyp)/ppapi_ppapi_shared_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_native_theme_native_theme_gyp)/ui_native_theme_native_theme_gyp.a \
- $(call intermediates-dir-for,GYP,webkit_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_common_aidl_gyp)/common_aidl.stamp \
@@ -177,6 +170,9 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,ui_snapshot_snapshot_gyp)/ui_snapshot_snapshot_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_child_gyp)/content_content_child_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_native_theme_native_theme_gyp)/ui_native_theme_native_theme_gyp.a \
+ $(call intermediates-dir-for,GYP,webkit_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -196,6 +192,7 @@
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_script_formatter_worker_js_gyp)/concatenated_script_formatter_worker_js.stamp \
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_css_gyp)/concatenated_devtools_css.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,net_http_server_gyp)/net_http_server_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
$(call intermediates-dir-for,GYP,sandbox_sandbox_gyp)/sandbox.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_sandbox_services_gyp)/sandbox_sandbox_services_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,components_webdata_common_gyp)/components_webdata_common_gyp.a \
@@ -535,15 +532,9 @@
third_party_WebKit_Source_modules_modules_gyp \
webkit_support_glue_gyp \
printing_printing_gyp \
- webkit_plugins_plugins_common_gyp \
webkit_renderer_compositor_bindings_webkit_compositor_support_gyp \
webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp \
webkit_common_gpu_webkit_gpu_gyp \
- webkit_support_plugins_gyp \
- ppapi_ppapi_shared_gyp \
- ui_surface_surface_gyp \
- webkit_support_glue_child_gyp \
- ui_native_theme_native_theme_gyp \
components_encryptor_gyp \
components_user_prefs_gyp \
base_base_prefs_gyp \
@@ -555,8 +546,11 @@
ui_snapshot_snapshot_gyp \
content_content_gpu_gyp \
content_content_child_gyp \
+ webkit_support_glue_child_gyp \
+ ui_native_theme_native_theme_gyp \
content_content_utility_gyp \
net_http_server_gyp \
+ ui_surface_surface_gyp \
sandbox_sandbox_services_gyp \
components_webdata_common_gyp \
third_party_libjingle_libjingle_gyp \
diff --git a/android_webview/libwebviewchromium.target.darwin-x86.mk b/android_webview/libwebviewchromium.target.darwin-x86.mk
index b2cbb0e..5bc5e16 100644
--- a/android_webview/libwebviewchromium.target.darwin-x86.mk
+++ b/android_webview/libwebviewchromium.target.darwin-x86.mk
@@ -38,6 +38,7 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_gyp)/skia_skia_opts_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_ssse3_gyp)/skia_skia_opts_ssse3_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_zlib_zlib_gyp)/third_party_zlib_zlib_gyp.a \
+ $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_freetype_ft2_gyp)/third_party_freetype_ft2_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a \
@@ -155,18 +156,10 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_modules_modules_gyp)/third_party_WebKit_Source_modules_modules_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,printing_printing_gyp)/printing_printing_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_plugins_plugins_common_gyp)/webkit_plugins_plugins_common_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_support_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_support_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_gpu_webkit_gpu_gyp)/webkit_common_gpu_webkit_gpu_gyp.a \
$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_plugins_gyp)/webkit_support_plugins_gyp.a \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ppapi_ppapi_shared_gyp)/ppapi_ppapi_shared_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_native_theme_native_theme_gyp)/ui_native_theme_native_theme_gyp.a \
- $(call intermediates-dir-for,GYP,webkit_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_common_aidl_gyp)/common_aidl.stamp \
@@ -183,6 +176,9 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,ui_snapshot_snapshot_gyp)/ui_snapshot_snapshot_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_child_gyp)/content_content_child_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_native_theme_native_theme_gyp)/ui_native_theme_native_theme_gyp.a \
+ $(call intermediates-dir-for,GYP,webkit_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -202,6 +198,7 @@
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_script_formatter_worker_js_gyp)/concatenated_script_formatter_worker_js.stamp \
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_css_gyp)/concatenated_devtools_css.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,net_http_server_gyp)/net_http_server_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
$(call intermediates-dir-for,GYP,sandbox_sandbox_gyp)/sandbox.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_sandbox_services_gyp)/sandbox_sandbox_services_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_seccomp_bpf_gyp)/sandbox_seccomp_bpf_gyp.a \
@@ -555,15 +552,9 @@
third_party_WebKit_Source_modules_modules_gyp \
webkit_support_glue_gyp \
printing_printing_gyp \
- webkit_plugins_plugins_common_gyp \
webkit_renderer_compositor_bindings_webkit_compositor_support_gyp \
webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp \
webkit_common_gpu_webkit_gpu_gyp \
- webkit_support_plugins_gyp \
- ppapi_ppapi_shared_gyp \
- ui_surface_surface_gyp \
- webkit_support_glue_child_gyp \
- ui_native_theme_native_theme_gyp \
components_encryptor_gyp \
components_user_prefs_gyp \
base_base_prefs_gyp \
@@ -575,8 +566,11 @@
ui_snapshot_snapshot_gyp \
content_content_gpu_gyp \
content_content_child_gyp \
+ webkit_support_glue_child_gyp \
+ ui_native_theme_native_theme_gyp \
content_content_utility_gyp \
net_http_server_gyp \
+ ui_surface_surface_gyp \
sandbox_sandbox_services_gyp \
sandbox_seccomp_bpf_gyp \
components_webdata_common_gyp \
diff --git a/android_webview/libwebviewchromium.target.linux-arm.mk b/android_webview/libwebviewchromium.target.linux-arm.mk
index a634af8..fe7c5a0 100644
--- a/android_webview/libwebviewchromium.target.linux-arm.mk
+++ b/android_webview/libwebviewchromium.target.linux-arm.mk
@@ -38,6 +38,7 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_gyp)/skia_skia_opts_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_neon_gyp)/skia_skia_opts_neon_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_zlib_zlib_gyp)/third_party_zlib_zlib_gyp.a \
+ $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_freetype_ft2_gyp)/third_party_freetype_ft2_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a \
@@ -151,18 +152,10 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_modules_modules_gyp)/third_party_WebKit_Source_modules_modules_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,printing_printing_gyp)/printing_printing_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_plugins_plugins_common_gyp)/webkit_plugins_plugins_common_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_support_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_support_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_gpu_webkit_gpu_gyp)/webkit_common_gpu_webkit_gpu_gyp.a \
$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_plugins_gyp)/webkit_support_plugins_gyp.a \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ppapi_ppapi_shared_gyp)/ppapi_ppapi_shared_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_native_theme_native_theme_gyp)/ui_native_theme_native_theme_gyp.a \
- $(call intermediates-dir-for,GYP,webkit_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_common_aidl_gyp)/common_aidl.stamp \
@@ -179,6 +172,9 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,ui_snapshot_snapshot_gyp)/ui_snapshot_snapshot_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_child_gyp)/content_content_child_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_native_theme_native_theme_gyp)/ui_native_theme_native_theme_gyp.a \
+ $(call intermediates-dir-for,GYP,webkit_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -198,6 +194,7 @@
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_script_formatter_worker_js_gyp)/concatenated_script_formatter_worker_js.stamp \
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_css_gyp)/concatenated_devtools_css.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,net_http_server_gyp)/net_http_server_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
$(call intermediates-dir-for,GYP,sandbox_sandbox_gyp)/sandbox.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_sandbox_services_gyp)/sandbox_sandbox_services_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_seccomp_bpf_gyp)/sandbox_seccomp_bpf_gyp.a \
@@ -548,15 +545,9 @@
third_party_WebKit_Source_modules_modules_gyp \
webkit_support_glue_gyp \
printing_printing_gyp \
- webkit_plugins_plugins_common_gyp \
webkit_renderer_compositor_bindings_webkit_compositor_support_gyp \
webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp \
webkit_common_gpu_webkit_gpu_gyp \
- webkit_support_plugins_gyp \
- ppapi_ppapi_shared_gyp \
- ui_surface_surface_gyp \
- webkit_support_glue_child_gyp \
- ui_native_theme_native_theme_gyp \
components_encryptor_gyp \
components_user_prefs_gyp \
base_base_prefs_gyp \
@@ -568,8 +559,11 @@
ui_snapshot_snapshot_gyp \
content_content_gpu_gyp \
content_content_child_gyp \
+ webkit_support_glue_child_gyp \
+ ui_native_theme_native_theme_gyp \
content_content_utility_gyp \
net_http_server_gyp \
+ ui_surface_surface_gyp \
sandbox_sandbox_services_gyp \
sandbox_seccomp_bpf_gyp \
components_webdata_common_gyp \
diff --git a/android_webview/libwebviewchromium.target.linux-mips.mk b/android_webview/libwebviewchromium.target.linux-mips.mk
index a8686e5..f153051 100644
--- a/android_webview/libwebviewchromium.target.linux-mips.mk
+++ b/android_webview/libwebviewchromium.target.linux-mips.mk
@@ -37,6 +37,7 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_gyp)/skia_skia_opts_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_zlib_zlib_gyp)/third_party_zlib_zlib_gyp.a \
+ $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_freetype_ft2_gyp)/third_party_freetype_ft2_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a \
@@ -149,18 +150,10 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_modules_modules_gyp)/third_party_WebKit_Source_modules_modules_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,printing_printing_gyp)/printing_printing_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_plugins_plugins_common_gyp)/webkit_plugins_plugins_common_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_support_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_support_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_gpu_webkit_gpu_gyp)/webkit_common_gpu_webkit_gpu_gyp.a \
$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_plugins_gyp)/webkit_support_plugins_gyp.a \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ppapi_ppapi_shared_gyp)/ppapi_ppapi_shared_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_native_theme_native_theme_gyp)/ui_native_theme_native_theme_gyp.a \
- $(call intermediates-dir-for,GYP,webkit_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_common_aidl_gyp)/common_aidl.stamp \
@@ -177,6 +170,9 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,ui_snapshot_snapshot_gyp)/ui_snapshot_snapshot_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_child_gyp)/content_content_child_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_native_theme_native_theme_gyp)/ui_native_theme_native_theme_gyp.a \
+ $(call intermediates-dir-for,GYP,webkit_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -196,6 +192,7 @@
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_script_formatter_worker_js_gyp)/concatenated_script_formatter_worker_js.stamp \
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_css_gyp)/concatenated_devtools_css.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,net_http_server_gyp)/net_http_server_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
$(call intermediates-dir-for,GYP,sandbox_sandbox_gyp)/sandbox.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_sandbox_services_gyp)/sandbox_sandbox_services_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,components_webdata_common_gyp)/components_webdata_common_gyp.a \
@@ -535,15 +532,9 @@
third_party_WebKit_Source_modules_modules_gyp \
webkit_support_glue_gyp \
printing_printing_gyp \
- webkit_plugins_plugins_common_gyp \
webkit_renderer_compositor_bindings_webkit_compositor_support_gyp \
webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp \
webkit_common_gpu_webkit_gpu_gyp \
- webkit_support_plugins_gyp \
- ppapi_ppapi_shared_gyp \
- ui_surface_surface_gyp \
- webkit_support_glue_child_gyp \
- ui_native_theme_native_theme_gyp \
components_encryptor_gyp \
components_user_prefs_gyp \
base_base_prefs_gyp \
@@ -555,8 +546,11 @@
ui_snapshot_snapshot_gyp \
content_content_gpu_gyp \
content_content_child_gyp \
+ webkit_support_glue_child_gyp \
+ ui_native_theme_native_theme_gyp \
content_content_utility_gyp \
net_http_server_gyp \
+ ui_surface_surface_gyp \
sandbox_sandbox_services_gyp \
components_webdata_common_gyp \
third_party_libjingle_libjingle_gyp \
diff --git a/android_webview/libwebviewchromium.target.linux-x86.mk b/android_webview/libwebviewchromium.target.linux-x86.mk
index b2cbb0e..5bc5e16 100644
--- a/android_webview/libwebviewchromium.target.linux-x86.mk
+++ b/android_webview/libwebviewchromium.target.linux-x86.mk
@@ -38,6 +38,7 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_gyp)/skia_skia_opts_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_ssse3_gyp)/skia_skia_opts_ssse3_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_zlib_zlib_gyp)/third_party_zlib_zlib_gyp.a \
+ $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_freetype_ft2_gyp)/third_party_freetype_ft2_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a \
@@ -155,18 +156,10 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_modules_modules_gyp)/third_party_WebKit_Source_modules_modules_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_gyp)/webkit_support_glue_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,printing_printing_gyp)/printing_printing_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_plugins_plugins_common_gyp)/webkit_plugins_plugins_common_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_support_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_support_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_gpu_webkit_gpu_gyp)/webkit_common_gpu_webkit_gpu_gyp.a \
$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_plugins_gyp)/webkit_support_plugins_gyp.a \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ppapi_ppapi_shared_gyp)/ppapi_ppapi_shared_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_native_theme_native_theme_gyp)/ui_native_theme_native_theme_gyp.a \
- $(call intermediates-dir-for,GYP,webkit_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp \
$(call intermediates-dir-for,GYP,content_common_aidl_gyp)/common_aidl.stamp \
@@ -183,6 +176,9 @@
$(call intermediates-dir-for,STATIC_LIBRARIES,ui_snapshot_snapshot_gyp)/ui_snapshot_snapshot_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_child_gyp)/content_content_child_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_native_theme_native_theme_gyp)/ui_native_theme_native_theme_gyp.a \
+ $(call intermediates-dir-for,GYP,webkit_support_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -202,6 +198,7 @@
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_script_formatter_worker_js_gyp)/concatenated_script_formatter_worker_js.stamp \
$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_css_gyp)/concatenated_devtools_css.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,net_http_server_gyp)/net_http_server_gyp.a \
+ $(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
$(call intermediates-dir-for,GYP,sandbox_sandbox_gyp)/sandbox.stamp \
$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_sandbox_services_gyp)/sandbox_sandbox_services_gyp.a \
$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_seccomp_bpf_gyp)/sandbox_seccomp_bpf_gyp.a \
@@ -555,15 +552,9 @@
third_party_WebKit_Source_modules_modules_gyp \
webkit_support_glue_gyp \
printing_printing_gyp \
- webkit_plugins_plugins_common_gyp \
webkit_renderer_compositor_bindings_webkit_compositor_support_gyp \
webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp \
webkit_common_gpu_webkit_gpu_gyp \
- webkit_support_plugins_gyp \
- ppapi_ppapi_shared_gyp \
- ui_surface_surface_gyp \
- webkit_support_glue_child_gyp \
- ui_native_theme_native_theme_gyp \
components_encryptor_gyp \
components_user_prefs_gyp \
base_base_prefs_gyp \
@@ -575,8 +566,11 @@
ui_snapshot_snapshot_gyp \
content_content_gpu_gyp \
content_content_child_gyp \
+ webkit_support_glue_child_gyp \
+ ui_native_theme_native_theme_gyp \
content_content_utility_gyp \
net_http_server_gyp \
+ ui_surface_surface_gyp \
sandbox_sandbox_services_gyp \
sandbox_seccomp_bpf_gyp \
components_webdata_common_gyp \
diff --git a/android_webview/native/DEPS b/android_webview/native/DEPS
index b45be10..f2d6372 100644
--- a/android_webview/native/DEPS
+++ b/android_webview/native/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+content/public/browser",
"+ui/gfx",
+ "+ui/shell_dialogs",
# Components that Android WebView depends on.
"+components/autofill/content/browser",
diff --git a/android_webview/native/android_webview_jni_registrar.cc b/android_webview/native/android_webview_jni_registrar.cc
index 9202999..4ee5a3b 100644
--- a/android_webview/native/android_webview_jni_registrar.cc
+++ b/android_webview/native/android_webview_jni_registrar.cc
@@ -11,6 +11,7 @@
#include "android_webview/native/aw_contents_io_thread_client_impl.h"
#include "android_webview/native/aw_form_database.h"
#include "android_webview/native/aw_http_auth_handler.h"
+#include "android_webview/native/aw_picture.h"
#include "android_webview/native/aw_quota_manager_bridge_impl.h"
#include "android_webview/native/aw_resource.h"
#include "android_webview/native/aw_settings.h"
@@ -31,8 +32,9 @@
{ "AwAutofillManagerDelegate", RegisterAwAutofillManagerDelegate },
{ "AwContents", RegisterAwContents },
{ "AwContentsClientBridge", RegisterAwContentsClientBridge },
- { "AwContentsIoThreadClientImpl", RegisterAwContentsIoThreadClientImpl},
- { "AwFormDatabase", RegisterAwFormDatabase},
+ { "AwContentsIoThreadClientImpl", RegisterAwContentsIoThreadClientImpl },
+ { "AwFormDatabase", RegisterAwFormDatabase },
+ { "AwPicture", RegisterAwPicture },
{ "AwSettings", RegisterAwSettings },
{ "AwHttpAuthHandler", RegisterAwHttpAuthHandler },
{ "AwQuotaManagerBridge", RegisterAwQuotaManagerBridge },
diff --git a/android_webview/native/android_webview_native_jni.target.darwin-arm.mk b/android_webview/native/android_webview_native_jni.target.darwin-arm.mk
index 1669251..2519432 100644
--- a/android_webview/native/android_webview_native_jni.target.darwin-arm.mk
+++ b/android_webview/native/android_webview_native_jni.target.darwin-arm.mk
@@ -16,7 +16,7 @@
### Generated for rule "android_webview_native_webview_native_gyp_android_webview_native_jni_target_generate_jni_headers":
-# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/android_webview/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../java/src/org/chromium/android_webview/AndroidProtocolHandler.java', '../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java', '../java/src/org/chromium/android_webview/AwContents.java', '../java/src/org/chromium/android_webview/AwContentsClientBridge.java', '../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java', '../java/src/org/chromium/android_webview/AwCookieManager.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', '../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java', '../java/src/org/chromium/android_webview/AwResource.java', '../java/src/org/chromium/android_webview/AwSettings.java', '../java/src/org/chromium/android_webview/AwWebContentsDelegate.java', '../java/src/org/chromium/android_webview/InterceptedRequestData.java', '../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/android_webview/jni', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/android_webview/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../java/src/org/chromium/android_webview/AndroidProtocolHandler.java', '../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java', '../java/src/org/chromium/android_webview/AwContents.java', '../java/src/org/chromium/android_webview/AwContentsClientBridge.java', '../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java', '../java/src/org/chromium/android_webview/AwCookieManager.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', '../java/src/org/chromium/android_webview/AwPicture.java', '../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java', '../java/src/org/chromium/android_webview/AwResource.java', '../java/src/org/chromium/android_webview/AwSettings.java', '../java/src/org/chromium/android_webview/AwWebContentsDelegate.java', '../java/src/org/chromium/android_webview/InterceptedRequestData.java', '../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/android_webview/jni', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_local_path := $(LOCAL_PATH)
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
@@ -97,6 +97,16 @@
.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwPicture.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+ mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwPicture.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h
+
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
@@ -168,6 +178,7 @@
$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+ $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
@@ -187,6 +198,7 @@
$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+ $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
diff --git a/android_webview/native/android_webview_native_jni.target.darwin-mips.mk b/android_webview/native/android_webview_native_jni.target.darwin-mips.mk
index 22ccb8f..e0d9362 100644
--- a/android_webview/native/android_webview_native_jni.target.darwin-mips.mk
+++ b/android_webview/native/android_webview_native_jni.target.darwin-mips.mk
@@ -16,7 +16,7 @@
### Generated for rule "android_webview_native_webview_native_gyp_android_webview_native_jni_target_generate_jni_headers":
-# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/android_webview/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../java/src/org/chromium/android_webview/AndroidProtocolHandler.java', '../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java', '../java/src/org/chromium/android_webview/AwContents.java', '../java/src/org/chromium/android_webview/AwContentsClientBridge.java', '../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java', '../java/src/org/chromium/android_webview/AwCookieManager.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', '../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java', '../java/src/org/chromium/android_webview/AwResource.java', '../java/src/org/chromium/android_webview/AwSettings.java', '../java/src/org/chromium/android_webview/AwWebContentsDelegate.java', '../java/src/org/chromium/android_webview/InterceptedRequestData.java', '../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/android_webview/jni', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/android_webview/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../java/src/org/chromium/android_webview/AndroidProtocolHandler.java', '../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java', '../java/src/org/chromium/android_webview/AwContents.java', '../java/src/org/chromium/android_webview/AwContentsClientBridge.java', '../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java', '../java/src/org/chromium/android_webview/AwCookieManager.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', '../java/src/org/chromium/android_webview/AwPicture.java', '../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java', '../java/src/org/chromium/android_webview/AwResource.java', '../java/src/org/chromium/android_webview/AwSettings.java', '../java/src/org/chromium/android_webview/AwWebContentsDelegate.java', '../java/src/org/chromium/android_webview/InterceptedRequestData.java', '../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/android_webview/jni', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_local_path := $(LOCAL_PATH)
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
@@ -97,6 +97,16 @@
.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwPicture.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+ mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwPicture.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h
+
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
@@ -168,6 +178,7 @@
$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+ $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
@@ -187,6 +198,7 @@
$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+ $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
diff --git a/android_webview/native/android_webview_native_jni.target.darwin-x86.mk b/android_webview/native/android_webview_native_jni.target.darwin-x86.mk
index 4ae68f7..d9893f7 100644
--- a/android_webview/native/android_webview_native_jni.target.darwin-x86.mk
+++ b/android_webview/native/android_webview_native_jni.target.darwin-x86.mk
@@ -16,7 +16,7 @@
### Generated for rule "android_webview_native_webview_native_gyp_android_webview_native_jni_target_generate_jni_headers":
-# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/android_webview/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../java/src/org/chromium/android_webview/AndroidProtocolHandler.java', '../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java', '../java/src/org/chromium/android_webview/AwContents.java', '../java/src/org/chromium/android_webview/AwContentsClientBridge.java', '../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java', '../java/src/org/chromium/android_webview/AwCookieManager.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', '../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java', '../java/src/org/chromium/android_webview/AwResource.java', '../java/src/org/chromium/android_webview/AwSettings.java', '../java/src/org/chromium/android_webview/AwWebContentsDelegate.java', '../java/src/org/chromium/android_webview/InterceptedRequestData.java', '../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/android_webview/jni', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/android_webview/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../java/src/org/chromium/android_webview/AndroidProtocolHandler.java', '../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java', '../java/src/org/chromium/android_webview/AwContents.java', '../java/src/org/chromium/android_webview/AwContentsClientBridge.java', '../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java', '../java/src/org/chromium/android_webview/AwCookieManager.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', '../java/src/org/chromium/android_webview/AwPicture.java', '../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java', '../java/src/org/chromium/android_webview/AwResource.java', '../java/src/org/chromium/android_webview/AwSettings.java', '../java/src/org/chromium/android_webview/AwWebContentsDelegate.java', '../java/src/org/chromium/android_webview/InterceptedRequestData.java', '../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/android_webview/jni', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_local_path := $(LOCAL_PATH)
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
@@ -97,6 +97,16 @@
.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwPicture.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+ mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwPicture.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h
+
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
@@ -168,6 +178,7 @@
$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+ $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
@@ -187,6 +198,7 @@
$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+ $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
diff --git a/android_webview/native/android_webview_native_jni.target.linux-arm.mk b/android_webview/native/android_webview_native_jni.target.linux-arm.mk
index 1669251..2519432 100644
--- a/android_webview/native/android_webview_native_jni.target.linux-arm.mk
+++ b/android_webview/native/android_webview_native_jni.target.linux-arm.mk
@@ -16,7 +16,7 @@
### Generated for rule "android_webview_native_webview_native_gyp_android_webview_native_jni_target_generate_jni_headers":
-# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/android_webview/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../java/src/org/chromium/android_webview/AndroidProtocolHandler.java', '../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java', '../java/src/org/chromium/android_webview/AwContents.java', '../java/src/org/chromium/android_webview/AwContentsClientBridge.java', '../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java', '../java/src/org/chromium/android_webview/AwCookieManager.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', '../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java', '../java/src/org/chromium/android_webview/AwResource.java', '../java/src/org/chromium/android_webview/AwSettings.java', '../java/src/org/chromium/android_webview/AwWebContentsDelegate.java', '../java/src/org/chromium/android_webview/InterceptedRequestData.java', '../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/android_webview/jni', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/android_webview/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../java/src/org/chromium/android_webview/AndroidProtocolHandler.java', '../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java', '../java/src/org/chromium/android_webview/AwContents.java', '../java/src/org/chromium/android_webview/AwContentsClientBridge.java', '../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java', '../java/src/org/chromium/android_webview/AwCookieManager.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', '../java/src/org/chromium/android_webview/AwPicture.java', '../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java', '../java/src/org/chromium/android_webview/AwResource.java', '../java/src/org/chromium/android_webview/AwSettings.java', '../java/src/org/chromium/android_webview/AwWebContentsDelegate.java', '../java/src/org/chromium/android_webview/InterceptedRequestData.java', '../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/android_webview/jni', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_local_path := $(LOCAL_PATH)
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
@@ -97,6 +97,16 @@
.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwPicture.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+ mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwPicture.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h
+
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
@@ -168,6 +178,7 @@
$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+ $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
@@ -187,6 +198,7 @@
$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+ $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
diff --git a/android_webview/native/android_webview_native_jni.target.linux-mips.mk b/android_webview/native/android_webview_native_jni.target.linux-mips.mk
index 22ccb8f..e0d9362 100644
--- a/android_webview/native/android_webview_native_jni.target.linux-mips.mk
+++ b/android_webview/native/android_webview_native_jni.target.linux-mips.mk
@@ -16,7 +16,7 @@
### Generated for rule "android_webview_native_webview_native_gyp_android_webview_native_jni_target_generate_jni_headers":
-# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/android_webview/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../java/src/org/chromium/android_webview/AndroidProtocolHandler.java', '../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java', '../java/src/org/chromium/android_webview/AwContents.java', '../java/src/org/chromium/android_webview/AwContentsClientBridge.java', '../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java', '../java/src/org/chromium/android_webview/AwCookieManager.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', '../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java', '../java/src/org/chromium/android_webview/AwResource.java', '../java/src/org/chromium/android_webview/AwSettings.java', '../java/src/org/chromium/android_webview/AwWebContentsDelegate.java', '../java/src/org/chromium/android_webview/InterceptedRequestData.java', '../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/android_webview/jni', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/android_webview/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../java/src/org/chromium/android_webview/AndroidProtocolHandler.java', '../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java', '../java/src/org/chromium/android_webview/AwContents.java', '../java/src/org/chromium/android_webview/AwContentsClientBridge.java', '../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java', '../java/src/org/chromium/android_webview/AwCookieManager.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', '../java/src/org/chromium/android_webview/AwPicture.java', '../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java', '../java/src/org/chromium/android_webview/AwResource.java', '../java/src/org/chromium/android_webview/AwSettings.java', '../java/src/org/chromium/android_webview/AwWebContentsDelegate.java', '../java/src/org/chromium/android_webview/InterceptedRequestData.java', '../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/android_webview/jni', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_local_path := $(LOCAL_PATH)
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
@@ -97,6 +97,16 @@
.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwPicture.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+ mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwPicture.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h
+
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
@@ -168,6 +178,7 @@
$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+ $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
@@ -187,6 +198,7 @@
$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+ $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
diff --git a/android_webview/native/android_webview_native_jni.target.linux-x86.mk b/android_webview/native/android_webview_native_jni.target.linux-x86.mk
index 4ae68f7..d9893f7 100644
--- a/android_webview/native/android_webview_native_jni.target.linux-x86.mk
+++ b/android_webview/native/android_webview_native_jni.target.linux-x86.mk
@@ -16,7 +16,7 @@
### Generated for rule "android_webview_native_webview_native_gyp_android_webview_native_jni_target_generate_jni_headers":
-# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/android_webview/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../java/src/org/chromium/android_webview/AndroidProtocolHandler.java', '../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java', '../java/src/org/chromium/android_webview/AwContents.java', '../java/src/org/chromium/android_webview/AwContentsClientBridge.java', '../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java', '../java/src/org/chromium/android_webview/AwCookieManager.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', '../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java', '../java/src/org/chromium/android_webview/AwResource.java', '../java/src/org/chromium/android_webview/AwSettings.java', '../java/src/org/chromium/android_webview/AwWebContentsDelegate.java', '../java/src/org/chromium/android_webview/InterceptedRequestData.java', '../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/android_webview/jni', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/android_webview/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../java/src/org/chromium/android_webview/AndroidProtocolHandler.java', '../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java', '../java/src/org/chromium/android_webview/AwContents.java', '../java/src/org/chromium/android_webview/AwContentsClientBridge.java', '../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java', '../java/src/org/chromium/android_webview/AwCookieManager.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', '../java/src/org/chromium/android_webview/AwPicture.java', '../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java', '../java/src/org/chromium/android_webview/AwResource.java', '../java/src/org/chromium/android_webview/AwSettings.java', '../java/src/org/chromium/android_webview/AwWebContentsDelegate.java', '../java/src/org/chromium/android_webview/InterceptedRequestData.java', '../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/android_webview/jni', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_local_path := $(LOCAL_PATH)
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
@@ -97,6 +97,16 @@
.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwPicture.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+ mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwPicture.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h
+
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
@@ -168,6 +178,7 @@
$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+ $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
@@ -187,6 +198,7 @@
$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+ $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc
index 4ef093e..4cabfe4 100644
--- a/android_webview/native/aw_contents.cc
+++ b/android_webview/native/aw_contents.cc
@@ -15,6 +15,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_picture.h"
#include "android_webview/native/aw_web_contents_delegate.h"
#include "android_webview/native/java_browser_view_renderer_helper.h"
#include "android_webview/native/state_serializer.h"
@@ -45,6 +46,7 @@
#include "content/public/common/ssl_status.h"
#include "jni/AwContents_jni.h"
#include "net/cert/x509_certificate.h"
+#include "third_party/skia/include/core/SkPicture.h"
#include "ui/base/l10n/l10n_util_android.h"
#include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/image/image.h"
@@ -84,9 +86,7 @@
namespace {
JavaBrowserViewRendererHelper* java_renderer_helper() {
- static JavaBrowserViewRendererHelper* g_instance
- = new JavaBrowserViewRendererHelper;
- return g_instance;
+ return JavaBrowserViewRendererHelper::GetInstance();
}
const void* kAwContentsUserDataKey = &kAwContentsUserDataKey;
@@ -758,11 +758,12 @@
page_scale_factor);
}
-ScopedJavaLocalRef<jobject> AwContents::CapturePicture(JNIEnv* env,
- jobject obj,
- int width,
- int height) {
- return browser_view_renderer_->CapturePicture(width, height);
+jint AwContents::CapturePicture(JNIEnv* env,
+ jobject obj,
+ int width,
+ int height) {
+ return reinterpret_cast<jint>(new AwPicture(
+ browser_view_renderer_->CapturePicture(width, height)));
}
void AwContents::EnableOnNewPicture(JNIEnv* env,
diff --git a/android_webview/native/aw_contents.h b/android_webview/native/aw_contents.h
index 270201a..38b433d 100644
--- a/android_webview/native/aw_contents.h
+++ b/android_webview/native/aw_contents.h
@@ -117,10 +117,7 @@
jint visible_right,
jint visible_bottom);
jint GetAwDrawGLViewContext(JNIEnv* env, jobject obj);
- base::android::ScopedJavaLocalRef<jobject> CapturePicture(JNIEnv* env,
- jobject obj,
- int width,
- int height);
+ jint CapturePicture(JNIEnv* env, jobject obj, int width, int height);
void EnableOnNewPicture(JNIEnv* env, jobject obj, jboolean enabled);
// Geolocation API support
diff --git a/android_webview/native/aw_picture.cc b/android_webview/native/aw_picture.cc
new file mode 100644
index 0000000..bc02b5b
--- /dev/null
+++ b/android_webview/native/aw_picture.cc
@@ -0,0 +1,56 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "android_webview/native/aw_picture.h"
+
+#include "android_webview/browser/in_process_view_renderer.h"
+#include "android_webview/native/java_browser_view_renderer_helper.h"
+#include "jni/AwPicture_jni.h"
+#include "third_party/skia/include/core/SkPicture.h"
+
+namespace android_webview {
+
+AwPicture::AwPicture(skia::RefPtr<SkPicture> picture)
+ : picture_(picture) {
+ DCHECK(picture_);
+}
+
+AwPicture::~AwPicture() {}
+
+void AwPicture::Destroy(JNIEnv* env, jobject obj) {
+ delete this;
+}
+
+jint AwPicture::GetWidth(JNIEnv* env, jobject obj) {
+ return picture_->width();
+}
+
+jint AwPicture::GetHeight(JNIEnv* env, jobject obj) {
+ return picture_->height();
+}
+
+namespace {
+bool RenderPictureToCanvas(SkPicture* picture, SkCanvas* canvas) {
+ picture->draw(canvas);
+ return true;
+}
+}
+
+void AwPicture::Draw(JNIEnv* env, jobject obj, jobject canvas,
+ jint left, jint top, jint right, jint bottom) {
+ bool ok = InProcessViewRenderer::RenderViaAuxilaryBitmapIfNeeded(
+ canvas,
+ JavaBrowserViewRendererHelper::GetInstance(),
+ gfx::Vector2d(),
+ gfx::Rect(left, top, right - left, bottom - top),
+ base::Bind(&RenderPictureToCanvas, base::Unretained(picture_.get())),
+ this);
+ LOG_IF(ERROR, !ok) << "Couldn't draw picture";
+}
+
+bool RegisterAwPicture(JNIEnv* env) {
+ return RegisterNativesImpl(env) >= 0;
+}
+
+} // namespace android_webview
diff --git a/android_webview/native/aw_picture.h b/android_webview/native/aw_picture.h
new file mode 100644
index 0000000..2cbb5b7
--- /dev/null
+++ b/android_webview/native/aw_picture.h
@@ -0,0 +1,42 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_NATIVE_AW_PICTURE_H_
+#define ANDROID_WEBVIEW_NATIVE_AW_PICTURE_H_
+
+#include <jni.h>
+
+#include "base/android/jni_helper.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "skia/ext/refptr.h"
+
+class SkPicture;
+
+namespace android_webview {
+
+class AwPicture {
+ public:
+ AwPicture(skia::RefPtr<SkPicture> picture);
+ ~AwPicture();
+
+ // Methods called from Java.
+ void Destroy(JNIEnv* env, jobject obj);
+ jint GetWidth(JNIEnv* env, jobject obj);
+ jint GetHeight(JNIEnv* env, jobject obj);
+ void Draw(JNIEnv* env, jobject obj, jobject canvas,
+ jint left, jint top, jint right, jint bottom);
+
+ private:
+ skia::RefPtr<SkPicture> picture_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(AwPicture);
+};
+
+bool RegisterAwPicture(JNIEnv* env);
+
+} // android_webview
+
+#endif // ANDROID_WEBVIEW_NATIVE_AW_PICTURE_
diff --git a/android_webview/native/aw_web_contents_delegate.cc b/android_webview/native/aw_web_contents_delegate.cc
index 91454ae..ddd623d 100644
--- a/android_webview/native/aw_web_contents_delegate.cc
+++ b/android_webview/native/aw_web_contents_delegate.cc
@@ -7,20 +7,38 @@
#include "android_webview/browser/aw_javascript_dialog_manager.h"
#include "android_webview/browser/find_helper.h"
#include "android_webview/native/aw_contents.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
+#include "base/strings/string_util.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/file_chooser_params.h"
#include "jni/AwWebContentsDelegate_jni.h"
+#include "ui/shell_dialogs/selected_file_info.h"
using base::android::AttachCurrentThread;
+using base::android::ConvertUTF16ToJavaString;
+using base::android::ConvertUTF8ToJavaString;
using base::android::ScopedJavaLocalRef;
+using content::FileChooserParams;
using content::WebContents;
namespace android_webview {
-static base::LazyInstance<AwJavaScriptDialogManager>::Leaky
+namespace {
+
+// WARNING: these constants are exposed in the public interface Java side, so
+// must remain in sync with what clients are expecting.
+const int kFileChooserModeOpenMultiple = 1 << 0;
+const int kFileChooserModeOpenFolder = 1 << 1;
+
+base::LazyInstance<AwJavaScriptDialogManager>::Leaky
g_javascript_dialog_manager = LAZY_INSTANCE_INITIALIZER;
+}
AwWebContentsDelegate::AwWebContentsDelegate(
JNIEnv* env,
@@ -63,8 +81,44 @@
callback.Run(false);
}
-void AwWebContentsDelegate::AddNewContents(content::WebContents* source,
- content::WebContents* new_contents,
+void AwWebContentsDelegate::RunFileChooser(WebContents* web_contents,
+ const FileChooserParams& params) {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> java_delegate = GetJavaDelegate(env);
+ if (!java_delegate.obj())
+ return;
+
+ int mode_flags = 0;
+ if (params.mode == FileChooserParams::OpenMultiple) {
+ mode_flags |= kFileChooserModeOpenMultiple;
+ } else if (params.mode == FileChooserParams::UploadFolder) {
+ // Folder implies multiple in Chrome.
+ mode_flags |= kFileChooserModeOpenMultiple | kFileChooserModeOpenFolder;
+ } else if (params.mode == FileChooserParams::Save) {
+ // Save not supported, so cancel it.
+ web_contents->GetRenderViewHost()->FilesSelectedInChooser(
+ std::vector<ui::SelectedFileInfo>(),
+ params.mode);
+ return;
+ } else {
+ DCHECK_EQ(FileChooserParams::Open, params.mode);
+ }
+ Java_AwWebContentsDelegate_runFileChooser(env,
+ java_delegate.obj(),
+ web_contents->GetRenderProcessHost()->GetID(),
+ web_contents->GetRenderViewHost()->GetRoutingID(),
+ mode_flags,
+ ConvertUTF16ToJavaString(env,
+ JoinString(params.accept_types, ',')).obj(),
+ params.title.empty() ? NULL :
+ ConvertUTF16ToJavaString(env, params.title).obj(),
+ params.default_file_name.empty() ? NULL :
+ ConvertUTF8ToJavaString(env, params.default_file_name.value()).obj(),
+ params.capture);
+}
+
+void AwWebContentsDelegate::AddNewContents(WebContents* source,
+ WebContents* new_contents,
WindowOpenDisposition disposition,
const gfx::Rect& initial_pos,
bool user_gesture,
@@ -104,7 +158,7 @@
}
}
-void AwWebContentsDelegate::CloseContents(content::WebContents* source) {
+void AwWebContentsDelegate::CloseContents(WebContents* source) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> java_delegate = GetJavaDelegate(env);
@@ -113,7 +167,7 @@
}
}
-void AwWebContentsDelegate::ActivateContents(content::WebContents* contents) {
+void AwWebContentsDelegate::ActivateContents(WebContents* contents) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> java_delegate = GetJavaDelegate(env);
@@ -133,6 +187,38 @@
env, obj.obj(), pref_size.width(), pref_size.height());
}
+static void FilesSelectedInChooser(
+ JNIEnv* env, jclass clazz,
+ jint process_id, jint render_id, jint mode_flags,
+ jobjectArray file_paths) {
+ content::RenderViewHost* rvh = content::RenderViewHost::FromID(process_id,
+ render_id);
+ if (!rvh)
+ return;
+
+ std::vector<std::string> file_path_str;
+ // Note file_paths maybe NULL, but this will just yield a zero-length vector.
+ base::android::AppendJavaStringArrayToStringVector(env, file_paths,
+ &file_path_str);
+ std::vector<ui::SelectedFileInfo> files;
+ files.reserve(file_path_str.size());
+ for (size_t i = 0; i < file_path_str.size(); ++i) {
+ files.push_back(ui::SelectedFileInfo(base::FilePath(file_path_str[i]),
+ base::FilePath()));
+ }
+ FileChooserParams::Mode mode;
+ if (mode_flags & kFileChooserModeOpenFolder) {
+ mode = FileChooserParams::UploadFolder;
+ } else if (mode_flags & kFileChooserModeOpenMultiple) {
+ mode = FileChooserParams::OpenMultiple;
+ } else {
+ mode = FileChooserParams::Open;
+ }
+ LOG(INFO) << "File Chooser result: mode = " << mode
+ << ", file paths = " << JoinString(file_path_str, ":");
+ rvh->FilesSelectedInChooser(files, mode);
+}
+
bool RegisterAwWebContentsDelegate(JNIEnv* env) {
return RegisterNativesImpl(env);
}
diff --git a/android_webview/native/aw_web_contents_delegate.h b/android_webview/native/aw_web_contents_delegate.h
index 3d84fbe..d84ca6c 100644
--- a/android_webview/native/aw_web_contents_delegate.h
+++ b/android_webview/native/aw_web_contents_delegate.h
@@ -31,7 +31,9 @@
int request_id,
const std::string& request_method,
const base::Callback<void(bool)>& callback) OVERRIDE;
-
+ virtual void RunFileChooser(
+ content::WebContents* web_contents,
+ const content::FileChooserParams& params) OVERRIDE;
virtual void AddNewContents(content::WebContents* source,
content::WebContents* new_contents,
WindowOpenDisposition disposition,
diff --git a/android_webview/native/java_browser_view_renderer_helper.cc b/android_webview/native/java_browser_view_renderer_helper.cc
index 0426bd1..b72e037 100644
--- a/android_webview/native/java_browser_view_renderer_helper.cc
+++ b/android_webview/native/java_browser_view_renderer_helper.cc
@@ -18,6 +18,13 @@
JavaBrowserViewRendererHelper::~JavaBrowserViewRendererHelper() {
}
+// static
+JavaBrowserViewRendererHelper* JavaBrowserViewRendererHelper::GetInstance() {
+ static JavaBrowserViewRendererHelper* g_instance =
+ new JavaBrowserViewRendererHelper;
+ return g_instance;
+}
+
ScopedJavaLocalRef<jobject> JavaBrowserViewRendererHelper::CreateBitmap(
JNIEnv* env,
int width,
diff --git a/android_webview/native/java_browser_view_renderer_helper.h b/android_webview/native/java_browser_view_renderer_helper.h
index 2d1aadc..986d737 100644
--- a/android_webview/native/java_browser_view_renderer_helper.h
+++ b/android_webview/native/java_browser_view_renderer_helper.h
@@ -18,6 +18,8 @@
JavaBrowserViewRendererHelper();
virtual ~JavaBrowserViewRendererHelper();
+ static JavaBrowserViewRendererHelper* GetInstance();
+
// BrowserViewRenderer::JavaHelper implementation.
virtual base::android::ScopedJavaLocalRef<jobject> CreateBitmap(
JNIEnv* env,
diff --git a/android_webview/native/webview_native.gyp b/android_webview/native/webview_native.gyp
index bc6d0e5..b1d7082 100644
--- a/android_webview/native/webview_native.gyp
+++ b/android_webview/native/webview_native.gyp
@@ -50,6 +50,8 @@
'aw_geolocation_permission_context.h',
'aw_http_auth_handler.cc',
'aw_http_auth_handler.h',
+ 'aw_picture.cc',
+ 'aw_picture.h',
'aw_quota_manager_bridge_impl.cc',
'aw_quota_manager_bridge_impl.h',
'aw_resource.cc',
@@ -94,6 +96,7 @@
'../java/src/org/chromium/android_webview/AwCookieManager.java',
'../java/src/org/chromium/android_webview/AwFormDatabase.java',
'../java/src/org/chromium/android_webview/AwHttpAuthHandler.java',
+ '../java/src/org/chromium/android_webview/AwPicture.java',
'../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java',
'../java/src/org/chromium/android_webview/AwResource.java',
'../java/src/org/chromium/android_webview/AwSettings.java',
diff --git a/android_webview/native/webview_native.target.darwin-arm.mk b/android_webview/native/webview_native.target.darwin-arm.mk
index 933ba49..4c5296c 100644
--- a/android_webview/native/webview_native.target.darwin-arm.mk
+++ b/android_webview/native/webview_native.target.darwin-arm.mk
@@ -37,6 +37,7 @@
android_webview/native/aw_form_database.cc \
android_webview/native/aw_geolocation_permission_context.cc \
android_webview/native/aw_http_auth_handler.cc \
+ android_webview/native/aw_picture.cc \
android_webview/native/aw_quota_manager_bridge_impl.cc \
android_webview/native/aw_resource.cc \
android_webview/native/aw_settings.cc \
@@ -104,6 +105,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -213,6 +215,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/native/webview_native.target.darwin-mips.mk b/android_webview/native/webview_native.target.darwin-mips.mk
index 2f11f10..f639290 100644
--- a/android_webview/native/webview_native.target.darwin-mips.mk
+++ b/android_webview/native/webview_native.target.darwin-mips.mk
@@ -37,6 +37,7 @@
android_webview/native/aw_form_database.cc \
android_webview/native/aw_geolocation_permission_context.cc \
android_webview/native/aw_http_auth_handler.cc \
+ android_webview/native/aw_picture.cc \
android_webview/native/aw_quota_manager_bridge_impl.cc \
android_webview/native/aw_resource.cc \
android_webview/native/aw_settings.cc \
@@ -103,6 +104,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -211,6 +213,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/native/webview_native.target.darwin-x86.mk b/android_webview/native/webview_native.target.darwin-x86.mk
index fd9bd3b..458710f 100644
--- a/android_webview/native/webview_native.target.darwin-x86.mk
+++ b/android_webview/native/webview_native.target.darwin-x86.mk
@@ -37,6 +37,7 @@
android_webview/native/aw_form_database.cc \
android_webview/native/aw_geolocation_permission_context.cc \
android_webview/native/aw_http_auth_handler.cc \
+ android_webview/native/aw_picture.cc \
android_webview/native/aw_quota_manager_bridge_impl.cc \
android_webview/native/aw_resource.cc \
android_webview/native/aw_settings.cc \
@@ -105,6 +106,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -216,6 +218,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/native/webview_native.target.linux-arm.mk b/android_webview/native/webview_native.target.linux-arm.mk
index 933ba49..4c5296c 100644
--- a/android_webview/native/webview_native.target.linux-arm.mk
+++ b/android_webview/native/webview_native.target.linux-arm.mk
@@ -37,6 +37,7 @@
android_webview/native/aw_form_database.cc \
android_webview/native/aw_geolocation_permission_context.cc \
android_webview/native/aw_http_auth_handler.cc \
+ android_webview/native/aw_picture.cc \
android_webview/native/aw_quota_manager_bridge_impl.cc \
android_webview/native/aw_resource.cc \
android_webview/native/aw_settings.cc \
@@ -104,6 +105,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -213,6 +215,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/native/webview_native.target.linux-mips.mk b/android_webview/native/webview_native.target.linux-mips.mk
index 2f11f10..f639290 100644
--- a/android_webview/native/webview_native.target.linux-mips.mk
+++ b/android_webview/native/webview_native.target.linux-mips.mk
@@ -37,6 +37,7 @@
android_webview/native/aw_form_database.cc \
android_webview/native/aw_geolocation_permission_context.cc \
android_webview/native/aw_http_auth_handler.cc \
+ android_webview/native/aw_picture.cc \
android_webview/native/aw_quota_manager_bridge_impl.cc \
android_webview/native/aw_resource.cc \
android_webview/native/aw_settings.cc \
@@ -103,6 +104,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -211,6 +213,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/native/webview_native.target.linux-x86.mk b/android_webview/native/webview_native.target.linux-x86.mk
index fd9bd3b..458710f 100644
--- a/android_webview/native/webview_native.target.linux-x86.mk
+++ b/android_webview/native/webview_native.target.linux-x86.mk
@@ -37,6 +37,7 @@
android_webview/native/aw_form_database.cc \
android_webview/native/aw_geolocation_permission_context.cc \
android_webview/native/aw_http_auth_handler.cc \
+ android_webview/native/aw_picture.cc \
android_webview/native/aw_quota_manager_bridge_impl.cc \
android_webview/native/aw_resource.cc \
android_webview/native/aw_settings.cc \
@@ -105,6 +106,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -216,6 +218,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/android_webview/public/browser/draw_sw.h b/android_webview/public/browser/draw_sw.h
index 2cdb45b..463f59c 100644
--- a/android_webview/public/browser/draw_sw.h
+++ b/android_webview/public/browser/draw_sw.h
@@ -14,16 +14,28 @@
class SkPicture;
+static const int kAwPixelInfoVersion = 2;
+
+// Values of the AwPixelInfo::config field.
+enum AwPixelConfig {
+ AwConfig_RGB_565 = 4,
+ AwConfig_ARGB_4444 = 5,
+ AwConfig_ARGB_8888 = 6,
+};
+
// Holds the information required to implement the SW draw to system canvas.
struct AwPixelInfo {
- int config; // In SkBitmap::Config format.
- int width; // In pixels.
- int height; // In pixels.
- int row_bytes; // Number of bytes from start of one line to next.
- void* pixels; // The pixels, all (height * row_bytes) of them.
- float matrix[9]; // The matrix currently in effect on the canvas.
- void* clip_region; // Flattened clip region.
- size_t clip_region_size; // Number of bytes in |clip_region|.
+ int version; // The kAwPixelInfoVersion this struct was built with.
+ int config; // |pixel| format: a value from AwPixelConfig.
+ int width; // In pixels.
+ int height; // In pixels.
+ int row_bytes; // Number of bytes from start of one line to next.
+ void* pixels; // The pixels, all (height * row_bytes) of them.
+ // The Matrix and Clip are relative to |pixels|, not the source canvas.
+ float matrix[9]; // The matrix currently in effect on the canvas.
+ int clip_rect_count; // Number of rects in |clip_rects|.
+ int* clip_rects; // Clip area: 4 ints per rect in {x,y,w,h} format.
+ // NOTE: If you add more members, bump kAwPixelInfoVersion.
};
// Function that can be called to fish out the underlying native pixel data
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java b/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java
index b83690e..e3c5077 100644
--- a/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java
+++ b/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java
@@ -219,6 +219,11 @@
}
@Override
+ public int super_getScrollBarStyle() {
+ return AwTestContainerView.super.getScrollBarStyle();
+ }
+
+ @Override
public boolean requestDrawGL(Canvas canvas) {
return false;
}
diff --git a/apps/DEPS b/apps/DEPS
index 0100480..7920f1a 100644
--- a/apps/DEPS
+++ b/apps/DEPS
@@ -20,6 +20,7 @@
"+chrome/browser/lifetime/application_lifetime.h",
"+chrome/browser/profiles",
"+chrome/browser/sessions/session_id.h",
+ "+chrome/browser/ui/extensions/app_metro_infobar_delegate_win.h",
"+chrome/browser/ui/host_desktop.h",
"+chrome/common/chrome_switches.h",
"+chrome/common/extensions",
diff --git a/apps/OWNERS b/apps/OWNERS
index ba62226..22c418a 100644
--- a/apps/OWNERS
+++ b/apps/OWNERS
@@ -4,4 +4,5 @@
koz@chromium.org
mek@chromium.org
miket@chromium.org
+scheib@chromium.org
tapted@chromium.org
diff --git a/apps/app_lifetime_monitor.cc b/apps/app_lifetime_monitor.cc
index 8e4819a..8547be9 100644
--- a/apps/app_lifetime_monitor.cc
+++ b/apps/app_lifetime_monitor.cc
@@ -15,7 +15,6 @@
using extensions::Extension;
using extensions::ExtensionHost;
-using extensions::ShellWindowRegistry;
AppLifetimeMonitor::AppLifetimeMonitor(Profile* profile)
: profile_(profile) {
diff --git a/apps/app_lifetime_monitor.h b/apps/app_lifetime_monitor.h
index f18a97d..2da6550 100644
--- a/apps/app_lifetime_monitor.h
+++ b/apps/app_lifetime_monitor.h
@@ -8,8 +8,8 @@
#include <string>
#include <vector>
+#include "apps/shell_window_registry.h"
#include "base/observer_list.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
@@ -26,7 +26,7 @@
// events.
class AppLifetimeMonitor : public BrowserContextKeyedService,
public content::NotificationObserver,
- public extensions::ShellWindowRegistry::Observer {
+ public ShellWindowRegistry::Observer {
public:
class Observer {
public:
@@ -61,7 +61,7 @@
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
- // extensions::ShellWindowRegistry::Observer overrides:
+ // ShellWindowRegistry::Observer overrides:
virtual void OnShellWindowAdded(ShellWindow* shell_window) OVERRIDE;
virtual void OnShellWindowIconChanged(ShellWindow* shell_window) OVERRIDE;
virtual void OnShellWindowRemoved(ShellWindow* shell_window) OVERRIDE;
diff --git a/apps/app_lifetime_monitor_factory.cc b/apps/app_lifetime_monitor_factory.cc
index 4d828b0..1fb7994 100644
--- a/apps/app_lifetime_monitor_factory.cc
+++ b/apps/app_lifetime_monitor_factory.cc
@@ -5,7 +5,7 @@
#include "apps/app_lifetime_monitor_factory.h"
#include "apps/app_lifetime_monitor.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
+#include "apps/shell_window_registry.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/profiles/profile.h"
#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
@@ -26,7 +26,7 @@
: BrowserContextKeyedServiceFactory(
"AppLifetimeMonitor",
BrowserContextDependencyManager::GetInstance()) {
- DependsOn(extensions::ShellWindowRegistry::Factory::GetInstance());
+ DependsOn(ShellWindowRegistry::Factory::GetInstance());
}
AppLifetimeMonitorFactory::~AppLifetimeMonitorFactory() {}
diff --git a/apps/app_load_service.cc b/apps/app_load_service.cc
index d2423c0..a0a6a66 100644
--- a/apps/app_load_service.cc
+++ b/apps/app_load_service.cc
@@ -6,12 +6,12 @@
#include "apps/app_load_service_factory.h"
#include "apps/launcher.h"
+#include "apps/shell_window_registry.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/extensions/unpacked_installer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/extension.h"
@@ -125,7 +125,7 @@
}
bool AppLoadService::HasShellWindows(const std::string& extension_id) {
- return !extensions::ShellWindowRegistry::Get(profile_)->
+ return !ShellWindowRegistry::Get(profile_)->
GetShellWindowsForApp(extension_id).empty();
}
diff --git a/apps/app_load_service_factory.cc b/apps/app_load_service_factory.cc
index 37c2d45..a68cf94 100644
--- a/apps/app_load_service_factory.cc
+++ b/apps/app_load_service_factory.cc
@@ -5,9 +5,9 @@
#include "apps/app_load_service_factory.h"
#include "apps/app_load_service.h"
+#include "apps/shell_window_registry.h"
#include "chrome/browser/extensions/extension_prefs_factory.h"
#include "chrome/browser/extensions/extension_system_factory.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/profiles/profile.h"
#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
@@ -30,7 +30,7 @@
BrowserContextDependencyManager::GetInstance()) {
DependsOn(extensions::ExtensionPrefsFactory::GetInstance());
DependsOn(extensions::ExtensionSystemFactory::GetInstance());
- DependsOn(extensions::ShellWindowRegistry::Factory::GetInstance());
+ DependsOn(ShellWindowRegistry::Factory::GetInstance());
}
AppLoadServiceFactory::~AppLoadServiceFactory() {
diff --git a/apps/app_restore_service.h b/apps/app_restore_service.h
index 5a66005..425364e 100644
--- a/apps/app_restore_service.h
+++ b/apps/app_restore_service.h
@@ -9,7 +9,7 @@
#include <vector>
#include "apps/app_lifetime_monitor.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
+#include "apps/shell_window_registry.h"
#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
namespace extensions {
diff --git a/apps/app_shim/extension_app_shim_handler_mac.cc b/apps/app_shim/extension_app_shim_handler_mac.cc
index 9173767..130c7f1 100644
--- a/apps/app_shim/extension_app_shim_handler_mac.cc
+++ b/apps/app_shim/extension_app_shim_handler_mac.cc
@@ -9,6 +9,7 @@
#include "apps/app_shim/app_shim_messages.h"
#include "apps/native_app_window.h"
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "chrome/browser/browser_process.h"
@@ -16,7 +17,6 @@
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
@@ -44,7 +44,7 @@
void TerminateIfNoShellWindows() {
bool shell_windows_left =
- extensions::ShellWindowRegistry::IsShellWindowRegisteredInAnyProfile(0);
+ apps::ShellWindowRegistry::IsShellWindowRegisteredInAnyProfile(0);
if (!shell_windows_left)
chrome::AttemptExit();
}
@@ -53,7 +53,7 @@
namespace apps {
-typedef extensions::ShellWindowRegistry::ShellWindowList ShellWindowList;
+typedef ShellWindowRegistry::ShellWindowList ShellWindowList;
bool ExtensionAppShimHandler::Delegate::ProfileExistsForPath(
const base::FilePath& path) {
@@ -89,8 +89,7 @@
ShellWindowList ExtensionAppShimHandler::Delegate::GetWindows(
Profile* profile,
const std::string& extension_id) {
- return extensions::ShellWindowRegistry::Get(profile)->
- GetShellWindowsForApp(extension_id);
+ return ShellWindowRegistry::Get(profile)->GetShellWindowsForApp(extension_id);
}
const extensions::Extension*
@@ -167,7 +166,7 @@
handler->OnShimQuit(host);
} else {
// App shims might be disabled or the shim is still starting up.
- extensions::ShellWindowRegistry::Get(shell_window->profile())->
+ ShellWindowRegistry::Get(shell_window->profile())->
CloseAllShellWindowsForApp(shell_window->extension_id());
}
}
@@ -305,7 +304,7 @@
const std::string& app_id = host->GetAppId();
const ShellWindowList windows =
delegate_->GetWindows(profile, app_id);
- for (extensions::ShellWindowRegistry::const_iterator it = windows.begin();
+ for (ShellWindowRegistry::const_iterator it = windows.begin();
it != windows.end(); ++it) {
(*it)->GetBaseWindow()->Close();
}
diff --git a/apps/app_shim/extension_app_shim_handler_mac.h b/apps/app_shim/extension_app_shim_handler_mac.h
index 616fd78..8a9f64e 100644
--- a/apps/app_shim/extension_app_shim_handler_mac.h
+++ b/apps/app_shim/extension_app_shim_handler_mac.h
@@ -10,9 +10,9 @@
#include "apps/app_lifetime_monitor.h"
#include "apps/app_shim/app_shim_handler_mac.h"
+#include "apps/shell_window_registry.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
@@ -47,7 +47,7 @@
virtual void LoadProfileAsync(const base::FilePath& path,
base::Callback<void(Profile*)> callback);
- virtual extensions::ShellWindowRegistry::ShellWindowList GetWindows(
+ virtual ShellWindowRegistry::ShellWindowList GetWindows(
Profile* profile, const std::string& extension_id);
virtual const extensions::Extension* GetAppExtension(
diff --git a/apps/app_shim/extension_app_shim_handler_mac_unittest.cc b/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
index 33941de..636ba1b 100644
--- a/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
+++ b/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
@@ -16,7 +16,7 @@
namespace apps {
using extensions::Extension;
-typedef extensions::ShellWindowRegistry::ShellWindowList ShellWindowList;
+typedef ShellWindowRegistry::ShellWindowList ShellWindowList;
using ::testing::_;
using ::testing::Invoke;
diff --git a/apps/apps.gypi b/apps/apps.gypi
index 59f4c75..7e2c179 100644
--- a/apps/apps.gypi
+++ b/apps/apps.gypi
@@ -70,6 +70,8 @@
'shell_window.h',
'shell_window_geometry_cache.cc',
'shell_window_geometry_cache.h',
+ 'shell_window_registry.cc',
+ 'shell_window_registry.h',
'switches.cc',
'switches.h',
],
diff --git a/apps/launcher.cc b/apps/launcher.cc
index d892da6..9ebb46e 100644
--- a/apps/launcher.cc
+++ b/apps/launcher.cc
@@ -23,6 +23,7 @@
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/lazy_background_task_queue.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/extensions/app_metro_infobar_delegate_win.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_messages.h"
#include "content/public/browser/browser_thread.h"
@@ -285,6 +286,17 @@
const Extension* extension,
const CommandLine* command_line,
const base::FilePath& current_directory) {
+#if defined(OS_WIN)
+ // On Windows 8's single window Metro mode we can not launch platform apps.
+ // Offer to switch Chrome to desktop mode.
+ if (win8::IsSingleWindowMetroMode()) {
+ AppMetroInfoBarDelegateWin::Create(
+ profile, AppMetroInfoBarDelegateWin::LAUNCH_PACKAGED_APP,
+ extension->id());
+ return;
+ }
+#endif
+
base::FilePath path;
if (!GetAbsolutePathFromCommandLine(command_line, current_directory, &path)) {
LaunchPlatformAppWithNoData(profile, extension);
diff --git a/apps/shell_window.cc b/apps/shell_window.cc
index 12585aa..10ab851 100644
--- a/apps/shell_window.cc
+++ b/apps/shell_window.cc
@@ -6,13 +6,13 @@
#include "apps/native_app_window.h"
#include "apps/shell_window_geometry_cache.h"
+#include "apps/shell_window_registry.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/extensions/suggest_permission_util.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/profiles/profile.h"
@@ -194,7 +194,7 @@
UpdateExtensionAppIcon();
- extensions::ShellWindowRegistry::Get(profile_)->AddShellWindow(this);
+ ShellWindowRegistry::Get(profile_)->AddShellWindow(this);
}
ShellWindow::~ShellWindow() {
@@ -280,7 +280,7 @@
}
void ShellWindow::OnNativeClose() {
- extensions::ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this);
+ ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this);
if (shell_window_contents_)
shell_window_contents_->NativeWindowClosed();
delete this;
@@ -293,7 +293,7 @@
}
void ShellWindow::OnNativeWindowActivated() {
- extensions::ShellWindowRegistry::Get(profile_)->ShellWindowActivated(this);
+ ShellWindowRegistry::Get(profile_)->ShellWindowActivated(this);
}
scoped_ptr<gfx::Image> ShellWindow::GetAppListIcon() {
@@ -374,7 +374,7 @@
return;
app_icon_ = image;
native_app_window_->UpdateWindowIcon();
- extensions::ShellWindowRegistry::Get(profile_)->ShellWindowIconChanged(this);
+ ShellWindowRegistry::Get(profile_)->ShellWindowIconChanged(this);
}
void ShellWindow::Fullscreen() {
diff --git a/chrome/browser/extensions/shell_window_registry.cc b/apps/shell_window_registry.cc
similarity index 96%
rename from chrome/browser/extensions/shell_window_registry.cc
rename to apps/shell_window_registry.cc
index d4275af..301bcf1 100644
--- a/chrome/browser/extensions/shell_window_registry.cc
+++ b/apps/shell_window_registry.cc
@@ -1,11 +1,11 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "apps/native_app_window.h"
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/extensions/extension.h"
@@ -17,8 +17,6 @@
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h"
-using apps::ShellWindow;
-
namespace {
// Create a key that identifies a ShellWindow in a RenderViewHost across App
@@ -27,9 +25,9 @@
// |id|, the chrome-extension://extension-id/page.html URL will be used. If the
// RenderViewHost is not for a ShellWindow, return an empty string.
std::string GetWindowKeyForRenderViewHost(
- const extensions::ShellWindowRegistry* registry,
+ const apps::ShellWindowRegistry* registry,
content::RenderViewHost* render_view_host) {
- ShellWindow* shell_window =
+ apps::ShellWindow* shell_window =
registry->GetShellWindowForRenderViewHost(render_view_host);
if (!shell_window)
return std::string(); // Not a ShellWindow.
@@ -45,7 +43,7 @@
} // namespace
-namespace extensions {
+namespace apps {
ShellWindowRegistry::ShellWindowRegistry(Profile* profile)
: profile_(profile),
diff --git a/chrome/browser/extensions/shell_window_registry.h b/apps/shell_window_registry.h
similarity index 95%
rename from chrome/browser/extensions/shell_window_registry.h
rename to apps/shell_window_registry.h
index fb5f48e..e23c5e9 100644
--- a/chrome/browser/extensions/shell_window_registry.h
+++ b/apps/shell_window_registry.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_EXTENSIONS_SHELL_WINDOW_REGISTRY_H_
-#define CHROME_BROWSER_EXTENSIONS_SHELL_WINDOW_REGISTRY_H_
+#ifndef APPS_SHELL_WINDOW_REGISTRY_H_
+#define APPS_SHELL_WINDOW_REGISTRY_H_
#include <list>
@@ -17,16 +17,14 @@
class Profile;
-namespace apps {
-class ShellWindow;
-}
-
namespace content {
class DevToolsAgentHost;
class RenderViewHost;
}
-namespace extensions {
+namespace apps {
+
+class ShellWindow;
// The ShellWindowRegistry tracks the ShellWindows for all platform apps for a
// particular profile.
@@ -150,4 +148,4 @@
} // namespace extensions
-#endif // CHROME_BROWSER_EXTENSIONS_SHELL_WINDOW_REGISTRY_H_
+#endif // APPS_SHELL_WINDOW_REGISTRY_H_
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc
index 2a75415..3d669bb 100644
--- a/ash/accelerators/accelerator_controller.cc
+++ b/ash/accelerators/accelerator_controller.cc
@@ -94,6 +94,12 @@
return true;
}
+bool HandleCycleWindowOverviewMRU(WindowSelector::Direction direction) {
+ Shell::GetInstance()->
+ window_selector_controller()->HandleCycleWindow(direction);
+ return true;
+}
+
void HandleCycleWindowLinear(CycleDirection direction) {
Shell::GetInstance()->
window_cycle_controller()->HandleLinearCycleWindow();
@@ -518,11 +524,19 @@
case CYCLE_BACKWARD_MRU:
if (key_code == ui::VKEY_TAB)
shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_PREVWINDOW_TAB);
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kAshEnableOverviewMode)) {
+ return HandleCycleWindowOverviewMRU(WindowSelector::BACKWARD);
+ }
return HandleCycleWindowMRU(WindowCycleController::BACKWARD,
accelerator.IsAltDown());
case CYCLE_FORWARD_MRU:
if (key_code == ui::VKEY_TAB)
shell->delegate()->RecordUserMetricsAction(UMA_ACCEL_NEXTWINDOW_TAB);
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kAshEnableOverviewMode)) {
+ return HandleCycleWindowOverviewMRU(WindowSelector::FORWARD);
+ }
return HandleCycleWindowMRU(WindowCycleController::FORWARD,
accelerator.IsAltDown());
case CYCLE_BACKWARD_LINEAR:
diff --git a/ash/ash.gyp b/ash/ash.gyp
index 82fb264..7a3f1be 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -108,6 +108,8 @@
'display/mouse_cursor_event_filter.h',
'display/output_configurator_animation.cc',
'display/output_configurator_animation.h',
+ 'display/resolution_notification_controller.cc',
+ 'display/resolution_notification_controller.h',
'display/root_window_transformers.cc',
'display/root_window_transformers.h',
'display/screen_position_controller.cc',
@@ -258,6 +260,8 @@
'system/chromeos/settings/tray_settings.h',
'system/chromeos/tray_display.cc',
'system/chromeos/tray_display.h',
+ 'system/chromeos/tray_tracing.cc',
+ 'system/chromeos/tray_tracing.h',
'system/date/clock_observer.h',
'system/date/date_view.cc',
'system/date/date_view.h',
@@ -673,6 +677,7 @@
'display/display_manager_unittest.cc',
'display/mirror_window_controller_unittest.cc',
'display/mouse_cursor_event_filter_unittest.cc',
+ 'display/resolution_notification_controller_unittest.cc',
'display/root_window_transformers_unittest.cc',
'display/screen_position_controller_unittest.cc',
'drag_drop/drag_drop_controller_unittest.cc',
diff --git a/ash/ash_chromeos_strings.grdp b/ash/ash_chromeos_strings.grdp
index 76b906b..1190db9 100644
--- a/ash/ash_chromeos_strings.grdp
+++ b/ash/ash_chromeos_strings.grdp
@@ -242,7 +242,10 @@
Authentication certificate rejected remotely
</message>
<message name="IDS_CHROMEOS_NETWORK_ERROR_PPP_AUTH_FAILED" desc="Network error details in notifications: PPP_AUTH_FAILED">
- Failed to authenticate with provided username or password
+ PPP authentication failed due to an incorrect username or password
+ </message>
+ <message name="IDS_CHROMEOS_NETWORK_ERROR_CONFIGURE_FAILED" desc="Network error details in notifications: Configuration error">
+ Failed to configure network
</message>
<message name="IDS_CHROMEOS_NETWORK_ERROR_UNRECOGNIZED" desc="Network error details in notifications: Unrecognized">
Unrecognized error
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index f43ba86..2d75802 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -285,6 +285,9 @@
<message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_DISCOVERING" desc="The label used in the tray popup to show bluetooth is discovering devices.">
Scanning for devices...
</message>
+ <message name="IDS_ASH_STATUS_TRAY_TRACING" desc="The status tray item indicating that performance tracing is running.">
+ Performance tracing enabled
+ </message>
<message name="IDS_ASH_STATUS_TRAY_UPDATE" desc="The label used in the tray popup to notify that the user should restart to get system updates.">
Restart to update
@@ -325,10 +328,10 @@
Dock mode
</message>
<message name="IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED" desc="The label used in the tray to notify that the display resolution settings has changed.">
- <ph name="DISPLAY_NAME">$1</ph> has been resized to <ph name="RESOLUTION">$2</ph>
+ <ph name="DISPLAY_NAME">$1</ph> resolution was changed to <ph name="RESOLUTION">$2</ph>
</message>
<message name="IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED" desc="The label used in the tray to notify that the display rotation settings has changed.">
- <ph name="DISPLAY_NAME">$1</ph> has been rotated
+ <ph name="DISPLAY_NAME">$1</ph> was rotated to <ph name="ROTATION">$2</ph>
</message>
<message name="IDS_ASH_STATUS_TRAY_DISPLAY_SINGLE_DISPLAY" desc="The label used in the tray to show a single display's configuration">
<ph name="DISPLAY_NAME">$1</ph>: <ph name="ANNOTATION">$2</ph>
@@ -345,6 +348,18 @@
<message name="IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATION_OVERSCAN" desc="Label used to describe that the system notice that this display device may have overscan area.">
overscan
</message>
+ <message name="IDS_ASH_STATUS_TRAY_DISPLAY_STANDARD_ORIENTATION" desc="The default value of display orientation option item.">
+ 0°
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90" desc="The value of display orientation option item: 90-degree rotated">
+ 90°
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_180" desc="The value of display orientation option item: 180-degree rotated">
+ 180°
+ </message>
+ <message name="IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_270" desc="The value of display orientation option item: 270-degree rotated">
+ 270°
+ </message>
<message name="IDS_ASH_STATUS_TRAY_DRIVE_SYNCING" desc="The label in the tray to indicate onoing file sync operations.">
Syncing <ph name="count">$1<ex>3</ex></ph> file(s)
</message>
@@ -524,6 +539,15 @@
<message name="IDS_ASH_DISPLAY_FAILURE_ON_NON_MIRRORING" desc="An error message to show that the system failed to enter the extended desktop mode or unknown status. Please translate the parentized text.">
Dear Monitor, it's not working out between us. (That monitor is not supported)
</message>
+ <message name="IDS_ASH_DISPLAY_RESOLUTION_CHANGE_ACCEPT" desc="A button label shown in the notification for the resolution change to accept the change">
+ Accept
+ </message>
+ <message name="IDS_ASH_DISPLAY_RESOLUTION_CHANGE_REVERT" desc="A button label shown in the notification for the resolution change to revert the change">
+ Revert
+ </message>
+ <message name="IDS_ASH_DISPLAY_RESOLUTION_TIMEOUT" desc="A message for to notify the user about the timeout of display resolution change.">
+ Reverting to old resolution in <ph name="TIMEOUT_SECONDS">$1</ph>
+ </message>
<message name="IDS_ASH_INTERNAL_DISPLAY_NAME" desc="The name of the internal display which is shown in the display settings.">
Internal Display
</message>
diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc
index ccba3e0..fce5a82 100644
--- a/ash/display/display_controller.cc
+++ b/ash/display/display_controller.cc
@@ -404,6 +404,10 @@
PreDisplayConfigurationChange();
// TODO(oshima): Call UpdateDisplays instead.
UpdateDisplayBoundsForLayout();
+ // Primary's bounds stay the same. Just notify bounds change
+ // on the secondary.
+ Shell::GetInstance()->screen()->NotifyBoundsChanged(
+ ScreenAsh::GetSecondaryDisplay());
PostDisplayConfigurationChange();
}
}
diff --git a/ash/display/display_controller_unittest.cc b/ash/display/display_controller_unittest.cc
index e9baf90..9131468 100644
--- a/ash/display/display_controller_unittest.cc
+++ b/ash/display/display_controller_unittest.cc
@@ -33,35 +33,67 @@
const char kDesktopBackgroundView[] = "DesktopBackgroundView";
-class TestObserver : public DisplayController::Observer {
+class TestObserver : public DisplayController::Observer,
+ public gfx::DisplayObserver {
public:
- TestObserver() : changing_count_(0), changed_count_(0) {
+ TestObserver()
+ : changing_count_(0),
+ changed_count_(0),
+ bounds_changed_count_(0),
+ changed_display_id_(0) {
Shell::GetInstance()->display_controller()->AddObserver(this);
+ Shell::GetScreen()->AddObserver(this);
}
virtual ~TestObserver() {
Shell::GetInstance()->display_controller()->RemoveObserver(this);
+ Shell::GetScreen()->RemoveObserver(this);
}
+ // Overridden from DisplayController::Observer
virtual void OnDisplayConfigurationChanging() OVERRIDE {
++changing_count_;
}
-
virtual void OnDisplayConfigurationChanged() OVERRIDE {
++changed_count_;
}
+ // Overrideen from gfx::DisplayObserver
+ virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE {
+ changed_display_id_ = display.id();
+ bounds_changed_count_ ++;
+ }
+ virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE {
+ }
+ virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE {
+ }
+
int CountAndReset() {
EXPECT_EQ(changing_count_, changed_count_);
- int c = changing_count_;
+ int count = changing_count_;
changing_count_ = changed_count_ = 0;
- return c;
+ return count;
+ }
+
+ int64 GetBoundsChangedCountAndReset() {
+ int count = bounds_changed_count_;
+ bounds_changed_count_ = 0;
+ return count;
+ }
+
+ int64 GetChangedDisplayIdAndReset() {
+ int64 id = changed_display_id_;
+ changed_display_id_ = 0;
+ return id;
}
private:
int changing_count_;
int changed_count_;
+ int bounds_changed_count_;
+ int64 changed_display_id_;
+
DISALLOW_COPY_AND_ASSIGN(TestObserver);
};
@@ -227,9 +259,11 @@
TestObserver observer;
UpdateDisplay("500x500,400x400");
EXPECT_EQ(1, observer.CountAndReset()); // resize and add
+ EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
gfx::Insets insets(5, 5, 5, 5);
+ int64 secondary_display_id = ScreenAsh::GetSecondaryDisplay().id();
Shell::GetInstance()->display_manager()->UpdateWorkAreaOfDisplay(
- ScreenAsh::GetSecondaryDisplay().id(), insets);
+ secondary_display_id, insets);
// Default layout is RIGHT.
EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
@@ -239,6 +273,8 @@
// Layout the secondary display to the bottom of the primary.
SetSecondaryDisplayLayout(DisplayLayout::BOTTOM);
EXPECT_EQ(1, observer.CountAndReset());
+ EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
+ EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ("0,500 400x400", GetSecondaryDisplay().bounds().ToString());
EXPECT_EQ("5,505 390x390", GetSecondaryDisplay().work_area().ToString());
@@ -246,6 +282,8 @@
// Layout the secondary display to the left of the primary.
SetSecondaryDisplayLayout(DisplayLayout::LEFT);
EXPECT_EQ(1, observer.CountAndReset());
+ EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
+ EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ("-400,0 400x400", GetSecondaryDisplay().bounds().ToString());
EXPECT_EQ("-395,5 390x390", GetSecondaryDisplay().work_area().ToString());
@@ -253,6 +291,8 @@
// Layout the secondary display to the top of the primary.
SetSecondaryDisplayLayout(DisplayLayout::TOP);
EXPECT_EQ(1, observer.CountAndReset());
+ EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
+ EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ("0,-400 400x400", GetSecondaryDisplay().bounds().ToString());
EXPECT_EQ("5,-395 390x390", GetSecondaryDisplay().work_area().ToString());
@@ -260,36 +300,56 @@
// Layout to the right with an offset.
SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, 300);
EXPECT_EQ(1, observer.CountAndReset()); // resize and add
+ EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
+ EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ("500,300 400x400", GetSecondaryDisplay().bounds().ToString());
// Keep the minimum 100.
SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, 490);
EXPECT_EQ(1, observer.CountAndReset()); // resize and add
+ EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
+ EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ("500,400 400x400", GetSecondaryDisplay().bounds().ToString());
SetSecondaryDisplayLayoutAndOffset(DisplayLayout::RIGHT, -400);
+ EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
+ EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
EXPECT_EQ(1, observer.CountAndReset()); // resize and add
EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ("500,-300 400x400", GetSecondaryDisplay().bounds().ToString());
// Layout to the bottom with an offset.
SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -200);
+ EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
+ EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
EXPECT_EQ(1, observer.CountAndReset()); // resize and add
EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ("-200,500 400x400", GetSecondaryDisplay().bounds().ToString());
// Keep the minimum 100.
SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, 490);
+ EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
+ EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
EXPECT_EQ(1, observer.CountAndReset()); // resize and add
EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ("400,500 400x400", GetSecondaryDisplay().bounds().ToString());
SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -400);
+ EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
+ EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
EXPECT_EQ(1, observer.CountAndReset()); // resize and add
EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString());
+
+ // Setting the same layout shouldn't invoke observers.
+ SetSecondaryDisplayLayoutAndOffset(DisplayLayout::BOTTOM, -400);
+ EXPECT_EQ(0, observer.GetChangedDisplayIdAndReset());
+ EXPECT_EQ(0, observer.GetBoundsChangedCountAndReset());
+ EXPECT_EQ(0, observer.CountAndReset()); // resize and add
+ EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
+ EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString());
}
TEST_F(DisplayControllerTest, BoundsUpdated) {
diff --git a/ash/display/resolution_notification_controller.cc b/ash/display/resolution_notification_controller.cc
new file mode 100644
index 0000000..a765d61
--- /dev/null
+++ b/ash/display/resolution_notification_controller.cc
@@ -0,0 +1,296 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/display/resolution_notification_controller.h"
+
+#include "ash/display/display_controller.h"
+#include "ash/display/display_manager.h"
+#include "ash/shell.h"
+#include "base/strings/utf_string_conversions.h"
+#include "grit/ash_resources.h"
+#include "grit/ash_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/time_format.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/screen.h"
+#include "ui/message_center/message_center.h"
+#include "ui/message_center/notification.h"
+#include "ui/message_center/notification_delegate.h"
+
+using message_center::Notification;
+
+namespace ash {
+namespace internal {
+namespace {
+
+bool g_use_timer = true;
+
+class ResolutionChangeNotificationDelegate
+ : public message_center::NotificationDelegate {
+ public:
+ ResolutionChangeNotificationDelegate(
+ ResolutionNotificationController* controller,
+ bool has_timeout);
+
+ protected:
+ virtual ~ResolutionChangeNotificationDelegate();
+
+ private:
+ // message_center::NotificationDelegate overrides:
+ virtual void Display() OVERRIDE;
+ virtual void Error() OVERRIDE;
+ virtual void Close(bool by_user) OVERRIDE;
+ virtual void Click() OVERRIDE;
+ virtual bool HasClickedListener() OVERRIDE;
+ virtual void ButtonClick(int button_index) OVERRIDE;
+
+ ResolutionNotificationController* controller_;
+ bool has_timeout_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResolutionChangeNotificationDelegate);
+};
+
+ResolutionChangeNotificationDelegate::ResolutionChangeNotificationDelegate(
+ ResolutionNotificationController* controller,
+ bool has_timeout)
+ : controller_(controller),
+ has_timeout_(has_timeout) {
+ DCHECK(controller_);
+}
+
+ResolutionChangeNotificationDelegate::~ResolutionChangeNotificationDelegate() {
+}
+
+void ResolutionChangeNotificationDelegate::Display() {
+}
+
+void ResolutionChangeNotificationDelegate::Error() {
+}
+
+void ResolutionChangeNotificationDelegate::Close(bool by_user) {
+ if (by_user)
+ controller_->AcceptResolutionChange();
+}
+
+void ResolutionChangeNotificationDelegate::Click() {
+ controller_->AcceptResolutionChange();
+}
+
+bool ResolutionChangeNotificationDelegate::HasClickedListener() {
+ return true;
+}
+
+void ResolutionChangeNotificationDelegate::ButtonClick(int button_index) {
+ // If there's the timeout, the first button is "Accept". Otherwise the
+ // button click should be "Revert".
+ if (has_timeout_ && button_index == 0)
+ controller_->AcceptResolutionChange();
+ else
+ controller_->RevertResolutionChange();
+}
+
+} // namespace
+
+// static
+const int ResolutionNotificationController::kTimeoutInSec = 15;
+
+// static
+const char ResolutionNotificationController::kNotificationId[] =
+ "chrome://settings/display/resolution";
+
+struct ResolutionNotificationController::ResolutionChangeInfo {
+ ResolutionChangeInfo(int64 display_id,
+ const gfx::Size& old_resolution,
+ const gfx::Size& new_resolution,
+ const base::Closure& accept_callback);
+ ~ResolutionChangeInfo();
+
+ // The id of the display where the resolution change happens.
+ int64 display_id;
+
+ // The resolution before the change.
+ gfx::Size old_resolution;
+
+ // The new resolution after the change.
+ gfx::Size new_resolution;
+
+ // The callback when accept is chosen.
+ base::Closure accept_callback;
+
+ // The remaining timeout in seconds. 0 if the change does not time out.
+ uint8 timeout_count;
+
+ // The timer to invoke OnTimerTick() every second. This cannot be
+ // OneShotTimer since the message contains text "automatically closed in xx
+ // seconds..." which has to be updated every second.
+ base::RepeatingTimer<ResolutionNotificationController> timer;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ResolutionChangeInfo);
+};
+
+ResolutionNotificationController::ResolutionChangeInfo::ResolutionChangeInfo(
+ int64 display_id,
+ const gfx::Size& old_resolution,
+ const gfx::Size& new_resolution,
+ const base::Closure& accept_callback)
+ : display_id(display_id),
+ old_resolution(old_resolution),
+ new_resolution(new_resolution),
+ accept_callback(accept_callback),
+ timeout_count(0) {
+ DisplayManager* display_manager = Shell::GetInstance()->display_manager();
+ if (!display_manager->HasInternalDisplay() &&
+ display_manager->num_connected_displays() == 1u) {
+ timeout_count = kTimeoutInSec;
+ }
+}
+
+ResolutionNotificationController::ResolutionChangeInfo::
+ ~ResolutionChangeInfo() {
+}
+
+ResolutionNotificationController::ResolutionNotificationController() {
+ Shell::GetInstance()->display_controller()->AddObserver(this);
+ Shell::GetScreen()->AddObserver(this);
+}
+
+ResolutionNotificationController::~ResolutionNotificationController() {
+ Shell::GetInstance()->display_controller()->RemoveObserver(this);
+ Shell::GetScreen()->RemoveObserver(this);
+}
+
+void ResolutionNotificationController::SetDisplayResolutionAndNotify(
+ int64 display_id,
+ const gfx::Size& old_resolution,
+ const gfx::Size& new_resolution,
+ const base::Closure& accept_callback) {
+ // If multiple resolution changes are invoked for the same display,
+ // the original resolution for the first resolution change has to be used
+ // instead of the specified |old_resolution|.
+ gfx::Size original_resolution;
+ if (change_info_ && change_info_->display_id == display_id) {
+ DCHECK(change_info_->new_resolution == old_resolution);
+ original_resolution = change_info_->old_resolution;
+ }
+
+ change_info_.reset(new ResolutionChangeInfo(
+ display_id, old_resolution, new_resolution, accept_callback));
+ if (!original_resolution.IsEmpty())
+ change_info_->old_resolution = original_resolution;
+
+ // SetDisplayResolution() causes OnConfigurationChanged() and the notification
+ // will be shown at that point.
+ Shell::GetInstance()->display_manager()->SetDisplayResolution(
+ display_id, new_resolution);
+}
+
+bool ResolutionNotificationController::DoesNotificationTimeout() {
+ return change_info_ && change_info_->timeout_count > 0;
+}
+
+void ResolutionNotificationController::CreateOrUpdateNotification() {
+ message_center::MessageCenter* message_center =
+ message_center::MessageCenter::Get();
+ if (!change_info_) {
+ message_center->RemoveNotification(kNotificationId, false /* by_user */);
+ return;
+ }
+
+ base::string16 timeout_message;
+ message_center::RichNotificationData data;
+ if (change_info_->timeout_count > 0) {
+ data.buttons.push_back(message_center::ButtonInfo(
+ l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_RESOLUTION_CHANGE_ACCEPT)));
+ timeout_message = l10n_util::GetStringFUTF16(
+ IDS_ASH_DISPLAY_RESOLUTION_TIMEOUT,
+ ui::TimeFormat::TimeDurationLong(
+ base::TimeDelta::FromSeconds(change_info_->timeout_count)));
+ }
+ data.buttons.push_back(message_center::ButtonInfo(
+ l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_RESOLUTION_CHANGE_REVERT)));
+
+ ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+ scoped_ptr<Notification> notification(new Notification(
+ message_center::NOTIFICATION_TYPE_SIMPLE,
+ kNotificationId,
+ l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED,
+ UTF8ToUTF16(Shell::GetInstance()->display_manager()->
+ GetDisplayNameForId(change_info_->display_id)),
+ UTF8ToUTF16(change_info_->new_resolution.ToString())),
+ timeout_message,
+ bundle.GetImageNamed(IDR_AURA_UBER_TRAY_DISPLAY),
+ base::string16() /* display_source */,
+ std::string() /* extension_id */,
+ data,
+ new ResolutionChangeNotificationDelegate(
+ this, change_info_->timeout_count > 0)));
+ notification->SetSystemPriority();
+ message_center->AddNotification(notification.Pass());
+}
+
+void ResolutionNotificationController::OnTimerTick() {
+ if (!change_info_)
+ return;
+
+ --change_info_->timeout_count;
+ if (change_info_->timeout_count == 0)
+ RevertResolutionChange();
+ else
+ CreateOrUpdateNotification();
+}
+
+void ResolutionNotificationController::AcceptResolutionChange() {
+ message_center::MessageCenter::Get()->RemoveNotification(
+ kNotificationId, false /* by_user */);
+ base::Closure callback = change_info_->accept_callback;
+ change_info_.reset();
+ callback.Run();
+}
+
+void ResolutionNotificationController::RevertResolutionChange() {
+ message_center::MessageCenter::Get()->RemoveNotification(
+ kNotificationId, false /* by_user */);
+ int64 display_id = change_info_->display_id;
+ gfx::Size old_resolution = change_info_->old_resolution;
+ change_info_.reset();
+ Shell::GetInstance()->display_manager()->SetDisplayResolution(
+ display_id, old_resolution);
+}
+
+void ResolutionNotificationController::OnDisplayBoundsChanged(
+ const gfx::Display& display) {
+}
+
+void ResolutionNotificationController::OnDisplayAdded(
+ const gfx::Display& new_display) {
+}
+
+void ResolutionNotificationController::OnDisplayRemoved(
+ const gfx::Display& old_display) {
+ if (change_info_ && change_info_->display_id == old_display.id())
+ RevertResolutionChange();
+}
+
+void ResolutionNotificationController::OnDisplayConfigurationChanged() {
+ if (!change_info_)
+ return;
+
+ CreateOrUpdateNotification();
+ if (g_use_timer && change_info_->timeout_count > 0) {
+ change_info_->timer.Start(FROM_HERE,
+ base::TimeDelta::FromSeconds(1),
+ this,
+ &ResolutionNotificationController::OnTimerTick);
+ }
+}
+
+void ResolutionNotificationController::SuppressTimerForTest() {
+ g_use_timer = false;
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/display/resolution_notification_controller.h b/ash/display/resolution_notification_controller.h
new file mode 100644
index 0000000..4de39c2
--- /dev/null
+++ b/ash/display/resolution_notification_controller.h
@@ -0,0 +1,95 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_DISPLAY_RESOLUTION_NOTIFICATION_CONTROLLER_H_
+#define ASH_DISPLAY_RESOLUTION_NOTIFICATION_CONTROLLER_H_
+
+#include "ash/ash_export.h"
+#include "ash/display/display_controller.h"
+#include "base/callback.h"
+#include "base/gtest_prod_util.h"
+#include "base/timer/timer.h"
+#include "ui/gfx/display_observer.h"
+#include "ui/gfx/size.h"
+
+namespace chromeos {
+FORWARD_DECLARE_TEST(DisplayPreferencesTest, PreventStore);
+} // namespace chromeos
+
+namespace views {
+class Label;
+class Widget;
+} // namespace views
+
+namespace ash {
+namespace internal {
+// A class which manages the notification of display resolution change and
+// also manages the timeout in case the new resolution is unusable.
+class ASH_EXPORT ResolutionNotificationController
+ : public gfx::DisplayObserver,
+ public DisplayController::Observer {
+ public:
+ ResolutionNotificationController();
+ virtual ~ResolutionNotificationController();
+
+ // Updates the display resolution for |display_id| to |new_resolution| and
+ // creates a notification for this change which offers a button to revert the
+ // change in case something goes wrong. The notification times out if there's
+ // only one display connected and the user is trying to modify its resolution.
+ // In that case, the timeout has to be set since the user cannot make any
+ // changes if something goes wrong.
+ void SetDisplayResolutionAndNotify(
+ int64 display_id,
+ const gfx::Size& old_resolution,
+ const gfx::Size& new_resolution,
+ const base::Closure& accept_callback);
+
+ // Returns true if the notification is visible or scheduled to be visible and
+ // the notification times out.
+ bool DoesNotificationTimeout();
+
+ // Called by the notification delegate when the user accepts the display
+ // resolution change.
+ void AcceptResolutionChange();
+
+ // Called by the notification delegate when the user wants to revert the
+ // display resolution change.
+ void RevertResolutionChange();
+
+ private:
+ friend class ResolutionNotificationControllerTest;
+ FRIEND_TEST_ALL_PREFIXES(ResolutionNotificationControllerTest, Timeout);
+ FRIEND_TEST_ALL_PREFIXES(chromeos::DisplayPreferencesTest, PreventStore);
+
+ // A struct to bundle the data for a single resolution change.
+ struct ResolutionChangeInfo;
+
+ static const int kTimeoutInSec;
+ static const char kNotificationId[];
+
+ // Create a new notification, or update its content if it already exists.
+ void CreateOrUpdateNotification();
+
+ // Called every second for timeout.
+ void OnTimerTick();
+
+ // gfx::DisplayObserver overrides:
+ virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE;
+ virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE;
+ virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE;
+
+ // DisplayController::Observer overrides:
+ virtual void OnDisplayConfigurationChanged() OVERRIDE;
+
+ static void SuppressTimerForTest();
+
+ scoped_ptr<ResolutionChangeInfo> change_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResolutionNotificationController);
+};
+
+} // namespace internal
+} // namespace ash
+
+#endif // ASH_DISPLAY_RESOLUTION_NOTIFICATION_CONTROLLER_H_
diff --git a/ash/display/resolution_notification_controller_unittest.cc b/ash/display/resolution_notification_controller_unittest.cc
new file mode 100644
index 0000000..bdb6f12
--- /dev/null
+++ b/ash/display/resolution_notification_controller_unittest.cc
@@ -0,0 +1,283 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/display/resolution_notification_controller.h"
+
+#include "ash/display/display_manager.h"
+#include "ash/screen_ash.h"
+#include "ash/shell.h"
+#include "ash/test/ash_test_base.h"
+#include "base/bind.h"
+#include "ui/gfx/size.h"
+#include "ui/message_center/message_center.h"
+
+namespace ash {
+namespace internal {
+
+class ResolutionNotificationControllerTest : public ash::test::AshTestBase {
+ public:
+ ResolutionNotificationControllerTest()
+ : accept_count_(0) {
+ }
+
+ virtual ~ResolutionNotificationControllerTest() {}
+
+ protected:
+ virtual void SetUp() OVERRIDE {
+ ash::test::AshTestBase::SetUp();
+ ResolutionNotificationController::SuppressTimerForTest();
+ }
+
+ void SetDisplayResolutionAndNotify(const gfx::Display& display,
+ const gfx::Size& new_resolution) {
+ DisplayManager* display_manager = Shell::GetInstance()->display_manager();
+ const DisplayInfo& info = display_manager->GetDisplayInfo(display.id());
+ Shell::GetInstance()->resolution_notification_controller()->
+ SetDisplayResolutionAndNotify(
+ display.id(),
+ info.size_in_pixel(),
+ new_resolution,
+ base::Bind(&ResolutionNotificationControllerTest::OnAccepted,
+ base::Unretained(this)));
+
+ // OnConfigurationChanged event won't be emitted in the test environment,
+ // so invoke UpdateDisplay() to emit that event explicitly.
+ std::string display_spec;
+ for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
+ if (i > 0)
+ display_spec.append(",");
+ int64 id = display_manager->GetDisplayAt(i).id();
+ gfx::Size size = (display.id() == id) ?
+ new_resolution : display_manager->GetDisplayInfo(id).size_in_pixel();
+ display_spec.append(size.ToString());
+ }
+ UpdateDisplay(display_spec);
+ RunAllPendingInMessageLoop();
+ }
+
+ void ClickOnNotification() {
+ message_center::MessageCenter::Get()->ClickOnNotification(
+ ResolutionNotificationController::kNotificationId);
+ }
+
+ void ClickOnNotificationButton(int index) {
+ message_center::MessageCenter::Get()->ClickOnNotificationButton(
+ ResolutionNotificationController::kNotificationId, index);
+ }
+
+ bool IsNotificationVisible() {
+ return message_center::MessageCenter::Get()->HasNotification(
+ ResolutionNotificationController::kNotificationId);
+ }
+
+ void TickTimer() {
+ controller()->OnTimerTick();
+ }
+
+ ResolutionNotificationController* controller() {
+ return Shell::GetInstance()->resolution_notification_controller();
+ }
+
+ int accept_count() const {
+ return accept_count_;
+ }
+
+ private:
+ void OnAccepted() {
+ EXPECT_FALSE(controller()->DoesNotificationTimeout());
+ accept_count_++;
+ }
+
+ int accept_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResolutionNotificationControllerTest);
+};
+
+// Basic behaviors and verifies it doesn't cause crashes.
+TEST_F(ResolutionNotificationControllerTest, Basic) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ UpdateDisplay("100x100,150x150");
+ int64 id2 = ash::ScreenAsh::GetSecondaryDisplay().id();
+ ash::internal::DisplayManager* display_manager =
+ ash::Shell::GetInstance()->display_manager();
+ ASSERT_EQ(0, accept_count());
+ EXPECT_FALSE(IsNotificationVisible());
+
+ // Changes the resolution and apply the result.
+ SetDisplayResolutionAndNotify(
+ ScreenAsh::GetSecondaryDisplay(), gfx::Size(200, 200));
+ EXPECT_TRUE(IsNotificationVisible());
+ EXPECT_FALSE(controller()->DoesNotificationTimeout());
+ gfx::Size resolution;
+ EXPECT_TRUE(
+ display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+ EXPECT_EQ("200x200", resolution.ToString());
+
+ // Click the revert button, which reverts the resolution.
+ ClickOnNotificationButton(0);
+ RunAllPendingInMessageLoop();
+ EXPECT_FALSE(IsNotificationVisible());
+ EXPECT_EQ(0, accept_count());
+ EXPECT_TRUE(
+ display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+ EXPECT_EQ("150x150", resolution.ToString());
+}
+
+TEST_F(ResolutionNotificationControllerTest, ClickMeansAccept) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ UpdateDisplay("100x100,150x150");
+ int64 id2 = ash::ScreenAsh::GetSecondaryDisplay().id();
+ ash::internal::DisplayManager* display_manager =
+ ash::Shell::GetInstance()->display_manager();
+ ASSERT_EQ(0, accept_count());
+ EXPECT_FALSE(IsNotificationVisible());
+
+ // Changes the resolution and apply the result.
+ SetDisplayResolutionAndNotify(
+ ScreenAsh::GetSecondaryDisplay(), gfx::Size(200, 200));
+ EXPECT_TRUE(IsNotificationVisible());
+ EXPECT_FALSE(controller()->DoesNotificationTimeout());
+ gfx::Size resolution;
+ EXPECT_TRUE(
+ display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+ EXPECT_EQ("200x200", resolution.ToString());
+
+ // Click the revert button, which reverts the resolution.
+ ClickOnNotification();
+ RunAllPendingInMessageLoop();
+ EXPECT_FALSE(IsNotificationVisible());
+ EXPECT_EQ(1, accept_count());
+ EXPECT_TRUE(
+ display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+ EXPECT_EQ("200x200", resolution.ToString());
+}
+
+TEST_F(ResolutionNotificationControllerTest, AcceptButton) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ ash::internal::DisplayManager* display_manager =
+ ash::Shell::GetInstance()->display_manager();
+
+ UpdateDisplay("100x100");
+ const gfx::Display& display = ash::Shell::GetScreen()->GetPrimaryDisplay();
+ SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
+ EXPECT_TRUE(IsNotificationVisible());
+
+ // If there's a single display only, it will have timeout and the first button
+ // becomes accept.
+ EXPECT_TRUE(controller()->DoesNotificationTimeout());
+ ClickOnNotificationButton(0);
+ EXPECT_FALSE(IsNotificationVisible());
+ EXPECT_EQ(1, accept_count());
+ gfx::Size resolution;
+ EXPECT_TRUE(display_manager->GetSelectedResolutionForDisplayId(
+ display.id(), &resolution));
+ EXPECT_EQ("200x200", resolution.ToString());
+
+ // In that case the second button is revert.
+ UpdateDisplay("100x100");
+ SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
+ EXPECT_TRUE(IsNotificationVisible());
+
+ EXPECT_TRUE(controller()->DoesNotificationTimeout());
+ ClickOnNotificationButton(1);
+ EXPECT_FALSE(IsNotificationVisible());
+ EXPECT_EQ(1, accept_count());
+ EXPECT_TRUE(display_manager->GetSelectedResolutionForDisplayId(
+ display.id(), &resolution));
+ EXPECT_EQ("100x100", resolution.ToString());
+}
+
+TEST_F(ResolutionNotificationControllerTest, Timeout) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ UpdateDisplay("100x100");
+ const gfx::Display& display = ash::Shell::GetScreen()->GetPrimaryDisplay();
+ SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
+
+ for (int i = 0; i < ResolutionNotificationController::kTimeoutInSec; ++i) {
+ EXPECT_TRUE(IsNotificationVisible()) << "notification is closed after "
+ << i << "-th timer tick";
+ TickTimer();
+ RunAllPendingInMessageLoop();
+ }
+ EXPECT_FALSE(IsNotificationVisible());
+ EXPECT_EQ(0, accept_count());
+ gfx::Size resolution;
+ ash::internal::DisplayManager* display_manager =
+ ash::Shell::GetInstance()->display_manager();
+ EXPECT_TRUE(display_manager->GetSelectedResolutionForDisplayId(
+ display.id(), &resolution));
+ EXPECT_EQ("100x100", resolution.ToString());
+}
+
+TEST_F(ResolutionNotificationControllerTest, DisplayDisconnected) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ UpdateDisplay("100x100,150x150");
+ int64 id2 = ash::ScreenAsh::GetSecondaryDisplay().id();
+ ash::internal::DisplayManager* display_manager =
+ ash::Shell::GetInstance()->display_manager();
+ SetDisplayResolutionAndNotify(
+ ScreenAsh::GetSecondaryDisplay(), gfx::Size(200, 200));
+ ASSERT_TRUE(IsNotificationVisible());
+
+ // Disconnects the secondary display and verifies it doesn't cause crashes.
+ UpdateDisplay("100x100");
+ RunAllPendingInMessageLoop();
+ EXPECT_FALSE(IsNotificationVisible());
+ EXPECT_EQ(0, accept_count());
+ gfx::Size resolution;
+ EXPECT_TRUE(
+ display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+ EXPECT_EQ("150x150", resolution.ToString());
+}
+
+TEST_F(ResolutionNotificationControllerTest, MultipleResolutionChange) {
+ if (!SupportsMultipleDisplays())
+ return;
+
+ UpdateDisplay("100x100,150x150");
+ int64 id2 = ash::ScreenAsh::GetSecondaryDisplay().id();
+ ash::internal::DisplayManager* display_manager =
+ ash::Shell::GetInstance()->display_manager();
+
+ SetDisplayResolutionAndNotify(
+ ScreenAsh::GetSecondaryDisplay(), gfx::Size(200, 200));
+ EXPECT_TRUE(IsNotificationVisible());
+ EXPECT_FALSE(controller()->DoesNotificationTimeout());
+ gfx::Size resolution;
+ EXPECT_TRUE(
+ display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+ EXPECT_EQ("200x200", resolution.ToString());
+
+ // Invokes SetDisplayResolutionAndNotify during the previous notification is
+ // visible.
+ SetDisplayResolutionAndNotify(
+ ScreenAsh::GetSecondaryDisplay(), gfx::Size(250, 250));
+ EXPECT_TRUE(
+ display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+ EXPECT_EQ("250x250", resolution.ToString());
+
+ // Then, click the revert button. Although |old_resolution| for the second
+ // SetDisplayResolutionAndNotify is 200x200, it should revert to the original
+ // size 150x150.
+ ClickOnNotificationButton(0);
+ RunAllPendingInMessageLoop();
+ EXPECT_FALSE(IsNotificationVisible());
+ EXPECT_EQ(0, accept_count());
+ EXPECT_TRUE(
+ display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+ EXPECT_EQ("150x150", resolution.ToString());
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/launcher/alternate_app_list_button.cc b/ash/launcher/alternate_app_list_button.cc
index 9a2ffcc..0466c71 100644
--- a/ash/launcher/alternate_app_list_button.cc
+++ b/ash/launcher/alternate_app_list_button.cc
@@ -146,26 +146,5 @@
state->name = host_->GetAccessibleName(this);
}
-void AlternateAppListButton::OnGestureEvent(ui::GestureEvent* event) {
- switch (event->type()) {
- case ui::ET_GESTURE_SCROLL_BEGIN:
- host_->PointerPressedOnButton(this, LauncherButtonHost::TOUCH, *event);
- event->SetHandled();
- return;
- case ui::ET_GESTURE_SCROLL_UPDATE:
- host_->PointerDraggedOnButton(this, LauncherButtonHost::TOUCH, *event);
- event->SetHandled();
- return;
- case ui::ET_GESTURE_SCROLL_END:
- case ui::ET_SCROLL_FLING_START:
- host_->PointerReleasedOnButton(this, LauncherButtonHost::TOUCH, false);
- event->SetHandled();
- return;
- default:
- ImageButton::OnGestureEvent(event);
- return;
- }
-}
-
} // namespace internal
} // namespace ash
diff --git a/ash/launcher/alternate_app_list_button.h b/ash/launcher/alternate_app_list_button.h
index b03c31e..f68207c 100644
--- a/ash/launcher/alternate_app_list_button.h
+++ b/ash/launcher/alternate_app_list_button.h
@@ -43,9 +43,6 @@
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
- // ui::EventHandler overrides:
- virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
-
private:
LauncherButtonHost* host_;
// Reference to the shelf widget containing this button, owned by the
diff --git a/ash/launcher/launcher.cc b/ash/launcher/launcher.cc
index 3dd2a14..5bd1262 100644
--- a/ash/launcher/launcher.cc
+++ b/ash/launcher/launcher.cc
@@ -142,6 +142,10 @@
return launcher_view_->visible();
}
+void Launcher::SchedulePaint() {
+ launcher_view_->SchedulePaintForAllButtons();
+}
+
views::View* Launcher::GetAppListButtonView() const {
return launcher_view_->GetAppListButtonView();
}
diff --git a/ash/launcher/launcher.h b/ash/launcher/launcher.h
index c670801..6781058 100644
--- a/ash/launcher/launcher.h
+++ b/ash/launcher/launcher.h
@@ -89,6 +89,8 @@
void SetVisible(bool visible) const;
bool IsVisible() const;
+ void SchedulePaint();
+
views::View* GetAppListButtonView() const;
// Launch a 0-indexed launcher item in the Launcher.
diff --git a/ash/launcher/launcher_button.cc b/ash/launcher/launcher_button.cc
index 194c7c4..2859d98 100644
--- a/ash/launcher/launcher_button.cc
+++ b/ash/launcher/launcher_button.cc
@@ -33,7 +33,7 @@
const int kIconSize = 32;
const int kHopSpacing = 2;
const int kIconPad = 8;
-const int kAlternateIconPad = 7;
+const int kAlternateIconPad = 5;
const int kHopUpMS = 0;
const int kHopDownMS = 200;
const int kAttentionThrobDurationMS = 800;
diff --git a/ash/launcher/launcher_model.cc b/ash/launcher/launcher_model.cc
index 8daf561..9607de6 100644
--- a/ash/launcher/launcher_model.cc
+++ b/ash/launcher/launcher_model.cc
@@ -14,18 +14,34 @@
namespace {
int LauncherItemTypeToWeight(LauncherItemType type) {
- switch (type) {
- case TYPE_BROWSER_SHORTCUT:
- case TYPE_APP_SHORTCUT:
- case TYPE_WINDOWED_APP:
- return 0;
- case TYPE_TABBED:
- case TYPE_PLATFORM_APP:
- return 1;
- case TYPE_APP_LIST:
- return ash::switches::UseAlternateShelfLayout() ? 0 : 2;
- case TYPE_APP_PANEL:
- return 3;
+ if (ash::switches::UseAlternateShelfLayout()) {
+ switch (type) {
+ case TYPE_APP_LIST:
+ return 0;
+ case TYPE_BROWSER_SHORTCUT:
+ case TYPE_APP_SHORTCUT:
+ case TYPE_WINDOWED_APP:
+ return 1;
+ case TYPE_TABBED:
+ case TYPE_PLATFORM_APP:
+ return 2;
+ case TYPE_APP_PANEL:
+ return 3;
+ }
+ } else {
+ switch (type) {
+ case TYPE_BROWSER_SHORTCUT:
+ case TYPE_APP_SHORTCUT:
+ case TYPE_WINDOWED_APP:
+ return 0;
+ case TYPE_TABBED:
+ case TYPE_PLATFORM_APP:
+ return 1;
+ case TYPE_APP_LIST:
+ return 2;
+ case TYPE_APP_PANEL:
+ return 3;
+ }
}
NOTREACHED() << "Invalid type " << type;
diff --git a/ash/launcher/launcher_tooltip_manager.cc b/ash/launcher/launcher_tooltip_manager.cc
index d3b35b6..2d92e0f 100644
--- a/ash/launcher/launcher_tooltip_manager.cc
+++ b/ash/launcher/launcher_tooltip_manager.cc
@@ -75,6 +75,8 @@
LauncherTooltipManager* host)
: views::BubbleDelegateView(anchor, arrow),
host_(host) {
+ // Make sure that the bubble follows the animation of the shelf.
+ set_move_with_anchor(true);
gfx::Insets insets = gfx::Insets(kArrowOffsetTopBottom,
kArrowOffsetLeftRight,
kArrowOffsetTopBottom,
diff --git a/ash/launcher/launcher_view.cc b/ash/launcher/launcher_view.cc
index 3d32892..82f75be 100644
--- a/ash/launcher/launcher_view.cc
+++ b/ash/launcher/launcher_view.cc
@@ -65,6 +65,10 @@
// Size between the buttons.
const int kButtonSpacing = 4;
+const int kAlternateButtonSpacing = 10;
+
+// Size allocated to for each button.
+const int kButtonSize = 44;
// Additional spacing for the left and right side of icons.
const int kHorizontalIconSpacing = 2;
@@ -465,6 +469,15 @@
overflow_bubble_->Hide();
}
+void LauncherView::SchedulePaintForAllButtons() {
+ for (int i = 0; i < view_model_->view_size(); ++i) {
+ if (i >= first_visible_index_ && i <= last_visible_index_)
+ view_model_->view_at(i)->SchedulePaint();
+ }
+ if (overflow_button_ && overflow_button_->visible())
+ overflow_button_->SchedulePaint();
+}
+
gfx::Rect LauncherView::GetIdealBoundsOfItemIcon(LauncherID id) {
int index = model_->ItemIndexByID(id);
if (index == -1 || (index > last_visible_index_ &&
@@ -685,28 +698,22 @@
return;
int first_panel_index = model_->FirstPanelIndex();
- // TODO(harrym): if alternate shelf layout stays, rename app_list_index.
- int app_list_index = first_panel_index - 1;
+ int last_button_index = first_panel_index - 1;
// Initial x,y values account both leading_inset in primary
// coordinate and secondary coordinate based on the dynamic edge of the
// launcher (eg top edge on bottom-aligned launcher).
- int x = shelf->SelectValueForShelfAlignment(
- leading_inset(),
- 0,
- 0,
- leading_inset());
- int y = shelf->SelectValueForShelfAlignment(
- 0,
- leading_inset(),
- leading_inset(),
- 0);
+ int inset = ash::switches::UseAlternateShelfLayout() ? 0 : leading_inset();
+ int x = shelf->SelectValueForShelfAlignment(inset, 0, 0, inset);
+ int y = shelf->SelectValueForShelfAlignment(0, inset, inset, 0);
- int shelf_size = ash::switches::UseAlternateShelfLayout() ?
- ShelfLayoutManager::kShelfSize : kLauncherPreferredSize;
+ int button_size = ash::switches::UseAlternateShelfLayout() ?
+ kButtonSize : kLauncherPreferredSize;
+ int button_spacing = ash::switches::UseAlternateShelfLayout() ?
+ kAlternateButtonSpacing : kButtonSpacing;
- int w = shelf->PrimaryAxisValue(shelf_size, width());
- int h = shelf->PrimaryAxisValue(height(), shelf_size);
+ int w = shelf->PrimaryAxisValue(button_size, width());
+ int h = shelf->PrimaryAxisValue(height(), button_size);
for (int i = 0; i < view_model_->view_size(); ++i) {
if (i < first_visible_index_) {
view_model_->set_ideal_bounds(i, gfx::Rect(x, y, 0, 0));
@@ -714,39 +721,42 @@
}
view_model_->set_ideal_bounds(i, gfx::Rect(x, y, w, h));
- if (i != app_list_index) {
- x = shelf->PrimaryAxisValue(x + w + kButtonSpacing, x);
- y = shelf->PrimaryAxisValue(y, y + h + kButtonSpacing);
+ if (i != last_button_index) {
+ x = shelf->PrimaryAxisValue(x + w + button_spacing, x);
+ y = shelf->PrimaryAxisValue(y, y + h + button_spacing);
}
}
if (is_overflow_mode()) {
DCHECK_LT(last_visible_index_, view_model_->view_size());
for (int i = 0; i < view_model_->view_size(); ++i) {
- view_model_->view_at(i)->SetVisible(
- i >= first_visible_index_ &&
- i != app_list_index &&
- i <= last_visible_index_);
+ bool visible = i >= first_visible_index_ &&
+ i <= last_visible_index_;
+ if (!ash::switches::UseAlternateShelfLayout())
+ visible &= i != last_button_index;
+ view_model_->view_at(i)->SetVisible(visible);
}
return;
}
// To address Fitt's law, we make the first launcher button include the
// leading inset (if there is one).
- if (view_model_->view_size() > 0) {
- view_model_->set_ideal_bounds(0, gfx::Rect(gfx::Size(
- shelf->PrimaryAxisValue(leading_inset() + w, w),
- shelf->PrimaryAxisValue(h, leading_inset() + h))));
+ if (!ash::switches::UseAlternateShelfLayout()) {
+ if (view_model_->view_size() > 0) {
+ view_model_->set_ideal_bounds(0, gfx::Rect(gfx::Size(
+ shelf->PrimaryAxisValue(inset + w, w),
+ shelf->PrimaryAxisValue(h, inset + h))));
+ }
}
// Right aligned icons.
- int end_position = available_size - kButtonSpacing;
+ int end_position = available_size - button_spacing;
x = shelf->PrimaryAxisValue(end_position, 0);
y = shelf->PrimaryAxisValue(0, end_position);
for (int i = view_model_->view_size() - 1;
i >= first_panel_index; --i) {
- x = shelf->PrimaryAxisValue(x - w - kButtonSpacing, x);
- y = shelf->PrimaryAxisValue(y, y - h - kButtonSpacing);
+ x = shelf->PrimaryAxisValue(x - w - button_spacing, x);
+ y = shelf->PrimaryAxisValue(y, y - h - button_spacing);
view_model_->set_ideal_bounds(i, gfx::Rect(x, y, w, h));
end_position = shelf->PrimaryAxisValue(x, y);
}
@@ -754,9 +764,11 @@
// Icons on the left / top are guaranteed up to kLeftIconProportion of
// the available space.
int last_icon_position = shelf->PrimaryAxisValue(
- view_model_->ideal_bounds(first_panel_index - 1).right(),
- view_model_->ideal_bounds(first_panel_index - 1).bottom()) +
- 2 * kLauncherPreferredSize + leading_inset();
+ view_model_->ideal_bounds(last_button_index).right(),
+ view_model_->ideal_bounds(last_button_index).bottom())
+ + button_size + inset;
+ if (!ash::switches::UseAlternateShelfLayout())
+ last_icon_position += button_size;
int reserved_icon_space = available_size * kReservedNonPanelIconProportion;
if (last_icon_position < reserved_icon_space)
end_position = last_icon_position;
@@ -766,34 +778,37 @@
bounds->overflow_bounds.set_size(gfx::Size(
shelf->PrimaryAxisValue(w, width()),
shelf->PrimaryAxisValue(height(), h)));
- last_visible_index_ = DetermineLastVisibleIndex(
- end_position - leading_inset() - 2 * kLauncherPreferredSize);
+ if (ash::switches::UseAlternateShelfLayout())
+ last_visible_index_ = DetermineLastVisibleIndex(
+ end_position - button_size);
+ else
+ last_visible_index_ = DetermineLastVisibleIndex(
+ end_position - inset - 2 * button_size);
last_hidden_index_ = DetermineFirstVisiblePanelIndex(end_position) - 1;
- bool show_overflow = (last_visible_index_ + 1 < app_list_index ||
- last_hidden_index_ >= first_panel_index);
+ bool show_overflow =
+ ((ash::switches::UseAlternateShelfLayout() ? 0 : 1) +
+ last_visible_index_ < last_button_index ||
+ last_hidden_index_ >= first_panel_index);
+ // Create Space for the overflow button
+ if (show_overflow && ash::switches::UseAlternateShelfLayout() &&
+ last_visible_index_ > 0)
+ --last_visible_index_;
for (int i = 0; i < view_model_->view_size(); ++i) {
- view_model_->view_at(i)->SetVisible(
- i <= last_visible_index_ ||
- i == app_list_index ||
- i > last_hidden_index_);
+ bool visible = i <= last_visible_index_ || i > last_hidden_index_;
+ // Always show the app list.
+ if (!ash::switches::UseAlternateShelfLayout())
+ visible |= (i == last_button_index);
+ view_model_->view_at(i)->SetVisible(visible);
}
overflow_button_->SetVisible(show_overflow);
if (show_overflow) {
DCHECK_NE(0, view_model_->view_size());
if (last_visible_index_ == -1) {
- x = shelf->SelectValueForShelfAlignment(
- leading_inset(),
- 0,
- 0,
- leading_inset());
- y = shelf->SelectValueForShelfAlignment(
- 0,
- leading_inset(),
- leading_inset(),
- 0);
- } else if (last_visible_index_ == app_list_index) {
+ x = shelf->SelectValueForShelfAlignment(inset, 0, 0, inset);
+ y = shelf->SelectValueForShelfAlignment(0, inset, inset, 0);
+ } else if (last_visible_index_ == last_button_index) {
x = view_model_->ideal_bounds(last_visible_index_).x();
y = view_model_->ideal_bounds(last_visible_index_).y();
} else {
@@ -804,20 +819,22 @@
view_model_->ideal_bounds(last_visible_index_).y(),
view_model_->ideal_bounds(last_visible_index_).bottom());
}
- gfx::Rect app_list_bounds = view_model_->ideal_bounds(app_list_index);
- bounds->overflow_bounds.set_x(x);
- bounds->overflow_bounds.set_y(y);
-
// Set all hidden panel icon positions to be on the overflow button.
for (int i = first_panel_index; i <= last_hidden_index_; ++i)
view_model_->set_ideal_bounds(i, gfx::Rect(x, y, w, h));
- x = shelf->PrimaryAxisValue(x + w + kButtonSpacing, x);
- y = shelf->PrimaryAxisValue(y, y + h + kButtonSpacing);
- app_list_bounds.set_x(x);
- app_list_bounds.set_y(y);
- view_model_->set_ideal_bounds(app_list_index, app_list_bounds);
+ bounds->overflow_bounds.set_x(x);
+ bounds->overflow_bounds.set_y(y);
+ if (!ash::switches::UseAlternateShelfLayout()) {
+ // Position app list after overflow button.
+ gfx::Rect app_list_bounds = view_model_->ideal_bounds(last_button_index);
+ x = shelf->PrimaryAxisValue(x + w + button_spacing, x);
+ y = shelf->PrimaryAxisValue(y, y + h + button_spacing);
+ app_list_bounds.set_x(x);
+ app_list_bounds.set_y(y);
+ view_model_->set_ideal_bounds(last_button_index, app_list_bounds);
+ }
if (overflow_bubble_.get() && overflow_bubble_->IsShowing())
UpdateOverflowRange(overflow_bubble_->launcher_view());
} else {
@@ -1035,36 +1052,17 @@
bool LauncherView::SameDragType(LauncherItemType typea,
LauncherItemType typeb) const {
- if (ash::switches::UseAlternateShelfLayout()) {
- // TODO(harrym): Allow app list to be repositionable, if this goes live
- // (no flag) the pref file has to be updated so the changes persist.
- switch (typea) {
- case TYPE_TABBED:
- case TYPE_PLATFORM_APP:
+ switch (typea) {
+ case TYPE_TABBED:
+ case TYPE_PLATFORM_APP:
return (typeb == TYPE_TABBED || typeb == TYPE_PLATFORM_APP);
- case TYPE_APP_SHORTCUT:
- case TYPE_APP_LIST:
- case TYPE_BROWSER_SHORTCUT:
- return (typeb == TYPE_APP_SHORTCUT ||
- typeb == TYPE_APP_LIST ||
- typeb == TYPE_BROWSER_SHORTCUT);
- case TYPE_WINDOWED_APP:
- case TYPE_APP_PANEL:
- return typeb == typea;
- }
- } else {
- switch (typea) {
- case TYPE_TABBED:
- case TYPE_PLATFORM_APP:
- return (typeb == TYPE_TABBED || typeb == TYPE_PLATFORM_APP);
- case TYPE_APP_SHORTCUT:
- case TYPE_BROWSER_SHORTCUT:
- return (typeb == TYPE_APP_SHORTCUT || typeb == TYPE_BROWSER_SHORTCUT);
- case TYPE_WINDOWED_APP:
- case TYPE_APP_LIST:
- case TYPE_APP_PANEL:
- return typeb == typea;
- }
+ case TYPE_APP_SHORTCUT:
+ case TYPE_BROWSER_SHORTCUT:
+ return (typeb == TYPE_APP_SHORTCUT || typeb == TYPE_BROWSER_SHORTCUT);
+ case TYPE_WINDOWED_APP:
+ case TYPE_APP_LIST:
+ case TYPE_APP_PANEL:
+ return typeb == typea;
}
NOTREACHED();
return false;
@@ -1110,6 +1108,9 @@
}
void LauncherView::UpdateFirstButtonPadding() {
+ if (ash::switches::UseAlternateShelfLayout())
+ return;
+
ShelfLayoutManager* shelf = tooltip_->shelf_layout_manager();
// Creates an empty border for first launcher button to make included leading
@@ -1420,9 +1421,12 @@
CancelDrag(-1);
} else if (drag_pointer_ == pointer) {
drag_pointer_ = NONE;
- drag_view_ = NULL;
AnimateToIdealBounds();
}
+ // If the drag pointer is NONE, no drag operation is going on and the
+ // drag_view can be released.
+ if (drag_pointer_ == NONE)
+ drag_view_ = NULL;
}
void LauncherView::MouseMovedOverButton(views::View* view) {
diff --git a/ash/launcher/launcher_view.h b/ash/launcher/launcher_view.h
index aa59f1e..507c768 100644
--- a/ash/launcher/launcher_view.h
+++ b/ash/launcher/launcher_view.h
@@ -67,6 +67,7 @@
void Init();
void OnShelfAlignmentChanged();
+ void SchedulePaintForAllButtons();
// Returns the ideal bounds of the specified item, or an empty rect if id
// isn't know.
diff --git a/ash/launcher/launcher_view_unittest.cc b/ash/launcher/launcher_view_unittest.cc
index 662284f..7731655 100644
--- a/ash/launcher/launcher_view_unittest.cc
+++ b/ash/launcher/launcher_view_unittest.cc
@@ -13,6 +13,7 @@
#include "ash/launcher/launcher_icon_observer.h"
#include "ash/launcher/launcher_model.h"
#include "ash/launcher/launcher_tooltip_manager.h"
+#include "ash/launcher/launcher_types.h"
#include "ash/root_window_controller.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shelf/shelf_widget.h"
@@ -333,17 +334,33 @@
}
}
- views::View* SimulateDrag(internal::LauncherButtonHost::Pointer pointer,
- int button_index,
- int destination_index) {
+ views::View* SimulateButtonPressed(
+ internal::LauncherButtonHost::Pointer pointer,
+ int button_index) {
internal::LauncherButtonHost* button_host = launcher_view_;
-
- // Mouse down.
views::View* button = test_api_->GetButton(button_index);
ui::MouseEvent click_event(ui::ET_MOUSE_PRESSED,
button->bounds().origin(),
button->bounds().origin(), 0);
button_host->PointerPressedOnButton(button, pointer, click_event);
+ return button;
+ }
+
+ views::View* SimulateClick(internal::LauncherButtonHost::Pointer pointer,
+ int button_index) {
+ internal::LauncherButtonHost* button_host = launcher_view_;
+ views::View* button = SimulateButtonPressed(pointer, button_index);
+ button_host->PointerReleasedOnButton(button,
+ internal::LauncherButtonHost::MOUSE,
+ false);
+ return button;
+ }
+
+ views::View* SimulateDrag(internal::LauncherButtonHost::Pointer pointer,
+ int button_index,
+ int destination_index) {
+ internal::LauncherButtonHost* button_host = launcher_view_;
+ views::View* button = SimulateButtonPressed(pointer, button_index);
// Drag.
views::View* destination = test_api_->GetButton(destination_index);
@@ -435,6 +452,49 @@
EXPECT_EQ(item_bounds.y(), ideal_bounds.y());
}
+// Checks that launcher view contents are considered in the correct drag group.
+TEST_F(LauncherViewTest, EnforceDragType) {
+ EXPECT_TRUE(test_api_->SameDragType(TYPE_TABBED, TYPE_TABBED));
+ EXPECT_TRUE(test_api_->SameDragType(TYPE_TABBED, TYPE_PLATFORM_APP));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_TABBED, TYPE_APP_SHORTCUT));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_TABBED, TYPE_BROWSER_SHORTCUT));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_TABBED, TYPE_WINDOWED_APP));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_TABBED, TYPE_APP_LIST));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_TABBED, TYPE_APP_PANEL));
+
+ EXPECT_TRUE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_PLATFORM_APP));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_APP_SHORTCUT));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP,
+ TYPE_BROWSER_SHORTCUT));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_WINDOWED_APP));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_APP_LIST));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_PLATFORM_APP, TYPE_APP_PANEL));
+
+ EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_SHORTCUT, TYPE_APP_SHORTCUT));
+ EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_SHORTCUT,
+ TYPE_BROWSER_SHORTCUT));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_SHORTCUT,
+ TYPE_WINDOWED_APP));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_SHORTCUT, TYPE_APP_LIST));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_SHORTCUT, TYPE_APP_PANEL));
+
+ EXPECT_TRUE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT,
+ TYPE_BROWSER_SHORTCUT));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT,
+ TYPE_WINDOWED_APP));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT, TYPE_APP_LIST));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_BROWSER_SHORTCUT, TYPE_APP_PANEL));
+
+ EXPECT_TRUE(test_api_->SameDragType(TYPE_WINDOWED_APP, TYPE_WINDOWED_APP));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_WINDOWED_APP, TYPE_APP_LIST));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_WINDOWED_APP, TYPE_APP_PANEL));
+
+ EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_LIST, TYPE_APP_LIST));
+ EXPECT_FALSE(test_api_->SameDragType(TYPE_APP_LIST, TYPE_APP_PANEL));
+
+ EXPECT_TRUE(test_api_->SameDragType(TYPE_APP_PANEL, TYPE_APP_PANEL));
+}
+
// Adds browser button until overflow and verifies that the last added browser
// button is hidden.
TEST_F(LauncherViewTest, AddBrowserUntilOverflow) {
@@ -753,6 +813,31 @@
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
}
+// Check that clicking first on one item and then dragging another works as
+// expected.
+TEST_F(LauncherViewTest, ClickOneDragAnother) {
+ internal::LauncherButtonHost* button_host = launcher_view_;
+
+ std::vector<std::pair<LauncherID, views::View*> > id_map;
+ SetupForDragTest(&id_map);
+
+ // A click on item 1 is simulated.
+ SimulateClick(internal::LauncherButtonHost::MOUSE, 1);
+
+ // Dragging browser index at 0 should change the model order correctly.
+ EXPECT_TRUE(model_->items()[0].type == TYPE_BROWSER_SHORTCUT);
+ views::View* dragged_button = SimulateDrag(
+ internal::LauncherButtonHost::MOUSE, 0, 2);
+ std::rotate(id_map.begin(),
+ id_map.begin() + 1,
+ id_map.begin() + 3);
+ ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
+ button_host->PointerReleasedOnButton(dragged_button,
+ internal::LauncherButtonHost::MOUSE,
+ false);
+ EXPECT_TRUE(model_->items()[2].type == TYPE_BROWSER_SHORTCUT);
+}
+
// Confirm that item status changes are reflected in the buttons.
TEST_F(LauncherViewTest, LauncherItemStatus) {
ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1,
diff --git a/ash/launcher/overflow_bubble.cc b/ash/launcher/overflow_bubble.cc
index 09613ca..7d84d1e 100644
--- a/ash/launcher/overflow_bubble.cc
+++ b/ash/launcher/overflow_bubble.cc
@@ -10,6 +10,7 @@
#include "ash/launcher/launcher_view.h"
#include "ash/root_window_controller.h"
#include "ash/shelf/shelf_layout_manager.h"
+#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ash/system/tray/system_tray.h"
#include "ui/aura/root_window.h"
@@ -200,7 +201,7 @@
views::BubbleBorder::is_arrow_on_horizontal(arrow()) ?
bubble_insets.left() : bubble_insets.top();
const int arrow_offset = border_size + kPadding + kLauncherViewLeadingInset +
- kLauncherPreferredSize / 2;
+ ShelfLayoutManager::GetPreferredShelfSize() / 2;
const gfx::Size content_size = GetPreferredSize();
border->set_arrow_offset(arrow_offset);
@@ -276,6 +277,8 @@
DCHECK(widget == bubble_->GetWidget());
bubble_ = NULL;
launcher_view_ = NULL;
+ ShelfLayoutManager::ForLauncher(
+ widget->GetNativeView())->shelf_widget()->launcher()->SchedulePaint();
}
} // namespace internal
diff --git a/ash/launcher/overflow_button.cc b/ash/launcher/overflow_button.cc
index 8847468..c3d5a68 100644
--- a/ash/launcher/overflow_button.cc
+++ b/ash/launcher/overflow_button.cc
@@ -4,7 +4,9 @@
#include "ash/launcher/overflow_button.h"
+#include "ash/ash_switches.h"
#include "ash/shelf/shelf_layout_manager.h"
+#include "ash/shelf/shelf_widget.h"
#include "grit/ash_resources.h"
#include "grit/ash_strings.h"
#include "third_party/skia/include/core/SkPaint.h"
@@ -13,6 +15,8 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/image/image_skia_operations.h"
+#include "ui/gfx/skbitmap_operations.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/transform.h"
#include "ui/views/widget/widget.h"
@@ -30,29 +34,18 @@
const int kBackgroundOffset = (48 - kButtonHoverSize) / 2;
-void RotateCounterclockwise(gfx::Transform* transform) {
- SkMatrix44 rotation;
- rotation.set3x3(0, -1, 0,
- 1, 0, 0,
- 0, 0, 1);
- transform->matrix().preConcat(rotation);
-}
-
-void RotateClockwise(gfx::Transform* transform) {
- SkMatrix44 rotation;
- rotation.set3x3( 0, 1, 0,
- -1, 0, 0,
- 0, 0, 1);
- transform->matrix().preConcat(rotation);
-}
+// Padding from the inner edge of the shelf (towards center of display) to
+// the edge of the background image of the overflow button.
+const int kImagePaddingFromShelf = 5;
} // namesapce
OverflowButton::OverflowButton(views::ButtonListener* listener)
: CustomButton(listener),
- image_(NULL) {
+ bottom_image_(NULL) {
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- image_ = rb.GetImageNamed(IDR_AURA_LAUNCHER_OVERFLOW).ToImageSkia();
+ bottom_image_ = rb.GetImageNamed(IDR_AURA_LAUNCHER_OVERFLOW).ToImageSkia();
+
set_accessibility_focusable(true);
SetAccessibleName(l10n_util::GetStringUTF16(IDS_ASH_SHELF_OVERFLOW_NAME));
@@ -96,55 +89,89 @@
}
void OverflowButton::OnPaint(gfx::Canvas* canvas) {
- ShelfAlignment alignment = ShelfLayoutManager::ForLauncher(
- GetWidget()->GetNativeView())->GetAlignment();
+ ShelfLayoutManager* layout_manager = ShelfLayoutManager::ForLauncher(
+ GetWidget()->GetNativeView());
+ ShelfAlignment alignment = layout_manager->GetAlignment();
- if (hover_animation_->is_animating()) {
- PaintBackground(
- canvas,
- kButtonHoverAlpha * hover_animation_->GetCurrentValue());
- } else if (state() == STATE_HOVERED || state() == STATE_PRESSED) {
- PaintBackground(canvas, kButtonHoverAlpha);
+ gfx::Rect bounds(GetContentsBounds());
+ if (ash::switches::UseAlternateShelfLayout()) {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ int background_image_id = 0;
+ if (layout_manager->shelf_widget()->launcher()->IsShowingOverflowBubble())
+ background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_PRESSED;
+ else if(layout_manager->shelf_widget()->GetDimsShelf())
+ background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_ON_BLACK;
+ else
+ background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_NORMAL;
+
+ const gfx::ImageSkia* background =
+ rb.GetImageNamed(background_image_id).ToImageSkia();
+ if (alignment == SHELF_ALIGNMENT_LEFT) {
+ bounds = gfx::Rect(
+ bounds.right() - background->width() - kImagePaddingFromShelf,
+ bounds.y() + (bounds.height() - background->height()) / 2,
+ background->width(), background->height());
+ } else if (alignment == SHELF_ALIGNMENT_RIGHT) {
+ bounds = gfx::Rect(
+ bounds.x() + kImagePaddingFromShelf,
+ bounds.y() + (bounds.height() - background->height()) / 2,
+ background->width(), background->height());
+ } else {
+ bounds = gfx::Rect(
+ bounds.x() + (bounds.width() - background->width()) / 2,
+ bounds.y() + kImagePaddingFromShelf,
+ background->width(), background->height());
+ }
+ canvas->DrawImageInt(*background, bounds.x(), bounds.y());
+ } else {
+ if (alignment == SHELF_ALIGNMENT_BOTTOM) {
+ bounds = gfx::Rect(
+ bounds.x() + ((bounds.width() - kButtonHoverSize) / 2) - 1,
+ bounds.y() + kBackgroundOffset - 1,
+ kButtonHoverSize, kButtonHoverSize);
+ } else {
+ bounds = gfx::Rect(
+ bounds.x() + kBackgroundOffset -1,
+ bounds.y() + ((bounds.height() - kButtonHoverSize) / 2) -1,
+ kButtonHoverSize, kButtonHoverSize);
+ }
+ if (hover_animation_->is_animating()) {
+ PaintBackground(
+ canvas,
+ kButtonHoverAlpha * hover_animation_->GetCurrentValue());
+ } else if (state() == STATE_HOVERED || state() == STATE_PRESSED) {
+ PaintBackground(canvas, kButtonHoverAlpha);
+ }
}
if (height() < kButtonHoverSize)
return;
- gfx::Transform transform;
+ const gfx::ImageSkia* image = NULL;
- switch (alignment) {
- case SHELF_ALIGNMENT_BOTTOM:
- // Shift 1 pixel left to align with overflow bubble tip.
- transform.Translate(-1, kBackgroundOffset);
- break;
+ switch(alignment) {
case SHELF_ALIGNMENT_LEFT:
- transform.Translate(kBackgroundOffset, -1);
- RotateClockwise(&transform);
+ if (left_image_.isNull()) {
+ left_image_ = gfx::ImageSkiaOperations::CreateRotatedImage(
+ *bottom_image_, SkBitmapOperations::ROTATION_90_CW);
+ }
+ image = &left_image_;
break;
case SHELF_ALIGNMENT_RIGHT:
- transform.Translate(kBackgroundOffset, height());
- RotateCounterclockwise(&transform);
+ if (right_image_.isNull()) {
+ right_image_ = gfx::ImageSkiaOperations::CreateRotatedImage(
+ *bottom_image_, SkBitmapOperations::ROTATION_270_CW);
+ }
+ image = &right_image_;
break;
- case SHELF_ALIGNMENT_TOP:
- transform.Translate(1, kBackgroundOffset);
+ default:
+ image = bottom_image_;
break;
}
- canvas->Save();
- canvas->Transform(transform);
-
- gfx::Rect rect(GetContentsBounds());
- if (alignment == SHELF_ALIGNMENT_BOTTOM ||
- alignment == SHELF_ALIGNMENT_TOP) {
- canvas->DrawImageInt(*image_,
- rect.x() + (rect.width() - image_->width()) / 2,
- kButtonHoverSize - image_->height());
- } else {
- canvas->DrawImageInt(*image_,
- kButtonHoverSize - image_->width(),
- rect.y() + (rect.height() - image_->height()) / 2);
- }
- canvas->Restore();
+ canvas->DrawImageInt(*image,
+ bounds.x() + ((bounds.width() - image->width()) / 2),
+ bounds.y() + ((bounds.height() - image->height()) / 2));
}
} // namespace internal
diff --git a/ash/launcher/overflow_button.h b/ash/launcher/overflow_button.h
index b1d2db1..0b225aa 100644
--- a/ash/launcher/overflow_button.h
+++ b/ash/launcher/overflow_button.h
@@ -8,12 +8,9 @@
#include "ash/shelf/shelf_types.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "ui/gfx/image/image_skia.h"
#include "ui/views/controls/button/custom_button.h"
-namespace gfx {
-class ImageSkia;
-}
-
namespace ash {
namespace internal {
@@ -31,7 +28,12 @@
// views::View overrides:
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
- const gfx::ImageSkia* image_;
+ // Left and right images are rotations of bottom_image and are
+ // owned by the overflow button.
+ gfx::ImageSkia left_image_;
+ gfx::ImageSkia right_image_;
+ // Bottom image is owned by the resource bundle.
+ const gfx::ImageSkia* bottom_image_;
DISALLOW_COPY_AND_ASSIGN(OverflowButton);
};
diff --git a/ash/resources/ash_resources.grd b/ash/resources/ash_resources.grd
index 7640f65..166fe5f 100644
--- a/ash/resources/ash_resources.grd
+++ b/ash/resources/ash_resources.grd
@@ -159,6 +159,7 @@
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_SHUTDOWN" file="cros/status/status_shutdown.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_SHUTDOWN_HOVER" file="cros/status/status_shutdown_hover.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_SMS" file="cros/status/status_sms.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_TRACING" file="cros/status/status_tracing.png" />
<!-- ChromeOS specific icons -->
<if expr="pp_ifdef('chromeos')">
@@ -176,6 +177,8 @@
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_BARS_LIGHT" file="cros/network/statusbar_network_bars_light.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_EDGE_DARK" file="cros/network/statusbar_network_edge_dark.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_EDGE_LIGHT" file="cros/network/statusbar_network_edge_light.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_EVDO_DARK" file="cros/network/statusbar_network_evdo_dark.png" />
+ <structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_EVDO_LIGHT" file="cros/network/statusbar_network_evdo_light.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_GPRS_DARK" file="cros/network/statusbar_network_gprs_dark.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_GPRS_LIGHT" file="cros/network/statusbar_network_gprs_light.png" />
<structure type="chrome_scaled_image" name="IDR_AURA_UBER_TRAY_NETWORK_HSPA_DARK" file="cros/network/statusbar_network_hspa_dark.png" />
diff --git a/ash/resources/default_100_percent/common/alert_small.png b/ash/resources/default_100_percent/common/alert_small.png
index 8873886..7b76b49 100644
--- a/ash/resources/default_100_percent/common/alert_small.png
+++ b/ash/resources/default_100_percent/common/alert_small.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_guest_icon.png b/ash/resources/default_100_percent/common/alt_launcher/status_guest_icon.png
index 4ee416f..12ac2bb 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_guest_icon.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_guest_icon.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_notification_icon.png b/ash/resources/default_100_percent/common/alt_launcher/status_notification_icon.png
index 388c1e0..a22e136 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_notification_icon.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_notification_icon.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_left.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_left.png
index 969c86b..3c97b3e 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_left.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_pressed_left.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png
index 665f597..0b6bd70 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_center.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_center.png
index 5fe9808..91674cc 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_center.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_center.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png
index 6aaddce..2b1b659 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png
index a5da305..9e3bb3c 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png
index 1b1ae62..d59b1ef 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_top.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_top.png
index 9dcf0fa..e0e0c5a 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_top.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_normal_top.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png
index 8701a76..b2762ba 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_center.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_center.png
index 560b350..7727193 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_center.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_center.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_top.png b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_top.png
index af88465..96453a6 100644
--- a/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_top.png
+++ b/ash/resources/default_100_percent/common/alt_launcher/status_tray_vertical_pressed_top.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/launcher/launcher_incognito_browser.png b/ash/resources/default_100_percent/common/launcher/launcher_incognito_browser.png
index 690de02..f9c4918 100644
--- a/ash/resources/default_100_percent/common/launcher/launcher_incognito_browser.png
+++ b/ash/resources/default_100_percent/common/launcher/launcher_incognito_browser.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/launcher/launcher_underline_right_hover.png b/ash/resources/default_100_percent/common/launcher/launcher_underline_right_hover.png
index 01e392e..82572f2 100644
--- a/ash/resources/default_100_percent/common/launcher/launcher_underline_right_hover.png
+++ b/ash/resources/default_100_percent/common/launcher/launcher_underline_right_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_close_fullscreen_pressed.png b/ash/resources/default_100_percent/common/window_close_fullscreen_pressed.png
index a0a0cc3..aa9219d 100644
--- a/ash/resources/default_100_percent/common/window_close_fullscreen_pressed.png
+++ b/ash/resources/default_100_percent/common/window_close_fullscreen_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_position_right_pressed.png b/ash/resources/default_100_percent/common/window_position_right_pressed.png
index f002fd4..7fa9303 100644
--- a/ash/resources/default_100_percent/common/window_position_right_pressed.png
+++ b/ash/resources/default_100_percent/common/window_position_right_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/status_data_none.png b/ash/resources/default_100_percent/cros/network/status_data_none.png
index 07aee20..26d5028 100644
--- a/ash/resources/default_100_percent/cros/network/status_data_none.png
+++ b/ash/resources/default_100_percent/cros/network/status_data_none.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/statusbar_network_evdo_dark.png b/ash/resources/default_100_percent/cros/network/statusbar_network_evdo_dark.png
new file mode 100644
index 0000000..85c0378
--- /dev/null
+++ b/ash/resources/default_100_percent/cros/network/statusbar_network_evdo_dark.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/statusbar_network_evdo_light.png b/ash/resources/default_100_percent/cros/network/statusbar_network_evdo_light.png
new file mode 100644
index 0000000..1ae959b
--- /dev/null
+++ b/ash/resources/default_100_percent/cros/network/statusbar_network_evdo_light.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_bluetooth.png b/ash/resources/default_100_percent/cros/status/status_bluetooth.png
index fd30d4d..25fbff0 100644
--- a/ash/resources/default_100_percent/cros/status/status_bluetooth.png
+++ b/ash/resources/default_100_percent/cros/status/status_bluetooth.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_ime.png b/ash/resources/default_100_percent/cros/status/status_ime.png
index 267abd0..b40d41e 100644
--- a/ash/resources/default_100_percent/cros/status/status_ime.png
+++ b/ash/resources/default_100_percent/cros/status/status_ime.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_more.png b/ash/resources/default_100_percent/cros/status/status_more.png
index 6c27f4e..41b5995 100644
--- a/ash/resources/default_100_percent/cros/status/status_more.png
+++ b/ash/resources/default_100_percent/cros/status/status_more.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_tracing.png b/ash/resources/default_100_percent/cros/status/status_tracing.png
new file mode 100644
index 0000000..eaba620
--- /dev/null
+++ b/ash/resources/default_100_percent/cros/status/status_tracing.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_update.png b/ash/resources/default_100_percent/cros/status/status_update.png
index 2489bbb..98256a8 100644
--- a/ash/resources/default_100_percent/cros/status/status_update.png
+++ b/ash/resources/default_100_percent/cros/status/status_update.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_guest_icon.png b/ash/resources/default_200_percent/common/alt_launcher/status_guest_icon.png
index 86f6bf1..11aca56 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_guest_icon.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_guest_icon.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_left.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_left.png
index 0ad8bd1..8c6f84c 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_left.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_pressed_left.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png
index 76a7e6c..0804518 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_bottom.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_center.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_center.png
index 22cba57..96859ea 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_center.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_center.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png
index 16c8adc..85bd1f1 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_bottom.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png
index ec56c28..d880b32 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_center.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png
index da0ca49..1884826 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_onblack_top.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_top.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_top.png
index 37b820c..fed0cab 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_top.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_normal_top.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png
index 3aea89a..53b3a0d 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_bottom.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_center.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_center.png
index 02e2755..4ec633f 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_center.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_center.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_top.png b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_top.png
index 5cb6e48..e47b081 100644
--- a/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_top.png
+++ b/ash/resources/default_200_percent/common/alt_launcher/status_tray_vertical_pressed_top.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser_panel.png b/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser_panel.png
index d0e2c63..4ba2a86 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser_panel.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_incognito_browser_panel.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/launcher/launcher_underline_left_hover.png b/ash/resources/default_200_percent/common/launcher/launcher_underline_left_hover.png
index fc1ee96..c2937e7 100644
--- a/ash/resources/default_200_percent/common/launcher/launcher_underline_left_hover.png
+++ b/ash/resources/default_200_percent/common/launcher/launcher_underline_left_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_short_black_hover.png b/ash/resources/default_200_percent/common/window_close_short_black_hover.png
index f237da7..13445f1 100644
--- a/ash/resources/default_200_percent/common/window_close_short_black_hover.png
+++ b/ash/resources/default_200_percent/common/window_close_short_black_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_short_black_normal.png b/ash/resources/default_200_percent/common/window_close_short_black_normal.png
index 174bee2..12aa993 100644
--- a/ash/resources/default_200_percent/common/window_close_short_black_normal.png
+++ b/ash/resources/default_200_percent/common/window_close_short_black_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_short_black_pressed.png b/ash/resources/default_200_percent/common/window_close_short_black_pressed.png
index c452fca..42c3ca7 100644
--- a/ash/resources/default_200_percent/common/window_close_short_black_pressed.png
+++ b/ash/resources/default_200_percent/common/window_close_short_black_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_close_short_pressed.png b/ash/resources/default_200_percent/common/window_close_short_pressed.png
index e136ec5..711c6de 100644
--- a/ash/resources/default_200_percent/common/window_close_short_pressed.png
+++ b/ash/resources/default_200_percent/common/window_close_short_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_minimize_short_hover.png b/ash/resources/default_200_percent/common/window_minimize_short_hover.png
index 452ebc8..61cd354 100644
--- a/ash/resources/default_200_percent/common/window_minimize_short_hover.png
+++ b/ash/resources/default_200_percent/common/window_minimize_short_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_position_left_pressed_restore.png b/ash/resources/default_200_percent/common/window_position_left_pressed_restore.png
index 6b319db..0f9e0c9 100644
--- a/ash/resources/default_200_percent/common/window_position_left_pressed_restore.png
+++ b/ash/resources/default_200_percent/common/window_position_left_pressed_restore.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_fullscreen_hover.png b/ash/resources/default_200_percent/common/window_size_fullscreen_hover.png
index 2855067..1c466bd 100644
--- a/ash/resources/default_200_percent/common/window_size_fullscreen_hover.png
+++ b/ash/resources/default_200_percent/common/window_size_fullscreen_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_fullscreen_normal.png b/ash/resources/default_200_percent/common/window_size_fullscreen_normal.png
index 688028d..3773c24 100644
--- a/ash/resources/default_200_percent/common/window_size_fullscreen_normal.png
+++ b/ash/resources/default_200_percent/common/window_size_fullscreen_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_size_tall_hover.png b/ash/resources/default_200_percent/common/window_size_tall_hover.png
index 8d33073..cc7508c 100644
--- a/ash/resources/default_200_percent/common/window_size_tall_hover.png
+++ b/ash/resources/default_200_percent/common/window_size_tall_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_wifi_enabled.png b/ash/resources/default_200_percent/cros/network/status_wifi_enabled.png
index 4fae330..e951ff3 100644
--- a/ash/resources/default_200_percent/cros/network/status_wifi_enabled.png
+++ b/ash/resources/default_200_percent/cros/network/status_wifi_enabled.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/status_wifi_enabled_hover.png b/ash/resources/default_200_percent/cros/network/status_wifi_enabled_hover.png
index bfb35bd..7a72884 100644
--- a/ash/resources/default_200_percent/cros/network/status_wifi_enabled_hover.png
+++ b/ash/resources/default_200_percent/cros/network/status_wifi_enabled_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_evdo_dark.png b/ash/resources/default_200_percent/cros/network/statusbar_network_evdo_dark.png
new file mode 100644
index 0000000..7135146
--- /dev/null
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_evdo_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_evdo_light.png b/ash/resources/default_200_percent/cros/network/statusbar_network_evdo_light.png
new file mode 100644
index 0000000..55b89af
--- /dev/null
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_evdo_light.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_help.png b/ash/resources/default_200_percent/cros/status/status_help.png
index 97de651..a8a9977 100644
--- a/ash/resources/default_200_percent/cros/status/status_help.png
+++ b/ash/resources/default_200_percent/cros/status/status_help.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_power_small_all_fluctuating.png b/ash/resources/default_200_percent/cros/status/status_power_small_all_fluctuating.png
index d46f7ca..be20d9b 100644
--- a/ash/resources/default_200_percent/cros/status/status_power_small_all_fluctuating.png
+++ b/ash/resources/default_200_percent/cros/status/status_power_small_all_fluctuating.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_tracing.png b/ash/resources/default_200_percent/cros/status/status_tracing.png
new file mode 100644
index 0000000..4680f3f
--- /dev/null
+++ b/ash/resources/default_200_percent/cros/status/status_tracing.png
Binary files differ
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index c0e5f77..e392cc2 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -36,6 +36,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "ui/aura/client/activation_client.h"
+#include "ui/aura/client/cursor_client.h"
#include "ui/aura/root_window.h"
#include "ui/base/events/event.h"
#include "ui/base/events/event_handler.h"
@@ -72,6 +73,9 @@
// the auto hidden shelf when the shelf is on the boundary between displays.
const int kMaxAutoHideShowShelfRegionSize = 10;
+// Const inset from the edget of the shelf to the edget of the status area.
+const int kStatusAreaInset = 3;
+
ui::Layer* GetLayer(views::Widget* widget) {
return widget->GetNativeView()->layer();
}
@@ -280,7 +284,8 @@
if (shelf_->launcher())
shelf_->launcher()->SetLauncherViewBounds(
target_bounds.launcher_bounds_in_shelf);
- GetLayer(shelf_->status_area_widget())->SetOpacity(target_bounds.opacity);
+ GetLayer(shelf_->status_area_widget())->SetOpacity(
+ target_bounds.status_opacity);
// TODO(harrym): Once status area widget is a child view of shelf
// this can be simplified.
gfx::Rect status_bounds = target_bounds.status_bounds_in_shelf;
@@ -571,12 +576,6 @@
state.window_state = workspace_controller_ ?
workspace_controller_->GetWindowState() : WORKSPACE_WINDOW_STATE_DEFAULT;
- // It's possible for SetState() when a window becomes maximized but the state
- // won't have changed value. Do the dimming check before the early exit.
- shelf_->SetDimsShelf(
- (state.visibility_state == SHELF_VISIBLE) &&
- state.window_state == WORKSPACE_WINDOW_STATE_MAXIMIZED);
-
if (state_.Equals(state))
return; // Nothing changed.
@@ -594,20 +593,6 @@
StopAutoHideTimer();
- // The transition of background from auto-hide to visible is janky if the
- // transition also cause the shelf's slide animation from the bottom edge.
- // This happens if:
- // - shelf is hidden
- // - or, shelf is visible but workspace state is maximized
- bool keep_maximized = state_.window_state == state.window_state &&
- state_.window_state == WORKSPACE_WINDOW_STATE_MAXIMIZED;
- BackgroundAnimator::ChangeType change_type =
- (state_.visibility_state == SHELF_AUTO_HIDE &&
- state.visibility_state == SHELF_VISIBLE &&
- (state_.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN ||
- keep_maximized)) ?
- BackgroundAnimator::CHANGE_IMMEDIATE : BackgroundAnimator::CHANGE_ANIMATE;
-
State old_state = state_;
state_ = state;
TargetBounds target_bounds;
@@ -631,29 +616,43 @@
status_animation_setter.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- // Delay updating the background when going from SHELF_AUTO_HIDE_SHOWN to
- // SHELF_AUTO_HIDE_HIDDEN until the shelf animates out. Otherwise during the
- // animation you see the background change.
- // Also delay the animation when the shelf was hidden, and has just been made
- // visible (e.g. using a gesture-drag).
- // But do not delay if the transition happens when a window is maximized.
- bool delay_shelf_update =
- state.visibility_state == SHELF_AUTO_HIDE &&
- state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN &&
- old_state.visibility_state == SHELF_AUTO_HIDE;
+ BackgroundAnimator::ChangeType change_type =
+ BackgroundAnimator::CHANGE_ANIMATE;
+ bool delay_background_change = false;
- if (!keep_maximized && state.visibility_state == SHELF_VISIBLE &&
- old_state.visibility_state == SHELF_AUTO_HIDE &&
- old_state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN)
- delay_shelf_update = true;
+ // Do not animate the background when:
+ // - Going from a hidden / auto hidden shelf in fullscreen to a visible shelf
+ // in maximized mode.
+ // - Going from an auto hidden shelf in maximized mode to a visible shelf in
+ // maximized mode.
+ if (state.visibility_state == SHELF_VISIBLE &&
+ state.window_state == WORKSPACE_WINDOW_STATE_MAXIMIZED &&
+ old_state.visibility_state != SHELF_VISIBLE) {
+ change_type = BackgroundAnimator::CHANGE_IMMEDIATE;
+ } else {
+ // Delay the animation when the shelf was hidden, and has just been made
+ // visible (e.g. using a gesture-drag).
+ if (state.visibility_state == SHELF_VISIBLE &&
+ old_state.visibility_state == SHELF_AUTO_HIDE &&
+ old_state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) {
+ delay_background_change = true;
+ }
+ }
- if (delay_shelf_update) {
+ if (delay_background_change) {
if (update_shelf_observer_)
update_shelf_observer_->Detach();
// UpdateShelfBackground deletes itself when the animation is done.
update_shelf_observer_ = new UpdateShelfObserver(this);
status_animation_setter.AddObserver(update_shelf_observer_);
+ } else {
+ UpdateShelfBackground(change_type);
}
+
+ shelf_->SetDimsShelf(
+ state.visibility_state == SHELF_VISIBLE &&
+ state.window_state == WORKSPACE_WINDOW_STATE_MAXIMIZED);
+
ui::Layer* layer = GetLayer(shelf_->status_area_widget());
// TODO(harrym): Remove when status_area is view (crbug.com/180422).
gfx::Rect status_bounds = target_bounds.status_bounds_in_shelf;
@@ -666,8 +665,6 @@
Shell::GetInstance()->SetDisplayWorkAreaInsets(
root_window_, target_bounds.work_area_insets);
UpdateHitTestBounds();
- if (!delay_shelf_update)
- UpdateShelfBackground(change_type);
// OnAutoHideStateChanged Should be emitted when:
// - firstly state changed to auto-hide from other state
@@ -747,6 +744,9 @@
int status_inset = std::max(0, GetPreferredShelfSize() -
PrimaryAxisValue(status_size.height(), status_size.width()));
+ if (ash::switches::UseAlternateShelfLayout())
+ status_inset = kStatusAreaInset;
+
target_bounds->status_bounds_in_shelf = SelectValueForShelfAlignment(
gfx::Rect(base::i18n::IsRTL() ? 0 : shelf_width - status_size.width(),
status_inset, status_size.width(), status_size.height()),
@@ -789,7 +789,8 @@
state.visibility_state == SHELF_AUTO_HIDE) ? 1.0f : 0.0f;
target_bounds->status_opacity =
(state.visibility_state == SHELF_AUTO_HIDE &&
- state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN) ?
+ state.auto_hide_state == SHELF_AUTO_HIDE_HIDDEN &&
+ gesture_drag_status_ != GESTURE_DRAG_IN_PROGRESS) ?
0.0f : target_bounds->opacity;
if (gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS)
@@ -855,12 +856,16 @@
available_bounds.bottom() - shelf_height);
}
- // The statusbar should be in the center of the shelf.
- gfx::Rect status_y = target_bounds->shelf_bounds_in_root;
- status_y.set_y(0);
- status_y.ClampToCenteredSize(
- target_bounds->status_bounds_in_shelf.size());
- target_bounds->status_bounds_in_shelf.set_y(status_y.y());
+ if (ash::switches::UseAlternateShelfLayout()) {
+ target_bounds->status_bounds_in_shelf.set_y(kStatusAreaInset);
+ } else {
+ // The statusbar should be in the center of the shelf.
+ gfx::Rect status_y = target_bounds->shelf_bounds_in_root;
+ status_y.set_y(0);
+ status_y.ClampToCenteredSize(
+ target_bounds->status_bounds_in_shelf.size());
+ target_bounds->status_bounds_in_shelf.set_y(status_y.y());
+ }
} else {
// Move and size the launcher with the gesture.
int shelf_width = target_bounds->shelf_bounds_in_root.width();
@@ -875,12 +880,21 @@
available_bounds.right() - shelf_width);
}
- // The statusbar should be in the center of the shelf.
- gfx::Rect status_x = target_bounds->shelf_bounds_in_root;
- status_x.set_x(0);
- status_x.ClampToCenteredSize(
- target_bounds->status_bounds_in_shelf.size());
- target_bounds->status_bounds_in_shelf.set_x(status_x.x());
+ if (ash::switches::UseAlternateShelfLayout()) {
+ if (alignment_ == SHELF_ALIGNMENT_RIGHT) {
+ target_bounds->shelf_bounds_in_root.set_x(
+ available_bounds.right() - shelf_width + kStatusAreaInset);
+ } else {
+ target_bounds->shelf_bounds_in_root.set_x(kStatusAreaInset);
+ }
+ } else {
+ // The statusbar should be in the center of the shelf.
+ gfx::Rect status_x = target_bounds->shelf_bounds_in_root;
+ status_x.set_x(0);
+ status_x.ClampToCenteredSize(
+ target_bounds->status_bounds_in_shelf.size());
+ target_bounds->status_bounds_in_shelf.set_x(status_x.x());
+ }
}
}
@@ -941,9 +955,6 @@
if (visibility_state != SHELF_AUTO_HIDE || !shelf_)
return SHELF_AUTO_HIDE_HIDDEN;
- if (gesture_drag_status_ == GESTURE_DRAG_COMPLETE_IN_PROGRESS)
- return gesture_drag_auto_hide_state_;
-
Shell* shell = Shell::GetInstance();
if (shell->GetAppListTargetVisibility())
return SHELF_AUTO_HIDE_SHOWN;
@@ -961,10 +972,36 @@
if (shelf_->IsActive() || shelf_->status_area_widget()->IsActive())
return SHELF_AUTO_HIDE_SHOWN;
+ const std::vector<aura::Window*> windows =
+ ash::MruWindowTracker::BuildWindowList(false);
+
+ // Process the window list and check if there are any visible windows.
+ bool visible_window = false;
+ for (size_t i = 0; i < windows.size(); ++i) {
+ if (windows[i] && windows[i]->IsVisible() &&
+ !ash::wm::IsWindowMinimized(windows[i]) &&
+ root_window_ == windows[i]->GetRootWindow()) {
+ visible_window = true;
+ break;
+ }
+ }
+ // If there are no visible windows do not hide the shelf.
+ if (!visible_window)
+ return SHELF_AUTO_HIDE_SHOWN;
+
+ if (gesture_drag_status_ == GESTURE_DRAG_COMPLETE_IN_PROGRESS)
+ return gesture_drag_auto_hide_state_;
+
// Don't show if the user is dragging the mouse.
if (auto_hide_event_filter_.get() && auto_hide_event_filter_->in_mouse_drag())
return SHELF_AUTO_HIDE_HIDDEN;
+ // Ignore the mouse position if mouse events are disabled.
+ aura::client::CursorClient* cursor_client = aura::client::GetCursorClient(
+ shelf_->GetNativeWindow()->GetRootWindow());
+ if (!cursor_client->IsMouseEventsEnabled())
+ return SHELF_AUTO_HIDE_HIDDEN;
+
gfx::Rect shelf_region = shelf_->GetWindowBoundsInScreen();
if (shelf_->status_area_widget() &&
shelf_->status_area_widget()->IsMessageBubbleShown() &&
@@ -1005,19 +1042,7 @@
return SHELF_AUTO_HIDE_SHOWN;
}
- const std::vector<aura::Window*> windows =
- ash::MruWindowTracker::BuildWindowList(false);
-
- // Process the window list and check if there are any visible windows.
- for (size_t i = 0; i < windows.size(); ++i) {
- if (windows[i] && windows[i]->IsVisible() &&
- !ash::wm::IsWindowMinimized(windows[i]) &&
- root_window_ == windows[i]->GetRootWindow())
- return SHELF_AUTO_HIDE_HIDDEN;
- }
-
- // If there are no visible windows do not hide the shelf.
- return SHELF_AUTO_HIDE_SHOWN;
+ return SHELF_AUTO_HIDE_HIDDEN;
}
void ShelfLayoutManager::UpdateHitTestBounds() {
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc
index 2781e6c..e62bcec 100644
--- a/ash/shelf/shelf_layout_manager_unittest.cc
+++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -576,6 +576,22 @@
// is fullscreen status.
widget->Close();
RunAllPendingInMessageLoop();
+
+ // The shelf should be shown because there are no more visible windows.
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
+
+ // Swipe-up to hide. This should have no effect because there are no visible
+ // windows.
+ end = below_start - delta;
+ generator.GestureScrollSequenceWithCallback(below_start, end,
+ base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
+ base::Bind(&ShelfDragCallback::ProcessScroll,
+ base::Unretained(&handler)));
+ EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+ EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
}
// Fails on Mac only. Need to be implemented. http://crbug.com/111279.
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc
index 7c478c7..d16f876 100644
--- a/ash/shelf/shelf_widget.cc
+++ b/ash/shelf/shelf_widget.cc
@@ -541,8 +541,10 @@
void ShelfWidget::SetDimsShelf(bool dimming) {
delegate_view_->SetDimmed(dimming);
+ // Repaint all children, allowing updates to reflect dimmed state eg:
+ // status area background, app list button and overflow button.
if (launcher_)
- launcher_->GetAppListButtonView()->SchedulePaint();
+ launcher_->SchedulePaint();
status_area_widget_->GetContentsView()->SchedulePaint();
}
diff --git a/ash/shell.cc b/ash/shell.cc
index 1bade43..996c817 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -17,6 +17,7 @@
#include "ash/display/display_manager.h"
#include "ash/display/event_transformation_handler.h"
#include "ash/display/mouse_cursor_event_filter.h"
+#include "ash/display/resolution_notification_controller.h"
#include "ash/display/screen_position_controller.h"
#include "ash/drag_drop/drag_drop_controller.h"
#include "ash/focus_cycler.h"
@@ -312,6 +313,8 @@
lock_state_controller_.reset();
mru_window_tracker_.reset();
+ resolution_notification_controller_.reset();
+
// This also deletes all RootWindows. Note that we invoke Shutdown() on
// DisplayController before resetting |display_controller_|, since destruction
// of its owned RootWindowControllers relies on the value.
@@ -505,6 +508,9 @@
aura::RootWindow* root_window = display_controller_->GetPrimaryRootWindow();
target_root_window_ = root_window;
+ resolution_notification_controller_.reset(
+ new internal::ResolutionNotificationController);
+
cursor_manager_.SetDisplay(DisplayController::GetPrimaryDisplay());
#if !defined(OS_MACOSX)
@@ -743,6 +749,18 @@
void Shell::OnLockStateChanged(bool locked) {
FOR_EACH_OBSERVER(ShellObserver, observers_, OnLockStateChanged(locked));
+#ifndef NDEBUG
+ // Make sure that there is no system modal in Lock layer when unlocked.
+ if (!locked) {
+ std::vector<aura::Window*> containers = GetContainersFromAllRootWindows(
+ internal::kShellWindowId_LockSystemModalContainer,
+ GetPrimaryRootWindow());
+ for (std::vector<aura::Window*>::const_iterator iter = containers.begin();
+ iter != containers.end(); ++iter) {
+ DCHECK_EQ(0u, (*iter)->children().size());
+ }
+ }
+#endif
}
void Shell::CreateLauncher() {
diff --git a/ash/shell.h b/ash/shell.h
index c3adade..ae08e7b 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -115,6 +115,7 @@
class OutputConfiguratorAnimation;
class OverlayEventFilter;
class ResizeShadowController;
+class ResolutionNotificationController;
class RootWindowController;
class RootWindowLayoutManager;
class ScopedTargetRootWindow;
@@ -450,6 +451,11 @@
}
#endif // defined(OS_CHROMEOS) && defined(USE_X11)
+ internal::ResolutionNotificationController*
+ resolution_notification_controller() {
+ return resolution_notification_controller_.get();
+ }
+
RootWindowHostFactory* root_window_host_factory() {
return root_window_host_factory_.get();
}
@@ -607,6 +613,9 @@
scoped_ptr<internal::DisplayChangeObserverX11> display_change_observer_;
#endif // defined(OS_CHROMEOS) && defined(USE_X11)
+ scoped_ptr<internal::ResolutionNotificationController>
+ resolution_notification_controller_;
+
// |native_cursor_manager_| is owned by |cursor_manager_|, but we keep a
// pointer to vend to test code.
AshNativeCursorManager* native_cursor_manager_;
diff --git a/ash/system/chromeos/managed/tray_locally_managed_user.cc b/ash/system/chromeos/managed/tray_locally_managed_user.cc
index 61e422d..49dea0c 100644
--- a/ash/system/chromeos/managed/tray_locally_managed_user.cc
+++ b/ash/system/chromeos/managed/tray_locally_managed_user.cc
@@ -10,46 +10,39 @@
#include "ash/system/user/login_status.h"
#include "base/logging.h"
#include "grit/ash_resources.h"
+#include "ui/message_center/message_center.h"
+#include "ui/message_center/notification.h"
+#include "ui/message_center/notification_delegate.h"
+
+using message_center::Notification;
namespace ash {
namespace internal {
-
namespace {
-class ManagedUserNotificationView : public TrayNotificationView {
- public:
- explicit ManagedUserNotificationView(TrayLocallyManagedUser* tray_managed)
- : TrayNotificationView(tray_managed, IDR_AURA_UBER_TRAY_MANAGED_USER),
- tray_managed_(tray_managed) {
- CreateMessageView();
- InitView(message_view_);
- }
+const char kLocallyManagedUserNotificationId[] =
+ "chrome://user/locally-managed";
- void Update() {
- CreateMessageView();
- UpdateView(message_view_);
- }
-
- private:
- void CreateMessageView() {
- message_view_ = new LabelTrayView(tray_managed_, 0);
- base::string16 message = Shell::GetInstance()->system_tray_delegate()->
- GetLocallyManagedUserMessage();
- message_view_->SetMessage(message);
- }
-
- LabelTrayView* message_view_;
- TrayLocallyManagedUser* tray_managed_;
-
- DISALLOW_COPY_AND_ASSIGN(ManagedUserNotificationView);
-};
+void CreateOrUpdateNotification(const base::string16& new_message) {
+ scoped_ptr<Notification> notification(new Notification(
+ message_center::NOTIFICATION_TYPE_SIMPLE,
+ kLocallyManagedUserNotificationId,
+ new_message,
+ base::string16() /* body is empty */,
+ gfx::Image() /* icon */,
+ base::string16() /* display_source */,
+ std::string() /* extension_id */,
+ message_center::RichNotificationData(),
+ NULL /* no delegate */));
+ notification->SetSystemPriority();
+ message_center::MessageCenter::Get()->AddNotification(notification.Pass());
+}
} // namespace
TrayLocallyManagedUser::TrayLocallyManagedUser(SystemTray* system_tray)
: SystemTrayItem(system_tray),
tray_view_(NULL),
- notification_view_(NULL),
status_(ash::user::LOGGED_IN_NONE) {
}
@@ -61,17 +54,10 @@
GetLocallyManagedUserMessage();
if (tray_view_)
tray_view_->SetMessage(message);
- if (notification_view_)
- tray_view_->SetMessage(message);
-}
-
-views::View* TrayLocallyManagedUser::CreateNotificationView(
- user::LoginStatus status) {
- CHECK(!notification_view_);
- if (status != ash::user::LOGGED_IN_LOCALLY_MANAGED)
- return NULL;
- notification_view_ = new ManagedUserNotificationView(this);
- return notification_view_;
+ if (message_center::MessageCenter::Get()->HasNotification(
+ kLocallyManagedUserNotificationId)) {
+ CreateOrUpdateNotification(message);
+ }
}
views::View* TrayLocallyManagedUser::CreateDefaultView(
@@ -89,10 +75,6 @@
tray_view_ = NULL;
}
-void TrayLocallyManagedUser::DestroyNotificationView() {
- notification_view_ = NULL;
-}
-
void TrayLocallyManagedUser::OnViewClicked(views::View* sender) {
Shell::GetInstance()->system_tray_delegate()->ShowLocallyManagedUserInfo();
}
@@ -103,11 +85,11 @@
return;
if (status == ash::user::LOGGED_IN_LOCALLY_MANAGED &&
status_ != ash::user::LOGGED_IN_LOCKED) {
- ShowNotificationView();
+ SystemTrayDelegate* delegate = Shell::GetInstance()->system_tray_delegate();
+ CreateOrUpdateNotification(delegate->GetLocallyManagedUserMessage());
}
status_ = status;
}
} // namespace internal
} // namespace ash
-
diff --git a/ash/system/chromeos/managed/tray_locally_managed_user.h b/ash/system/chromeos/managed/tray_locally_managed_user.h
index eda2be0..e028634 100644
--- a/ash/system/chromeos/managed/tray_locally_managed_user.h
+++ b/ash/system/chromeos/managed/tray_locally_managed_user.h
@@ -29,10 +29,7 @@
// Overridden from SystemTrayItem.
virtual views::View* CreateDefaultView(user::LoginStatus status) OVERRIDE;
- virtual views::View* CreateNotificationView(
- user::LoginStatus status) OVERRIDE;
virtual void DestroyDefaultView() OVERRIDE;
- virtual void DestroyNotificationView() OVERRIDE;
virtual void UpdateAfterLoginStatusChange(user::LoginStatus status) OVERRIDE;
// Overridden from ViewClickListener.
@@ -40,7 +37,6 @@
private:
LabelTrayView* tray_view_;
- views::View* notification_view_;
// Previous login status to avoid showing notification upon unlock.
user::LoginStatus status_;
@@ -51,4 +47,3 @@
} // namespace ash
#endif // ASH_SYSTEM_CHROMEOS_LOCALLY_MANAGED_TRAY_LOCALLY_MANAGED_USER_H
-
diff --git a/ash/system/chromeos/network/network_connect.cc b/ash/system/chromeos/network/network_connect.cc
index 5c62499..3aca162 100644
--- a/ash/system/chromeos/network/network_connect.cc
+++ b/ash/system/chromeos/network/network_connect.cc
@@ -13,77 +13,315 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "chromeos/login/login_state.h"
+#include "chromeos/network/device_state.h"
+#include "chromeos/network/network_configuration_handler.h"
#include "chromeos/network/network_connection_handler.h"
+#include "chromeos/network/network_event_log.h"
+#include "chromeos/network/network_handler_callbacks.h"
+#include "chromeos/network/network_profile.h"
+#include "chromeos/network/network_profile_handler.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "grit/ash_strings.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/l10n/l10n_util.h"
+using chromeos::DeviceState;
+using chromeos::NetworkConfigurationHandler;
using chromeos::NetworkConnectionHandler;
using chromeos::NetworkHandler;
+using chromeos::NetworkProfile;
+using chromeos::NetworkProfileHandler;
using chromeos::NetworkState;
namespace ash {
namespace {
+// TODO(stevenjb): This should be in service_constants.h
+const char kErrorInProgress[] = "org.chromium.flimflam.Error.InProgress";
+
+// Returns true for carriers that can be activated through Shill instead of
+// through a WebUI dialog.
+bool IsDirectActivatedCarrier(const std::string& carrier) {
+ if (carrier == shill::kCarrierSprint)
+ return true;
+ return false;
+}
+
+void ShowErrorNotification(const std::string& error,
+ const std::string& service_path) {
+ Shell::GetInstance()->system_tray_notifier()->network_state_notifier()->
+ ShowNetworkConnectError(error, service_path);
+}
+
void OnConnectFailed(const std::string& service_path,
+ gfx::NativeWindow owning_window,
const std::string& error_name,
scoped_ptr<base::DictionaryValue> error_data) {
- VLOG(1) << "Connect Failed for " << service_path << ": " << error_name;
- if (error_name == NetworkConnectionHandler::kErrorPassphraseRequired) {
- // TODO(stevenjb): Possibly add inline UI to handle passphrase entry here.
- ash::Shell::GetInstance()->system_tray_delegate()->ConfigureNetwork(
- service_path);
+ 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)
return;
- }
- if (error_name == NetworkConnectionHandler::kErrorActivationRequired ||
- error_name == NetworkConnectionHandler::kErrorCertificateRequired ||
+
+ if (error_name == NetworkConnectionHandler::kErrorPassphraseRequired ||
error_name == NetworkConnectionHandler::kErrorConfigurationRequired ||
error_name == NetworkConnectionHandler::kErrorAuthenticationRequired) {
ash::Shell::GetInstance()->system_tray_delegate()->ConfigureNetwork(
service_path);
return;
}
+
+ if (error_name == NetworkConnectionHandler::kErrorCertificateRequired) {
+ ash::Shell::GetInstance()->system_tray_delegate()->EnrollOrConfigureNetwork(
+ service_path, owning_window);
+ return;
+ }
+
+ if (error_name == NetworkConnectionHandler::kErrorActivationRequired) {
+ network_connect::ActivateCellular(service_path);
+ return;
+ }
+
if (error_name == NetworkConnectionHandler::kErrorConnected ||
error_name == NetworkConnectionHandler::kErrorConnecting) {
ash::Shell::GetInstance()->system_tray_delegate()->ShowNetworkSettings(
service_path);
return;
}
- // Shill does not always provide a helpful error. In this case, show the
- // configuration UI and a notification. See crbug.com/217033 for an example.
- if (error_name == NetworkConnectionHandler::kErrorConnectFailed) {
- ash::Shell::GetInstance()->system_tray_delegate()->ConfigureNetwork(
- service_path);
- }
- ash::Shell::GetInstance()->system_tray_notifier()->network_state_notifier()->
- ShowNetworkConnectError(error_name, service_path);
+
+ // ConnectFailed or unknown error; show a notification.
+ ShowErrorNotification(error_name, service_path);
+
+ // Show a configure dialog for ConnectFailed errors.
+ if (error_name != NetworkConnectionHandler::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 == kErrorInProgress)
+ return;
+
+ ash::Shell::GetInstance()->system_tray_delegate()->ConfigureNetwork(
+ service_path);
}
void OnConnectSucceeded(const std::string& service_path) {
- VLOG(1) << "Connect Succeeded for " << service_path;
+ NET_LOG_USER("Connect Succeeded", service_path);
ash::Shell::GetInstance()->system_tray_notifier()->NotifyClearNetworkMessage(
NetworkObserver::ERROR_CONNECT_FAILED);
}
+// If |check_error_state| is true, error state for the network is checked,
+// otherwise any current error state is ignored (e.g. for recently configured
+// networks or repeat connect attempts). |owning_window| will be used to parent
+// any configuration UI on failure and may be NULL (in which case the default
+// window will be used).
+void CallConnectToNetwork(const std::string& service_path,
+ bool check_error_state,
+ gfx::NativeWindow owning_window) {
+ NET_LOG_USER("ConnectToNetwork", service_path);
+
+ ash::Shell::GetInstance()->system_tray_notifier()->NotifyClearNetworkMessage(
+ NetworkObserver::ERROR_CONNECT_FAILED);
+
+ NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
+ service_path,
+ base::Bind(&OnConnectSucceeded, service_path),
+ base::Bind(&OnConnectFailed, service_path, owning_window),
+ check_error_state);
+}
+
+void OnActivateFailed(const std::string& service_path,
+ const std::string& error_name,
+ scoped_ptr<base::DictionaryValue> error_data) {
+ NET_LOG_ERROR("Unable to activate network", service_path);
+ ShowErrorNotification(
+ NetworkConnectionHandler::kErrorActivateFailed, service_path);
+}
+
+void OnActivateSucceeded(const std::string& service_path) {
+ NET_LOG_USER("Activation Succeeded", service_path);
+}
+
+void OnConfigureFailed(const std::string& error_name,
+ scoped_ptr<base::DictionaryValue> error_data) {
+ NET_LOG_ERROR("Unable to configure network", "");
+ ShowErrorNotification(NetworkConnectionHandler::kErrorConfigureFailed, "");
+}
+
+void OnConfigureSucceeded(const std::string& service_path) {
+ NET_LOG_USER("Configure Succeeded", service_path);
+ // After configuring a network, ignore any (possibly stale) error state.
+ const bool check_error_state = false;
+ const gfx::NativeWindow owning_window = NULL;
+ CallConnectToNetwork(service_path, check_error_state, owning_window);
+}
+
+void SetPropertiesFailed(const std::string& desc,
+ const std::string& service_path,
+ const std::string& config_error_name,
+ scoped_ptr<base::DictionaryValue> error_data) {
+ NET_LOG_ERROR(desc + ": Failed: " + config_error_name, service_path);
+ ShowErrorNotification(
+ NetworkConnectionHandler::kErrorConfigureFailed, service_path);
+}
+
+void SetPropertiesToClear(base::DictionaryValue* properties_to_set,
+ std::vector<std::string>* properties_to_clear) {
+ // Move empty string properties to properties_to_clear.
+ for (base::DictionaryValue::Iterator iter(*properties_to_set);
+ !iter.IsAtEnd(); iter.Advance()) {
+ std::string value_str;
+ if (iter.value().GetAsString(&value_str) && value_str.empty())
+ properties_to_clear->push_back(iter.key());
+ }
+ // Remove cleared properties from properties_to_set.
+ for (std::vector<std::string>::iterator iter = properties_to_clear->begin();
+ iter != properties_to_clear->end(); ++iter) {
+ properties_to_set->RemoveWithoutPathExpansion(*iter, NULL);
+ }
+}
+
+void ClearPropertiesAndConnect(
+ const std::string& service_path,
+ const std::vector<std::string>& properties_to_clear) {
+ NET_LOG_USER("ClearPropertiesAndConnect", service_path);
+ // After configuring a network, ignore any (possibly stale) error state.
+ const bool check_error_state = false;
+ const gfx::NativeWindow owning_window = NULL;
+ NetworkHandler::Get()->network_configuration_handler()->ClearProperties(
+ service_path,
+ properties_to_clear,
+ base::Bind(&CallConnectToNetwork,
+ service_path, check_error_state,
+ owning_window),
+ base::Bind(&SetPropertiesFailed, "ClearProperties", service_path));
+}
+
+// Returns false if !shared and no valid profile is available, which will
+// trigger an error and abort.
+bool GetNetworkProfilePath(bool shared, std::string* profile_path) {
+ if (shared) {
+ *profile_path = NetworkProfileHandler::kSharedProfilePath;
+ return true;
+ }
+
+ if (!chromeos::LoginState::Get()->IsUserAuthenticated()) {
+ NET_LOG_ERROR("User profile specified before login", "");
+ return false;
+ }
+
+ const NetworkProfile* profile =
+ NetworkHandler::Get()->network_profile_handler()->
+ GetDefaultUserProfile();
+ if (!profile) {
+ NET_LOG_ERROR("No user profile for unshared network configuration", "");
+ return false;
+ }
+
+ *profile_path = profile->path;
+ return true;
+}
+
+void ConfigureSetProfileSucceeded(
+ const std::string& service_path,
+ scoped_ptr<base::DictionaryValue> properties_to_set) {
+ std::vector<std::string> properties_to_clear;
+ SetPropertiesToClear(properties_to_set.get(), &properties_to_clear);
+ NetworkHandler::Get()->network_configuration_handler()->SetProperties(
+ service_path,
+ *properties_to_set,
+ base::Bind(&ClearPropertiesAndConnect,
+ service_path,
+ properties_to_clear),
+ base::Bind(&SetPropertiesFailed, "SetProperties", service_path));
+}
+
} // namespace
namespace network_connect {
-void ConnectToNetwork(const std::string& service_path) {
- const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
- GetNetworkState(service_path);
- if (!network)
+void ConnectToNetwork(const std::string& service_path,
+ gfx::NativeWindow owning_window) {
+ const bool check_error_state = true;
+ CallConnectToNetwork(service_path, check_error_state, owning_window);
+}
+
+void ActivateCellular(const std::string& service_path) {
+ NET_LOG_USER("ActivateCellular", service_path);
+ const DeviceState* cellular_device =
+ NetworkHandler::Get()->network_state_handler()->
+ GetDeviceStateByType(flimflam::kTypeCellular);
+ if (!cellular_device) {
+ NET_LOG_ERROR("ActivateCellular with no Device", service_path);
return;
- ash::Shell::GetInstance()->system_tray_notifier()->NotifyClearNetworkMessage(
- NetworkObserver::ERROR_CONNECT_FAILED);
- NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
+ }
+ if (!IsDirectActivatedCarrier(cellular_device->carrier())) {
+ // For non direct activation, show the mobile setup dialog which can be
+ // used to activate the network.
+ ash::Shell::GetInstance()->system_tray_delegate()->ShowMobileSetup(
+ service_path);
+ return;
+ }
+ const NetworkState* cellular =
+ NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path);
+ if (!cellular || cellular->type() != flimflam::kTypeCellular) {
+ NET_LOG_ERROR("ActivateCellular with no Service", service_path);
+ return;
+ }
+ if (cellular->activation_state() == flimflam::kActivationStateActivated) {
+ NET_LOG_ERROR("ActivateCellular for activated service", service_path);
+ return;
+ }
+
+ NetworkHandler::Get()->network_connection_handler()->ActivateNetwork(
service_path,
- base::Bind(&OnConnectSucceeded, service_path),
- base::Bind(&OnConnectFailed, service_path),
- true /* check_error_state */);
+ "", // carrier
+ base::Bind(&OnActivateSucceeded, service_path),
+ base::Bind(&OnActivateFailed, service_path));
+}
+
+void ConfigureNetworkAndConnect(const std::string& service_path,
+ const base::DictionaryValue& properties,
+ bool shared) {
+ NET_LOG_USER("ConfigureNetworkAndConnect", service_path);
+
+ scoped_ptr<base::DictionaryValue> properties_to_set(properties.DeepCopy());
+
+ std::string profile_path;
+ if (!GetNetworkProfilePath(shared, &profile_path)) {
+ ShowErrorNotification(
+ NetworkConnectionHandler::kErrorConfigureFailed, service_path);
+ return;
+ }
+ NetworkHandler::Get()->network_configuration_handler()->SetNetworkProfile(
+ service_path, profile_path,
+ base::Bind(&ConfigureSetProfileSucceeded,
+ service_path, base::Passed(&properties_to_set)),
+ base::Bind(&SetPropertiesFailed,
+ "SetProfile: " + profile_path, service_path));
+}
+
+void CreateConfigurationAndConnect(base::DictionaryValue* properties,
+ bool shared) {
+ NET_LOG_USER("CreateConfigurationAndConnect", "");
+ std::string profile_path;
+ if (!GetNetworkProfilePath(shared, &profile_path)) {
+ ShowErrorNotification(NetworkConnectionHandler::kErrorConfigureFailed, "");
+ return;
+ }
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kProfileProperty, profile_path);
+ NetworkHandler::Get()->network_configuration_handler()->CreateConfiguration(
+ *properties,
+ base::Bind(&OnConfigureSucceeded),
+ base::Bind(&OnConfigureFailed));
}
string16 ErrorString(const std::string& error) {
diff --git a/ash/system/chromeos/network/network_connect.h b/ash/system/chromeos/network/network_connect.h
index 3966140..65c430d 100644
--- a/ash/system/chromeos/network/network_connect.h
+++ b/ash/system/chromeos/network/network_connect.h
@@ -9,12 +9,35 @@
#include "ash/ash_export.h"
#include "base/strings/string16.h"
+#include "ui/gfx/native_widget_types.h" // gfx::NativeWindow
+
+namespace base {
+class DictionaryValue;
+}
namespace ash {
namespace network_connect {
-// Request a network connection and handle any errors and notifications.
-ASH_EXPORT void ConnectToNetwork(const std::string& service_path);
+// Requests a network connection and handles any errors and notifications.
+// |owning_window| is used to parent any UI on failure (e.g. for certificate
+// enrollment). If NULL, the default window will be used.
+ASH_EXPORT void ConnectToNetwork(const std::string& service_path,
+ gfx::NativeWindow owning_window);
+
+// Requests network activation and handles any errors and notifications.
+ASH_EXPORT void ActivateCellular(const std::string& service_path);
+
+// Configures a network with a dictionary of Shill properties, then sends a
+// connect request. The profile is set according to 'shared' if allowed.
+ASH_EXPORT void ConfigureNetworkAndConnect(
+ const std::string& service_path,
+ const base::DictionaryValue& properties,
+ bool shared);
+
+// Requests a new network configuration to be created from a dictionary of
+// Shill properties. The profile used is determined by |shared|.
+ASH_EXPORT void CreateConfigurationAndConnect(base::DictionaryValue* properties,
+ bool shared);
// Returns the localized string for shill error string |error|.
ASH_EXPORT base::string16 ErrorString(const std::string& error);
diff --git a/ash/system/chromeos/network/network_icon.cc b/ash/system/chromeos/network/network_icon.cc
index e931035..efe7e07 100644
--- a/ash/system/chromeos/network/network_icon.cc
+++ b/ash/system/chromeos/network/network_icon.cc
@@ -411,8 +411,8 @@
const std::string& technology = network->network_technology();
if (technology == flimflam::kNetworkTechnologyEvdo) {
id = IconTypeIsDark(icon_type) ?
- IDR_AURA_UBER_TRAY_NETWORK_3G_DARK :
- IDR_AURA_UBER_TRAY_NETWORK_3G_LIGHT;
+ IDR_AURA_UBER_TRAY_NETWORK_EVDO_DARK :
+ IDR_AURA_UBER_TRAY_NETWORK_EVDO_LIGHT;
} else if (technology == flimflam::kNetworkTechnology1Xrtt) {
id = IDR_AURA_UBER_TRAY_NETWORK_1X;
} else if (technology == flimflam::kNetworkTechnologyGprs) {
@@ -783,7 +783,6 @@
// network.
if (connecting_network &&
(!connected_network ||
- state_handler->connecting_network() == connecting_network->path() ||
connect_handler->HasConnectingNetwork(connecting_network->path()))) {
network = connecting_network;
} else {
diff --git a/ash/system/chromeos/network/network_state_list_detailed_view.cc b/ash/system/chromeos/network/network_state_list_detailed_view.cc
index abc888a..64e6d3b 100644
--- a/ash/system/chromeos/network/network_state_list_detailed_view.cc
+++ b/ash/system/chromeos/network/network_state_list_detailed_view.cc
@@ -315,12 +315,8 @@
if (!network || network->IsConnectedState() || network->IsConnectingState()) {
Shell::GetInstance()->system_tray_delegate()->ShowNetworkSettings(
service_path);
- } else if (CommandLine::ForCurrentProcess()->HasSwitch(
- chromeos::switches::kUseNewNetworkConnectionHandler)) {
- ash::network_connect::ConnectToNetwork(service_path);
} else {
- Shell::GetInstance()->system_tray_delegate()->ConnectToNetwork(
- service_path);
+ ash::network_connect::ConnectToNetwork(service_path, NULL);
}
}
diff --git a/ash/system/chromeos/network/network_state_notifier.cc b/ash/system/chromeos/network/network_state_notifier.cc
index a903505..1c971a3 100644
--- a/ash/system/chromeos/network/network_state_notifier.cc
+++ b/ash/system/chromeos/network/network_state_notifier.cc
@@ -32,6 +32,12 @@
string16 GetConnectErrorString(const std::string& error_name) {
if (error_name == NetworkConnectionHandler::kErrorNotFound)
return l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_CONNECT_FAILED);
+ if (error_name == NetworkConnectionHandler::kErrorConfigureFailed)
+ return l10n_util::GetStringUTF16(
+ IDS_CHROMEOS_NETWORK_ERROR_CONFIGURE_FAILED);
+ if (error_name == NetworkConnectionHandler::kErrorActivateFailed)
+ return l10n_util::GetStringUTF16(
+ IDS_CHROMEOS_NETWORK_ERROR_ACTIVATION_FAILED);
return string16();
}
@@ -41,17 +47,31 @@
NetworkStateNotifier::NetworkStateNotifier()
: cellular_out_of_credits_(false) {
- if (NetworkHandler::IsInitialized()) {
- NetworkHandler::Get()->network_state_handler()->AddObserver(
- this, FROM_HERE);
- InitializeNetworks();
- }
+ if (!NetworkHandler::IsInitialized())
+ return;
+ NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);
+
+ // Initialize |last_active_network_|.
+ const NetworkState* default_network =
+ NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
+ if (default_network && default_network->IsConnectedState())
+ last_active_network_ = default_network->path();
}
NetworkStateNotifier::~NetworkStateNotifier() {
- if (NetworkHandler::IsInitialized()) {
- NetworkHandler::Get()->network_state_handler()->RemoveObserver(
- this, FROM_HERE);
+ if (!NetworkHandler::IsInitialized())
+ return;
+ NetworkHandler::Get()->network_state_handler()->RemoveObserver(
+ this, FROM_HERE);
+}
+
+void NetworkStateNotifier::NetworkListChanged() {
+ // Trigger any pending connect failed error if the network list changes
+ // (which indicates all NetworkState entries are up to date). This is in
+ // case a connect attempt fails because a network is no longer visible.
+ if (!connect_failed_network_.empty()) {
+ ShowNetworkConnectError(
+ NetworkConnectionHandler::kErrorConnectFailed, connect_failed_network_);
}
}
@@ -65,40 +85,15 @@
}
}
-void NetworkStateNotifier::NetworkConnectionStateChanged(
- const NetworkState* network) {
- NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
- std::string prev_state;
- std::string new_state = network->connection_state();
- CachedStateMap::iterator iter = cached_state_.find(network->path());
- if (iter != cached_state_.end()) {
- prev_state = iter->second;
- if (prev_state == new_state)
- return; // No state change
- VLOG(1) << "NetworkStateNotifier: State: " << prev_state
- << " ->: " << new_state;
- iter->second = new_state;
- } else {
- VLOG(1) << "NetworkStateNotifier: New Service: " << network->path()
- << " State: " << new_state;
- cached_state_[network->path()] = new_state;
- return; // New network, no state change
- }
-
- if (new_state != flimflam::kStateFailure)
- return;
-
- if (network->path() != handler->connecting_network())
- return; // Only show notifications for explicitly connected networks
-
- NET_LOG_EVENT("ConnectionFailure", network->path());
-
- ShowConnectError("", network);
-}
-
void NetworkStateNotifier::NetworkPropertiesUpdated(
const NetworkState* network) {
DCHECK(network);
+ // Trigger a pending connect failed error for |network| when the Error
+ // property has been set.
+ if (network->path() == connect_failed_network_ && !network->error().empty()) {
+ ShowNetworkConnectError(
+ NetworkConnectionHandler::kErrorConnectFailed, connect_failed_network_);
+ }
// Trigger "Out of credits" notification if the cellular network is the most
// recent default network (i.e. we have not switched to another network).
if (network->type() == flimflam::kTypeCellular &&
@@ -146,17 +141,24 @@
const std::string& service_path) {
const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
GetNetworkState(service_path);
- ShowConnectError(error_name, network);
-}
+ if (error_name == NetworkConnectionHandler::kErrorConnectFailed &&
+ service_path != connect_failed_network_) {
+ // Shill may not have set the Error property yet. First request an update
+ // and wait for either the update to complete or the network list to be
+ // updated before displaying the error.
+ connect_failed_network_ = service_path;
+ return;
+ }
+ connect_failed_network_.clear();
-void NetworkStateNotifier::ShowConnectError(const std::string& error_name,
- const NetworkState* network) {
- std::vector<string16> no_links;
string16 error = GetConnectErrorString(error_name);
if (error.empty() && network)
error = network_connect::ErrorString(network->error());
if (error.empty())
error = l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN);
+ NET_LOG_ERROR("Connect error notification: " + UTF16ToUTF8(error),
+ service_path);
+
std::string name = network ? network->name() : "";
string16 error_msg;
if (network && !network->error_details().empty()) {
@@ -168,6 +170,8 @@
IDS_NETWORK_CONNECTION_ERROR_MESSAGE_WITH_DETAILS,
UTF8ToUTF16(name), error);
}
+
+ std::vector<string16> no_links;
ash::Shell::GetInstance()->system_tray_notifier()->NotifySetNetworkMessage(
this,
NetworkObserver::ERROR_CONNECT_FAILED,
@@ -177,21 +181,4 @@
no_links);
}
-void NetworkStateNotifier::InitializeNetworks() {
- NetworkStateHandler::NetworkStateList network_list;
- NetworkHandler::Get()->network_state_handler()->GetNetworkList(&network_list);
- VLOG(1) << "NetworkStateNotifier:InitializeNetworks: "
- << network_list.size();
- for (NetworkStateHandler::NetworkStateList::iterator iter =
- network_list.begin(); iter != network_list.end(); ++iter) {
- const NetworkState* network = *iter;
- VLOG(2) << " Network: " << network->path();
- cached_state_[network->path()] = network->connection_state();
- }
- const NetworkState* default_network =
- NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
- if (default_network && default_network->IsConnectedState())
- last_active_network_ = default_network->path();
-}
-
} // namespace ash
diff --git a/ash/system/chromeos/network/network_state_notifier.h b/ash/system/chromeos/network/network_state_notifier.h
index cfcc4b7..30a41b3 100644
--- a/ash/system/chromeos/network/network_state_notifier.h
+++ b/ash/system/chromeos/network/network_state_notifier.h
@@ -20,12 +20,19 @@
namespace ash {
-// This class observes NetworkStateHandler and generates notifications
-// on connection failures. NOTE: The Observer for this class only triggers
-// "Out of credits" notifications, and failures triggered from NetworkLibrary
-// calls (which sets NetworkStateHandler::connecting_network()).
-// Failures from NetworkStateListDetailedView::ConnectToNetwork are now
-// handled by the ConnectToNetwork callbacks.
+// This class has two purposes:
+// 1. ShowNetworkConnectError() gets called after any user initiated connect
+// failure. This will handle displaying an error notification.
+// NOTE: Because Shill sets the Error property of a Service *after*
+// the Connect call fails, this class will delay the notification if
+// necessary until the Error property is set so that the correct
+// message can be displayed.
+// TODO(stevenjb): convert this class to use the new MessageCenter
+// notification system, generate a notification immediately, and update
+// it when the Error property is set to guarantee that a notification is
+// displayed for every failure.
+// 2. It observes NetworkState changes to generate notifications when a
+// Cellular network is out of credits.
class ASH_EXPORT NetworkStateNotifier :
public chromeos::NetworkStateHandlerObserver,
public NetworkTrayDelegate {
@@ -34,10 +41,9 @@
virtual ~NetworkStateNotifier();
// NetworkStateHandlerObserver
+ virtual void NetworkListChanged() OVERRIDE;
virtual void DefaultNetworkChanged(
const chromeos::NetworkState* network) OVERRIDE;
- virtual void NetworkConnectionStateChanged(
- const chromeos::NetworkState* network) OVERRIDE;
virtual void NetworkPropertiesUpdated(
const chromeos::NetworkState* network) OVERRIDE;
@@ -53,14 +59,9 @@
private:
typedef std::map<std::string, std::string> CachedStateMap;
- void ShowConnectError(const std::string& error_name,
- const chromeos::NetworkState* network);
-
- void InitializeNetworks();
-
- CachedStateMap cached_state_;
std::string last_active_network_;
std::string cellular_network_;
+ std::string connect_failed_network_;
bool cellular_out_of_credits_;
base::Time out_of_credits_notify_time_;
diff --git a/ash/system/chromeos/network/network_state_notifier_unittest.cc b/ash/system/chromeos/network/network_state_notifier_unittest.cc
index 2f681bc..6e2069d 100644
--- a/ash/system/chromeos/network/network_state_notifier_unittest.cc
+++ b/ash/system/chromeos/network/network_state_notifier_unittest.cc
@@ -7,13 +7,14 @@
#include "ash/root_window_controller.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
+#include "ash/system/chromeos/network/network_connect.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/tray/system_tray.h"
#include "ash/test/ash_test_base.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_device_client.h"
#include "chromeos/dbus/shill_service_client.h"
-#include "chromeos/network/network_state_handler.h"
+#include "chromeos/network/network_connection_handler.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace {
@@ -27,7 +28,7 @@
using chromeos::DBusThreadManager;
using chromeos::NetworkHandler;
-using chromeos::NetworkStateHandler;
+using chromeos::NetworkConnectionHandler;
using chromeos::ShillDeviceClient;
using chromeos::ShillServiceClient;
@@ -71,17 +72,17 @@
const bool add_to_visible = true;
// Create wifi and cellular networks and set to online.
service_test->AddService("wifi1", "wifi1",
- flimflam::kTypeWifi, flimflam::kStateOnline,
+ flimflam::kTypeWifi, flimflam::kStateIdle,
add_to_visible, add_to_watchlist);
- RunAllPendingInMessageLoop();
- }
-
- void SetServiceState(const std::string& service_path,
- const std::string& state) {
- ShillServiceClient::TestInterface* service_test =
- DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
- service_test->SetServiceProperty(service_path, flimflam::kStateProperty,
- base::StringValue(state));
+ service_test->SetServiceProperty("wifi1",
+ flimflam::kSecurityProperty,
+ base::StringValue(flimflam::kSecurityWep));
+ service_test->SetServiceProperty("wifi1",
+ flimflam::kConnectableProperty,
+ base::FundamentalValue(true));
+ service_test->SetServiceProperty("wifi1",
+ flimflam::kPassphraseProperty,
+ base::StringValue("failure"));
RunAllPendingInMessageLoop();
}
@@ -91,20 +92,10 @@
TEST_F(NetworkStateNotifierTest, ConnectionFailure) {
EXPECT_FALSE(GetSystemTray()->HasNotificationBubble());
- // State -> Failure for non connecting network should not spawn a notification
- SetServiceState("wifi1", flimflam::kStateFailure);
- EXPECT_FALSE(GetSystemTray()->CloseNotificationBubbleForTest());
- // State -> Failure for connecting network should spawn a notification
- SetServiceState("wifi1", flimflam::kStateAssociation);
- NetworkHandler::Get()->network_state_handler()->SetConnectingNetwork("wifi1");
- SetServiceState("wifi1", flimflam::kStateFailure);
+ ash::network_connect::ConnectToNetwork("wifi1", NULL /* owning_window */);
+ RunAllPendingInMessageLoop();
+ // Failure should spawn a notification.
EXPECT_TRUE(GetSystemTray()->CloseNotificationBubbleForTest());
- // Failure -> Idle should not spawn a notification
- SetServiceState("wifi1", flimflam::kStateIdle);
- EXPECT_FALSE(GetSystemTray()->HasNotificationBubble());
- // Idle -> Failure should also not spawn a notification
- SetServiceState("wifi1", flimflam::kStateFailure);
- EXPECT_FALSE(GetSystemTray()->HasNotificationBubble());
}
} // namespace test
diff --git a/ash/system/chromeos/tray_display.cc b/ash/system/chromeos/tray_display.cc
index 4f4e8c1..ebafa37 100644
--- a/ash/system/chromeos/tray_display.cc
+++ b/ash/system/chromeos/tray_display.cc
@@ -195,7 +195,7 @@
message_center::NOTIFICATION_TYPE_SIMPLE,
kDisplayNotificationId,
message,
- GetAllDisplayInfo(),
+ base::string16(), // body is intentionally empty, see crbug.com/265915
bundle.GetImageNamed(IDR_AURA_UBER_TRAY_DISPLAY),
base::string16(), // display_source
"", // extension_id
@@ -367,8 +367,25 @@
return true;
}
if (iter->second.rotation() != old_iter->second.rotation()) {
+ int rotation_text_id = 0;
+ switch (iter->second.rotation()) {
+ case gfx::Display::ROTATE_0:
+ rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_STANDARD_ORIENTATION;
+ break;
+ case gfx::Display::ROTATE_90:
+ rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90;
+ break;
+ case gfx::Display::ROTATE_180:
+ rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_180;
+ break;
+ case gfx::Display::ROTATE_270:
+ rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_270;
+ break;
+ }
*message = l10n_util::GetStringFUTF16(
- IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetDisplayName(iter->first));
+ IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED,
+ GetDisplayName(iter->first),
+ l10n_util::GetStringUTF16(rotation_text_id));
return true;
}
}
diff --git a/ash/system/chromeos/tray_display_unittest.cc b/ash/system/chromeos/tray_display_unittest.cc
index 8fa2949..1c5970d 100644
--- a/ash/system/chromeos/tray_display_unittest.cc
+++ b/ash/system/chromeos/tray_display_unittest.cc
@@ -326,13 +326,21 @@
// rotation.
UpdateDisplay("400x400/r");
- base::string16 rotation_message = l10n_util::GetStringFUTF16(
- IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetFirstDisplayName());
- EXPECT_EQ(rotation_message, GetDisplayNotificationText());
+ EXPECT_EQ(
+ l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetFirstDisplayName(),
+ l10n_util::GetStringUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90)),
+ GetDisplayNotificationText());
CloseNotification();
UpdateDisplay("400x400");
- EXPECT_EQ(rotation_message, GetDisplayNotificationText());
+ EXPECT_EQ(
+ l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetFirstDisplayName(),
+ l10n_util::GetStringUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_STANDARD_ORIENTATION)),
+ GetDisplayNotificationText());
// UI-scale
CloseNotification();
@@ -395,7 +403,10 @@
UpdateDisplay("400x400@1.5,200x200/r");
EXPECT_EQ(
l10n_util::GetStringFUTF16(
- IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetSecondDisplayName()),
+ IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED,
+ GetSecondDisplayName(),
+ l10n_util::GetStringUTF16(
+ IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90)),
GetDisplayNotificationText());
}
diff --git a/ash/system/chromeos/tray_tracing.cc b/ash/system/chromeos/tray_tracing.cc
new file mode 100644
index 0000000..b6a8cf1
--- /dev/null
+++ b/ash/system/chromeos/tray_tracing.cc
@@ -0,0 +1,112 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/system/chromeos/tray_tracing.h"
+
+#include "ash/system/tray/actionable_view.h"
+#include "ash/system/tray/fixed_sized_image_view.h"
+#include "ash/system/tray/system_tray.h"
+#include "ash/system/tray/system_tray_delegate.h"
+#include "ash/system/tray/system_tray_notifier.h"
+#include "ash/system/tray/tray_constants.h"
+#include "grit/ash_resources.h"
+#include "grit/ash_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/image/image.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/box_layout.h"
+
+namespace ash {
+namespace internal {
+
+namespace tray {
+
+class DefaultTracingView : public ash::internal::ActionableView {
+ public:
+ DefaultTracingView() {
+ SetLayoutManager(new views::BoxLayout(
+ views::BoxLayout::kHorizontal,
+ ash::kTrayPopupPaddingHorizontal, 0,
+ ash::kTrayPopupPaddingBetweenItems));
+
+ ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+ image_ =
+ new ash::internal::FixedSizedImageView(0, ash::kTrayPopupItemHeight);
+ image_->SetImage(
+ bundle.GetImageNamed(IDR_AURA_UBER_TRAY_TRACING).ToImageSkia());
+ AddChildView(image_);
+
+ label_ = new views::Label();
+ label_->SetMultiLine(true);
+ label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ label_->SetText(bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_TRACING));
+ AddChildView(label_);
+ }
+
+ virtual ~DefaultTracingView() {}
+
+ private:
+ // Overridden from ActionableView.
+ virtual bool PerformAction(const ui::Event& event) OVERRIDE {
+ ash::Shell::GetInstance()->system_tray_delegate()->ShowChromeSlow();
+ return true;
+ }
+
+ views::ImageView* image_;
+ views::Label* label_;
+
+ DISALLOW_COPY_AND_ASSIGN(DefaultTracingView);
+};
+
+} // namespace tray
+
+////////////////////////////////////////////////////////////////////////////////
+// ash::internal::TrayTracing
+
+TrayTracing::TrayTracing(SystemTray* system_tray)
+ : TrayImageItem(system_tray, IDR_AURA_UBER_TRAY_TRACING),
+ default_(NULL) {
+ DCHECK(Shell::GetInstance()->delegate());
+ DCHECK(system_tray);
+ Shell::GetInstance()->system_tray_notifier()->AddTracingObserver(this);
+}
+
+TrayTracing::~TrayTracing() {
+ Shell::GetInstance()->system_tray_notifier()->RemoveTracingObserver(this);
+}
+
+void TrayTracing::SetTrayIconVisible(bool visible) {
+ if (tray_view())
+ tray_view()->SetVisible(visible);
+}
+
+bool TrayTracing::GetInitialVisibility() {
+ return false;
+}
+
+views::View* TrayTracing::CreateDefaultView(user::LoginStatus status) {
+ CHECK(default_ == NULL);
+ default_ = new tray::DefaultTracingView();
+ return default_;
+}
+
+views::View* TrayTracing::CreateDetailedView(user::LoginStatus status) {
+ return NULL;
+}
+
+void TrayTracing::DestroyDefaultView() {
+ default_ = NULL;
+}
+
+void TrayTracing::DestroyDetailedView() {
+}
+
+void TrayTracing::OnTracingModeChanged(bool value) {
+ SetTrayIconVisible(value);
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/system/chromeos/tray_tracing.h b/ash/system/chromeos/tray_tracing.h
new file mode 100644
index 0000000..f9491e1
--- /dev/null
+++ b/ash/system/chromeos/tray_tracing.h
@@ -0,0 +1,57 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_SYSTEM_TRAY_TRACING_H_
+#define ASH_SYSTEM_TRAY_TRACING_H_
+
+#include "ash/ash_export.h"
+#include "ash/system/tray/tray_image_item.h"
+
+namespace views {
+class View;
+}
+
+namespace ash {
+
+class ASH_EXPORT TracingObserver {
+ public:
+ virtual ~TracingObserver() {}
+
+ // Notifies when tracing mode changes.
+ virtual void OnTracingModeChanged(bool value) = 0;
+};
+
+namespace internal {
+
+// This is the item that displays when users enable performance tracing at
+// chrome://slow. It alerts them that this mode is running, and provides an
+// easy way to open the page to disable it.
+class TrayTracing : public TrayImageItem,
+ public TracingObserver {
+ public:
+ explicit TrayTracing(SystemTray* system_tray);
+ virtual ~TrayTracing();
+
+ private:
+ void SetTrayIconVisible(bool visible);
+
+ // Overridden from TrayImageItem.
+ virtual bool GetInitialVisibility() OVERRIDE;
+ virtual views::View* CreateDefaultView(user::LoginStatus status) OVERRIDE;
+ virtual views::View* CreateDetailedView(user::LoginStatus status) OVERRIDE;
+ virtual void DestroyDefaultView() OVERRIDE;
+ virtual void DestroyDetailedView() OVERRIDE;
+
+ // Overridden from TracingObserver.
+ virtual void OnTracingModeChanged(bool value) OVERRIDE;
+
+ views::View* default_;
+
+ DISALLOW_COPY_AND_ASSIGN(TrayTracing);
+};
+
+} // namespace internal
+} // namespace ash
+
+#endif // ASH_SYSTEM_TRAY_TRACING_H_
diff --git a/ash/system/locale/locale_notification_controller.cc b/ash/system/locale/locale_notification_controller.cc
index bc515e9..342c5a6 100644
--- a/ash/system/locale/locale_notification_controller.cc
+++ b/ash/system/locale/locale_notification_controller.cc
@@ -63,10 +63,11 @@
}
bool LocaleNotificationDelegate::HasClickedListener() {
- return false;
+ return true;
}
void LocaleNotificationDelegate::Click() {
+ delegate_->AcceptLocaleChange();
}
void LocaleNotificationDelegate::ButtonClick(int button_index) {
diff --git a/ash/system/status_area_widget_delegate.cc b/ash/system/status_area_widget_delegate.cc
index 77d3cbf..7e15b7e 100644
--- a/ash/system/status_area_widget_delegate.cc
+++ b/ash/system/status_area_widget_delegate.cc
@@ -5,6 +5,7 @@
#include "ash/system/status_area_widget_delegate.h"
#include "ash/ash_export.h"
+#include "ash/ash_switches.h"
#include "ash/focus_cycler.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
@@ -98,7 +99,7 @@
if (!child->visible())
continue;
if (!is_first_visible_child)
- columns->AddPaddingColumn(0, kTraySpacing);
+ columns->AddPaddingColumn(0, GetTraySpacing());
is_first_visible_child = false;
columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::FILL,
0, /* resize percent */
@@ -124,7 +125,7 @@
if (!child->visible())
continue;
if (!is_first_visible_child)
- layout->AddPaddingRow(0, kTraySpacing);
+ layout->AddPaddingRow(0, GetTraySpacing());
is_first_visible_child = false;
layout->StartRow(0, 0);
layout->AddView(child);
diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc
index c93efc9..122253f 100644
--- a/ash/system/tray/system_tray.cc
+++ b/ash/system/tray/system_tray.cc
@@ -11,6 +11,7 @@
#include "ash/shell_window_ids.h"
#include "ash/system/bluetooth/tray_bluetooth.h"
#include "ash/system/brightness/tray_brightness.h"
+#include "ash/system/chromeos/tray_tracing.h"
#include "ash/system/date/tray_date.h"
#include "ash/system/drive/tray_drive.h"
#include "ash/system/ime/tray_ime.h"
@@ -167,6 +168,7 @@
tray_accessibility_ = new internal::TrayAccessibility(this);
AddTrayItem(tray_accessibility_);
#if defined(OS_CHROMEOS)
+ AddTrayItem(new internal::TrayTracing(this));
AddTrayItem(
new internal::TrayPower(this, message_center::MessageCenter::Get()));
#endif
diff --git a/ash/system/tray/system_tray_delegate.h b/ash/system/tray/system_tray_delegate.h
index 45b0c71..0dcc07d 100644
--- a/ash/system/tray/system_tray_delegate.h
+++ b/ash/system/tray/system_tray_delegate.h
@@ -15,6 +15,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/native_widget_types.h"
namespace base {
class TimeDelta;
@@ -136,10 +137,11 @@
// Returns notification for enterprise enrolled devices.
virtual const base::string16 GetEnterpriseMessage() const = 0;
- // Returns the email of user that manages current locally managed user.
+ // Returns the display email of user that manages current
+ // locally managed user.
virtual const std::string GetLocallyManagedUserManager() const = 0;
- // Returns the email of user that manages current locally managed user.
+ // Returns the name of user that manages current locally managed user.
virtual const base::string16 GetLocallyManagedUserManagerName() const = 0;
// Returns notification for locally managed users.
@@ -167,6 +169,9 @@
// Shows settings related to multiple displays.
virtual void ShowDisplaySettings() = 0;
+ // Shows the page that lets you disable performance tracing.
+ virtual void ShowChromeSlow() = 0;
+
// Returns true if the notification for the display configuration change
// should appear.
virtual bool ShouldShowDisplayNotification() = 0;
@@ -250,8 +255,11 @@
// Shows UI to configure or activate the network specified by |network_id|.
virtual void ConfigureNetwork(const std::string& network_id) = 0;
- // Sends a connect request for the network specified by |network_id|.
- virtual void ConnectToNetwork(const std::string& network_id) = 0;
+ // Shows UI to enroll the network specified by |network_id| if appropriate,
+ // otherwise behaves the same as ConfigureNetwork. |parent_window| is used
+ // to parent any configuration UI. If NULL a default window will be used.
+ virtual void EnrollOrConfigureNetwork(const std::string& network_id,
+ gfx::NativeWindow parent_window) = 0;
// Shows UI to manage bluetooth devices.
virtual void ManageBluetoothDevices() = 0;
@@ -262,6 +270,9 @@
// Shows UI to unlock a mobile sim.
virtual void ShowMobileSimDialog() = 0;
+ // Shows UI to setup a mobile network.
+ virtual void ShowMobileSetup(const std::string& network_id) = 0;
+
// Shows UI to connect to an unlisted wifi network.
virtual void ShowOtherWifi() = 0;
diff --git a/ash/system/tray/system_tray_notifier.cc b/ash/system/tray/system_tray_notifier.cc
index f726a8f..73f6195 100644
--- a/ash/system/tray/system_tray_notifier.cc
+++ b/ash/system/tray/system_tray_notifier.cc
@@ -106,6 +106,14 @@
session_length_limit_observers_.RemoveObserver(observer);
}
+void SystemTrayNotifier::AddTracingObserver(TracingObserver* observer) {
+ tracing_observers_.AddObserver(observer);
+}
+
+void SystemTrayNotifier::RemoveTracingObserver(TracingObserver* observer) {
+ tracing_observers_.RemoveObserver(observer);
+}
+
void SystemTrayNotifier::AddUpdateObserver(UpdateObserver* observer) {
update_observers_.AddObserver(observer);
}
@@ -179,6 +187,13 @@
OnAccessibilityModeChanged(notify));
}
+void SystemTrayNotifier::NotifyTracingModeChanged(bool value) {
+ FOR_EACH_OBSERVER(
+ TracingObserver,
+ tracing_observers_,
+ OnTracingModeChanged(value));
+}
+
void SystemTrayNotifier::NotifyRefreshBluetooth() {
FOR_EACH_OBSERVER(BluetoothObserver,
bluetooth_observers_,
diff --git a/ash/system/tray/system_tray_notifier.h b/ash/system/tray/system_tray_notifier.h
index 5546be0..86210b4 100644
--- a/ash/system/tray/system_tray_notifier.h
+++ b/ash/system/tray/system_tray_notifier.h
@@ -14,6 +14,7 @@
#include "ash/system/chromeos/enterprise/enterprise_domain_observer.h"
#include "ash/system/chromeos/network/network_observer.h"
#include "ash/system/chromeos/network/sms_observer.h"
+#include "ash/system/chromeos/tray_tracing.h"
#include "ash/system/date/clock_observer.h"
#include "ash/system/drive/drive_observer.h"
#include "ash/system/ime/ime_observer.h"
@@ -74,6 +75,9 @@
void AddSessionLengthLimitObserver(SessionLengthLimitObserver* observer);
void RemoveSessionLengthLimitObserver(SessionLengthLimitObserver* observer);
+ void AddTracingObserver(TracingObserver* observer);
+ void RemoveTracingObserver(TracingObserver* observer);
+
void AddUpdateObserver(UpdateObserver* observer);
void RemoveUpdateObserver(UpdateObserver* observer);
@@ -99,6 +103,7 @@
void NotifyAccessibilityModeChanged(
AccessibilityNotificationVisibility notify);
+ void NotifyTracingModeChanged(bool value);
void NotifyRefreshBluetooth();
void NotifyBluetoothDiscoveringChanged();
void NotifyBrightnessChanged(double level, bool user_initialted);
@@ -151,6 +156,7 @@
ObserverList<LocaleObserver> locale_observers_;
ObserverList<LogoutButtonObserver> logout_button_observers_;
ObserverList<SessionLengthLimitObserver> session_length_limit_observers_;
+ ObserverList<TracingObserver> tracing_observers_;
ObserverList<UpdateObserver> update_observers_;
ObserverList<UserObserver> user_observers_;
#if defined(OS_CHROMEOS)
diff --git a/ash/system/tray/test_system_tray_delegate.cc b/ash/system/tray/test_system_tray_delegate.cc
index 33d912a..c3a2bfc 100644
--- a/ash/system/tray/test_system_tray_delegate.cc
+++ b/ash/system/tray/test_system_tray_delegate.cc
@@ -127,6 +127,9 @@
void TestSystemTrayDelegate::ShowDisplaySettings() {
}
+void TestSystemTrayDelegate::ShowChromeSlow() {
+}
+
bool TestSystemTrayDelegate::ShouldShowDisplayNotification() {
return should_show_display_notification_;
}
@@ -212,7 +215,9 @@
void TestSystemTrayDelegate::ConfigureNetwork(const std::string& network_id) {
}
-void TestSystemTrayDelegate::ConnectToNetwork(const std::string& network_id) {
+void TestSystemTrayDelegate::EnrollOrConfigureNetwork(
+ const std::string& network_id,
+ gfx::NativeWindow parent_window) {
}
void TestSystemTrayDelegate::ManageBluetoothDevices() {
@@ -229,6 +234,9 @@
void TestSystemTrayDelegate::ShowMobileSimDialog() {
}
+void TestSystemTrayDelegate::ShowMobileSetup(const std::string& network_id) {
+}
+
void TestSystemTrayDelegate::ShowOtherWifi() {
}
diff --git a/ash/system/tray/test_system_tray_delegate.h b/ash/system/tray/test_system_tray_delegate.h
index 26a3dc7..4dc847d 100644
--- a/ash/system/tray/test_system_tray_delegate.h
+++ b/ash/system/tray/test_system_tray_delegate.h
@@ -42,6 +42,7 @@
virtual void ShowNetworkSettings(const std::string& service_path) OVERRIDE;
virtual void ShowBluetoothSettings() OVERRIDE;
virtual void ShowDisplaySettings() OVERRIDE;
+ virtual void ShowChromeSlow() OVERRIDE;
virtual bool ShouldShowDisplayNotification() OVERRIDE;
virtual void ShowDriveSettings() OVERRIDE;
virtual void ShowIMESettings() OVERRIDE;
@@ -69,11 +70,14 @@
virtual void GetDriveOperationStatusList(
ash::DriveOperationStatusList*) OVERRIDE;
virtual void ConfigureNetwork(const std::string& network_id) OVERRIDE;
- virtual void ConnectToNetwork(const std::string& network_id) OVERRIDE;
+ virtual void EnrollOrConfigureNetwork(
+ const std::string& network_id,
+ gfx::NativeWindow parent_window) OVERRIDE;
virtual void ManageBluetoothDevices() OVERRIDE;
virtual void ToggleBluetooth() OVERRIDE;
virtual bool IsBluetoothDiscovering() OVERRIDE;
virtual void ShowMobileSimDialog() OVERRIDE;
+ virtual void ShowMobileSetup(const std::string& network_id) OVERRIDE;
virtual void ShowOtherWifi() OVERRIDE;
virtual void ShowOtherVPN() OVERRIDE;
virtual void ShowOtherCellular() OVERRIDE;
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc
index 2d788d6..9f84322 100644
--- a/ash/system/tray/tray_background_view.cc
+++ b/ash/system/tray/tray_background_view.cc
@@ -288,8 +288,8 @@
set_border(views::Border::CreateEmptyBorder(
vertical_padding,
horizontal_padding,
- horizontal_padding,
- vertical_padding));
+ vertical_padding,
+ horizontal_padding));
views::BoxLayout* layout =
new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0);
@@ -530,11 +530,15 @@
}
} else if (anchor_type == TrayBubbleView::ANCHOR_TYPE_BUBBLE) {
// Invert the offsets to align with the bubble below.
+ // Note that with the alternate shelf layout the tips are not shown and
+ // the offsets for left and right alignment do not need to be applied.
+ int vertical_alignment = ash::switches::UseAlternateShelfLayout() ?
+ 0 : kPaddingFromInnerEdgeOfLauncherVerticalAlignment;
if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_LEFT) {
- rect.Inset(kPaddingFromInnerEdgeOfLauncherVerticalAlignment,
+ rect.Inset(vertical_alignment,
0, 0, kPaddingFromBottomOfScreenVerticalAlignment);
} else if (anchor_alignment == TrayBubbleView::ANCHOR_ALIGNMENT_RIGHT) {
- rect.Inset(0, 0, kPaddingFromInnerEdgeOfLauncherVerticalAlignment,
+ rect.Inset(0, 0, vertical_alignment,
kPaddingFromBottomOfScreenVerticalAlignment);
}
}
diff --git a/ash/system/tray/tray_constants.cc b/ash/system/tray/tray_constants.cc
index 45047e7..6d108c8 100644
--- a/ash/system/tray/tray_constants.cc
+++ b/ash/system/tray/tray_constants.cc
@@ -4,6 +4,7 @@
#include "ash/system/tray/tray_constants.h"
+#include "ash/ash_switches.h"
#include "third_party/skia/include/core/SkColor.h"
namespace ash {
@@ -65,5 +66,13 @@
(kNotificationIconWidth + kNotificationButtonWidth +
(kTrayPopupPaddingHorizontal / 2) * 3);
const int kTraySpacing = 8;
+const int kAlternateTraySpacing = 4;
+
+// Returns kTraySpacing or kAlternateTraySpacing as applicable
+// (Determined by ash::switches::UseAlternateShelfLayout).
+int GetTraySpacing() {
+ return ash::switches::UseAlternateShelfLayout() ?
+ kAlternateTraySpacing : kTraySpacing;
+}
} // namespace ash
diff --git a/ash/system/tray/tray_constants.h b/ash/system/tray/tray_constants.h
index 2b0f5ae..480d5d5 100644
--- a/ash/system/tray/tray_constants.h
+++ b/ash/system/tray/tray_constants.h
@@ -62,7 +62,9 @@
extern const int kNotificationButtonWidth;
extern const int kTrayNotificationContentsWidth;
-extern const int kTraySpacing;
+// Returns kTraySpacing or kAlternateTraySpacing as applicable
+// (Determined by ash::switches::UseAlternateShelfLayout).
+int GetTraySpacing();
} // namespace ash
diff --git a/ash/system/user/tray_user.cc b/ash/system/user/tray_user.cc
index e50aece..2ab24a8 100644
--- a/ash/system/user/tray_user.cc
+++ b/ash/system/user/tray_user.cc
@@ -1202,30 +1202,14 @@
bundle.GetLocalizedString(IDS_ASH_STATUS_TRAY_LOCALLY_MANAGED_LABEL));
}
- int icon_size = kUserIconSize;
if (avatar_ && ash::switches::UseAlternateShelfLayout()) {
- icon_size = kUserIconLargeSize;
avatar_->SetCornerRadii(0,
kUserIconLargeCornerRadius,
kUserIconLargeCornerRadius,
0);
avatar_->set_border(NULL);
}
- if (avatar_) {
- if (status == user::LOGGED_IN_GUEST) {
- int image_name = ash::switches::UseAlternateShelfLayout() ?
- IDR_AURA_UBER_TRAY_GUEST_ICON_LARGE :
- IDR_AURA_UBER_TRAY_GUEST_ICON;
- avatar_->SetImage(*ui::ResourceBundle::GetSharedInstance().
- GetImageNamed(image_name).ToImageSkia(),
- gfx::Size(icon_size, icon_size));
- } else {
- avatar_->SetImage(
- ash::Shell::GetInstance()->session_state_delegate()->GetUserImage(
- multiprofile_index_),
- gfx::Size(icon_size, icon_size));
- }
- }
+ UpdateAvatarImage(status);
}
void TrayUser::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
@@ -1281,10 +1265,25 @@
}
void TrayUser::OnUserUpdate() {
- // Check for null to avoid crbug.com/150944.
- if (avatar_) {
- int icon_size = ash::switches::UseAlternateShelfLayout() ?
- kUserIconLargeSize : kUserIconSize;
+ UpdateAvatarImage(Shell::GetInstance()->system_tray_delegate()->
+ GetUserLoginStatus());
+}
+
+void TrayUser::UpdateAvatarImage(user::LoginStatus status) {
+ if (!avatar_)
+ return;
+
+ int icon_size = ash::switches::UseAlternateShelfLayout() ?
+ kUserIconLargeSize : kUserIconSize;
+
+ if (status == user::LOGGED_IN_GUEST) {
+ int image_name = ash::switches::UseAlternateShelfLayout() ?
+ IDR_AURA_UBER_TRAY_GUEST_ICON_LARGE :
+ IDR_AURA_UBER_TRAY_GUEST_ICON;
+ avatar_->SetImage(*ui::ResourceBundle::GetSharedInstance().
+ GetImageNamed(image_name).ToImageSkia(),
+ gfx::Size(icon_size, icon_size));
+ } else {
avatar_->SetImage(
ash::Shell::GetInstance()->session_state_delegate()->GetUserImage(
multiprofile_index_),
diff --git a/ash/system/user/tray_user.h b/ash/system/user/tray_user.h
index fa10bf2..70b54bb 100644
--- a/ash/system/user/tray_user.h
+++ b/ash/system/user/tray_user.h
@@ -68,6 +68,8 @@
// Overridden from UserObserver.
virtual void OnUserUpdate() OVERRIDE;
+ void UpdateAvatarImage(user::LoginStatus status);
+
// The user index to use.
MultiProfileIndex multiprofile_index_;
diff --git a/ash/system/web_notification/web_notification_tray.cc b/ash/system/web_notification/web_notification_tray.cc
index 2b33e44..2a6e2de 100644
--- a/ash/system/web_notification/web_notification_tray.cc
+++ b/ash/system/web_notification/web_notification_tray.cc
@@ -330,7 +330,8 @@
NOTREACHED();
}
- message_center_bubble->SetMaxHeight(std::max(0, max_height - kTraySpacing));
+ message_center_bubble->SetMaxHeight(std::max(0,
+ max_height - GetTraySpacing()));
if (show_settings)
message_center_bubble->SetSettingsVisible();
message_center_bubble_.reset(
diff --git a/ash/test/launcher_view_test_api.cc b/ash/test/launcher_view_test_api.cc
index 13881b3..e357920 100644
--- a/ash/test/launcher_view_test_api.cc
+++ b/ash/test/launcher_view_test_api.cc
@@ -95,5 +95,10 @@
launcher_view_->bounds_animator_->RemoveObserver(observer.get());
}
+bool LauncherViewTestAPI::SameDragType(LauncherItemType typea,
+ LauncherItemType typeb) const {
+ return launcher_view_->SameDragType(typea, typeb);
+}
+
} // namespace test
} // namespace ash
diff --git a/ash/test/launcher_view_test_api.h b/ash/test/launcher_view_test_api.h
index 35cb444..0162f7f 100644
--- a/ash/test/launcher_view_test_api.h
+++ b/ash/test/launcher_view_test_api.h
@@ -5,6 +5,7 @@
#ifndef ASH_TEST_LAUNCHER_VIEW_TEST_API_H_
#define ASH_TEST_LAUNCHER_VIEW_TEST_API_H_
+#include "ash/launcher/launcher_types.h"
#include "base/basictypes.h"
namespace gfx {
@@ -54,6 +55,9 @@
// An accessor for |launcher_view|.
internal::LauncherView* launcher_view() { return launcher_view_; }
+ // Wrapper for LauncherView::SameDragType.
+ bool SameDragType(LauncherItemType typea, LauncherItemType typeb) const;
+
private:
internal::LauncherView* launcher_view_;
diff --git a/ash/wm/resize_shadow.h b/ash/wm/resize_shadow.h
index d9f2452..f61f393 100644
--- a/ash/wm/resize_shadow.h
+++ b/ash/wm/resize_shadow.h
@@ -47,6 +47,10 @@
// Updates the effect positions based on the |bounds| of the window.
void Layout(const gfx::Rect& bounds);
+ int GetLastHitTestForTest() const {
+ return last_hit_test_;
+ }
+
private:
// Images for the shadow effect.
scoped_ptr<views::corewm::ImageGrid> image_grid_;
diff --git a/ash/wm/resize_shadow_controller.cc b/ash/wm/resize_shadow_controller.cc
index c875265..85778d3 100644
--- a/ash/wm/resize_shadow_controller.cc
+++ b/ash/wm/resize_shadow_controller.cc
@@ -35,6 +35,11 @@
shadow->Hide();
}
+ResizeShadow* ResizeShadowController::GetShadowForWindowForTest(
+ aura::Window* window) {
+ return GetShadowForWindow(window);
+}
+
void ResizeShadowController::OnWindowBoundsChanged(
aura::Window* window,
const gfx::Rect& old_bounds,
diff --git a/ash/wm/resize_shadow_controller.h b/ash/wm/resize_shadow_controller.h
index d818a75..1eccf4c 100644
--- a/ash/wm/resize_shadow_controller.h
+++ b/ash/wm/resize_shadow_controller.h
@@ -7,6 +7,7 @@
#include <map>
+#include "ash/ash_export.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/linked_ptr.h"
@@ -23,7 +24,7 @@
// ResizeShadowController observes changes to resizable windows and shows
// a resize handle visual effect when the cursor is near the edges.
-class ResizeShadowController : public aura::WindowObserver {
+class ASH_EXPORT ResizeShadowController : public aura::WindowObserver {
public:
ResizeShadowController();
virtual ~ResizeShadowController();
@@ -34,6 +35,8 @@
// Hides the shadow for a |window|, if it has one.
void HideShadow(aura::Window* window);
+ ResizeShadow* GetShadowForWindowForTest(aura::Window* window);
+
// aura::WindowObserver overrides:
virtual void OnWindowBoundsChanged(
aura::Window* window,
diff --git a/ash/wm/toplevel_window_event_handler.cc b/ash/wm/toplevel_window_event_handler.cc
index 71753c4..a0d4b5e 100644
--- a/ash/wm/toplevel_window_event_handler.cc
+++ b/ash/wm/toplevel_window_event_handler.cc
@@ -215,6 +215,25 @@
return;
switch (event->type()) {
+ case ui::ET_GESTURE_TAP_DOWN: {
+ int component =
+ target->delegate()->GetNonClientComponent(event->location());
+ if (!(WindowResizer::GetBoundsChangeForWindowComponent(component) &
+ WindowResizer::kBoundsChange_Resizes))
+ return;
+ internal::ResizeShadowController* controller =
+ Shell::GetInstance()->resize_shadow_controller();
+ if (controller)
+ controller->ShowShadow(target, component);
+ return;
+ }
+ case ui::ET_GESTURE_END: {
+ internal::ResizeShadowController* controller =
+ Shell::GetInstance()->resize_shadow_controller();
+ if (controller)
+ controller->HideShadow(target);
+ return;
+ }
case ui::ET_GESTURE_SCROLL_BEGIN: {
if (in_gesture_drag_)
return;
@@ -481,7 +500,7 @@
if (event->flags() & ui::EF_IS_NON_CLIENT) {
int component =
target->delegate()->GetNonClientComponent(event->location());
- controller->ShowShadow(target, component);
+ controller->ShowShadow(target, component);
} else {
controller->HideShadow(target);
}
diff --git a/ash/wm/toplevel_window_event_handler_unittest.cc b/ash/wm/toplevel_window_event_handler_unittest.cc
index 0076d3d..c84f8b3 100644
--- a/ash/wm/toplevel_window_event_handler_unittest.cc
+++ b/ash/wm/toplevel_window_event_handler_unittest.cc
@@ -4,12 +4,15 @@
#include "ash/wm/toplevel_window_event_handler.h"
+#include "ash/ash_constants.h"
#include "ash/root_window_controller.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/lock_state_controller_impl2.h"
#include "ash/wm/property_util.h"
+#include "ash/wm/resize_shadow.h"
+#include "ash/wm/resize_shadow_controller.h"
#include "ash/wm/window_util.h"
#include "ash/wm/workspace/snap_sizer.h"
#include "ash/wm/workspace_controller.h"
@@ -42,30 +45,17 @@
// requested and applies a minimum size constraint if there is one.
class TestWindowDelegate : public aura::test::TestWindowDelegate {
public:
- explicit TestWindowDelegate(int hittest_code)
- : hittest_code_(hittest_code) {
+ explicit TestWindowDelegate(int hittest_code) {
+ set_window_component(hittest_code);
}
virtual ~TestWindowDelegate() {}
- void set_min_size(const gfx::Size& size) {
- min_size_ = size;
- }
-
private:
// Overridden from aura::Test::TestWindowDelegate:
- virtual gfx::Size GetMinimumSize() const OVERRIDE {
- return min_size_;
- }
- virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE {
- return hittest_code_;
- }
virtual void OnWindowDestroyed() OVERRIDE {
delete this;
}
- int hittest_code_;
- gfx::Size min_size_;
-
DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate);
};
@@ -137,8 +127,8 @@
TEST_F(ToplevelWindowEventHandlerTest, GrowBox) {
scoped_ptr<aura::Window> w1(CreateWindow(HTGROWBOX));
TestWindowDelegate* window_delegate =
- static_cast<TestWindowDelegate*>(w1->delegate());
- window_delegate->set_min_size(gfx::Size(40, 40));
+ static_cast<TestWindowDelegate*>(w1->delegate());
+ window_delegate->set_minimum_size(gfx::Size(40, 40));
gfx::Point position = w1->bounds().origin();
aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
@@ -239,7 +229,7 @@
scoped_ptr<aura::Window> w1(CreateWindow(HTLEFT));
TestWindowDelegate* window_delegate =
static_cast<TestWindowDelegate*>(w1->delegate());
- window_delegate->set_min_size(gfx::Size(40, 40));
+ window_delegate->set_minimum_size(gfx::Size(40, 40));
// Simulate a large left-to-right drag. Window width should be clamped to
// minimum and position change should be limited as well.
@@ -252,7 +242,7 @@
scoped_ptr<aura::Window> w1(CreateWindow(HTRIGHT));
TestWindowDelegate* window_delegate =
static_cast<TestWindowDelegate*>(w1->delegate());
- window_delegate->set_min_size(gfx::Size(40, 40));
+ window_delegate->set_minimum_size(gfx::Size(40, 40));
gfx::Point position = w1->bounds().origin();
// Simulate a large right-to-left drag. Window width should be clamped to
@@ -266,7 +256,7 @@
scoped_ptr<aura::Window> w1(CreateWindow(HTTOPLEFT));
TestWindowDelegate* window_delegate =
static_cast<TestWindowDelegate*>(w1->delegate());
- window_delegate->set_min_size(gfx::Size(40, 40));
+ window_delegate->set_minimum_size(gfx::Size(40, 40));
// Simulate a large top-left to bottom-right drag. Window width should be
// clamped to minimum and position should be limited.
@@ -279,7 +269,7 @@
scoped_ptr<aura::Window> w1(CreateWindow(HTTOPRIGHT));
TestWindowDelegate* window_delegate =
static_cast<TestWindowDelegate*>(w1->delegate());
- window_delegate->set_min_size(gfx::Size(40, 40));
+ window_delegate->set_minimum_size(gfx::Size(40, 40));
// Simulate a large top-right to bottom-left drag. Window size should be
// clamped to minimum, x position should not change, and y position should
@@ -293,7 +283,7 @@
scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMLEFT));
TestWindowDelegate* window_delegate =
static_cast<TestWindowDelegate*>(w1->delegate());
- window_delegate->set_min_size(gfx::Size(40, 40));
+ window_delegate->set_minimum_size(gfx::Size(40, 40));
// Simulate a large bottom-left to top-right drag. Window size should be
// clamped to minimum, x position should be clamped, and y position should
@@ -307,7 +297,7 @@
scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMRIGHT));
TestWindowDelegate* window_delegate =
static_cast<TestWindowDelegate*>(w1->delegate());
- window_delegate->set_min_size(gfx::Size(40, 40));
+ window_delegate->set_minimum_size(gfx::Size(40, 40));
gfx::Point position = w1->bounds().origin();
// Simulate a large bottom-right to top-left drag. Window size should be
@@ -696,5 +686,131 @@
}
}
+// Test class for mouse and touch resize shadow tests.
+class ToplevelWindowEventHandlerResizeTest
+ : public ToplevelWindowEventHandlerTest {
+ public:
+ ToplevelWindowEventHandlerResizeTest() : delegate_(NULL) {}
+ virtual ~ToplevelWindowEventHandlerResizeTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ ToplevelWindowEventHandlerTest::SetUp();
+
+ delegate_ = new TestWindowDelegate(HTNOWHERE);
+ target_.reset(CreateTestWindowInShellWithDelegate(
+ delegate_, 0, gfx::Rect(0, 0, 100, 100)));
+
+ gfx::Insets mouse_insets = gfx::Insets(-ash::kResizeOutsideBoundsSize,
+ -ash::kResizeOutsideBoundsSize,
+ -ash::kResizeOutsideBoundsSize,
+ -ash::kResizeOutsideBoundsSize);
+ gfx::Insets touch_insets =
+ mouse_insets.Scale(ash::kResizeOutsideBoundsScaleForTouch);
+ target_->SetHitTestBoundsOverrideOuter(mouse_insets, touch_insets);
+ target_->set_hit_test_bounds_override_inner(mouse_insets);
+ }
+
+ virtual void TearDown() OVERRIDE {
+ target_.reset();
+ ToplevelWindowEventHandlerTest::TearDown();
+ }
+
+ // Called on each scroll event. Checks if the correct resize shadow is shown.
+ void ProcessEvent(ui::EventType type, const gfx::Vector2dF& delta) {
+ if (type == ui::ET_GESTURE_SCROLL_END) {
+ // After gesture scroll ends, there should be no resize shadow.
+ EXPECT_FALSE(HasResizeShadow());
+ } else {
+ // Check if there is a resize shadow under the correct border.
+ ASSERT_TRUE(HasResizeShadow());
+ EXPECT_EQ(HTBOTTOMRIGHT, ResizeShadowLastHitTest());
+ }
+ }
+
+ protected:
+ void SetHittestCode(int hittest_code) {
+ delegate_->set_window_component(hittest_code);
+ }
+
+ aura::Window* target() { return target_.get(); }
+
+ bool HasResizeShadow() const {
+ // There is no shadow if no ResizeShadow object is associated with the
+ // window or there is one but its hit test is set to HTNOWHERE. Since we
+ // don't want to tie tests to that implementation detail, both cases are
+ // considered here.
+ return ResizeShadow() && ResizeShadowLastHitTest() != HTNOWHERE;
+ }
+
+ int ResizeShadowLastHitTest() const {
+ return ResizeShadow()->GetLastHitTestForTest();
+ }
+
+ private:
+ internal::ResizeShadow* ResizeShadow() const {
+ return Shell::GetInstance()->resize_shadow_controller()->
+ GetShadowForWindowForTest(target_.get());
+ }
+
+ TestWindowDelegate* delegate_;
+ scoped_ptr<aura::Window> target_;
+
+ DISALLOW_COPY_AND_ASSIGN(ToplevelWindowEventHandlerResizeTest);
+};
+
+// Tests resize shadows for touch resizing.
+TEST_F(ToplevelWindowEventHandlerResizeTest, TouchResizeShadows) {
+ aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), target());
+
+ // Drag bottom right border of the window and check for the resize shadows.
+ // Shadows are checked in the callback function.
+ SetHittestCode(HTBOTTOMRIGHT);
+ generator.GestureScrollSequenceWithCallback(
+ gfx::Point(105, 105),
+ gfx::Point(150, 150),
+ base::TimeDelta::FromMilliseconds(100),
+ 3,
+ base::Bind(&ToplevelWindowEventHandlerResizeTest::ProcessEvent,
+ base::Unretained(this)));
+ RunAllPendingInMessageLoop();
+}
+
+// Tests resize shadows for mouse resizing.
+TEST_F(ToplevelWindowEventHandlerResizeTest, MouseResizeShadows) {
+ aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), target());
+
+ // There should be no shadow at the beginning.
+ EXPECT_FALSE(HasResizeShadow());
+
+ // Move mouse over the right border. Shadows should appear.
+ SetHittestCode(HTRIGHT);
+ generator.MoveMouseTo(gfx::Point(100, 50));
+ ASSERT_TRUE(HasResizeShadow());
+ EXPECT_EQ(HTRIGHT, ResizeShadowLastHitTest());
+
+ // Move mouse over the bottom right border. Shadows should stay.
+ SetHittestCode(HTBOTTOMRIGHT);
+ generator.MoveMouseTo(100, 100);
+ ASSERT_TRUE(HasResizeShadow());
+ EXPECT_EQ(HTBOTTOMRIGHT, ResizeShadowLastHitTest());
+
+ // Move mouse into the window. Shadows should disappear.
+ SetHittestCode(HTCLIENT);
+ generator.MoveMouseTo(50, 50);
+ EXPECT_FALSE(HasResizeShadow());
+
+ // Move mouse over the bottom order. Shadows should reappear.
+ SetHittestCode(HTBOTTOM);
+ generator.MoveMouseTo(50, 100);
+ ASSERT_TRUE(HasResizeShadow());
+ EXPECT_EQ(HTBOTTOM, ResizeShadowLastHitTest());
+
+ // Move mouse out of the window. Shadows should disappear.
+ generator.MoveMouseTo(150, 150);
+ EXPECT_FALSE(HasResizeShadow());
+
+ RunAllPendingInMessageLoop();
+}
+
} // namespace test
} // namespace ash
diff --git a/ash/wm/window_selector.cc b/ash/wm/window_selector.cc
index f9de84c..8e87a95 100644
--- a/ash/wm/window_selector.cc
+++ b/ash/wm/window_selector.cc
@@ -12,29 +12,273 @@
#include "ash/wm/window_selector_delegate.h"
#include "ash/wm/window_util.h"
#include "base/memory/scoped_ptr.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/base/events/event.h"
+#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/gfx/display.h"
#include "ui/gfx/interpolated_transform.h"
#include "ui/gfx/transform_util.h"
+#include "ui/views/corewm/shadow_types.h"
#include "ui/views/corewm/window_animations.h"
+#include "ui/views/corewm/window_util.h"
+#include "ui/views/widget/widget.h"
namespace ash {
namespace {
const float kCardAspectRatio = 4.0f / 3.0f;
-const int kWindowMargin = 20;
+const int kWindowMargin = 30;
const int kMinCardsMajor = 3;
const int kOverviewTransitionMilliseconds = 100;
+const SkColor kWindowSelectorSelectionColor = SK_ColorBLACK;
+const float kWindowSelectorSelectionOpacity = 0.5f;
+const int kWindowSelectorSelectionPadding = 15;
-// Applies a transform to |window| to fit within |target_bounds| while
-// maintaining its aspect ratio.
-void TransformWindowToFitBounds(aura::Window* window,
- const gfx::Rect& target_bounds) {
- const gfx::Rect bounds = window->bounds();
+// Creates a copy of |window| with |recreated_layer| in the |target_root|.
+views::Widget* CreateCopyOfWindow(aura::RootWindow* target_root,
+ aura::Window* src_window,
+ ui::Layer* recreated_layer) {
+ views::Widget* widget = new views::Widget;
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
+ params.parent = src_window->parent();
+ params.can_activate = false;
+ params.keep_on_top = true;
+ widget->set_focus_on_creation(false);
+ widget->Init(params);
+ widget->SetVisibilityChangedAnimationsEnabled(false);
+ std::string name = src_window->name() + " (Copy)";
+ widget->GetNativeWindow()->SetName(name);
+ views::corewm::SetShadowType(widget->GetNativeWindow(),
+ views::corewm::SHADOW_TYPE_RECTANGULAR);
+
+ // Set the bounds in the target root window.
+ gfx::Display target_display =
+ Shell::GetScreen()->GetDisplayNearestWindow(target_root);
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(src_window->GetRootWindow());
+ if (screen_position_client && target_display.is_valid()) {
+ screen_position_client->SetBounds(widget->GetNativeWindow(),
+ src_window->GetBoundsInScreen(), target_display);
+ } else {
+ widget->SetBounds(src_window->GetBoundsInScreen());
+ }
+ widget->StackAbove(src_window);
+
+ // Move the |recreated_layer| to the newly created window.
+ recreated_layer->set_delegate(src_window->layer()->delegate());
+ gfx::Rect layer_bounds = recreated_layer->bounds();
+ layer_bounds.set_origin(gfx::Point(0, 0));
+ recreated_layer->SetBounds(layer_bounds);
+ recreated_layer->SetVisible(false);
+ recreated_layer->parent()->Remove(recreated_layer);
+
+ aura::Window* window = widget->GetNativeWindow();
+ recreated_layer->SetVisible(true);
+ window->layer()->Add(recreated_layer);
+ window->layer()->StackAtTop(recreated_layer);
+ window->layer()->SetOpacity(1);
+ window->Show();
+ return widget;
+}
+
+// An observer which closes the widget and deletes the layer after an
+// animation finishes.
+class CleanupWidgetAfterAnimationObserver : public ui::LayerAnimationObserver {
+ public:
+ CleanupWidgetAfterAnimationObserver(views::Widget* widget, ui::Layer* layer);
+
+ virtual void OnLayerAnimationEnded(
+ ui::LayerAnimationSequence* sequence) OVERRIDE;
+ virtual void OnLayerAnimationAborted(
+ ui::LayerAnimationSequence* sequence) OVERRIDE;
+ virtual void OnLayerAnimationScheduled(
+ ui::LayerAnimationSequence* sequence) OVERRIDE;
+
+ protected:
+ virtual ~CleanupWidgetAfterAnimationObserver();
+
+ private:
+ views::Widget* widget_;
+ ui::Layer* layer_;
+
+ DISALLOW_COPY_AND_ASSIGN(CleanupWidgetAfterAnimationObserver);
+};
+
+CleanupWidgetAfterAnimationObserver::CleanupWidgetAfterAnimationObserver(
+ views::Widget* widget,
+ ui::Layer* layer)
+ : widget_(widget),
+ layer_(layer) {
+ widget_->GetNativeWindow()->layer()->GetAnimator()->AddObserver(this);
+}
+
+void CleanupWidgetAfterAnimationObserver::OnLayerAnimationEnded(
+ ui::LayerAnimationSequence* sequence) {
+ delete this;
+}
+
+void CleanupWidgetAfterAnimationObserver::OnLayerAnimationAborted(
+ ui::LayerAnimationSequence* sequence) {
+ delete this;
+}
+
+void CleanupWidgetAfterAnimationObserver::OnLayerAnimationScheduled(
+ ui::LayerAnimationSequence* sequence) {
+}
+
+CleanupWidgetAfterAnimationObserver::~CleanupWidgetAfterAnimationObserver() {
+ widget_->GetNativeWindow()->layer()->GetAnimator()->RemoveObserver(this);
+ widget_->Close();
+ widget_ = NULL;
+ if (layer_) {
+ views::corewm::DeepDeleteLayers(layer_);
+ layer_ = NULL;
+ }
+}
+
+// The animation settings used for window selector animations.
+class WindowSelectorAnimationSettings
+ : public ui::ScopedLayerAnimationSettings {
+ public:
+ WindowSelectorAnimationSettings(aura::Window* window) :
+ ui::ScopedLayerAnimationSettings(window->layer()->GetAnimator()) {
+ SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ SetTransitionDuration(
+ base::TimeDelta::FromMilliseconds(kOverviewTransitionMilliseconds));
+ }
+
+ virtual ~WindowSelectorAnimationSettings() {
+ }
+};
+
+} // namespace
+
+// TODO(flackr): Split up into separate file under subdirectory in ash/wm.
+class WindowSelectorWindow {
+ public:
+ explicit WindowSelectorWindow(aura::Window* window);
+ virtual ~WindowSelectorWindow();
+
+ aura::Window* window() { return window_; }
+ const aura::Window* window() const { return window_; }
+
+ // Returns true if this window selector window contains the |target|. This is
+ // used to determine if an event targetted this window.
+ bool Contains(const aura::Window* target) const;
+
+ // Restores this window on exit rather than returning it to a minimized state
+ // if it was minimized on entering overview mode.
+ void RestoreWindowOnExit();
+
+ // Informs the WindowSelectorWindow that the window being watched was
+ // destroyed. This resets the internal window pointer to avoid calling
+ // anything on the window at destruction time.
+ void OnWindowDestroyed();
+
+ // Applies a transform to the window to fit within |target_bounds| while
+ // maintaining its aspect ratio.
+ void TransformToFitBounds(aura::RootWindow* root_window,
+ const gfx::Rect& target_bounds);
+
+ gfx::Rect bounds() { return fit_bounds_; }
+
+ private:
+ // A weak pointer to the real window in the overview.
+ aura::Window* window_;
+
+ // A copy of the window used to transition the window to another root.
+ views::Widget* window_copy_;
+
+ // A weak pointer to a deep copy of the window's layers.
+ ui::Layer* layer_;
+
+ // If true, the window was minimized and should be restored if the window
+ // was not selected.
+ bool minimized_;
+
+ // The original transform of the window before entering overview mode.
+ gfx::Transform original_transform_;
+
+ // The bounds this window is fit to.
+ gfx::Rect fit_bounds_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowSelectorWindow);
+};
+
+WindowSelectorWindow::WindowSelectorWindow(aura::Window* window)
+ : window_(window),
+ window_copy_(NULL),
+ layer_(NULL),
+ minimized_(window->GetProperty(aura::client::kShowStateKey) ==
+ ui::SHOW_STATE_MINIMIZED),
+ original_transform_(window->layer()->transform()) {
+ if (minimized_)
+ window_->Show();
+}
+
+WindowSelectorWindow::~WindowSelectorWindow() {
+ if (window_) {
+ WindowSelectorAnimationSettings animation_settings(window_);
+ gfx::Transform transform;
+ window_->SetTransform(original_transform_);
+ if (minimized_) {
+ // Setting opacity 0 and visible false ensures that the property change
+ // to SHOW_STATE_MINIMIZED will not animate the window from its original
+ // bounds to the minimized position.
+ window_->layer()->SetOpacity(0);
+ window_->layer()->SetVisible(false);
+ window_->SetProperty(aura::client::kShowStateKey,
+ ui::SHOW_STATE_MINIMIZED);
+ }
+ }
+ // If a copy of the window was created, clean it up.
+ if (window_copy_) {
+ if (window_) {
+ // If the initial window wasn't destroyed, the copy needs to be animated
+ // out. CleanupWidgetAfterAnimationObserver will destroy the widget and
+ // layer after the animation is complete.
+ new CleanupWidgetAfterAnimationObserver(window_copy_, layer_);
+ WindowSelectorAnimationSettings animation_settings(
+ window_copy_->GetNativeWindow());
+ window_copy_->GetNativeWindow()->SetTransform(original_transform_);
+ } else {
+ window_copy_->Close();
+ if (layer_)
+ views::corewm::DeepDeleteLayers(layer_);
+ }
+ window_copy_ = NULL;
+ layer_ = NULL;
+ }
+}
+
+bool WindowSelectorWindow::Contains(const aura::Window* window) const {
+ if (window_copy_ && window_copy_->GetNativeWindow()->Contains(window))
+ return true;
+ return window_->Contains(window);
+}
+
+void WindowSelectorWindow::RestoreWindowOnExit() {
+ minimized_ = false;
+ original_transform_ = gfx::Transform();
+}
+
+void WindowSelectorWindow::OnWindowDestroyed() {
+ window_ = NULL;
+}
+
+void WindowSelectorWindow::TransformToFitBounds(
+ aura::RootWindow* root_window,
+ const gfx::Rect& target_bounds) {
+ fit_bounds_ = target_bounds;
+ const gfx::Rect bounds = window_->GetBoundsInScreen();
float scale = std::min(1.0f,
std::min(static_cast<float>(target_bounds.width()) / bounds.width(),
static_cast<float>(target_bounds.height()) / bounds.height()));
@@ -45,137 +289,188 @@
transform.Translate(target_bounds.x() - bounds.x() + offset.x(),
target_bounds.y() - bounds.y() + offset.y());
transform.Scale(scale, scale);
- // TODO(flackr): The window bounds or transform could change during overview
- // mode. WindowSelector should create a copy of the window so that the
- // displayed windows are not affected by changes happening in the background.
- // This will be necessary for alt-tab cycling as well, as some windows will
- // be coming from other displays: http://crbug.com/263481.
- window->SetTransform(transform);
+ if (root_window != window_->GetRootWindow()) {
+ if (!window_copy_) {
+ DCHECK(!layer_);
+ layer_ = views::corewm::RecreateWindowLayers(window_, true);
+ window_copy_ = CreateCopyOfWindow(root_window, window_, layer_);
+ }
+ WindowSelectorAnimationSettings animation_settings(
+ window_copy_->GetNativeWindow());
+ window_copy_->GetNativeWindow()->SetTransform(transform);
+ }
+ WindowSelectorAnimationSettings animation_settings(window_);
+ window_->SetTransform(transform);
}
-} // namespace
+// A comparator for locating a given target window.
+struct WindowSelectorWindowComparator
+ : public std::unary_function<WindowSelectorWindow*, bool> {
+ explicit WindowSelectorWindowComparator(const aura::Window* target_window)
+ : target(target_window) {
+ }
+
+ bool operator()(const WindowSelectorWindow* window) const {
+ return target == window->window();
+ }
+
+ const aura::Window* target;
+};
WindowSelector::WindowSelector(const WindowList& windows,
+ WindowSelector::Mode mode,
WindowSelectorDelegate* delegate)
- : delegate_(delegate) {
+ : mode_(mode),
+ delegate_(delegate),
+ selected_window_(0),
+ selection_root_(NULL) {
DCHECK(delegate_);
for (size_t i = 0; i < windows.size(); ++i) {
windows[i]->AddObserver(this);
- WindowDetails details;
- details.window = windows[i];
- details.minimized = windows[i]->GetProperty(aura::client::kShowStateKey) ==
- ui::SHOW_STATE_MINIMIZED;
- details.original_transform = windows[i]->layer()->transform();
- if (details.minimized) {
- windows[i]->Show();
- }
- windows_.push_back(details);
+ windows_.push_back(new WindowSelectorWindow(windows[i]));
}
+ if (mode == WindowSelector::CYCLE)
+ selection_root_ = ash::Shell::GetActiveRootWindow();
PositionWindows();
ash::Shell::GetInstance()->AddPreTargetHandler(this);
}
WindowSelector::~WindowSelector() {
for (size_t i = 0; i < windows_.size(); i++) {
- ui::ScopedLayerAnimationSettings animation_settings(
- windows_[i].window->layer()->GetAnimator());
- animation_settings.SetPreemptionStrategy(
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- animation_settings.SetTransitionDuration(
- base::TimeDelta::FromMilliseconds(kOverviewTransitionMilliseconds));
- windows_[i].window->RemoveObserver(this);
- gfx::Transform transform;
- windows_[i].window->SetTransform(windows_[i].original_transform);
- if (windows_[i].minimized) {
- // Setting opacity 0 and visible false ensures that the property change
- // to SHOW_STATE_MINIMIZED will not animate the window from its original
- // bounds to the minimized position.
- windows_[i].window->layer()->SetOpacity(0);
- windows_[i].window->layer()->SetVisible(false);
- windows_[i].window->SetProperty(aura::client::kShowStateKey,
- ui::SHOW_STATE_MINIMIZED);
- }
+ windows_[i]->window()->RemoveObserver(this);
}
ash::Shell::GetInstance()->RemovePreTargetHandler(this);
}
+void WindowSelector::Step(WindowSelector::Direction direction) {
+ DCHECK(windows_.size() > 0);
+ if (!selection_widget_)
+ InitializeSelectionWidget();
+ selected_window_ = (selected_window_ + windows_.size() +
+ (direction == WindowSelector::FORWARD ? 1 : -1)) % windows_.size();
+ UpdateSelectionLocation(true);
+}
+
+void WindowSelector::SelectWindow() {
+ delegate_->OnWindowSelected(windows_[selected_window_]->window());
+}
+
void WindowSelector::OnEvent(ui::Event* event) {
- // TODO(flackr): This will prevent anything else from working while overview
- // mode is active. This should only stop events from being sent to the windows
- // in the overview but still allow interaction with the launcher / tray and
- // hotkeys http://crbug.com/264289.
- EventHandler::OnEvent(event);
- event->StopPropagation();
+ // If the event is targetted at any of the windows in the overview, then
+ // prevent it from propagating.
+ aura::Window* target = static_cast<aura::Window*>(event->target());
+ for (size_t i = 0; i < windows_.size(); ++i) {
+ if (windows_[i]->Contains(target)) {
+ event->StopPropagation();
+ break;
+ }
+ }
+
+ // This object may not be valid after this call as a selection event can
+ // trigger deletion of the window selector.
+ ui::EventHandler::OnEvent(event);
}
void WindowSelector::OnMouseEvent(ui::MouseEvent* event) {
if (event->type() != ui::ET_MOUSE_RELEASED)
return;
- aura::Window* target = static_cast<aura::Window*>(event->target());
- if (!target->HitTest(event->location()))
+ WindowSelectorWindow* target = GetEventTarget(event);
+ if (!target)
return;
- HandleSelectionEvent(event);
+ HandleSelectionEvent(target);
}
void WindowSelector::OnGestureEvent(ui::GestureEvent* event) {
if (event->type() != ui::ET_GESTURE_TAP)
return;
- HandleSelectionEvent(event);
+ WindowSelectorWindow* target = GetEventTarget(event);
+ if (!target)
+ return;
+
+ HandleSelectionEvent(target);
}
void WindowSelector::OnWindowDestroyed(aura::Window* window) {
- std::vector<WindowDetails>::iterator iter =
- std::find(windows_.begin(), windows_.end(), window);
+ ScopedVector<WindowSelectorWindow>::iterator iter =
+ std::find_if(windows_.begin(), windows_.end(),
+ WindowSelectorWindowComparator(window));
DCHECK(iter != windows_.end());
+ size_t deleted_index = iter - windows_.begin();
+ (*iter)->OnWindowDestroyed();
windows_.erase(iter);
if (windows_.empty()) {
delegate_->OnSelectionCanceled();
return;
}
+ if (selected_window_ >= deleted_index) {
+ if (selected_window_ > deleted_index)
+ selected_window_--;
+ selected_window_ = selected_window_ % windows_.size();
+ UpdateSelectionLocation(true);
+ }
PositionWindows();
}
-void WindowSelector::HandleSelectionEvent(ui::Event* event) {
+WindowSelectorWindow* WindowSelector::GetEventTarget(ui::LocatedEvent* event) {
aura::Window* target = static_cast<aura::Window*>(event->target());
+ // If the target window doesn't actually contain the event location (i.e.
+ // mouse down over the window and mouse up elsewhere) then do not select the
+ // window.
+ if (!target->HitTest(event->location()))
+ return NULL;
for (size_t i = 0; i < windows_.size(); i++) {
- if (windows_[i].window->Contains(target)) {
- // The selected window should not be minimized when window selection is
- // ended.
- windows_[i].minimized = false;
- windows_[i].original_transform = gfx::Transform();
-
- // The delegate may delete the WindowSelector, assume the object may no
- // longer valid after calling this.
- delegate_->OnWindowSelected(windows_[i].window);
- return;
- }
+ if (windows_[i]->Contains(target))
+ return windows_[i];
}
+ return NULL;
+}
+
+void WindowSelector::HandleSelectionEvent(WindowSelectorWindow* target) {
+ // The selected window should not be minimized when window selection is
+ // ended.
+ target->RestoreWindowOnExit();
+ delegate_->OnWindowSelected(target->window());
}
void WindowSelector::PositionWindows() {
- Shell::RootWindowList root_window_list = Shell::GetAllRootWindows();
- for (size_t i = 0; i < root_window_list.size(); ++i) {
- PositionWindowsOnRoot(root_window_list[i]);
+ if (selection_root_) {
+ DCHECK_EQ(mode_, CYCLE);
+ std::vector<WindowSelectorWindow*> windows;
+ for (size_t i = 0; i < windows_.size(); ++i)
+ windows.push_back(windows_[i]);
+ PositionWindowsOnRoot(selection_root_, windows);
+ } else {
+ DCHECK_EQ(mode_, OVERVIEW);
+ Shell::RootWindowList root_window_list = Shell::GetAllRootWindows();
+ for (size_t i = 0; i < root_window_list.size(); ++i)
+ PositionWindowsFromRoot(root_window_list[i]);
}
}
-void WindowSelector::PositionWindowsOnRoot(aura::RootWindow* root_window) {
- gfx::Size window_size;
- gfx::Rect total_bounds = ScreenAsh::GetDisplayWorkAreaBoundsInParent(
- Shell::GetContainer(root_window,
- internal::kShellWindowId_DefaultContainer));
-
- std::vector<WindowDetails> windows;
+void WindowSelector::PositionWindowsFromRoot(aura::RootWindow* root_window) {
+ std::vector<WindowSelectorWindow*> windows;
for (size_t i = 0; i < windows_.size(); ++i) {
- if (windows_[i].window->GetRootWindow() == root_window)
+ if (windows_[i]->window()->GetRootWindow() == root_window)
windows.push_back(windows_[i]);
}
+ PositionWindowsOnRoot(root_window, windows);
+}
+
+void WindowSelector::PositionWindowsOnRoot(
+ aura::RootWindow* root_window,
+ const std::vector<WindowSelectorWindow*>& windows) {
if (windows.empty())
return;
+ gfx::Size window_size;
+ gfx::Rect total_bounds = ScreenAsh::ConvertRectToScreen(root_window,
+ ScreenAsh::GetDisplayWorkAreaBoundsInParent(
+ Shell::GetContainer(root_window,
+ internal::kShellWindowId_DefaultContainer)));
+
// Find the minimum number of windows per row that will fit all of the
// windows on screen.
size_t columns = std::max(
@@ -195,12 +490,6 @@
int y_offset = total_bounds.y() + (total_bounds.height() -
rows * window_size.height()) / 2;
for (size_t i = 0; i < windows.size(); ++i) {
- ui::ScopedLayerAnimationSettings animation_settings(
- windows[i].window->layer()->GetAnimator());
- animation_settings.SetPreemptionStrategy(
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- animation_settings.SetTransitionDuration(
- base::TimeDelta::FromMilliseconds(kOverviewTransitionMilliseconds));
gfx::Transform transform;
int column = i % columns;
int row = i / columns;
@@ -209,7 +498,48 @@
window_size.width(),
window_size.height());
target_bounds.Inset(kWindowMargin, kWindowMargin);
- TransformWindowToFitBounds(windows[i].window, target_bounds);
+ windows[i]->TransformToFitBounds(root_window, target_bounds);
+ }
+}
+
+void WindowSelector::InitializeSelectionWidget() {
+ selection_widget_.reset(new views::Widget);
+ views::Widget::InitParams params;
+ params.type = views::Widget::InitParams::TYPE_POPUP;
+ params.can_activate = false;
+ params.keep_on_top = false;
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.opacity = views::Widget::InitParams::OPAQUE_WINDOW;
+ params.parent = Shell::GetContainer(
+ selection_root_,
+ internal::kShellWindowId_DefaultContainer);
+ params.accept_events = false;
+ selection_widget_->set_focus_on_creation(false);
+ selection_widget_->Init(params);
+ views::View* content_view = new views::View;
+ content_view->set_background(
+ views::Background::CreateSolidBackground(kWindowSelectorSelectionColor));
+ selection_widget_->SetContentsView(content_view);
+ UpdateSelectionLocation(false);
+ selection_widget_->GetNativeWindow()->parent()->StackChildAtBottom(
+ selection_widget_->GetNativeWindow());
+ selection_widget_->Show();
+ selection_widget_->GetNativeWindow()->layer()->SetOpacity(
+ kWindowSelectorSelectionOpacity);
+}
+
+void WindowSelector::UpdateSelectionLocation(bool animate) {
+ if (!selection_widget_)
+ return;
+ gfx::Rect target_bounds = windows_[selected_window_]->bounds();
+ target_bounds.Inset(-kWindowSelectorSelectionPadding,
+ -kWindowSelectorSelectionPadding);
+ if (animate) {
+ WindowSelectorAnimationSettings animation_settings(
+ selection_widget_->GetNativeWindow());
+ selection_widget_->SetBounds(target_bounds);
+ } else {
+ selection_widget_->SetBounds(target_bounds);
}
}
diff --git a/ash/wm/window_selector.h b/ash/wm/window_selector.h
index 900787d..92ed607 100644
--- a/ash/wm/window_selector.h
+++ b/ash/wm/window_selector.h
@@ -8,6 +8,8 @@
#include <vector>
#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
#include "ui/aura/window_observer.h"
#include "ui/base/events/event_handler.h"
#include "ui/gfx/transform.h"
@@ -16,21 +18,49 @@
class RootWindow;
}
+namespace ui {
+class LocatedEvent;
+}
+
+namespace views {
+class Widget;
+}
+
namespace ash {
class WindowSelectorDelegate;
+class WindowSelectorWindow;
// The WindowSelector shows a grid of all of your windows and allows selecting
-// a window by clicking or tapping on it.
+// a window by clicking or tapping on it (OVERVIEW mode) or by alt-tabbing to
+// it (CYCLE mode).
class WindowSelector : public ui::EventHandler,
public aura::WindowObserver {
public:
+ enum Direction {
+ FORWARD,
+ BACKWARD
+ };
+ enum Mode {
+ CYCLE,
+ OVERVIEW
+ };
+
typedef std::vector<aura::Window*> WindowList;
WindowSelector(const WindowList& windows,
+ Mode mode,
WindowSelectorDelegate* delegate);
virtual ~WindowSelector();
+ // Step to the next window in |direction|.
+ void Step(Direction direction);
+
+ // Select the current window.
+ void SelectWindow();
+
+ Mode mode() { return mode_; }
+
// ui::EventHandler:
virtual void OnEvent(ui::Event* event) OVERRIDE;
virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
@@ -40,37 +70,48 @@
virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
private:
- struct WindowDetails {
- WindowDetails() : window(NULL), minimized(false) {}
+ // Returns the target of |event| or NULL if the event is not targeted at
+ // any of the windows in the selector.
+ WindowSelectorWindow* GetEventTarget(ui::LocatedEvent* event);
- bool operator==(const aura::Window* other_window) const {
- return window == other_window;
- }
+ // Handles a selection event for |target|.
+ void HandleSelectionEvent(WindowSelectorWindow* target);
- // A weak pointer to the window.
- aura::Window* window;
-
- // If true, the window was minimized and this should be restored if the
- // window was not selected.
- bool minimized;
-
- // The original transform of the window before entering overview mode.
- gfx::Transform original_transform;
- };
-
- void HandleSelectionEvent(ui::Event* event);
+ // Position all of the windows based on the current selection mode.
void PositionWindows();
- void PositionWindowsOnRoot(aura::RootWindow* root_window);
+ // Position all of the windows from |root_window| on |root_window|.
+ void PositionWindowsFromRoot(aura::RootWindow* root_window);
+ // Position all of the |windows| to fit on the |root_window|.
+ void PositionWindowsOnRoot(aura::RootWindow* root_window,
+ const std::vector<WindowSelectorWindow*>& windows);
- void SelectWindow(aura::Window*);
+ void InitializeSelectionWidget();
- // List of weak pointers of windows to select from.
- std::vector<WindowDetails> windows_;
+ // Updates the selection widget's location to the currently selected window.
+ // If |animate| the transition to the new location is animated.
+ void UpdateSelectionLocation(bool animate);
+
+ // The collection of windows in the overview wrapped by a helper class which
+ // restores their state and helps transform them to other root windows.
+ ScopedVector<WindowSelectorWindow> windows_;
+
+ // The window selection mode.
+ Mode mode_;
// Weak pointer to the selector delegate which will be called when a
// selection is made.
WindowSelectorDelegate* delegate_;
+ // Index of the currently selected window if the mode is CYCLE.
+ size_t selected_window_;
+
+ // Widget indicating which window is currently selected.
+ scoped_ptr<views::Widget> selection_widget_;
+
+ // In CYCLE mode, the root window in which selection is taking place.
+ // NULL otherwise.
+ aura::RootWindow* selection_root_;
+
DISALLOW_COPY_AND_ASSIGN(WindowSelector);
};
diff --git a/ash/wm/window_selector_controller.cc b/ash/wm/window_selector_controller.cc
index c7fe696..e6cd383 100644
--- a/ash/wm/window_selector_controller.cc
+++ b/ash/wm/window_selector_controller.cc
@@ -9,9 +9,47 @@
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/window_selector.h"
#include "ash/wm/window_util.h"
+#include "ui/base/events/event.h"
+#include "ui/base/events/event_handler.h"
namespace ash {
+namespace {
+
+// Filter to watch for the termination of a keyboard gesture to cycle through
+// multiple windows.
+class WindowSelectorEventFilter : public ui::EventHandler {
+ public:
+ WindowSelectorEventFilter();
+ virtual ~WindowSelectorEventFilter();
+
+ // Overridden from ui::EventHandler:
+ virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WindowSelectorEventFilter);
+};
+
+// Watch for all keyboard events by filtering the root window.
+WindowSelectorEventFilter::WindowSelectorEventFilter() {
+ Shell::GetInstance()->AddPreTargetHandler(this);
+}
+
+WindowSelectorEventFilter::~WindowSelectorEventFilter() {
+ Shell::GetInstance()->RemovePreTargetHandler(this);
+}
+
+void WindowSelectorEventFilter::OnKeyEvent(ui::KeyEvent* event) {
+ // Views uses VKEY_MENU for both left and right Alt keys.
+ if (event->key_code() == ui::VKEY_MENU &&
+ event->type() == ui::ET_KEY_RELEASED) {
+ Shell::GetInstance()->window_selector_controller()->AltKeyReleased();
+ // Warning: |this| will be deleted from here on.
+ }
+}
+
+} // namespace
+
WindowSelectorController::WindowSelectorController() {
}
@@ -41,10 +79,33 @@
aura::Window* active_window = wm::GetActiveWindow();
if (active_window)
wm::DeactivateWindow(active_window);
- window_selector_.reset(new WindowSelector(windows, this));
+ window_selector_.reset(
+ new WindowSelector(windows, WindowSelector::OVERVIEW, this));
}
}
+void WindowSelectorController::HandleCycleWindow(
+ WindowSelector::Direction direction) {
+ if (!CanSelect())
+ return;
+
+ if (!IsSelecting()) {
+ event_handler_.reset(new WindowSelectorEventFilter());
+ std::vector<aura::Window*> windows = ash::Shell::GetInstance()->
+ mru_window_tracker()->BuildMruWindowList();
+ window_selector_.reset(
+ new WindowSelector(windows, WindowSelector::CYCLE, this));
+ window_selector_->Step(direction);
+ } else if (window_selector_->mode() == WindowSelector::CYCLE) {
+ window_selector_->Step(direction);
+ }
+}
+
+void WindowSelectorController::AltKeyReleased() {
+ event_handler_.reset();
+ window_selector_->SelectWindow();
+}
+
bool WindowSelectorController::IsSelecting() {
return window_selector_.get() != NULL;
}
diff --git a/ash/wm/window_selector_controller.h b/ash/wm/window_selector_controller.h
index 8b11005..385c30e 100644
--- a/ash/wm/window_selector_controller.h
+++ b/ash/wm/window_selector_controller.h
@@ -9,6 +9,7 @@
#include <vector>
#include "ash/ash_export.h"
+#include "ash/wm/window_selector.h"
#include "ash/wm/window_selector_delegate.h"
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
@@ -18,6 +19,10 @@
class Window;
}
+namespace ui {
+class EventHandler;
+}
+
namespace ash {
class WindowSelector;
@@ -39,6 +44,15 @@
// or touch rather than keypresses.
void ToggleOverview();
+ // Cycles between windows in the given |direction|. It is assumed that the
+ // alt key is held down and a key filter is installed to watch for alt being
+ // released.
+ void HandleCycleWindow(WindowSelector::Direction direction);
+
+ // Informs the controller that the Alt key has been released and it can
+ // terminate the existing multi-step cycle.
+ void AltKeyReleased();
+
// Returns true if window selection mode is active.
bool IsSelecting();
@@ -48,6 +62,7 @@
private:
scoped_ptr<WindowSelector> window_selector_;
+ scoped_ptr<ui::EventHandler> event_handler_;
DISALLOW_COPY_AND_ASSIGN(WindowSelectorController);
};
diff --git a/ash/wm/window_selector_unittest.cc b/ash/wm/window_selector_unittest.cc
index 01a96bf..9ac15d6 100644
--- a/ash/wm/window_selector_unittest.cc
+++ b/ash/wm/window_selector_unittest.cc
@@ -107,6 +107,27 @@
}
}
+ void Cycle(WindowSelector::Direction direction) {
+ if (!IsSelecting()) {
+ std::vector<aura::Window*> windows = ash::Shell::GetInstance()->
+ mru_window_tracker()->BuildMruWindowList();
+ ScopedVector<LayerAnimationObserver> animations;
+ for (size_t i = 0; i < windows.size(); ++i)
+ animations.push_back(new LayerAnimationObserver(windows[i]->layer()));
+ ash::Shell::GetInstance()->window_selector_controller()->
+ HandleCycleWindow(direction);
+ for (size_t i = 0; i < animations.size(); ++i)
+ animations[i]->WaitUntilDone();
+ } else {
+ ash::Shell::GetInstance()->window_selector_controller()->
+ HandleCycleWindow(direction);
+ }
+ }
+
+ void StopCycling() {
+ ash::Shell::GetInstance()->window_selector_controller()->AltKeyReleased();
+ }
+
gfx::RectF GetTransformedBounds(aura::Window* window) {
gfx::RectF bounds(window->layer()->bounds());
window->layer()->transform().TransformRect(&bounds);
@@ -125,6 +146,11 @@
event_generator.ClickLeftButton();
}
+ bool IsSelecting() {
+ return ash::Shell::GetInstance()->window_selector_controller()->
+ IsSelecting();
+ }
+
private:
aura::test::TestWindowDelegate wd;
@@ -151,6 +177,29 @@
EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
}
+// Tests entering overview mode with three windows and cycling through them.
+TEST_F(WindowSelectorTest, BasicCycle) {
+ gfx::Rect bounds(0, 0, 400, 400);
+ scoped_ptr<aura::Window> window1(CreateWindow(bounds));
+ scoped_ptr<aura::Window> window2(CreateWindow(bounds));
+ scoped_ptr<aura::Window> window3(CreateWindow(bounds));
+ wm::ActivateWindow(window3.get());
+ wm::ActivateWindow(window2.get());
+ wm::ActivateWindow(window1.get());
+ EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
+ EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
+ EXPECT_FALSE(wm::IsActiveWindow(window3.get()));
+
+ Cycle(WindowSelector::FORWARD);
+ EXPECT_TRUE(IsSelecting());
+ Cycle(WindowSelector::FORWARD);
+ StopCycling();
+ EXPECT_FALSE(IsSelecting());
+ EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
+ EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
+ EXPECT_TRUE(wm::IsActiveWindow(window3.get()));
+}
+
// Tests that overview mode is exited if the last remaining window is destroyed.
TEST_F(WindowSelectorTest, LastWindowDestroyed) {
gfx::Rect bounds(0, 0, 400, 400);
@@ -160,8 +209,7 @@
window1.reset();
window2.reset();
- EXPECT_FALSE(ash::Shell::GetInstance()->window_selector_controller()->
- IsSelecting());
+ EXPECT_FALSE(IsSelecting());
}
// Tests that windows remain on the display they are currently on in overview
diff --git a/ash/wm/workspace/workspace_event_handler_unittest.cc b/ash/wm/workspace/workspace_event_handler_unittest.cc
index e592ad5..9f4d326 100644
--- a/ash/wm/workspace/workspace_event_handler_unittest.cc
+++ b/ash/wm/workspace/workspace_event_handler_unittest.cc
@@ -16,7 +16,6 @@
#include "ui/aura/test/event_generator.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
-#include "ui/aura/window_property.h"
#include "ui/base/hit_test.h"
#include "ui/gfx/screen.h"
diff --git a/ash/wm/workspace/workspace_layout_manager.cc b/ash/wm/workspace/workspace_layout_manager.cc
index 2fd56af..c748d9a 100644
--- a/ash/wm/workspace/workspace_layout_manager.cc
+++ b/ash/wm/workspace/workspace_layout_manager.cc
@@ -4,6 +4,7 @@
#include "ash/wm/workspace/workspace_layout_manager.h"
+#include "ash/display/display_controller.h"
#include "ash/root_window_controller.h"
#include "ash/screen_ash.h"
#include "ash/shelf/shelf_layout_manager.h"
@@ -41,6 +42,33 @@
state == ui::SHOW_STATE_FULLSCREEN;
}
+void MoveToDisplayForRestore(aura::Window* window) {
+ const gfx::Rect* restore_bounds = GetRestoreBoundsInScreen(window);
+ if (!restore_bounds)
+ return;
+
+ // Move only if the restore bounds is outside of
+ // the root window. There is no information about in which
+ // display it should be restored, so this is best guess.
+ // TODO(oshima): Restore information should contain the
+ // work area information like WindowResizer does for the
+ // last window location.
+ if (!window->GetRootWindow()->GetBoundsInScreen().Intersects(
+ *restore_bounds)) {
+ DisplayController* display_controller =
+ Shell::GetInstance()->display_controller();
+ const gfx::Display& display =
+ display_controller->GetDisplayMatching(*restore_bounds);
+ aura::RootWindow* new_root =
+ display_controller->GetRootWindowForDisplayId(display.id());
+ if (new_root != window->GetRootWindow()) {
+ aura::Window* new_container =
+ Shell::GetContainer(new_root, window->parent()->id());
+ new_container->AddChild(window);
+ }
+ }
+}
+
} // namespace
WorkspaceLayoutManager::WorkspaceLayoutManager(aura::Window* window)
@@ -285,14 +313,15 @@
}
case ui::SHOW_STATE_MAXIMIZED:
+ MoveToDisplayForRestore(window);
CrossFadeToBounds(window, ScreenAsh::GetMaximizedWindowBoundsInParent(
window->parent()->parent()));
break;
case ui::SHOW_STATE_FULLSCREEN:
+ MoveToDisplayForRestore(window);
CrossFadeToBounds(window, ScreenAsh::GetDisplayBoundsInParent(
window->parent()->parent()));
break;
-
default:
break;
}
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc
index 3e3a1c7..3dce5b0 100644
--- a/ash/wm/workspace/workspace_layout_manager_unittest.cc
+++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -17,11 +17,35 @@
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
#include "ui/gfx/insets.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
namespace ash {
-
namespace {
+class MaximizeDelegateView : public views::WidgetDelegateView {
+ public:
+ MaximizeDelegateView(const gfx::Rect& initial_bounds)
+ : initial_bounds_(initial_bounds) {
+ }
+ virtual ~MaximizeDelegateView() {}
+
+ virtual bool GetSavedWindowPlacement(
+ gfx::Rect* bounds,
+ ui::WindowShowState* show_state) const OVERRIDE {
+ *bounds = initial_bounds_;
+ *show_state = ui::SHOW_STATE_MAXIMIZED;
+ return true;
+ }
+
+ private:
+ const gfx::Rect initial_bounds_;
+
+ DISALLOW_COPY_AND_ASSIGN(MaximizeDelegateView);
+};
+
+} // namespace
+
typedef test::AshTestBase WorkspaceLayoutManagerTest;
// Verifies that a window containing a restore coordinate will be restored to
@@ -98,6 +122,91 @@
EXPECT_EQ("-20,-30 30x40", window->bounds().ToString());
}
+TEST_F(WorkspaceLayoutManagerTest, MaximizeInDisplayToBeRestored) {
+ if (!SupportsMultipleDisplays())
+ return;
+ UpdateDisplay("300x400,400x500");
+
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+
+ scoped_ptr<aura::Window> window(
+ CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40)));
+ EXPECT_EQ(root_windows[0], window->GetRootWindow());
+
+ SetRestoreBoundsInScreen(window.get(), gfx::Rect(400, 0, 30, 40));
+ // Maximize the window in 2nd display as the restore bounds
+ // is inside 2nd display.
+ wm::MaximizeWindow(window.get());
+ EXPECT_EQ(root_windows[1], window->GetRootWindow());
+ EXPECT_EQ("300,0 400x452", window->GetBoundsInScreen().ToString());
+
+ wm::RestoreWindow(window.get());
+ EXPECT_EQ(root_windows[1], window->GetRootWindow());
+ EXPECT_EQ("400,0 30x40", window->GetBoundsInScreen().ToString());
+
+ // If the restore bounds intersects with the current display,
+ // don't move.
+ SetRestoreBoundsInScreen(window.get(), gfx::Rect(280, 0, 30, 40));
+ wm::MaximizeWindow(window.get());
+ EXPECT_EQ(root_windows[1], window->GetRootWindow());
+ EXPECT_EQ("300,0 400x452", window->GetBoundsInScreen().ToString());
+
+ wm::RestoreWindow(window.get());
+ EXPECT_EQ(root_windows[1], window->GetRootWindow());
+ EXPECT_EQ("280,0 30x40", window->GetBoundsInScreen().ToString());
+
+ // Restoring widget state.
+ scoped_ptr<views::Widget> w1(new views::Widget);
+ views::Widget::InitParams params;
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.delegate = new MaximizeDelegateView(gfx::Rect(400, 0, 30, 40));
+ params.context = root_windows[0];
+ w1->Init(params);
+ w1->Show();
+ EXPECT_TRUE(w1->IsMaximized());
+ EXPECT_EQ(root_windows[1], w1->GetNativeView()->GetRootWindow());
+ EXPECT_EQ("300,0 400x452", w1->GetWindowBoundsInScreen().ToString());
+ w1->Restore();
+ EXPECT_EQ(root_windows[1], w1->GetNativeView()->GetRootWindow());
+ EXPECT_EQ("400,0 30x40", w1->GetWindowBoundsInScreen().ToString());
+}
+
+TEST_F(WorkspaceLayoutManagerTest, FullscreenInDisplayToBeRestored) {
+ if (!SupportsMultipleDisplays())
+ return;
+ UpdateDisplay("300x400,400x500");
+
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+
+ scoped_ptr<aura::Window> window(
+ CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40)));
+ EXPECT_EQ(root_windows[0], window->GetRootWindow());
+
+ SetRestoreBoundsInScreen(window.get(), gfx::Rect(400, 0, 30, 40));
+ // Maximize the window in 2nd display as the restore bounds
+ // is inside 2nd display.
+ window->SetProperty(aura::client::kShowStateKey,
+ ui::SHOW_STATE_FULLSCREEN);
+ EXPECT_EQ(root_windows[1], window->GetRootWindow());
+ EXPECT_EQ("300,0 400x500", window->GetBoundsInScreen().ToString());
+
+ wm::RestoreWindow(window.get());
+ EXPECT_EQ(root_windows[1], window->GetRootWindow());
+ EXPECT_EQ("400,0 30x40", window->GetBoundsInScreen().ToString());
+
+ // If the restore bounds intersects with the current display,
+ // don't move.
+ SetRestoreBoundsInScreen(window.get(), gfx::Rect(280, 0, 30, 40));
+ window->SetProperty(aura::client::kShowStateKey,
+ ui::SHOW_STATE_FULLSCREEN);
+ EXPECT_EQ(root_windows[1], window->GetRootWindow());
+ EXPECT_EQ("300,0 400x500", window->GetBoundsInScreen().ToString());
+
+ wm::RestoreWindow(window.get());
+ EXPECT_EQ(root_windows[1], window->GetRootWindow());
+ EXPECT_EQ("280,0 30x40", window->GetBoundsInScreen().ToString());
+}
+
// WindowObserver implementation used by DontClobberRestoreBoundsWindowObserver.
// This code mirrors what BrowserFrameAura does. In particular when this code
// sees the window was maximized it changes the bounds of a secondary
@@ -250,5 +359,4 @@
window->bounds().ToString());
}
-} // namespace
} // namespace ash
diff --git a/base/base.gyp b/base/base.gyp
index 4b92a91..e2af06b 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -877,6 +877,8 @@
'test/null_task_runner.h',
'test/perf_test_suite.cc',
'test/perf_test_suite.h',
+ 'test/power_monitor_test_base.cc',
+ 'test/power_monitor_test_base.h',
'test/scoped_locale.cc',
'test/scoped_locale.h',
'test/scoped_path_override.cc',
diff --git a/base/base.gypi b/base/base.gypi
index bfe5a57..6d82ee3 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -390,8 +390,6 @@
'power_monitor/power_monitor_device_source_win.cc',
'power_monitor/power_monitor_source.cc',
'power_monitor/power_monitor_source.h',
- 'power_monitor/power_monitor_test_base.cc',
- 'power_monitor/power_monitor_test_base.h',
'power_monitor/power_observer.h',
'process/internal_linux.cc',
'process/internal_linux.h',
@@ -417,6 +415,7 @@
'process/process_handle_posix.cc',
'process/process_handle_win.cc',
'process/process_info.h',
+ 'process/process_info_linux.cc',
'process/process_info_mac.cc',
'process/process_info_win.cc',
'process/process_iterator.cc',
diff --git a/base/base.target.darwin-arm.mk b/base/base.target.darwin-arm.mk
index dfa23a3..27dc2e8 100644
--- a/base/base.target.darwin-arm.mk
+++ b/base/base.target.darwin-arm.mk
@@ -148,7 +148,6 @@
base/power_monitor/power_monitor_device_source_android.cc \
base/power_monitor/power_monitor_device_source.cc \
base/power_monitor/power_monitor_source.cc \
- base/power_monitor/power_monitor_test_base.cc \
base/process/internal_linux.cc \
base/process/kill.cc \
base/process/kill_posix.cc \
diff --git a/base/base.target.darwin-mips.mk b/base/base.target.darwin-mips.mk
index 2847ad4..acca7ec 100644
--- a/base/base.target.darwin-mips.mk
+++ b/base/base.target.darwin-mips.mk
@@ -148,7 +148,6 @@
base/power_monitor/power_monitor_device_source_android.cc \
base/power_monitor/power_monitor_device_source.cc \
base/power_monitor/power_monitor_source.cc \
- base/power_monitor/power_monitor_test_base.cc \
base/process/internal_linux.cc \
base/process/kill.cc \
base/process/kill_posix.cc \
diff --git a/base/base.target.darwin-x86.mk b/base/base.target.darwin-x86.mk
index d3c3e49..293ec02 100644
--- a/base/base.target.darwin-x86.mk
+++ b/base/base.target.darwin-x86.mk
@@ -149,7 +149,6 @@
base/power_monitor/power_monitor_device_source_android.cc \
base/power_monitor/power_monitor_device_source.cc \
base/power_monitor/power_monitor_source.cc \
- base/power_monitor/power_monitor_test_base.cc \
base/process/internal_linux.cc \
base/process/kill.cc \
base/process/kill_posix.cc \
diff --git a/base/base.target.linux-arm.mk b/base/base.target.linux-arm.mk
index dfa23a3..27dc2e8 100644
--- a/base/base.target.linux-arm.mk
+++ b/base/base.target.linux-arm.mk
@@ -148,7 +148,6 @@
base/power_monitor/power_monitor_device_source_android.cc \
base/power_monitor/power_monitor_device_source.cc \
base/power_monitor/power_monitor_source.cc \
- base/power_monitor/power_monitor_test_base.cc \
base/process/internal_linux.cc \
base/process/kill.cc \
base/process/kill_posix.cc \
diff --git a/base/base.target.linux-mips.mk b/base/base.target.linux-mips.mk
index 2847ad4..acca7ec 100644
--- a/base/base.target.linux-mips.mk
+++ b/base/base.target.linux-mips.mk
@@ -148,7 +148,6 @@
base/power_monitor/power_monitor_device_source_android.cc \
base/power_monitor/power_monitor_device_source.cc \
base/power_monitor/power_monitor_source.cc \
- base/power_monitor/power_monitor_test_base.cc \
base/process/internal_linux.cc \
base/process/kill.cc \
base/process/kill_posix.cc \
diff --git a/base/base.target.linux-x86.mk b/base/base.target.linux-x86.mk
index d3c3e49..293ec02 100644
--- a/base/base.target.linux-x86.mk
+++ b/base/base.target.linux-x86.mk
@@ -149,7 +149,6 @@
base/power_monitor/power_monitor_device_source_android.cc \
base/power_monitor/power_monitor_device_source.cc \
base/power_monitor/power_monitor_source.cc \
- base/power_monitor/power_monitor_test_base.cc \
base/process/internal_linux.cc \
base/process/kill.cc \
base/process/kill_posix.cc \
diff --git a/base/debug/trace_event.h b/base/debug/trace_event.h
index f6a903d..6805513 100644
--- a/base/debug/trace_event.h
+++ b/base/debug/trace_event.h
@@ -17,13 +17,14 @@
// Events are issued against categories. Whereas LOG's
// categories are statically defined, TRACE categories are created
// implicitly with a string. For example:
-// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")
+// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent",
+// TRACE_EVENT_SCOPE_THREAD)
//
// It is often the case that one trace may belong in multiple categories at the
// same time. The first argument to the trace can be a comma-separated list of
// categories, forming a category group, like:
//
-// TRACE_EVENT_INSTANT0("input,views", "OnMouseOver")
+// TRACE_EVENT_INSTANT0("input,views", "OnMouseOver", TRACE_EVENT_SCOPE_THREAD)
//
// We can enable/disable tracing of OnMouseOver by enabling/disabling either
// category.
@@ -97,7 +98,7 @@
// This indicates to the tracing UI that these counters should be displayed
// in a single graph, as a summed area chart.
//
-// Since counters are in a global namespace, you may want to disembiguate with a
+// Since counters are in a global namespace, you may want to disambiguate with a
// unique ID, by using the TRACE_COUNTER_ID* variations.
//
// By default, trace collection is compiled in, but turned off at runtime.
@@ -132,7 +133,7 @@
// "arg1", std::string("string will be copied"));
//
//
-// Convertable notes:
+// Convertible notes:
// Converting a large data type to a string can be costly. To help with this,
// the trace framework provides an interface ConvertableToTraceFormat. If you
// inherit from it and implement the AppendAsTraceFormat method the trace
@@ -183,7 +184,7 @@
// again under lock.
//
// Without the use of these static category pointers and enabled flags all
-// trace points would carry a significant performance cost of aquiring a lock
+// trace points would carry a significant performance cost of acquiring a lock
// and resolving the category.
#ifndef BASE_DEBUG_TRACE_EVENT_H_
@@ -688,7 +689,7 @@
category_group, name, id, TRACE_EVENT_FLAG_COPY, \
arg1_name, arg1_val, arg2_name, arg2_val)
-// Macros to track the life time and value of arbitratry client objects.
+// Macros to track the life time and value of arbitrary client objects.
// See also TraceTrackableObject.
#define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_CREATE_OBJECT, \
@@ -803,7 +804,7 @@
// Implementation detail: trace event macros create temporary variables
// to keep instrumentation overhead low. These macros give each temporary
-// variable a unique name based on the line number to prevent name collissions.
+// variable a unique name based on the line number to prevent name collisions.
#define INTERNAL_TRACE_EVENT_UID3(a,b) \
trace_event_unique_##a##b
#define INTERNAL_TRACE_EVENT_UID2(a,b) \
diff --git a/base/debug/trace_event_impl.cc b/base/debug/trace_event_impl.cc
index 6e1f08c..cc22424 100644
--- a/base/debug/trace_event_impl.cc
+++ b/base/debug/trace_event_impl.cc
@@ -1174,12 +1174,6 @@
unsigned char flags) {
DCHECK(name);
- TimeDelta duration;
- if (phase == TRACE_EVENT_PHASE_END && trace_options_ & ECHO_TO_CONSOLE) {
- duration = timestamp - thread_event_start_times_[thread_id].top();
- thread_event_start_times_[thread_id].pop();
- }
-
if (flags & TRACE_EVENT_FLAG_MANGLE_ID)
id ^= process_id_hash_;
@@ -1189,20 +1183,17 @@
flags);
#endif
+ if (!IsCategoryGroupEnabled(category_group_enabled))
+ return;
+
TimeTicks now = timestamp - time_offset_;
EventCallback event_callback_copy;
NotificationHelper notifier(this);
- do {
- AutoLock lock(lock_);
- if (!IsCategoryGroupEnabled(category_group_enabled))
- return;
-
- event_callback_copy = event_callback_;
- if (logged_events_->IsFull())
- break;
-
+ // Check and update the current thread name only if the event is for the
+ // current thread to avoid locks in most cases.
+ if (thread_id == static_cast<int>(PlatformThread::CurrentId())) {
const char* new_name = ThreadIdNameManager::GetInstance()->
GetName(thread_id);
// Check if the thread name has been set or changed since the previous
@@ -1213,6 +1204,7 @@
new_name && *new_name) {
g_current_thread_name.Get().Set(new_name);
+ AutoLock lock(lock_);
hash_map<int, std::string>::iterator existing_name =
thread_names_.find(thread_id);
if (existing_name == thread_names_.end()) {
@@ -1232,15 +1224,29 @@
}
}
}
+ }
- TraceEvent trace_event(thread_id,
- now, phase, category_group_enabled, name, id,
- num_args, arg_names, arg_types, arg_values,
- convertable_values, flags);
+ TraceEvent trace_event(thread_id,
+ now, phase, category_group_enabled, name, id,
+ num_args, arg_names, arg_types, arg_values,
+ convertable_values, flags);
+
+ do {
+ AutoLock lock(lock_);
+
+ event_callback_copy = event_callback_;
+ if (logged_events_->IsFull())
+ break;
logged_events_->AddEvent(trace_event);
if (trace_options_ & ECHO_TO_CONSOLE) {
+ TimeDelta duration;
+ if (phase == TRACE_EVENT_PHASE_END) {
+ duration = timestamp - thread_event_start_times_[thread_id].top();
+ thread_event_start_times_[thread_id].pop();
+ }
+
std::string thread_name = thread_names_[thread_id];
if (thread_colors_.find(thread_name) == thread_colors_.end())
thread_colors_[thread_name] = (thread_colors_.size() % 6) + 1;
@@ -1263,6 +1269,9 @@
log << base::StringPrintf(" (%.3f ms)", duration.InMillisecondsF());
LOG(ERROR) << log.str() << "\x1b[0;m";
+
+ if (phase == TRACE_EVENT_PHASE_BEGIN)
+ thread_event_start_times_[thread_id].push(timestamp);
}
if (logged_events_->IsFull())
@@ -1272,9 +1281,6 @@
notifier.AddNotificationWhileLocked(EVENT_WATCH_NOTIFICATION);
} while (0); // release lock
- if (phase == TRACE_EVENT_PHASE_BEGIN && trace_options_ & ECHO_TO_CONSOLE)
- thread_event_start_times_[thread_id].push(timestamp);
-
notifier.SendNotificationIfAny();
if (event_callback_copy != NULL) {
event_callback_copy(phase, category_group_enabled, name, id,
@@ -1455,6 +1461,7 @@
}
void TraceLog::RemoveProcessLabel(int label_id) {
+ AutoLock lock(lock_);
base::hash_map<int, std::string>::iterator it = process_labels_.find(
label_id);
if (it == process_labels_.end())
diff --git a/base/debug/trace_event_impl.h b/base/debug/trace_event_impl.h
index c3ceec6..be1a104 100644
--- a/base/debug/trace_event_impl.h
+++ b/base/debug/trace_event_impl.h
@@ -55,7 +55,7 @@
virtual ~ConvertableToTraceFormat() {}
// Append the class info to the provided |out| string. The appended
- // data must be a valid JSON object. Strings must be propertly quoted, and
+ // data must be a valid JSON object. Strings must be properly quoted, and
// escaped. There is no processing applied to the content after it is
// appended.
virtual void AppendAsTraceFormat(std::string* out) const = 0;
@@ -65,7 +65,7 @@
// Output records are "Events" and can be obtained via the
// OutputCallback whenever the tracing system decides to flush. This
-// can happen at any time, on any thread, or you can programatically
+// can happen at any time, on any thread, or you can programmatically
// force it to happen.
class BASE_EXPORT TraceEvent {
public:
@@ -291,7 +291,7 @@
// Enable the sampling profiler.
ENABLE_SAMPLING = 1 << 2,
- // Echo to console. Events are discared.
+ // Echo to console. Events are discarded.
ECHO_TO_CONSOLE = 1 << 3
};
@@ -357,8 +357,8 @@
typedef base::Callback<void(int)> NotificationCallback;
void SetNotificationCallback(const NotificationCallback& cb);
- // Not using base::Callback because of its limited by 7 parameteters.
- // Also, using primitive type allows directly passsing callback from WebCore.
+ // Not using base::Callback because of its limited by 7 parameters.
+ // Also, using primitive type allows directly passing callback from WebCore.
// WARNING: It is possible for the previously set callback to be called
// after a call to SetEventCallback() that replaces or clears the callback.
// This callback may be invoked on any thread.
@@ -511,7 +511,7 @@
inline ~NotificationHelper();
// Called only while TraceLog::lock_ is held. This ORs the given
- // notification with any existing notifcations.
+ // notification with any existing notifications.
inline void AddNotificationWhileLocked(int notification);
// Called only while TraceLog::lock_ is NOT held. If there are any pending
diff --git a/base/platform_file_posix.cc b/base/platform_file_posix.cc
index e1bab1e..056577c 100644
--- a/base/platform_file_posix.cc
+++ b/base/platform_file_posix.cc
@@ -379,9 +379,50 @@
info->is_directory = S_ISDIR(file_info.st_mode);
info->is_symbolic_link = S_ISLNK(file_info.st_mode);
info->size = file_info.st_size;
- info->last_modified = base::Time::FromTimeT(file_info.st_mtime);
- info->last_accessed = base::Time::FromTimeT(file_info.st_atime);
- info->creation_time = base::Time::FromTimeT(file_info.st_ctime);
+
+#if defined(OS_LINUX)
+ const time_t last_modified_sec = file_info.st_mtim.tv_sec;
+ const int64 last_modified_nsec = file_info.st_mtim.tv_nsec;
+ const time_t last_accessed_sec = file_info.st_atim.tv_sec;
+ const int64 last_accessed_nsec = file_info.st_atim.tv_nsec;
+ const time_t creation_time_sec = file_info.st_ctim.tv_sec;
+ const int64 creation_time_nsec = file_info.st_ctim.tv_nsec;
+#elif defined(OS_ANDROID)
+ const time_t last_modified_sec = file_info.st_mtime;
+ const int64 last_modified_nsec = file_info.st_mtime_nsec;
+ const time_t last_accessed_sec = file_info.st_atime;
+ const int64 last_accessed_nsec = file_info.st_atime_nsec;
+ const time_t creation_time_sec = file_info.st_ctime;
+ const int64 creation_time_nsec = file_info.st_ctime_nsec;
+#elif defined(OS_MACOSX) || defined(OS_IOS) || defined(OS_BSD)
+ const time_t last_modified_sec = file_info.st_mtimespec.tv_sec;
+ const int64 last_modified_nsec = file_info.st_mtimespec.tv_nsec;
+ const time_t last_accessed_sec = file_info.st_atimespec.tv_sec;
+ const int64 last_accessed_nsec = file_info.st_atimespec.tv_nsec;
+ const time_t creation_time_sec = file_info.st_ctimespec.tv_sec;
+ const int64 creation_time_nsec = file_info.st_ctimespec.tv_nsec;
+#else
+ // TODO(gavinp): Investigate a good high resolution option for OS_NACL.
+ const time_t last_modified_sec = file_info.st_mtime;
+ const int64 last_modified_nsec = 0;
+ const time_t last_accessed_sec = file_info.st_atime;
+ const int64 last_accessed_nsec = 0;
+ const time_t creation_time_sec = file_info.st_ctime;
+ const int64 creation_time_nsec = 0;
+#endif
+
+ info->last_modified =
+ base::Time::FromTimeT(last_modified_sec) +
+ base::TimeDelta::FromMicroseconds(last_modified_nsec /
+ base::Time::kNanosecondsPerMicrosecond);
+ info->last_accessed =
+ base::Time::FromTimeT(last_accessed_sec) +
+ base::TimeDelta::FromMicroseconds(last_accessed_nsec /
+ base::Time::kNanosecondsPerMicrosecond);
+ info->creation_time =
+ base::Time::FromTimeT(creation_time_sec) +
+ base::TimeDelta::FromMicroseconds(creation_time_nsec /
+ base::Time::kNanosecondsPerMicrosecond);
return true;
}
diff --git a/base/power_monitor/power_monitor_unittest.cc b/base/power_monitor/power_monitor_unittest.cc
index 61b720e..5f7b531 100644
--- a/base/power_monitor/power_monitor_unittest.cc
+++ b/base/power_monitor/power_monitor_unittest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "base/power_monitor/power_monitor.h"
-#include "base/power_monitor/power_monitor_test_base.h"
+#include "base/test/power_monitor_test_base.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
diff --git a/base/process/internal_linux.cc b/base/process/internal_linux.cc
index 7da50b3..ee1107c 100644
--- a/base/process/internal_linux.cc
+++ b/base/process/internal_linux.cc
@@ -6,6 +6,7 @@
#include <unistd.h>
+#include <map>
#include <string>
#include <vector>
@@ -15,6 +16,7 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
+#include "base/time/time.h"
namespace base {
namespace internal {
@@ -47,19 +49,23 @@
return pid;
}
-bool ReadProcStats(pid_t pid, std::string* buffer) {
+bool ReadProcFile(const FilePath& file, std::string* buffer) {
buffer->clear();
// Synchronously reading files in /proc is safe.
ThreadRestrictions::ScopedAllowIO allow_io;
- FilePath stat_file = internal::GetProcPidDir(pid).Append(kStatFile);
- if (!file_util::ReadFileToString(stat_file, buffer)) {
- DLOG(WARNING) << "Failed to get process stats.";
+ if (!file_util::ReadFileToString(file, buffer)) {
+ DLOG(WARNING) << "Failed to read " << file.MaybeAsASCII();
return false;
}
return !buffer->empty();
}
+bool ReadProcStats(pid_t pid, std::string* buffer) {
+ FilePath stat_file = internal::GetProcPidDir(pid).Append(kStatFile);
+ return ReadProcFile(stat_file, buffer);
+}
+
bool ParseProcStats(const std::string& stats_data,
std::vector<std::string>* proc_stats) {
// |stats_data| may be empty if the process disappeared somehow.
@@ -98,6 +104,17 @@
return true;
}
+typedef std::map<std::string, std::string> ProcStatMap;
+void ParseProcStat(const std::string& contents, ProcStatMap* output) {
+ typedef std::pair<std::string, std::string> StringPair;
+ std::vector<StringPair> key_value_pairs;
+ SplitStringIntoKeyValuePairs(contents, ' ', '\n', &key_value_pairs);
+ for (size_t i = 0; i < key_value_pairs.size(); ++i) {
+ const StringPair& key_value_pair = key_value_pairs[i];
+ output->insert(key_value_pair);
+ }
+}
+
int GetProcStatsFieldAsInt(const std::vector<std::string>& proc_stats,
ProcStatsFields field_num) {
DCHECK_GE(field_num, VM_PPID);
@@ -138,5 +155,36 @@
return GetProcStatsFieldAsSizeT(proc_stats, field_num);
}
+Time GetBootTime() {
+ FilePath path("/proc/stat");
+ std::string contents;
+ if (!ReadProcFile(path, &contents))
+ return Time();
+ ProcStatMap proc_stat;
+ ParseProcStat(contents, &proc_stat);
+ ProcStatMap::const_iterator btime_it = proc_stat.find("btime");
+ if (btime_it == proc_stat.end())
+ return Time();
+ int btime;
+ if (!StringToInt(btime_it->second, &btime))
+ return Time();
+ return Time::FromTimeT(btime);
+}
+
+TimeDelta ClockTicksToTimeDelta(int clock_ticks) {
+ // This queries the /proc-specific scaling factor which is
+ // conceptually the system hertz. To dump this value on another
+ // system, try
+ // od -t dL /proc/self/auxv
+ // and look for the number after 17 in the output; mine is
+ // 0000040 17 100 3 134512692
+ // which means the answer is 100.
+ // It may be the case that this value is always 100.
+ static const int kHertz = sysconf(_SC_CLK_TCK);
+
+ return TimeDelta::FromMicroseconds(
+ Time::kMicrosecondsPerSecond * clock_ticks / kHertz);
+}
+
} // namespace internal
} // namespace base
diff --git a/base/process/internal_linux.h b/base/process/internal_linux.h
index 88d32ee..a10cee3 100644
--- a/base/process/internal_linux.h
+++ b/base/process/internal_linux.h
@@ -11,6 +11,10 @@
#include "base/files/file_path.h"
namespace base {
+
+class Time;
+class TimeDelta;
+
namespace internal {
// "/proc"
@@ -49,6 +53,7 @@
VM_UTIME = 13, // Time scheduled in user mode in clock ticks.
VM_STIME = 14, // Time scheduled in kernel mode in clock ticks.
VM_NUMTHREADS = 19, // Number of threads.
+ VM_STARTTIME = 21, // The time the process started in clock ticks.
VM_VSIZE = 22, // Virtual memory size in bytes.
VM_RSS = 23, // Resident Set Size in pages.
};
@@ -72,6 +77,12 @@
size_t ReadProcStatsAndGetFieldAsSizeT(pid_t pid,
ProcStatsFields field_num);
+// Returns the time that the OS started. Clock ticks are relative to this.
+Time GetBootTime();
+
+// Converts Linux clock ticks to a wall time delta.
+TimeDelta ClockTicksToTimeDelta(int clock_ticks);
+
} // namespace internal
} // namespace base
diff --git a/base/process/process_info.h b/base/process/process_info.h
index e72c56b..e9e7b4e 100644
--- a/base/process/process_info.h
+++ b/base/process/process_info.h
@@ -15,9 +15,9 @@
// Vends information about the current process.
class BASE_EXPORT CurrentProcessInfo {
public:
- // Returns the time at which the process was launched or NULL if an error
- // occurred retrieving the information.
- static const Time* CreationTime();
+ // Returns the time at which the process was launched. May be empty if an
+ // error occurred retrieving the information.
+ static const Time CreationTime();
};
} // namespace base
diff --git a/base/process/process_info_linux.cc b/base/process/process_info_linux.cc
new file mode 100644
index 0000000..da34c18
--- /dev/null
+++ b/base/process/process_info_linux.cc
@@ -0,0 +1,27 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/process/process_info.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/process/internal_linux.h"
+#include "base/process/process_handle.h"
+#include "base/time/time.h"
+
+namespace base {
+
+//static
+const Time CurrentProcessInfo::CreationTime() {
+ ProcessHandle pid = GetCurrentProcessHandle();
+ int start_ticks = internal::ReadProcStatsAndGetFieldAsInt(
+ pid, internal::VM_STARTTIME);
+ DCHECK(start_ticks);
+ TimeDelta start_offset = internal::ClockTicksToTimeDelta(start_ticks);
+ Time boot_time = internal::GetBootTime();
+ DCHECK(!boot_time.is_null());
+ return Time(boot_time + start_offset);
+}
+
+} // namespace base
diff --git a/base/process/process_info_mac.cc b/base/process/process_info_mac.cc
index d83acd1..ab8394b 100644
--- a/base/process/process_info_mac.cc
+++ b/base/process/process_info_mac.cc
@@ -12,32 +12,20 @@
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
-namespace {
+namespace base {
-using base::Time;
-
-// Returns the process creation time, or NULL if an error occurred.
-Time* ProcessCreationTimeInternal() {
+//static
+const Time CurrentProcessInfo::CreationTime() {
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
size_t len = 0;
if (sysctl(mib, arraysize(mib), NULL, &len, NULL, 0) < 0)
- return NULL;
+ return Time();
scoped_ptr_malloc<struct kinfo_proc>
proc(static_cast<struct kinfo_proc*>(malloc(len)));
if (sysctl(mib, arraysize(mib), proc.get(), &len, NULL, 0) < 0)
- return NULL;
- return new Time(Time::FromTimeVal(proc->kp_proc.p_un.__p_starttime));
-}
-
-} // namespace
-
-namespace base {
-
-//static
-const Time* CurrentProcessInfo::CreationTime() {
- static Time* process_creation_time = ProcessCreationTimeInternal();
- return process_creation_time;
+ return Time();
+ return Time::FromTimeVal(proc->kp_proc.p_un.__p_starttime);
}
} // namespace base
diff --git a/base/process/process_info_win.cc b/base/process/process_info_win.cc
index 5290b76..b930ae6 100644
--- a/base/process/process_info_win.cc
+++ b/base/process/process_info_win.cc
@@ -9,29 +9,17 @@
#include "base/basictypes.h"
#include "base/time/time.h"
-namespace {
+namespace base {
-using base::Time;
-
-// Returns the process creation time, or NULL if an error occurred.
-Time* ProcessCreationTimeInternal() {
+//static
+const Time CurrentProcessInfo::CreationTime() {
FILETIME creation_time = {};
FILETIME ignore = {};
if (::GetProcessTimes(::GetCurrentProcess(), &creation_time, &ignore,
&ignore, &ignore) == false)
- return NULL;
+ return Time();
- return new Time(Time::FromFileTime(creation_time));
-}
-
-} // namespace
-
-namespace base {
-
-//static
-const Time* CurrentProcessInfo::CreationTime() {
- static Time* process_creation_time = ProcessCreationTimeInternal();
- return process_creation_time;
+ return Time::FromFileTime(creation_time);
}
} // namespace base
diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc
index 0171020..1c86ee4 100644
--- a/base/process/process_metrics_linux.cc
+++ b/base/process/process_metrics_linux.cc
@@ -167,16 +167,6 @@
}
double ProcessMetrics::GetCPUUsage() {
- // This queries the /proc-specific scaling factor which is
- // conceptually the system hertz. To dump this value on another
- // system, try
- // od -t dL /proc/self/auxv
- // and look for the number after 17 in the output; mine is
- // 0000040 17 100 3 134512692
- // which means the answer is 100.
- // It may be the case that this value is always 100.
- static const int kHertz = sysconf(_SC_CLK_TCK);
-
struct timeval now;
int retval = gettimeofday(&now, NULL);
if (retval)
@@ -200,8 +190,10 @@
// We have the number of jiffies in the time period. Convert to percentage.
// Note this means we will go *over* 100 in the case where multiple threads
// are together adding to more than one CPU's worth.
- int percentage = 100 * (cpu - last_cpu_) /
- (kHertz * TimeDelta::FromMicroseconds(time_delta).InSecondsF());
+ TimeDelta cpu_time = internal::ClockTicksToTimeDelta(cpu);
+ TimeDelta last_cpu_time = internal::ClockTicksToTimeDelta(last_cpu_);
+ int percentage = 100 * (cpu_time - last_cpu_time).InSecondsF() /
+ TimeDelta::FromMicroseconds(time_delta).InSecondsF();
last_time_ = time;
last_cpu_ = cpu;
diff --git a/base/strings/string_split.cc b/base/strings/string_split.cc
index d959fd0..210789c 100644
--- a/base/strings/string_split.cc
+++ b/base/strings/string_split.cc
@@ -80,12 +80,11 @@
return true;
}
-bool SplitStringIntoKeyValuePairs(
- const std::string& line,
- char key_value_delimiter,
- char key_value_pair_delimiter,
- std::vector<std::pair<std::string, std::string> >* kv_pairs) {
- kv_pairs->clear();
+bool SplitStringIntoKeyValuePairs(const std::string& line,
+ char key_value_delimiter,
+ char key_value_pair_delimiter,
+ StringPairs* key_value_pairs) {
+ key_value_pairs->clear();
std::vector<std::string> pairs;
SplitString(line, key_value_pair_delimiter, &pairs);
@@ -107,7 +106,7 @@
success = false;
}
DCHECK_LE(value.size(), 1U);
- kv_pairs->push_back(
+ key_value_pairs->push_back(
make_pair(key, value.empty() ? std::string() : value[0]));
}
return success;
diff --git a/base/strings/string_split.h b/base/strings/string_split.h
index 2803752..faf08d6 100644
--- a/base/strings/string_split.h
+++ b/base/strings/string_split.h
@@ -36,11 +36,13 @@
std::string* key,
std::vector<std::string>* values);
+typedef std::vector<std::pair<std::string, std::string> > StringPairs;;
+
BASE_EXPORT bool SplitStringIntoKeyValuePairs(
const std::string& line,
char key_value_delimiter,
char key_value_pair_delimiter,
- std::vector<std::pair<std::string, std::string> >* kv_pairs);
+ StringPairs* key_value_pairs);
// The same as SplitString, but use a substring delimiter instead of a char.
BASE_EXPORT void SplitStringUsingSubstr(const string16& str,
diff --git a/base/power_monitor/power_monitor_test_base.cc b/base/test/power_monitor_test_base.cc
similarity index 96%
rename from base/power_monitor/power_monitor_test_base.cc
rename to base/test/power_monitor_test_base.cc
index 990b8d1..73438ea 100644
--- a/base/power_monitor/power_monitor_test_base.cc
+++ b/base/test/power_monitor_test_base.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 "base/power_monitor/power_monitor_test_base.h"
+#include "base/test/power_monitor_test_base.h"
#include "base/message_loop/message_loop.h"
#include "base/power_monitor/power_monitor.h"
diff --git a/base/power_monitor/power_monitor_test_base.h b/base/test/power_monitor_test_base.h
similarity index 84%
rename from base/power_monitor/power_monitor_test_base.h
rename to base/test/power_monitor_test_base.h
index 6f82fc0..95b530e 100644
--- a/base/power_monitor/power_monitor_test_base.h
+++ b/base/test/power_monitor_test_base.h
@@ -2,13 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef BASE_TEST_POWER_MONITOR_TEST_BASE_H_
+#define BASE_TEST_POWER_MONITOR_TEST_BASE_H_
+
#include "base/message_loop/message_loop.h"
#include "base/power_monitor/power_monitor.h"
#include "base/power_monitor/power_monitor_source.h"
namespace base {
-class BASE_EXPORT PowerMonitorTestSource : public PowerMonitorSource {
+class PowerMonitorTestSource : public PowerMonitorSource {
public:
PowerMonitorTestSource();
virtual ~PowerMonitorTestSource();
@@ -24,7 +27,7 @@
MessageLoop message_loop_;
};
-class BASE_EXPORT PowerMonitorTestObserver : public PowerObserver {
+class PowerMonitorTestObserver : public PowerObserver {
public:
PowerMonitorTestObserver();
virtual ~PowerMonitorTestObserver();
@@ -47,4 +50,6 @@
int resumes_; // Count of OnResume notifications.
};
-} // namespace base
\ No newline at end of file
+} // namespace base
+
+#endif // BASE_TEST_POWER_MONITOR_TEST_BASE_H_
\ No newline at end of file
diff --git a/base/win/registry.cc b/base/win/registry.cc
index 588bd27..8bfe432 100644
--- a/base/win/registry.cc
+++ b/base/win/registry.cc
@@ -39,6 +39,11 @@
watch_event_(0) {
}
+RegKey::RegKey(HKEY key)
+ : key_(key),
+ watch_event_(0) {
+}
+
RegKey::RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access)
: key_(NULL),
watch_event_(0) {
@@ -112,6 +117,20 @@
}
}
+void RegKey::Set(HKEY key) {
+ if (key_ != key) {
+ Close();
+ key_ = key;
+ }
+}
+
+HKEY RegKey::Take() {
+ StopWatching();
+ HKEY key = key_;
+ key_ = NULL;
+ return key;
+}
+
bool RegKey::HasValue(const wchar_t* name) const {
return RegQueryValueEx(key_, name, 0, NULL, NULL, NULL) == ERROR_SUCCESS;
}
diff --git a/base/win/registry.h b/base/win/registry.h
index 7a3d970..f97f4f5 100644
--- a/base/win/registry.h
+++ b/base/win/registry.h
@@ -26,6 +26,7 @@
class BASE_EXPORT RegKey {
public:
RegKey();
+ explicit RegKey(HKEY key);
RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access);
~RegKey();
@@ -46,6 +47,12 @@
// Closes this reg key.
void Close();
+ // Replaces the handle of the registry key and takes ownership of the handle.
+ void Set(HKEY key);
+
+ // Transfers ownership away from this object.
+ HKEY Take();
+
// Returns false if this key does not have the specified value, of if an error
// occurrs while attempting to access it.
bool HasValue(const wchar_t* value_name) const;
diff --git a/build/all.gyp b/build/all.gyp
index 865bb18..d90b5a5 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -255,7 +255,7 @@
'../sandbox/sandbox.gyp:sbox_integration_tests',
'../sandbox/sandbox.gyp:sbox_unittests',
'../sandbox/sandbox.gyp:sbox_validation_tests',
- '../third_party/WebKit/Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp:copy_TestNetscapePlugIn',
+ '../third_party/WebKit/public/blink_test_plugin.gyp:blink_test_plugin',
'../ui/app_list/app_list.gyp:app_list_unittests',
'../ui/views/views.gyp:views_unittests',
],
@@ -645,7 +645,7 @@
'../ui/views/views.gyp:views_unittests',
'../url/url.gyp:url_unittests',
'../webkit/renderer/compositor_bindings/compositor_bindings_tests.gyp:webkit_compositor_bindings_unittests',
- '../third_party/WebKit/Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp:copy_TestNetscapePlugIn',
+ '../third_party/WebKit/public/blink_test_plugin.gyp:blink_test_plugin',
],
'conditions': [
['target_arch!="x64"', {
diff --git a/build/android/ant/apk-codegen.xml b/build/android/ant/apk-codegen.xml
index e60d6ca..37abb07 100644
--- a/build/android/ant/apk-codegen.xml
+++ b/build/android/ant/apk-codegen.xml
@@ -26,15 +26,13 @@
<!-- tools location -->
<property name="sdk.dir" location="${ANDROID_SDK_ROOT}"/>
- <property name="target" value="android-${ANDROID_SDK_VERSION}"/>
- <property name="android.tools.dir" location="${sdk.dir}/tools" />
- <property name="android.platform.tools.dir" location="${sdk.dir}/platform-tools" />
- <property name="aapt" location="${android.platform.tools.dir}/aapt" />
+ <property name="android.sdk.tools.dir" location="${ANDROID_SDK_TOOLS}" />
+ <property name="aapt" location="${android.sdk.tools.dir}/aapt" />
<property name="project.target.android.jar" location="${ANDROID_SDK_JAR}" />
<!-- jar file from where the tasks are loaded -->
<path id="android.antlibs">
- <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
+ <pathelement path="${sdk.dir}/tools/lib/ant-tasks.jar" />
</path>
<!-- Custom tasks -->
diff --git a/build/android/ant/apk-compile.xml b/build/android/ant/apk-compile.xml
index 10ffd37..4f3d664 100644
--- a/build/android/ant/apk-compile.xml
+++ b/build/android/ant/apk-compile.xml
@@ -39,7 +39,7 @@
<!-- jar file from where the tasks are loaded -->
<path id="android.antlibs">
- <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
+ <pathelement path="${sdk.dir}/tools/lib/ant-tasks.jar" />
</path>
<!-- Custom tasks -->
diff --git a/build/android/ant/apk-obfuscate.xml b/build/android/ant/apk-obfuscate.xml
index d0600ca..b15ce73 100644
--- a/build/android/ant/apk-obfuscate.xml
+++ b/build/android/ant/apk-obfuscate.xml
@@ -26,7 +26,6 @@
<!-- tools location -->
<property name="sdk.dir" location="${ANDROID_SDK_ROOT}"/>
- <property name="target" value="android-${ANDROID_SDK_VERSION}"/>
<property name="android.tools.dir" location="${sdk.dir}/tools" />
<property name="project.target.android.jar" location="${ANDROID_SDK_JAR}" />
@@ -37,7 +36,7 @@
<!-- jar file from where the tasks are loaded -->
<path id="android.antlibs">
- <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
+ <pathelement path="${sdk.dir}/tools/lib/ant-tasks.jar" />
</path>
<!-- Custom tasks -->
diff --git a/build/android/ant/apk-package-resources.xml b/build/android/ant/apk-package-resources.xml
index c29dff7..3bfd3c9 100644
--- a/build/android/ant/apk-package-resources.xml
+++ b/build/android/ant/apk-package-resources.xml
@@ -24,12 +24,11 @@
<!-- tools location -->
<property name="sdk.dir" location="${ANDROID_SDK_ROOT}"/>
<property name="project.target.android.jar" location="${ANDROID_SDK_JAR}" />
- <property name="android.tools.dir" location="${sdk.dir}/tools" />
- <property name="android.platform.tools.dir" location="${sdk.dir}/platform-tools" />
+ <property name="android.sdk.tools.dir" location="${ANDROID_SDK_TOOLS}" />
<!-- jar file from where the tasks are loaded -->
<path id="android.antlibs">
- <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
+ <pathelement path="${sdk.dir}/tools/lib/ant-tasks.jar" />
</path>
<!-- Custom tasks -->
@@ -48,7 +47,7 @@
<property name="asset.dir" value="${ASSET_DIR}" />
<property name="asset.absolute.dir" location="${asset.dir}" />
- <property name="aapt" location="${android.platform.tools.dir}/aapt" />
+ <property name="aapt" location="${android.sdk.tools.dir}/aapt" />
<property name="version.code" value="${APP_MANIFEST_VERSION_CODE}"/>
<property name="version.name" value="${APP_MANIFEST_VERSION_NAME}"/>
diff --git a/build/android/ant/apk-package.xml b/build/android/ant/apk-package.xml
index 61524f9..eeb156c 100644
--- a/build/android/ant/apk-package.xml
+++ b/build/android/ant/apk-package.xml
@@ -24,7 +24,7 @@
<!-- jar file from where the tasks are loaded -->
<path id="android.antlibs">
- <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
+ <pathelement path="${sdk.dir}/tools/lib/ant-tasks.jar" />
</path>
<!-- Custom tasks -->
diff --git a/build/android/bb_run_sharded_steps.py b/build/android/bb_run_sharded_steps.py
index 086a3a1..9b36957 100755
--- a/build/android/bb_run_sharded_steps.py
+++ b/build/android/bb_run_sharded_steps.py
@@ -175,12 +175,10 @@
os.kill(int(pid), signal.SIGQUIT)
except Exception as e:
logging.warning('Failed killing %s %s %s', server, pid, e)
- # Restart the adb server with full trace, and redirect stderr to stdout
- # so the extra tracing won't confuse higher up layers.
- os.environ['ADB_TRACE'] = 'all'
+ # Restart the adb server with taskset to set a single CPU affinity.
cmd_helper.RunCmd(['adb', 'kill-server'])
- cmd_helper.RunCmd(['adb', 'start-server'])
- cmd_helper.RunCmd(['adb', 'root'])
+ cmd_helper.RunCmd(['taskset', '-c', '0', 'adb', 'start-server'])
+ cmd_helper.RunCmd(['taskset', '-c', '0', 'adb', 'root'])
i = 1
while not android_commands.GetAttachedDevices():
time.sleep(i)
diff --git a/build/android/buildbot/bb_device_steps.py b/build/android/buildbot/bb_device_steps.py
index 8bc537f..32438ae 100755
--- a/build/android/buildbot/bb_device_steps.py
+++ b/build/android/buildbot/bb_device_steps.py
@@ -64,7 +64,8 @@
'webview:android_webview/test/data/device_files'),
])
-VALID_TESTS = set(['chromedriver', 'ui', 'unit', 'webkit', 'webkit_layout'])
+VALID_TESTS = set(['chromedriver', 'ui', 'unit', 'webkit', 'webkit_layout',
+ 'webrtc'])
RunCmd = bb_utils.RunCmd
@@ -277,13 +278,18 @@
RunWebkitLint(options.target)
+def RunWebRTCTests(options):
+ RunTestSuites(options, gtest_config.WEBRTC_TEST_SUITES)
+
+
def GetTestStepCmds():
return [
('chromedriver', RunChromeDriverTests),
('unit', RunUnitTests),
('ui', RunInstrumentationTests),
('webkit', RunWebkitTests),
- ('webkit_layout', RunWebkitLayoutTests)
+ ('webkit_layout', RunWebkitLayoutTests),
+ ('webrtc', RunWebRTCTests),
]
diff --git a/build/android/buildbot/bb_run_bot.py b/build/android/buildbot/bb_run_bot.py
index 6718aef..7637024 100755
--- a/build/android/buildbot/bb_run_bot.py
+++ b/build/android/buildbot/bb_run_bot.py
@@ -161,6 +161,7 @@
B('webkit-latest-contentshell', H(compile_step),
T(['webkit_layout'], ['--auto-reconnect'])),
B('builder-unit-tests', H(compile_step), T(['unit'])),
+ B('webrtc-tests', H(std_test_steps), T(['webrtc'], [flakiness_server])),
# Generic builder config (for substring match).
B('builder', H(std_build_steps)),
@@ -179,6 +180,7 @@
('try-tests', 'main-tests'),
('try-fyi-tests', 'fyi-tests'),
('webkit-latest-tests', 'main-tests'),
+ ('webrtc-builder', 'main-builder-rel'),
]
for to_id, from_id in copy_map:
assert to_id not in bot_map
diff --git a/build/android/dex_action.gypi b/build/android/dex_action.gypi
index c41effb..ac956b6 100644
--- a/build/android/dex_action.gypi
+++ b/build/android/dex_action.gypi
@@ -47,7 +47,7 @@
'action': [
'python', '<(DEPTH)/build/android/gyp/dex.py',
'--dex-path=<(output_path)',
- '--android-sdk-root=<(android_sdk_root)',
+ '--android-sdk-tools=<(android_sdk_tools)',
'--configuration-name=<(CONFIGURATION_NAME)',
'--proguard-enabled=<(proguard_enabled)',
'--proguard-enabled-input-path=<(proguard_enabled_input_path)',
diff --git a/build/android/envsetup.sh b/build/android/envsetup.sh
index 33b6764..f9e3e5e 100755
--- a/build/android/envsetup.sh
+++ b/build/android/envsetup.sh
@@ -88,9 +88,6 @@
echo "${CHROME_SRC}"
fi
-# Android sdk platform version to use
-export ANDROID_SDK_VERSION=17
-
if [[ "${ANDROID_SDK_BUILD}" -eq 1 ]]; then
if [[ -z "${TARGET_ARCH}" ]]; then
return 1
diff --git a/build/android/envsetup_functions.sh b/build/android/envsetup_functions.sh
index d1a894b..9554bc9 100755
--- a/build/android/envsetup_functions.sh
+++ b/build/android/envsetup_functions.sh
@@ -62,6 +62,8 @@
export PATH=$PATH:${ANDROID_NDK_ROOT}
export PATH=$PATH:${ANDROID_SDK_ROOT}/tools
export PATH=$PATH:${ANDROID_SDK_ROOT}/platform-tools
+ export PATH=$PATH:${ANDROID_SDK_ROOT}/build-tools/\
+${ANDROID_SDK_BUILD_TOOLS_VERSION}
# This must be set before ANDROID_TOOLCHAIN, so that clang could find the
# gold linker.
@@ -216,6 +218,9 @@
# > make
################################################################################
sdk_build_init() {
+ export ANDROID_SDK_VERSION=18
+ export ANDROID_SDK_BUILD_TOOLS_VERSION=18.0.1
+
# If ANDROID_NDK_ROOT is set when envsetup is run, use the ndk pointed to by
# the environment variable. Otherwise, use the default ndk from the tree.
if [[ -z "${ANDROID_NDK_ROOT}" || ! -d "${ANDROID_NDK_ROOT}" ]]; then
@@ -252,6 +257,9 @@
return 1
fi
+ # Directory containing build-tools: aapt, aidl, dx
+ export ANDROID_SDK_TOOLS="${ANDROID_SDK_ROOT}/build-tools/\
+${ANDROID_SDK_BUILD_TOOLS_VERSION}"
}
################################################################################
@@ -260,6 +268,9 @@
# settings specified there.
#############################################################################
webview_build_init() {
+ # Use the latest API in the AOSP prebuilts directory (change with AOSP roll).
+ export ANDROID_SDK_VERSION=17
+
# For the WebView build we always use the NDK and SDK in the Android tree,
# and we don't touch ANDROID_TOOLCHAIN which is already set by Android.
export ANDROID_NDK_ROOT=${ANDROID_BUILD_TOP}/prebuilts/ndk/8
diff --git a/build/android/findbugs_filter/findbugs_exclude.xml b/build/android/findbugs_filter/findbugs_exclude.xml
index ab27ae4..7b6860d 100644
--- a/build/android/findbugs_filter/findbugs_exclude.xml
+++ b/build/android/findbugs_filter/findbugs_exclude.xml
@@ -21,11 +21,16 @@
<Match>
<Class name="~org\.chromium\.content\..*\.NativeLibraries.*?" />
</Match>
+ <!-- Ignore errors in JavaBridge due to reflection. -->
<Match>
<Class name="~.*\.JavaBridge.*"/>
- <!-- Ignore errors in JavaBridge due to reflection. -->
<Bug code="UuF,UrF,UMAC" />
</Match>
+ <!-- "Struct" like classes expect to have unused public data members -->
+ <Match>
+ <Class name="~.*android_webview.*FileChooserParams"/>
+ <Bug code="UrF" />
+ </Match>
<!-- Ignore "reliance on default String encoding" warnings, as we're not multi-platform -->
<Bug pattern="DM_DEFAULT_ENCODING" />
<!-- Ignore bugs that are often false-positives in test code -->
diff --git a/build/android/gyp/apk_install.py b/build/android/gyp/apk_install.py
index f0ed973..e308aab 100755
--- a/build/android/gyp/apk_install.py
+++ b/build/android/gyp/apk_install.py
@@ -54,8 +54,6 @@
def main(argv):
parser = optparse.OptionParser()
- parser.add_option('--android-sdk-tools',
- help='Path to Android SDK tools.')
parser.add_option('--apk-path',
help='Path to .apk to install.')
parser.add_option('--install-record',
diff --git a/build/android/gyp/dex.py b/build/android/gyp/dex.py
index 86f3878..21e1183 100755
--- a/build/android/gyp/dex.py
+++ b/build/android/gyp/dex.py
@@ -14,7 +14,7 @@
def DoDex(options, paths):
- dx_binary = os.path.join(options.android_sdk_root, 'platform-tools', 'dx')
+ dx_binary = os.path.join(options.android_sdk_tools, 'dx')
dex_cmd = [dx_binary, '--dex', '--output', options.dex_path] + paths
record_path = '%s.md5.stamp' % options.dex_path
@@ -29,7 +29,8 @@
def main(argv):
parser = optparse.OptionParser()
- parser.add_option('--android-sdk-root', help='Android sdk root directory.')
+ parser.add_option('--android-sdk-tools',
+ help='Android sdk build tools directory.')
parser.add_option('--dex-path', help='Dex output path.')
parser.add_option('--configuration-name',
help='The build CONFIGURATION_NAME.')
diff --git a/build/android/gyp/process_resources.py b/build/android/gyp/process_resources.py
index 40f1017..393a666 100755
--- a/build/android/gyp/process_resources.py
+++ b/build/android/gyp/process_resources.py
@@ -21,7 +21,7 @@
parser = optparse.OptionParser()
parser.add_option('--android-sdk', help='path to the Android SDK folder')
parser.add_option('--android-sdk-tools',
- help='path to the Android SDK platform tools folder')
+ help='path to the Android SDK build tools folder')
parser.add_option('--R-dir', help='directory to hold generated R.java')
parser.add_option('--res-dirs',
help='directories containing resources to be packaged')
@@ -43,8 +43,8 @@
parser.error('No positional arguments should be given.')
# Check that required options have been provided.
- required_options = ('android_sdk', 'android_sdk_tools', 'R_dir', 'res_dirs',
- 'crunch_input_dir', 'crunch_output_dir')
+ required_options = ('android_sdk', 'android_sdk_tools', 'R_dir',
+ 'res_dirs', 'crunch_input_dir', 'crunch_output_dir')
build_utils.CheckOptions(options, parser, required=required_options)
return options
diff --git a/build/android/pylib/cmd_helper.py b/build/android/pylib/cmd_helper.py
index de091ef..1237912 100644
--- a/build/android/pylib/cmd_helper.py
+++ b/build/android/pylib/cmd_helper.py
@@ -100,7 +100,8 @@
class OutDirectory(object):
- _out_directory = os.path.join(constants.DIR_SOURCE_ROOT, 'out')
+ _out_directory = os.path.join(constants.DIR_SOURCE_ROOT,
+ os.environ.get('CHROMIUM_OUT_DIR','out'))
@staticmethod
def set(out_directory):
OutDirectory._out_directory = out_directory
diff --git a/build/android/pylib/constants.py b/build/android/pylib/constants.py
index 6ca9a31..6cbe727 100644
--- a/build/android/pylib/constants.py
+++ b/build/android/pylib/constants.py
@@ -74,7 +74,7 @@
SCREENSHOTS_DIR = os.path.join(DIR_SOURCE_ROOT, 'out_screenshots')
-ANDROID_SDK_VERSION = 17
+ANDROID_SDK_VERSION = 18
ANDROID_SDK_ROOT = os.path.join(DIR_SOURCE_ROOT,
'third_party/android_tools/sdk')
ANDROID_NDK_ROOT = os.path.join(DIR_SOURCE_ROOT,
diff --git a/build/android/pylib/gtest/filter/ui_unittests_disabled b/build/android/pylib/gtest/filter/ui_unittests_disabled
index ac8c536..57db61f 100644
--- a/build/android/pylib/gtest/filter/ui_unittests_disabled
+++ b/build/android/pylib/gtest/filter/ui_unittests_disabled
@@ -4,10 +4,13 @@
CanvasTest.StringWidth
ClipboardTest.RTFTest
FontListTest.FontDescString_FromFont
+FontListTest.FontDescString_FromFontNamesStyleAndSize
FontListTest.FontDescString_FromFontVector
FontListTest.FontDescString_FromFontWithNonNormalStyle
FontListTest.Fonts_DeriveFontList
FontListTest.Fonts_DeriveFontListWithSize
+FontListTest.Fonts_DeriveFontListWithSizeDelta
+FontListTest.Fonts_DeriveFontListWithSizeDeltaAndStyle
FontListTest.Fonts_DescStringWithStyleInFlexibleFormat_RoundTrip
FontListTest.Fonts_FontVector_RoundTrip
FontListTest.Fonts_FromDescString
diff --git a/build/android/pylib/gtest/gtest_config.py b/build/android/pylib/gtest/gtest_config.py
index d74c032..f77d858 100644
--- a/build/android/pylib/gtest/gtest_config.py
+++ b/build/android/pylib/gtest/gtest_config.py
@@ -6,7 +6,6 @@
# Add new suites here before upgrading them to the stable list below.
EXPERIMENTAL_TEST_SUITES = [
- 'content_browsertests',
]
# Do not modify this list without approval of an android owner.
@@ -30,4 +29,20 @@
'webkit_unit_tests',
'breakpad_unittests',
'sandbox_linux_unittests',
+ 'content_browsertests',
+]
+
+WEBRTC_TEST_SUITES = [
+ 'audio_decoder_unittests',
+ 'common_audio_unittests',
+ 'common_video_unittests',
+ 'metrics_unittests',
+ 'modules_integrationtests',
+ 'modules_unittests',
+ 'neteq_unittests',
+ 'system_wrappers_unittests',
+ 'test_support_unittests',
+ 'tools_unittests',
+ 'video_engine_core_unittests',
+ 'voice_engine_unittests',
]
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 8655720..acee213 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -357,16 +357,22 @@
def AddMonkeyTestOptions(option_parser):
"""Adds monkey test options to |option_parser|."""
+
+ option_parser.usage = '%prog monkey [options]'
+ option_parser.command_list = []
+ option_parser.example = (
+ '%prog monkey --package-name=org.chromium.content_shell_apk'
+ ' --activity-name=.ContentShellActivity')
+
option_parser.add_option('--package-name', help='Allowed package.')
option_parser.add_option(
- '--activity-name', default='com.google.android.apps.chrome.Main',
- help='Name of the activity to start [default: %default].')
+ '--activity-name', help='Name of the activity to start.')
option_parser.add_option(
'--event-count', default=10000, type='int',
help='Number of events to generate [default: %default].')
option_parser.add_option(
'--category', default='',
- help='A list of allowed categories [default: %default].')
+ help='A list of allowed categories.')
option_parser.add_option(
'--throttle', default=100, type='int',
help='Delay between events (ms) [default: %default]. ')
@@ -676,8 +682,7 @@
command_list=VALID_COMMANDS.keys())
if len(argv) < 2 or argv[1] not in VALID_COMMANDS:
- option_parser.print_help()
- return 0
+ option_parser.error('Invalid command.')
command = argv[1]
VALID_COMMANDS[command].add_options_func(option_parser)
options, args = option_parser.parse_args(argv)
diff --git a/build/common.gypi b/build/common.gypi
index 72e9ecb7..1589955 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -530,8 +530,8 @@
'native_memory_pressure_signals%': 1,
}],
- # Enable autofill dialog for Mac and Views-enabled platforms for now.
- ['toolkit_views==1 or OS=="mac"', {
+ # Enable autofill dialog for Android, Mac and Views-enabled platforms.
+ ['toolkit_views==1 or (OS=="android" and android_webview_build==0) or OS=="mac"', {
'enable_autofill_dialog%': 1
}],
@@ -963,11 +963,6 @@
# remaining.
'win_third_party_warn_as_error%': 'true',
- # This is the location of the sandbox binary. Chrome looks for this before
- # running the zygote process. If found, and SUID, it will be used to
- # sandbox the zygote process and, thus, all renderer processes.
- 'linux_sandbox_path%': '',
-
# Clang stuff.
'clang%': '<(clang)',
'make_clang_dir%': 'third_party/llvm-build/Release+Asserts',
@@ -1227,12 +1222,15 @@
'android_sdk_root%': '<!(cd <(DEPTH) && pwd -P)/third_party/android_tools/sdk/',
'android_host_arch%': '<!(uname -m)',
# Android API-level of the SDK used for compilation.
- 'android_sdk_version%': '17',
+ 'android_sdk_version%': '<!(/bin/echo -n ${ANDROID_SDK_VERSION})',
+ # Android SDK build tools (e.g. dx, aapt, aidl)
+ 'android_sdk_tools%': '<!(/bin/echo -n ${ANDROID_SDK_TOOLS})',
},
# Copy conditionally-set variables out one scope.
'android_ndk_root%': '<(android_ndk_root)',
'android_sdk_root%': '<(android_sdk_root)',
'android_sdk_version%': '<(android_sdk_version)',
+ 'android_sdk_tools%': '<(android_sdk_tools)',
'android_stlport_root': '<(android_ndk_root)/sources/cxx-stl/stlport',
'android_sdk%': '<(android_sdk_root)/platforms/android-<(android_sdk_version)',
@@ -1278,7 +1276,7 @@
'android_ndk_include': '<(android_ndk_sysroot)/usr/include',
'android_ndk_lib': '<(android_ndk_sysroot)/usr/lib',
- 'android_sdk_tools%': '<(android_sdk_root)/platform-tools',
+ 'android_sdk_tools%': '<(android_sdk_tools)',
'android_sdk%': '<(android_sdk)',
'android_sdk_jar%': '<(android_sdk)/android.jar',
diff --git a/build/install-build-deps-android.sh b/build/install-build-deps-android.sh
index d8bc11a..f6b445b 100755
--- a/build/install-build-deps-android.sh
+++ b/build/install-build-deps-android.sh
@@ -46,6 +46,9 @@
# common
sudo apt-get -y install lighttpd python-pexpect xvfb x11-utils
+# Few binaries in the Android SDK require 32-bit libraries on the host.
+sudo apt-get -y install lib32z1 g++-multilib
+
if /usr/bin/lsb_release -r -s | grep -q "12."; then
# Ubuntu 12.x
sudo apt-get -y install ant
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt
index 277e3fe..ed15d46 100644
--- a/build/ios/grit_whitelist.txt
+++ b/build/ios/grit_whitelist.txt
@@ -204,6 +204,7 @@
IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_TITLE
IDS_CHROME_TO_DEVICE_PRINT_TO_PHONE
IDS_CHROME_TO_DEVICE_SNAPSHOTS
+IDS_CONTENT_CONTEXT_SEARCHWEBFORIMAGE
IDS_COPY_URL_MAC
IDS_COULDNT_OPEN_PROFILE_ERROR
IDS_CRASHES_BUG_LINK_LABEL
diff --git a/build/java_apk.gypi b/build/java_apk.gypi
index e388690..2457d3a 100644
--- a/build/java_apk.gypi
+++ b/build/java_apk.gypi
@@ -364,7 +364,6 @@
],
'action': [
'python', '<(DEPTH)/build/android/gyp/apk_install.py',
- '--android-sdk-tools=<(android_sdk_tools)',
'--apk-path=<(incomplete_apk_path)',
'--build-device-configuration=<(build_device_config_path)',
'--install-record=<(apk_install_record)',
@@ -408,6 +407,7 @@
'-DANDROID_SDK_JAR=<(android_sdk_jar)',
'-DANDROID_SDK_ROOT=<(android_sdk_root)',
'-DANDROID_SDK_VERSION=<(android_sdk_version)',
+ '-DANDROID_SDK_TOOLS=<(android_sdk_tools)',
'-DLIBRARY_MANIFEST_PATHS=>(library_manifest_paths)',
'-DOUT_DIR=<(intermediate_dir)',
'-DRESOURCE_DIR=<(resource_dir)',
@@ -504,6 +504,7 @@
'-DANDROID_SDK_JAR=<(android_sdk_jar)',
'-DANDROID_SDK_ROOT=<(android_sdk_root)',
'-DANDROID_SDK_VERSION=<(android_sdk_version)',
+ '-DANDROID_SDK_TOOLS=<(android_sdk_tools)',
'-DAPK_NAME=<(apk_name)',
'-DCREATE_TEST_JAR_PATH=<(DEPTH)/build/android/ant/create-test-jar.js',
'-DCONFIGURATION_NAME=<(CONFIGURATION_NAME)',
@@ -576,6 +577,7 @@
'-DADDITIONAL_R_TEXT_FILES=>(additional_R_text_files)',
'-DANDROID_SDK_JAR=<(android_sdk_jar)',
'-DANDROID_SDK_ROOT=<(android_sdk_root)',
+ '-DANDROID_SDK_TOOLS=<(android_sdk_tools)',
'-DAPK_NAME=<(apk_name)',
'-DAPP_MANIFEST_VERSION_CODE=<(app_manifest_version_code)',
'-DAPP_MANIFEST_VERSION_NAME=<(app_manifest_version_name)',
@@ -616,6 +618,7 @@
'python', '<(DEPTH)/build/android/gyp/ant.py',
'-quiet',
'-DANDROID_SDK_ROOT=<(android_sdk_root)',
+ '-DANDROID_SDK_TOOLS=<(android_sdk_tools)',
'-DAPK_NAME=<(apk_name)',
'-DCONFIGURATION_NAME=<(CONFIGURATION_NAME)',
'-DNATIVE_LIBS_DIR=<(apk_package_native_libs_dir)',
diff --git a/build/java_prebuilt.gypi b/build/java_prebuilt.gypi
index fdc20ce..8000374 100644
--- a/build/java_prebuilt.gypi
+++ b/build/java_prebuilt.gypi
@@ -46,7 +46,7 @@
'action': [
'python', '<(DEPTH)/build/android/gyp/dex.py',
'--dex-path=<(dex_path)',
- '--android-sdk-root=<(android_sdk_root)',
+ '--android-sdk-tools=<(android_sdk_tools)',
# TODO(newt): remove this once http://crbug.com/177552 is fixed in ninja.
'--ignore=>!(echo \'>(_inputs)\' | md5sum)',
diff --git a/build/uiautomator_test.gypi b/build/uiautomator_test.gypi
index 20c96c7..2fcc3d8 100644
--- a/build/uiautomator_test.gypi
+++ b/build/uiautomator_test.gypi
@@ -35,7 +35,7 @@
'action': [
'python', '<(DEPTH)/build/android/gyp/dex.py',
'--dex-path=<(output_dex_path)',
- '--android-sdk-root=<(android_sdk_root)',
+ '--android-sdk-tools=<(android_sdk_tools)',
# TODO(newt): remove this once http://crbug.com/177552 is fixed in ninja.
'--ignore=>!(echo \'>(_inputs)\' | md5sum)',
diff --git a/build/util/LASTCHANGE b/build/util/LASTCHANGE
index aae8668..63a3a52 100644
--- a/build/util/LASTCHANGE
+++ b/build/util/LASTCHANGE
@@ -1 +1 @@
-LASTCHANGE=216370
+LASTCHANGE=216972
diff --git a/build/util/LASTCHANGE.blink b/build/util/LASTCHANGE.blink
index 03e4ec2..aa8f059 100644
--- a/build/util/LASTCHANGE.blink
+++ b/build/util/LASTCHANGE.blink
@@ -1 +1 @@
-LASTCHANGE=155688
+LASTCHANGE=155921
diff --git a/build/whitespace_file.txt b/build/whitespace_file.txt
index 4d8ced4..405a489 100644
--- a/build/whitespace_file.txt
+++ b/build/whitespace_file.txt
@@ -58,7 +58,7 @@
CHAPTER 5:
Many years later, Mr. Usagi would laugh at the memory of the earnest,
-well-intentioned Domo-Kun. Another day in the life...
+well-intentioned Domo-Kun. Another day in the life.
TRUISMS (1978-1983)
JENNY HOLZER
diff --git a/cc/base/math_util.cc b/cc/base/math_util.cc
index 39a183e..fa7b21a 100644
--- a/cc/base/math_util.cc
+++ b/cc/base/math_util.cc
@@ -487,6 +487,13 @@
return res.PassAs<base::Value>();
}
+scoped_ptr<base::Value> MathUtil::AsValue(gfx::SizeF s) {
+ scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
+ res->SetDouble("width", s.width());
+ res->SetDouble("height", s.height());
+ return res.PassAs<base::Value>();
+}
+
scoped_ptr<base::Value> MathUtil::AsValue(gfx::Rect r) {
scoped_ptr<base::ListValue> res(new base::ListValue());
res->AppendInteger(r.x());
@@ -546,6 +553,16 @@
return res.PassAs<base::Value>();
}
+scoped_ptr<base::Value> MathUtil::AsValue(const gfx::Transform& transform) {
+ scoped_ptr<base::ListValue> res(new base::ListValue());
+ const SkMatrix44& m = transform.matrix();
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col)
+ res->AppendDouble(m.getDouble(row, col));
+ }
+ return res.PassAs<base::Value>();
+}
+
scoped_ptr<base::Value> MathUtil::AsValueSafely(double value) {
return scoped_ptr<base::Value>(base::Value::CreateDoubleValue(
std::min(value, std::numeric_limits<double>::max())));
diff --git a/cc/base/math_util.h b/cc/base/math_util.h
index 23eb20f..37f0c07 100644
--- a/cc/base/math_util.h
+++ b/cc/base/math_util.h
@@ -156,11 +156,13 @@
// Conversion to value.
static scoped_ptr<base::Value> AsValue(gfx::Size s);
+ static scoped_ptr<base::Value> AsValue(gfx::SizeF s);
static scoped_ptr<base::Value> AsValue(gfx::Rect r);
static bool FromValue(const base::Value*, gfx::Rect* out_rect);
static scoped_ptr<base::Value> AsValue(gfx::PointF q);
static scoped_ptr<base::Value> AsValue(const gfx::QuadF& q);
static scoped_ptr<base::Value> AsValue(const gfx::RectF& rect);
+ static scoped_ptr<base::Value> AsValue(const gfx::Transform& transform);
// Returns a base::Value representation of the floating point value.
// If the value is inf, returns max double/float representation.
diff --git a/cc/cc.target.darwin-arm.mk b/cc/cc.target.darwin-arm.mk
index 7029dcc..68deea0 100644
--- a/cc/cc.target.darwin-arm.mk
+++ b/cc/cc.target.darwin-arm.mk
@@ -249,6 +249,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMEDIA_DISABLE_LIBVPX' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
@@ -364,6 +365,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMEDIA_DISABLE_LIBVPX' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
diff --git a/cc/cc.target.darwin-mips.mk b/cc/cc.target.darwin-mips.mk
index d0f7ee7..d633058 100644
--- a/cc/cc.target.darwin-mips.mk
+++ b/cc/cc.target.darwin-mips.mk
@@ -248,6 +248,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMEDIA_DISABLE_LIBVPX' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
@@ -362,6 +363,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMEDIA_DISABLE_LIBVPX' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
diff --git a/cc/cc.target.darwin-x86.mk b/cc/cc.target.darwin-x86.mk
index 3f83839..84112c8 100644
--- a/cc/cc.target.darwin-x86.mk
+++ b/cc/cc.target.darwin-x86.mk
@@ -251,6 +251,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMEDIA_DISABLE_LIBVPX' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
@@ -368,6 +369,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMEDIA_DISABLE_LIBVPX' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/cc/cc.target.linux-arm.mk b/cc/cc.target.linux-arm.mk
index 7029dcc..68deea0 100644
--- a/cc/cc.target.linux-arm.mk
+++ b/cc/cc.target.linux-arm.mk
@@ -249,6 +249,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMEDIA_DISABLE_LIBVPX' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
@@ -364,6 +365,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMEDIA_DISABLE_LIBVPX' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
diff --git a/cc/cc.target.linux-mips.mk b/cc/cc.target.linux-mips.mk
index d0f7ee7..d633058 100644
--- a/cc/cc.target.linux-mips.mk
+++ b/cc/cc.target.linux-mips.mk
@@ -248,6 +248,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMEDIA_DISABLE_LIBVPX' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
@@ -362,6 +363,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMEDIA_DISABLE_LIBVPX' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
diff --git a/cc/cc.target.linux-x86.mk b/cc/cc.target.linux-x86.mk
index 3f83839..84112c8 100644
--- a/cc/cc.target.linux-x86.mk
+++ b/cc/cc.target.linux-x86.mk
@@ -251,6 +251,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMEDIA_DISABLE_LIBVPX' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
@@ -368,6 +369,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMEDIA_DISABLE_LIBVPX' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/cc/debug/traced_value.cc b/cc/debug/traced_value.cc
index 637c700..fbca5c6 100644
--- a/cc/debug/traced_value.cc
+++ b/cc/debug/traced_value.cc
@@ -21,6 +21,15 @@
dict->SetString("id", base::StringPrintf("%s/%p", object_name, id));
}
+void TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
+ const char* category,
+ base::DictionaryValue* dict,
+ const char* object_name,
+ const void* id) {
+ dict->SetString("cat", category);
+ MakeDictIntoImplicitSnapshot(dict, object_name, id);
+}
+
scoped_ptr<base::debug::ConvertableToTraceFormat> TracedValue::FromValue(
base::Value* value) {
TracedValue* ptr = new TracedValue(value);
diff --git a/cc/debug/traced_value.h b/cc/debug/traced_value.h
index e5d63a1..148aca8 100644
--- a/cc/debug/traced_value.h
+++ b/cc/debug/traced_value.h
@@ -21,6 +21,11 @@
static scoped_ptr<base::Value> CreateIDRef(const void* id);
static void MakeDictIntoImplicitSnapshot(
base::DictionaryValue* dict, const char* object_name, const void* id);
+ static void MakeDictIntoImplicitSnapshotWithCategory(
+ const char* category,
+ base::DictionaryValue* dict,
+ const char* object_name,
+ const void* id);
static scoped_ptr<ConvertableToTraceFormat> FromValue(
base::Value* value);
diff --git a/cc/layers/delegated_renderer_layer.cc b/cc/layers/delegated_renderer_layer.cc
index cbff44e..66064d9 100644
--- a/cc/layers/delegated_renderer_layer.cc
+++ b/cc/layers/delegated_renderer_layer.cc
@@ -41,28 +41,19 @@
delegated_impl->SetDisplaySize(display_size_);
- if (!frame_data_) {
- delegated_impl->SetFrameData(scoped_ptr<DelegatedFrameData>(),
- gfx::Rect(),
- &unused_resources_for_child_compositor_);
- } else if (frame_size_.IsEmpty()) {
- scoped_ptr<DelegatedFrameData> empty_frame(new DelegatedFrameData);
- delegated_impl->SetFrameData(empty_frame.Pass(),
- gfx::Rect(),
- &unused_resources_for_child_compositor_);
- } else {
- delegated_impl->SetFrameData(frame_data_.Pass(),
- damage_in_frame_,
- &unused_resources_for_child_compositor_);
- }
+ if (frame_data_)
+ delegated_impl->SetFrameData(frame_data_.Pass(), damage_in_frame_);
frame_data_.reset();
damage_in_frame_ = gfx::RectF();
+ delegated_impl->CollectUnusedResources(
+ &unused_resources_for_child_compositor_);
+
if (client_)
client_->DidCommitFrameData();
// TODO(danakj): TakeUnusedResourcesForChildCompositor requires a push
- // properties to happen in order to push up newly unused resources returned
+ // properties to happen in order to collect unused resources returned
// from the parent compositor. crbug.com/259090
needs_push_properties_ = true;
}
diff --git a/cc/layers/delegated_renderer_layer_impl.cc b/cc/layers/delegated_renderer_layer_impl.cc
index 31b0a8d..2dfdac6 100644
--- a/cc/layers/delegated_renderer_layer_impl.cc
+++ b/cc/layers/delegated_renderer_layer_impl.cc
@@ -92,8 +92,13 @@
void DelegatedRendererLayerImpl::SetFrameData(
scoped_ptr<DelegatedFrameData> frame_data,
- gfx::RectF damage_in_frame,
- TransferableResourceArray* resources_for_ack) {
+ gfx::RectF damage_in_frame) {
+ DCHECK(frame_data);
+
+ // A frame with an empty root render pass is invalid.
+ DCHECK(frame_data->render_pass_list.empty() ||
+ !frame_data->render_pass_list.back()->output_rect.IsEmpty());
+
CreateChildIdIfNeeded();
DCHECK(child_id_);
@@ -101,48 +106,53 @@
const ResourceProvider::ResourceIdMap& resource_map =
resource_provider->GetChildToParentMap(child_id_);
- if (frame_data) {
- // A frame with an empty root render pass is invalid.
- DCHECK(frame_data->render_pass_list.empty() ||
- !frame_data->render_pass_list.back()->output_rect.IsEmpty());
+ resource_provider->ReceiveFromChild(child_id_, frame_data->resource_list);
- // Display size is already set so we can compute what the damage rect
- // will be in layer space.
- if (!frame_data->render_pass_list.empty()) {
- RenderPass* new_root_pass = frame_data->render_pass_list.back();
- gfx::RectF damage_in_layer = MathUtil::MapClippedRect(
- DelegatedFrameToLayerSpaceTransform(
- new_root_pass->output_rect.size()),
- damage_in_frame);
- set_update_rect(gfx::UnionRects(update_rect(), damage_in_layer));
- }
-
- resource_provider->ReceiveFromChild(child_id_, frame_data->resource_list);
-
- bool invalid_frame = false;
- ResourceProvider::ResourceIdSet used_resources;
- DrawQuad::ResourceIteratorCallback remap_resources_to_parent_callback =
- base::Bind(&ResourceRemapHelper,
- &invalid_frame,
- resource_map,
- &used_resources);
- for (size_t i = 0; i < frame_data->render_pass_list.size(); ++i) {
- RenderPass* pass = frame_data->render_pass_list[i];
- for (size_t j = 0; j < pass->quad_list.size(); ++j) {
- DrawQuad* quad = pass->quad_list[j];
- quad->IterateResources(remap_resources_to_parent_callback);
- }
- }
-
- if (!invalid_frame) {
- // Save the remapped quads on the layer. This steals the quads and render
- // passes from the frame_data.
- SetRenderPasses(&frame_data->render_pass_list);
- resources_.swap(used_resources);
- have_render_passes_to_push_ = true;
+ bool invalid_frame = false;
+ ResourceProvider::ResourceIdSet used_resources;
+ DrawQuad::ResourceIteratorCallback remap_resources_to_parent_callback =
+ base::Bind(&ResourceRemapHelper,
+ &invalid_frame,
+ resource_map,
+ &used_resources);
+ for (size_t i = 0; i < frame_data->render_pass_list.size(); ++i) {
+ RenderPass* pass = frame_data->render_pass_list[i];
+ for (size_t j = 0; j < pass->quad_list.size(); ++j) {
+ DrawQuad* quad = pass->quad_list[j];
+ quad->IterateResources(remap_resources_to_parent_callback);
}
}
+ if (invalid_frame)
+ return;
+
+ // Display size is already set so we can compute what the damage rect
+ // will be in layer space.
+ if (!frame_data->render_pass_list.empty()) {
+ RenderPass* new_root_pass = frame_data->render_pass_list.back();
+ gfx::RectF damage_in_layer = MathUtil::MapClippedRect(
+ DelegatedFrameToLayerSpaceTransform(
+ new_root_pass->output_rect.size()),
+ damage_in_frame);
+ set_update_rect(gfx::UnionRects(update_rect(), damage_in_layer));
+ }
+
+ // Save the remapped quads on the layer. This steals the quads and render
+ // passes from the frame_data.
+ SetRenderPasses(&frame_data->render_pass_list);
+ resources_.swap(used_resources);
+ have_render_passes_to_push_ = true;
+}
+
+void DelegatedRendererLayerImpl::CollectUnusedResources(
+ TransferableResourceArray* resources_for_ack) {
+ CreateChildIdIfNeeded();
+ DCHECK(child_id_);
+
+ ResourceProvider* resource_provider = layer_tree_impl()->resource_provider();
+ const ResourceProvider::ResourceIdMap& resource_map =
+ resource_provider->GetChildToParentMap(child_id_);
+
ResourceProvider::ResourceIdArray unused_resources;
for (ResourceProvider::ResourceIdMap::const_iterator it =
resource_map.begin();
diff --git a/cc/layers/delegated_renderer_layer_impl.h b/cc/layers/delegated_renderer_layer_impl.h
index 5725454..9cfdcb6 100644
--- a/cc/layers/delegated_renderer_layer_impl.h
+++ b/cc/layers/delegated_renderer_layer_impl.h
@@ -41,8 +41,9 @@
void AppendContributingRenderPasses(RenderPassSink* render_pass_sink);
void SetFrameData(scoped_ptr<DelegatedFrameData> frame_data,
- gfx::RectF damage_in_frame,
- TransferableResourceArray* resources_for_ack);
+ gfx::RectF damage_in_frame);
+
+ void CollectUnusedResources(TransferableResourceArray* resources_for_ack);
void SetDisplaySize(gfx::Size size);
diff --git a/cc/output/filter_operation.cc b/cc/output/filter_operation.cc
index de59cfc..6a77838 100644
--- a/cc/output/filter_operation.cc
+++ b/cc/output/filter_operation.cc
@@ -4,6 +4,7 @@
#include <algorithm>
+#include "base/values.h"
#include "cc/base/math_util.h"
#include "cc/output/filter_operation.h"
#include "third_party/skia/include/core/SkMath.h"
@@ -217,4 +218,40 @@
return blended_filter;
}
+scoped_ptr<base::Value> FilterOperation::AsValue() const {
+ scoped_ptr<base::DictionaryValue> value(new DictionaryValue);
+ value->SetInteger("type", type_);
+ switch (type_) {
+ case FilterOperation::GRAYSCALE:
+ case FilterOperation::SEPIA:
+ case FilterOperation::SATURATE:
+ case FilterOperation::HUE_ROTATE:
+ case FilterOperation::INVERT:
+ case FilterOperation::BRIGHTNESS:
+ case FilterOperation::CONTRAST:
+ case FilterOperation::OPACITY:
+ case FilterOperation::BLUR:
+ case FilterOperation::SATURATING_BRIGHTNESS:
+ value->SetDouble("amount", amount_);
+ break;
+ case FilterOperation::DROP_SHADOW:
+ value->SetDouble("std_deviation", amount_);
+ value->Set("offset", MathUtil::AsValue(drop_shadow_offset_).release());
+ value->SetInteger("color", drop_shadow_color_);
+ break;
+ case FilterOperation::COLOR_MATRIX: {
+ scoped_ptr<ListValue> matrix(new ListValue);
+ for (size_t i = 0; i < arraysize(matrix_); ++i)
+ matrix->AppendDouble(matrix_[i]);
+ value->Set("matrix", matrix.release());
+ break;
+ }
+ case FilterOperation::ZOOM:
+ value->SetDouble("amount", amount_);
+ value->SetDouble("inset", zoom_inset_);
+ break;
+ }
+ return value.PassAs<base::Value>();
+}
+
} // namespace cc
diff --git a/cc/output/filter_operation.h b/cc/output/filter_operation.h
index ad25cf4..f561762 100644
--- a/cc/output/filter_operation.h
+++ b/cc/output/filter_operation.h
@@ -6,11 +6,16 @@
#define CC_OUTPUT_FILTER_OPERATION_H_
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
#include "cc/base/cc_export.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkScalar.h"
#include "ui/gfx/point.h"
+namespace base {
+class Value;
+}
+
namespace cc {
class CC_EXPORT FilterOperation {
@@ -161,6 +166,8 @@
const FilterOperation* to,
double progress);
+ scoped_ptr<base::Value> AsValue() const;
+
private:
FilterOperation(FilterType type, float amount);
diff --git a/cc/output/filter_operations.cc b/cc/output/filter_operations.cc
index 4331527..2420841 100644
--- a/cc/output/filter_operations.cc
+++ b/cc/output/filter_operations.cc
@@ -4,9 +4,11 @@
#include <cmath>
-#include "cc/output/filter_operation.h"
#include "cc/output/filter_operations.h"
+#include "base/values.h"
+#include "cc/output/filter_operation.h"
+
namespace cc {
FilterOperations::FilterOperations() {}
@@ -145,4 +147,11 @@
return blended_filters;
}
+scoped_ptr<base::Value> FilterOperations::AsValue() const {
+ scoped_ptr<base::ListValue> value(new ListValue);
+ for (size_t i = 0; i < operations_.size(); ++i)
+ value->Append(operations_[i].AsValue().release());
+ return value.PassAs<base::Value>();
+}
+
} // namespace cc
diff --git a/cc/output/filter_operations.h b/cc/output/filter_operations.h
index d7198d1..aa8d58d 100644
--- a/cc/output/filter_operations.h
+++ b/cc/output/filter_operations.h
@@ -8,8 +8,13 @@
#include <vector>
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
#include "cc/output/filter_operation.h"
+namespace base {
+class Value;
+}
+
namespace cc {
// An ordered list of filter operations.
@@ -62,6 +67,8 @@
// of this.
FilterOperations Blend(const FilterOperations& from, double progress) const;
+ scoped_ptr<base::Value> AsValue() const;
+
private:
std::vector<FilterOperation> operations_;
};
diff --git a/cc/quads/checkerboard_draw_quad.cc b/cc/quads/checkerboard_draw_quad.cc
index fcc6dc5..5e17d88 100644
--- a/cc/quads/checkerboard_draw_quad.cc
+++ b/cc/quads/checkerboard_draw_quad.cc
@@ -5,6 +5,7 @@
#include "cc/quads/checkerboard_draw_quad.h"
#include "base/logging.h"
+#include "base/values.h"
namespace cc {
@@ -45,4 +46,8 @@
return static_cast<const CheckerboardDrawQuad*>(quad);
}
+void CheckerboardDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+ value->SetInteger("color", color);
+}
+
} // namespace cc
diff --git a/cc/quads/checkerboard_draw_quad.h b/cc/quads/checkerboard_draw_quad.h
index b2ed876..4f7452eb 100644
--- a/cc/quads/checkerboard_draw_quad.h
+++ b/cc/quads/checkerboard_draw_quad.h
@@ -35,6 +35,7 @@
static const CheckerboardDrawQuad* MaterialCast(const DrawQuad*);
private:
+ virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
CheckerboardDrawQuad();
};
diff --git a/cc/quads/content_draw_quad_base.cc b/cc/quads/content_draw_quad_base.cc
index 2c2b4ae..947af0b 100644
--- a/cc/quads/content_draw_quad_base.cc
+++ b/cc/quads/content_draw_quad_base.cc
@@ -5,6 +5,8 @@
#include "cc/quads/content_draw_quad_base.h"
#include "base/logging.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
namespace cc {
@@ -47,4 +49,10 @@
this->swizzle_contents = swizzle_contents;
}
+void ContentDrawQuadBase::ExtendValue(base::DictionaryValue* value) const {
+ value->Set("tex_coord_rect", MathUtil::AsValue(tex_coord_rect).release());
+ value->Set("texture_size", MathUtil::AsValue(texture_size).release());
+ value->SetBoolean("swizzle_contents", swizzle_contents);
+}
+
} // namespace cc
diff --git a/cc/quads/content_draw_quad_base.h b/cc/quads/content_draw_quad_base.h
index b2c936f..cbf18ca 100644
--- a/cc/quads/content_draw_quad_base.h
+++ b/cc/quads/content_draw_quad_base.h
@@ -41,6 +41,7 @@
protected:
ContentDrawQuadBase();
virtual ~ContentDrawQuadBase();
+ virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
};
} // namespace cc
diff --git a/cc/quads/debug_border_draw_quad.cc b/cc/quads/debug_border_draw_quad.cc
index 1ebc0a6..89ee8e0 100644
--- a/cc/quads/debug_border_draw_quad.cc
+++ b/cc/quads/debug_border_draw_quad.cc
@@ -5,6 +5,7 @@
#include "cc/quads/debug_border_draw_quad.h"
#include "base/logging.h"
+#include "base/values.h"
namespace cc {
@@ -52,4 +53,9 @@
return static_cast<const DebugBorderDrawQuad*>(quad);
}
+void DebugBorderDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+ value->SetInteger("color", color);
+ value->SetInteger("width", width);
+}
+
} // namespace cc
diff --git a/cc/quads/debug_border_draw_quad.h b/cc/quads/debug_border_draw_quad.h
index 2f4b3ca..5b36951 100644
--- a/cc/quads/debug_border_draw_quad.h
+++ b/cc/quads/debug_border_draw_quad.h
@@ -39,6 +39,7 @@
private:
DebugBorderDrawQuad();
+ virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
};
} // namespace cc
diff --git a/cc/quads/draw_quad.cc b/cc/quads/draw_quad.cc
index 6c8d9b6..0d021d9 100644
--- a/cc/quads/draw_quad.cc
+++ b/cc/quads/draw_quad.cc
@@ -5,6 +5,9 @@
#include "cc/quads/draw_quad.h"
#include "base/logging.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
+#include "cc/debug/traced_value.h"
#include "cc/quads/checkerboard_draw_quad.h"
#include "cc/quads/debug_border_draw_quad.h"
#include "cc/quads/io_surface_draw_quad.h"
@@ -15,6 +18,7 @@
#include "cc/quads/texture_draw_quad.h"
#include "cc/quads/tile_draw_quad.h"
#include "cc/quads/yuv_video_draw_quad.h"
+#include "ui/gfx/quad_f.h"
namespace {
template<typename T> T* TypedCopy(const cc::DrawQuad* other) {
@@ -90,4 +94,48 @@
return copy_quad.Pass();
}
+scoped_ptr<base::Value> DrawQuad::AsValue() const {
+ scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
+ value->SetInteger("material", material);
+ value->Set("shared_state",
+ TracedValue::CreateIDRef(shared_quad_state).release());
+
+ value->Set("content_space_rect", MathUtil::AsValue(rect).release());
+ bool rect_is_clipped;
+ gfx::QuadF rect_as_target_space_quad = MathUtil::MapQuad(
+ shared_quad_state->content_to_target_transform,
+ gfx::QuadF(rect),
+ &rect_is_clipped);
+ value->Set("rect_as_target_space_quad",
+ MathUtil::AsValue(rect_as_target_space_quad).release());
+ value->SetBoolean("rect_is_clipped", rect_is_clipped);
+
+ value->Set("content_space_opaque_rect",
+ MathUtil::AsValue(opaque_rect).release());
+ bool opaque_rect_is_clipped;
+ gfx::QuadF opaque_rect_as_target_space_quad = MathUtil::MapQuad(
+ shared_quad_state->content_to_target_transform,
+ gfx::QuadF(opaque_rect),
+ &opaque_rect_is_clipped);
+ value->Set("opaque_rect_as_target_space_quad",
+ MathUtil::AsValue(opaque_rect_as_target_space_quad).release());
+ value->SetBoolean("opaque_rect_is_clipped", opaque_rect_is_clipped);
+
+ value->Set("content_space_visible_rect",
+ MathUtil::AsValue(visible_rect).release());
+ bool visible_rect_is_clipped;
+ gfx::QuadF visible_rect_as_target_space_quad = MathUtil::MapQuad(
+ shared_quad_state->content_to_target_transform,
+ gfx::QuadF(visible_rect),
+ &visible_rect_is_clipped);
+ value->Set("visible_rect_as_target_space_quad",
+ MathUtil::AsValue(visible_rect_as_target_space_quad).release());
+ value->SetBoolean("visible_rect_is_clipped", visible_rect_is_clipped);
+
+ value->SetBoolean("needs_blending", needs_blending);
+ value->SetBoolean("should_draw_with_blending", ShouldDrawWithBlending());
+ ExtendValue(value.get());
+ return value.PassAs<base::Value>();
+}
+
} // namespace cc
diff --git a/cc/quads/draw_quad.h b/cc/quads/draw_quad.h
index a92cddf..c3696d6 100644
--- a/cc/quads/draw_quad.h
+++ b/cc/quads/draw_quad.h
@@ -10,12 +10,24 @@
#include "cc/quads/shared_quad_state.h"
#include "cc/resources/resource_provider.h"
+namespace base {
+class Value;
+class DictionaryValue;
+}
+
namespace cc {
// DrawQuad is a bag of data used for drawing a quad. Because different
// materials need different bits of per-quad data to render, classes that derive
// from DrawQuad store additional data in their derived instance. The Material
// enum is used to "safely" downcast to the derived class.
+// Note: quads contain rects and sizes, which live in different spaces. There is
+// the "content space", which is the arbitrary space in which the quad's
+// geometry is defined (generally related to the layer that produced the quad,
+// e.g. the content space for TiledLayerImpls, or the geometry space for
+// PictureLayerImpls). There is also the "target space", which is the space, in
+// "physical" pixels, of the render target where the quads is drawn. The quad's
+// transform maps the content space to the target space.
class CC_EXPORT DrawQuad {
public:
enum Material {
@@ -51,14 +63,15 @@
Material material;
// This rect, after applying the quad_transform(), gives the geometry that
- // this quad should draw to.
+ // this quad should draw to. This rect lives in content space.
gfx::Rect rect;
- // This specifies the region of the quad that is opaque.
+ // This specifies the region of the quad that is opaque. This rect lives in
+ // content space.
gfx::Rect opaque_rect;
// Allows changing the rect that gets drawn to make it smaller. This value
- // should be clipped to |rect|.
+ // should be clipped to |rect|. This rect lives in content space.
gfx::Rect visible_rect;
// By default blending is used when some part of the quad is not opaque.
@@ -111,6 +124,8 @@
return IsLeftEdge() || IsTopEdge() || IsRightEdge() || IsBottomEdge();
}
+ scoped_ptr<base::Value> AsValue() const;
+
protected:
DrawQuad();
@@ -120,6 +135,7 @@
gfx::Rect opaque_rect,
gfx::Rect visible_rect,
bool needs_blending);
+ virtual void ExtendValue(base::DictionaryValue* value) const = 0;
};
} // namespace cc
diff --git a/cc/quads/io_surface_draw_quad.cc b/cc/quads/io_surface_draw_quad.cc
index 1bbf8a4..2c986dd 100644
--- a/cc/quads/io_surface_draw_quad.cc
+++ b/cc/quads/io_surface_draw_quad.cc
@@ -5,6 +5,8 @@
#include "cc/quads/io_surface_draw_quad.h"
#include "base/logging.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
namespace cc {
@@ -58,4 +60,20 @@
return static_cast<const IOSurfaceDrawQuad*>(quad);
}
+void IOSurfaceDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+ value->Set("io_surface_size", MathUtil::AsValue(io_surface_size).release());
+ value->SetInteger("io_surface_resource_id", io_surface_resource_id);
+ const char* orientation_string = NULL;
+ switch (orientation) {
+ case FLIPPED:
+ orientation_string = "flipped";
+ break;
+ case UNFLIPPED:
+ orientation_string = "unflipped";
+ break;
+ }
+
+ value->SetString("orientation", orientation_string);
+}
+
} // namespace cc
diff --git a/cc/quads/io_surface_draw_quad.h b/cc/quads/io_surface_draw_quad.h
index 1a30c90..fc8b501 100644
--- a/cc/quads/io_surface_draw_quad.h
+++ b/cc/quads/io_surface_draw_quad.h
@@ -48,6 +48,7 @@
private:
IOSurfaceDrawQuad();
+ virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
};
} // namespace cc
diff --git a/cc/quads/picture_draw_quad.cc b/cc/quads/picture_draw_quad.cc
index 81f7913..0494764 100644
--- a/cc/quads/picture_draw_quad.cc
+++ b/cc/quads/picture_draw_quad.cc
@@ -4,6 +4,9 @@
#include "cc/quads/picture_draw_quad.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
+
namespace cc {
PictureDrawQuad::PictureDrawQuad() {
@@ -68,4 +71,13 @@
return static_cast<const PictureDrawQuad*>(quad);
}
+void PictureDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+ ContentDrawQuadBase::ExtendValue(value);
+ value->Set("content_rect", MathUtil::AsValue(content_rect).release());
+ value->SetDouble("contents_scale", contents_scale);
+ value->SetBoolean("can_draw_direct_to_backbuffer",
+ can_draw_direct_to_backbuffer);
+ // TODO(piman): picture_pile?
+}
+
} // namespace cc
diff --git a/cc/quads/picture_draw_quad.h b/cc/quads/picture_draw_quad.h
index 29af6d5..beec88c 100644
--- a/cc/quads/picture_draw_quad.h
+++ b/cc/quads/picture_draw_quad.h
@@ -58,6 +58,7 @@
private:
PictureDrawQuad();
+ virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
};
} // namespace cc
diff --git a/cc/quads/render_pass.cc b/cc/quads/render_pass.cc
index ef6308c..50d5028 100644
--- a/cc/quads/render_pass.cc
+++ b/cc/quads/render_pass.cc
@@ -4,12 +4,20 @@
#include "cc/quads/render_pass.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
+#include "cc/debug/traced_value.h"
#include "cc/output/copy_output_request.h"
#include "cc/quads/draw_quad.h"
#include "cc/quads/shared_quad_state.h"
namespace cc {
+void* RenderPass::Id::AsTracingId() const {
+ COMPILE_ASSERT(sizeof(size_t) <= sizeof(void*), size_t_bigger_than_pointer);
+ return reinterpret_cast<void*>(base::HashPair(layer_id, index));
+}
+
scoped_ptr<RenderPass> RenderPass::Create() {
return make_scoped_ptr(new RenderPass);
}
@@ -19,7 +27,11 @@
has_transparent_background(true),
has_occlusion_from_outside_target_surface(false) {}
-RenderPass::~RenderPass() {}
+RenderPass::~RenderPass() {
+ TRACE_EVENT_OBJECT_DELETED_WITH_ID(
+ TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"),
+ "cc::RenderPass", id.AsTracingId());
+}
scoped_ptr<RenderPass> RenderPass::Copy(Id new_id) const {
scoped_ptr<RenderPass> copy_pass(Create());
@@ -69,4 +81,29 @@
DCHECK(shared_quad_state_list.empty());
}
+scoped_ptr<base::Value> RenderPass::AsValue() const {
+ scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
+ value->Set("output_rect", MathUtil::AsValue(output_rect).release());
+ value->Set("damage_rect", MathUtil::AsValue(damage_rect).release());
+ value->SetBoolean("has_transparent_background", has_transparent_background);
+ value->SetBoolean("has_occlusion_from_outside_target_surface",
+ has_occlusion_from_outside_target_surface);
+ value->SetInteger("copy_requests", copy_requests.size());
+ scoped_ptr<base::ListValue> shared_states_value(new base::ListValue());
+ for (size_t i = 0; i < shared_quad_state_list.size(); ++i) {
+ shared_states_value->Append(shared_quad_state_list[i]->AsValue().release());
+ }
+ value->Set("shared_quad_state_list", shared_states_value.release());
+ scoped_ptr<base::ListValue> quad_list_value(new base::ListValue());
+ for (size_t i = 0; i < quad_list.size(); ++i) {
+ quad_list_value->Append(quad_list[i]->AsValue().release());
+ }
+ value->Set("quad_list", quad_list_value.release());
+
+ TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
+ TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"),
+ value.get(), "cc::RenderPass", id.AsTracingId());
+ return value.PassAs<base::Value>();
+}
+
} // namespace cc
diff --git a/cc/quads/render_pass.h b/cc/quads/render_pass.h
index 3d5a37c..224a050 100644
--- a/cc/quads/render_pass.h
+++ b/cc/quads/render_pass.h
@@ -20,6 +20,10 @@
#include "ui/gfx/rect_f.h"
#include "ui/gfx/transform.h"
+namespace base {
+class Value;
+};
+
namespace cc {
class DrawQuad;
@@ -47,6 +51,7 @@
int index;
Id(int layer_id, int index) : layer_id(layer_id), index(index) {}
+ void* AsTracingId() const;
bool operator==(const Id& other) const {
return layer_id == other.layer_id && index == other.index;
@@ -79,6 +84,8 @@
bool has_transparent_background,
bool has_occlusion_from_outside_target_surface);
+ scoped_ptr<base::Value> AsValue() const;
+
// Uniquely identifies the render pass in the compositor's current frame.
Id id;
diff --git a/cc/quads/render_pass_draw_quad.cc b/cc/quads/render_pass_draw_quad.cc
index ead3d79..0528cd5 100644
--- a/cc/quads/render_pass_draw_quad.cc
+++ b/cc/quads/render_pass_draw_quad.cc
@@ -4,6 +4,10 @@
#include "cc/quads/render_pass_draw_quad.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
+#include "cc/debug/traced_value.h"
+
namespace cc {
RenderPassDrawQuad::RenderPassDrawQuad()
@@ -93,4 +97,19 @@
return static_cast<const RenderPassDrawQuad*>(quad);
}
+void RenderPassDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+ value->Set("render_pass_id",
+ TracedValue::CreateIDRef(render_pass_id.AsTracingId()).release());
+ value->SetBoolean("is_replica", is_replica);
+ value->SetInteger("mask_resource_id", mask_resource_id);
+ value->Set("contents_changed_since_last_frame",
+ MathUtil::AsValue(contents_changed_since_last_frame).release());
+ value->Set("mask_uv_rect", MathUtil::AsValue(mask_uv_rect).release());
+ value->Set("filters", filters.AsValue().release());
+ // TODO(piman): dump SkImageFilters rather than just indicating if there are
+ // any or not.
+ value->SetBoolean("has_filter", !!filter);
+ value->Set("background_filters", background_filters.AsValue().release());
+}
+
} // namespace cc
diff --git a/cc/quads/render_pass_draw_quad.h b/cc/quads/render_pass_draw_quad.h
index f0c76a9..e253dec 100644
--- a/cc/quads/render_pass_draw_quad.h
+++ b/cc/quads/render_pass_draw_quad.h
@@ -72,6 +72,7 @@
private:
RenderPassDrawQuad();
+ virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
};
} // namespace cc
diff --git a/cc/quads/shared_quad_state.cc b/cc/quads/shared_quad_state.cc
index 7bfb2b4..6a53d9f 100644
--- a/cc/quads/shared_quad_state.cc
+++ b/cc/quads/shared_quad_state.cc
@@ -4,11 +4,19 @@
#include "cc/quads/shared_quad_state.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
+#include "cc/debug/traced_value.h"
+
namespace cc {
SharedQuadState::SharedQuadState() : is_clipped(false), opacity(0.f) {}
-SharedQuadState::~SharedQuadState() {}
+SharedQuadState::~SharedQuadState() {
+ TRACE_EVENT_OBJECT_DELETED_WITH_ID(
+ TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"),
+ "cc::SharedQuadState", this);
+}
scoped_ptr<SharedQuadState> SharedQuadState::Create() {
return make_scoped_ptr(new SharedQuadState);
@@ -33,4 +41,21 @@
this->opacity = opacity;
}
+scoped_ptr<base::Value> SharedQuadState::AsValue() const {
+ scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
+ value->Set("transform",
+ MathUtil::AsValue(content_to_target_transform).release());
+ value->Set("layer_content_bounds",
+ MathUtil::AsValue(content_bounds).release());
+ value->Set("layer_visible_content_rect",
+ MathUtil::AsValue(visible_content_rect).release());
+ value->SetBoolean("is_clipped", is_clipped);
+ value->Set("clip_rect", MathUtil::AsValue(clip_rect).release());
+ value->SetDouble("opacity", opacity);
+ TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
+ TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"),
+ value.get(), "cc::SharedQuadState", this);
+ return value.PassAs<base::Value>();
+}
+
} // namespace cc
diff --git a/cc/quads/shared_quad_state.h b/cc/quads/shared_quad_state.h
index eb3e91e..79bd09b 100644
--- a/cc/quads/shared_quad_state.h
+++ b/cc/quads/shared_quad_state.h
@@ -10,6 +10,10 @@
#include "ui/gfx/rect.h"
#include "ui/gfx/transform.h"
+namespace base {
+class Value;
+}
+
namespace cc {
class CC_EXPORT SharedQuadState {
@@ -25,12 +29,15 @@
gfx::Rect clip_rect,
bool is_clipped,
float opacity);
+ scoped_ptr<base::Value> AsValue() const;
// Transforms from quad's original content space to its target content space.
gfx::Transform content_to_target_transform;
- // This rect lives in the content space for the quad's originating layer.
+ // This size lives in the content space for the quad's originating layer.
gfx::Size content_bounds;
+ // This rect lives in the content space for the quad's originating layer.
gfx::Rect visible_content_rect;
+ // This rect lives in the target content space.
gfx::Rect clip_rect;
bool is_clipped;
float opacity;
diff --git a/cc/quads/solid_color_draw_quad.cc b/cc/quads/solid_color_draw_quad.cc
index 5575aaf..ae3b914 100644
--- a/cc/quads/solid_color_draw_quad.cc
+++ b/cc/quads/solid_color_draw_quad.cc
@@ -5,6 +5,7 @@
#include "cc/quads/solid_color_draw_quad.h"
#include "base/logging.h"
+#include "base/values.h"
namespace cc {
@@ -50,4 +51,9 @@
return static_cast<const SolidColorDrawQuad*>(quad);
}
-} // namespacec cc
+void SolidColorDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+ value->SetInteger("color", color);
+ value->SetBoolean("force_anti_aliasing_off", force_anti_aliasing_off);
+}
+
+} // namespace cc
diff --git a/cc/quads/solid_color_draw_quad.h b/cc/quads/solid_color_draw_quad.h
index 4d7ab9f..2c41243 100644
--- a/cc/quads/solid_color_draw_quad.h
+++ b/cc/quads/solid_color_draw_quad.h
@@ -39,6 +39,7 @@
private:
SolidColorDrawQuad();
+ virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
};
} // namespace cc
diff --git a/cc/quads/stream_video_draw_quad.cc b/cc/quads/stream_video_draw_quad.cc
index 831304f..c239256 100644
--- a/cc/quads/stream_video_draw_quad.cc
+++ b/cc/quads/stream_video_draw_quad.cc
@@ -5,6 +5,8 @@
#include "cc/quads/stream_video_draw_quad.h"
#include "base/logging.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
namespace cc {
@@ -51,4 +53,9 @@
return static_cast<const StreamVideoDrawQuad*>(quad);
}
+void StreamVideoDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+ value->SetInteger("resource_id", resource_id);
+ value->Set("matrix", MathUtil::AsValue(matrix).release());
+}
+
} // namespace cc
diff --git a/cc/quads/stream_video_draw_quad.h b/cc/quads/stream_video_draw_quad.h
index 0ce31af..e610f43 100644
--- a/cc/quads/stream_video_draw_quad.h
+++ b/cc/quads/stream_video_draw_quad.h
@@ -40,6 +40,7 @@
private:
StreamVideoDrawQuad();
+ virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
};
} // namespace cc
diff --git a/cc/quads/texture_draw_quad.cc b/cc/quads/texture_draw_quad.cc
index c894985..ae7cfd6 100644
--- a/cc/quads/texture_draw_quad.cc
+++ b/cc/quads/texture_draw_quad.cc
@@ -5,6 +5,8 @@
#include "cc/quads/texture_draw_quad.h"
#include "base/logging.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
#include "ui/gfx/vector2d_f.h"
namespace cc {
@@ -156,4 +158,17 @@
return true;
}
+void TextureDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+ value->SetInteger("resource_id", resource_id);
+ value->SetBoolean("premultiplied_alpha", premultiplied_alpha);
+ value->Set("uv_top_left", MathUtil::AsValue(uv_top_left).release());
+ value->Set("uv_bottom_right", MathUtil::AsValue(uv_bottom_right).release());
+ value->SetInteger("background_color", background_color);
+ scoped_ptr<ListValue> vertex_opacity_value(new ListValue);
+ for (size_t i = 0; i < 4; ++i)
+ vertex_opacity_value->AppendDouble(vertex_opacity[i]);
+ value->Set("vertex_opacity", vertex_opacity_value.release());
+ value->SetBoolean("flipped", flipped);
+}
+
} // namespace cc
diff --git a/cc/quads/texture_draw_quad.h b/cc/quads/texture_draw_quad.h
index 3db10c6..7f06618 100644
--- a/cc/quads/texture_draw_quad.h
+++ b/cc/quads/texture_draw_quad.h
@@ -57,6 +57,7 @@
private:
TextureDrawQuad();
+ virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
};
} // namespace cc
diff --git a/cc/quads/tile_draw_quad.cc b/cc/quads/tile_draw_quad.cc
index 414b320..3ff9809 100644
--- a/cc/quads/tile_draw_quad.cc
+++ b/cc/quads/tile_draw_quad.cc
@@ -5,6 +5,7 @@
#include "cc/quads/tile_draw_quad.h"
#include "base/logging.h"
+#include "base/values.h"
#include "third_party/khronos/GLES2/gl2.h"
namespace cc {
@@ -58,4 +59,9 @@
return static_cast<const TileDrawQuad*>(quad);
}
+void TileDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+ ContentDrawQuadBase::ExtendValue(value);
+ value->SetInteger("resource_id", resource_id);
+}
+
} // namespace cc
diff --git a/cc/quads/tile_draw_quad.h b/cc/quads/tile_draw_quad.h
index 25957f6..6da1e54 100644
--- a/cc/quads/tile_draw_quad.h
+++ b/cc/quads/tile_draw_quad.h
@@ -41,6 +41,7 @@
private:
TileDrawQuad();
+ virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
};
} // namespace cc
diff --git a/cc/quads/yuv_video_draw_quad.cc b/cc/quads/yuv_video_draw_quad.cc
index 2ac75dc..ecdc78f 100644
--- a/cc/quads/yuv_video_draw_quad.cc
+++ b/cc/quads/yuv_video_draw_quad.cc
@@ -5,6 +5,8 @@
#include "cc/quads/yuv_video_draw_quad.h"
#include "base/logging.h"
+#include "base/values.h"
+#include "cc/base/math_util.h"
namespace cc {
@@ -72,4 +74,12 @@
return static_cast<const YUVVideoDrawQuad*>(quad);
}
+void YUVVideoDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+ value->Set("tex_scale", MathUtil::AsValue(tex_scale).release());
+ value->SetInteger("y_plane_resource_id", y_plane_resource_id);
+ value->SetInteger("u_plane_resource_id", u_plane_resource_id);
+ value->SetInteger("v_plane_resource_id", v_plane_resource_id);
+ value->SetInteger("a_plane_resource_id", a_plane_resource_id);
+}
+
} // namespace cc
diff --git a/cc/quads/yuv_video_draw_quad.h b/cc/quads/yuv_video_draw_quad.h
index 34a0612..aa750fa 100644
--- a/cc/quads/yuv_video_draw_quad.h
+++ b/cc/quads/yuv_video_draw_quad.h
@@ -52,6 +52,7 @@
private:
YUVVideoDrawQuad();
+ virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
};
} // namespace cc
diff --git a/cc/resources/pixel_buffer_raster_worker_pool.cc b/cc/resources/pixel_buffer_raster_worker_pool.cc
index 112de14..a03ed81 100644
--- a/cc/resources/pixel_buffer_raster_worker_pool.cc
+++ b/cc/resources/pixel_buffer_raster_worker_pool.cc
@@ -590,10 +590,6 @@
scoped_refptr<internal::RasterWorkerPoolTask> task,
bool was_canceled,
bool needs_upload) {
- TRACE_EVENT2("cc", "PixelBufferRasterWorkerPool::OnRasterTaskCompleted",
- "was_canceled", was_canceled,
- "needs_upload", needs_upload);
-
DCHECK(pixel_buffer_tasks_.find(task.get()) != pixel_buffer_tasks_.end());
// Balanced with MapPixelBuffer() call in ScheduleMoreTasks().
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index 6d6ac9d..11eaab0 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -785,7 +785,6 @@
void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
TransferableResourceArray* list) {
DCHECK(thread_checker_.CalledOnValidThread());
- list->clear();
WebGraphicsContext3D* context3d = output_surface_->context3d();
if (!context3d || !context3d->makeContextCurrent()) {
// TODO(skaslev): Implement this path for software compositing.
@@ -818,7 +817,6 @@
const ResourceIdArray& resources,
TransferableResourceArray* list) {
DCHECK(thread_checker_.CalledOnValidThread());
- list->clear();
WebGraphicsContext3D* context3d = output_surface_->context3d();
if (!context3d || !context3d->makeContextCurrent()) {
// TODO(skaslev): Implement this path for software compositing.
diff --git a/cc/resources/video_resource_updater_unittest.cc b/cc/resources/video_resource_updater_unittest.cc
index 95b3124..ff574ff 100644
--- a/cc/resources/video_resource_updater_unittest.cc
+++ b/cc/resources/video_resource_updater_unittest.cc
@@ -36,18 +36,17 @@
return media::VideoFrame::WrapExternalYuvData(
media::VideoFrame::YV16, // format
- size, // coded_size
- gfx::Rect(size), // visible_rect
- size, // natural_size
- size.width(), // y_stride
- size.width() / 2, // u_stride
- size.width() / 2, // v_stride
- y_data, // y_data
- u_data, // u_data
- v_data, // v_data
- base::TimeDelta(), // timestamp,
- base::SharedMemory::NULLHandle(), // shm_handle
- base::Closure()); // no_longer_needed_cb
+ size, // coded_size
+ gfx::Rect(size), // visible_rect
+ size, // natural_size
+ size.width(), // y_stride
+ size.width() / 2, // u_stride
+ size.width() / 2, // v_stride
+ y_data, // y_data
+ u_data, // u_data
+ v_data, // v_data
+ base::TimeDelta(), // timestamp,
+ base::Closure()); // no_longer_needed_cb
}
TestWebGraphicsContext3D* context3d_;
diff --git a/cc/resources/worker_pool.cc b/cc/resources/worker_pool.cc
index 812bbeb..dca0c70 100644
--- a/cc/resources/worker_pool.cc
+++ b/cc/resources/worker_pool.cc
@@ -402,7 +402,8 @@
void WorkerPool::ProcessCompletedTasks(
const TaskVector& completed_tasks) {
- TRACE_EVENT0("cc", "WorkerPool::ProcessCompletedTasks");
+ TRACE_EVENT1("cc", "WorkerPool::ProcessCompletedTasks",
+ "completed_task_count", completed_tasks.size());
// Worker pool instance is not reentrant while processing completed tasks.
in_dispatch_completion_callbacks_ = true;
diff --git a/cc/test/fake_delegated_renderer_layer_impl.cc b/cc/test/fake_delegated_renderer_layer_impl.cc
index 8ae1fa5..c6a639e 100644
--- a/cc/test/fake_delegated_renderer_layer_impl.cc
+++ b/cc/test/fake_delegated_renderer_layer_impl.cc
@@ -16,6 +16,12 @@
FakeDelegatedRendererLayerImpl::~FakeDelegatedRendererLayerImpl() {}
+scoped_ptr<LayerImpl> FakeDelegatedRendererLayerImpl::CreateLayerImpl(
+ LayerTreeImpl* tree_impl) {
+ return FakeDelegatedRendererLayerImpl::Create(
+ tree_impl, id()).PassAs<LayerImpl>();
+}
+
static ResourceProvider::ResourceId AddResourceToFrame(
DelegatedFrameData* frame,
ResourceProvider::ResourceId resource_id) {
@@ -40,7 +46,8 @@
}
TransferableResourceArray resources_for_ack;
- SetFrameData(delegated_frame.Pass(), gfx::RectF(), &resources_for_ack);
+ SetFrameData(delegated_frame.Pass(), gfx::RectF());
+ CollectUnusedResources(&resources_for_ack);
}
} // namespace cc
diff --git a/cc/test/fake_delegated_renderer_layer_impl.h b/cc/test/fake_delegated_renderer_layer_impl.h
index b9789f5..a9ca0f9 100644
--- a/cc/test/fake_delegated_renderer_layer_impl.h
+++ b/cc/test/fake_delegated_renderer_layer_impl.h
@@ -17,6 +17,9 @@
}
virtual ~FakeDelegatedRendererLayerImpl();
+ virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl)
+ OVERRIDE;
+
int ChildId() const { return ChildIdForTesting(); }
const ScopedPtrVector<RenderPass>& RenderPassesInDrawOrder() const {
return RenderPassesInDrawOrderForTesting();
diff --git a/cc/test/fake_output_surface.cc b/cc/test/fake_output_surface.cc
index 09af44c..9ae7552 100644
--- a/cc/test/fake_output_surface.cc
+++ b/cc/test/fake_output_surface.cc
@@ -61,6 +61,14 @@
if (frame->software_frame_data || frame->delegated_frame_data ||
!context3d()) {
frame->AssignTo(&last_sent_frame_);
+
+ if (last_sent_frame_.delegated_frame_data) {
+ resources_held_by_parent_.insert(
+ resources_held_by_parent_.end(),
+ last_sent_frame_.delegated_frame_data->resource_list.begin(),
+ last_sent_frame_.delegated_frame_data->resource_list.end());
+ }
+
++num_sent_frames_;
PostSwapBuffersComplete();
DidSwapBuffers();
@@ -116,4 +124,17 @@
client_->SetTreeActivationCallback(callback);
}
+void FakeOutputSurface::ReturnResource(unsigned id, CompositorFrameAck* ack) {
+ TransferableResourceArray::iterator it;
+ for (it = resources_held_by_parent_.begin();
+ it != resources_held_by_parent_.end();
+ ++it) {
+ if (it->id == id)
+ break;
+ }
+ DCHECK(it != resources_held_by_parent_.end());
+ ack->resources.push_back(*it);
+ resources_held_by_parent_.erase(it);
+}
+
} // namespace cc
diff --git a/cc/test/fake_output_surface.h b/cc/test/fake_output_surface.h
index dfd4db5..5091dff 100644
--- a/cc/test/fake_output_surface.h
+++ b/cc/test/fake_output_surface.h
@@ -95,6 +95,12 @@
void SetTreeActivationCallback(const base::Closure& callback);
+ const TransferableResourceArray& resources_held_by_parent() {
+ return resources_held_by_parent_;
+ }
+
+ void ReturnResource(unsigned id, CompositorFrameAck* ack);
+
protected:
FakeOutputSurface(
scoped_ptr<WebKit::WebGraphicsContext3D> context3d,
@@ -117,6 +123,7 @@
bool needs_begin_frame_;
bool forced_draw_to_software_device_;
base::WeakPtrFactory<FakeOutputSurface> fake_weak_ptr_factory_;
+ TransferableResourceArray resources_held_by_parent_;
};
static inline scoped_ptr<cc::OutputSurface> CreateFakeOutputSurface() {
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index c61e6be..d4a9498 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "base/basictypes.h"
+#include "base/containers/hash_tables.h"
#include "base/json/json_writer.h"
#include "base/metrics/histogram.h"
#include "base/stl_util.h"
@@ -437,6 +438,25 @@
}
}
+scoped_ptr<base::Value> LayerTreeHostImpl::FrameData::AsValue() const {
+ scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
+ value->SetBoolean("contains_incomplete_tile", contains_incomplete_tile);
+ value->SetBoolean("has_no_damage", has_no_damage);
+
+ // Quad data can be quite large, so only dump render passes if we select
+ // cc.debug.quads.
+ bool quads_enabled;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED(
+ TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"), &quads_enabled);
+ if (quads_enabled) {
+ scoped_ptr<base::ListValue> render_pass_list(new base::ListValue());
+ for (size_t i = 0; i < render_passes.size(); ++i)
+ render_pass_list->Append(render_passes[i]->AsValue().release());
+ value->Set("render_passes", render_pass_list.release());
+ }
+ return value.PassAs<base::Value>();
+}
+
void LayerTreeHostImpl::FrameData::AppendRenderPass(
scoped_ptr<RenderPass> render_pass) {
render_passes_by_id[render_pass->id] = render_pass.get();
@@ -1257,8 +1277,9 @@
}
TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
- TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::LayerTreeHostImpl", this,
- TracedValue::FromValue(AsValue().release()));
+ TRACE_DISABLED_BY_DEFAULT("cc.debug") ","
+ TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"), "cc::LayerTreeHostImpl",
+ this, TracedValue::FromValue(AsValueWithFrame(frame).release()));
// Because the contents of the HUD depend on everything else in the frame, the
// contents of its texture are updated as the last thing before the frame is
@@ -2136,6 +2157,7 @@
pinch_gesture_active_ = true;
previous_pinch_anchor_ = gfx::Point();
client_->RenewTreePriority();
+ active_tree_->SetCurrentlyScrollingLayer(RootScrollLayer());
}
void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta,
@@ -2430,7 +2452,8 @@
return base::TimeTicks::Now();
}
-scoped_ptr<base::Value> LayerTreeHostImpl::AsValue() const {
+scoped_ptr<base::Value> LayerTreeHostImpl::AsValueWithFrame(
+ FrameData* frame) const {
scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
if (this->pending_tree_)
state->Set("activation_state", ActivationStateAsValue().release());
@@ -2441,6 +2464,8 @@
state->Set("active_tree", active_tree_->AsValue().release());
if (pending_tree_)
state->Set("pending_tree", pending_tree_->AsValue().release());
+ if (frame)
+ state->Set("frame", frame->AsValue().release());
return state.PassAs<base::Value>();
}
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index ae6f3c1..31870ac 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -139,6 +139,7 @@
struct CC_EXPORT FrameData : public RenderPassSink {
FrameData();
virtual ~FrameData();
+ scoped_ptr<base::Value> AsValue() const;
std::vector<gfx::Rect> occluding_screen_space_rects;
std::vector<gfx::Rect> non_occluding_screen_space_rects;
@@ -371,7 +372,8 @@
virtual base::TimeTicks CurrentPhysicalTimeTicks() const;
- scoped_ptr<base::Value> AsValue() const;
+ scoped_ptr<base::Value> AsValue() const { return AsValueWithFrame(NULL); }
+ scoped_ptr<base::Value> AsValueWithFrame(FrameData* frame) const;
scoped_ptr<base::Value> ActivationStateAsValue() const;
bool page_scale_animation_active() const { return !!page_scale_animation_; }
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 72a72b4..ab81c67 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -770,9 +770,10 @@
scroll_layer->SetScrollDelta(gfx::Vector2d());
float page_scale_delta = 2.f;
- host_impl_->PinchGestureBegin();
+ host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
host_impl_->PinchGestureEnd();
+ host_impl_->ScrollEnd();
EXPECT_TRUE(did_request_redraw_);
EXPECT_TRUE(did_request_commit_);
@@ -794,9 +795,11 @@
scroll_layer->SetScrollDelta(gfx::Vector2d());
float page_scale_delta = 2.f;
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
host_impl_->PinchGestureEnd();
+ host_impl_->ScrollEnd();
gfx::Vector2d scroll_delta(0, 10);
EXPECT_EQ(InputHandler::ScrollStarted,
@@ -832,9 +835,11 @@
scroll_layer->SetScrollDelta(gfx::Vector2d());
float page_scale_delta = 2.f;
+ host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
host_impl_->PinchGestureEnd();
+ host_impl_->ScrollEnd();
EXPECT_TRUE(did_request_redraw_);
EXPECT_TRUE(did_request_commit_);
@@ -851,9 +856,11 @@
scroll_layer->SetScrollDelta(gfx::Vector2d());
float page_scale_delta = 10.f;
+ host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
host_impl_->PinchGestureEnd();
+ host_impl_->ScrollEnd();
scoped_ptr<ScrollAndScaleSet> scroll_info =
host_impl_->ProcessScrollDeltas();
@@ -869,9 +876,11 @@
scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
float page_scale_delta = 0.1f;
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
host_impl_->PinchGestureEnd();
+ host_impl_->ScrollEnd();
scoped_ptr<ScrollAndScaleSet> scroll_info =
host_impl_->ProcessScrollDeltas();
@@ -889,10 +898,12 @@
scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
float page_scale_delta = 1.f;
+ host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
host_impl_->PinchGestureEnd();
+ host_impl_->ScrollEnd();
scoped_ptr<ScrollAndScaleSet> scroll_info =
host_impl_->ProcessScrollDeltas();
@@ -909,7 +920,7 @@
scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
float page_scale_delta = 1.f;
- host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Wheel);
+ host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
@@ -922,6 +933,30 @@
EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
}
+
+ // Two-finger panning should work when starting fully zoomed out.
+ {
+ host_impl_->active_tree()->SetPageScaleFactorAndLimits(0.5f,
+ 0.5f,
+ 4.f);
+ scroll_layer->SetScrollDelta(gfx::Vector2d());
+ scroll_layer->SetScrollOffset(gfx::Vector2d(0, 0));
+ host_impl_->active_tree()->UpdateMaxScrollOffset();
+
+ host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture);
+ host_impl_->PinchGestureBegin();
+ host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
+ host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
+ host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
+ host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
+ host_impl_->PinchGestureEnd();
+ host_impl_->ScrollEnd();
+
+ scoped_ptr<ScrollAndScaleSet> scroll_info =
+ host_impl_->ProcessScrollDeltas();
+ EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
+ ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
+ }
}
TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
@@ -1184,9 +1219,11 @@
}
// Page scale should update metadata correctly (shrinking only the viewport).
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(2.f, gfx::Point());
host_impl_->PinchGestureEnd();
+ host_impl_->ScrollEnd();
{
CompositorFrameMetadata metadata =
host_impl_->MakeCompositorFrameMetadata();
@@ -1789,9 +1826,11 @@
host_impl_->ScrollEnd();
// Set new page scale on impl thread by pinching.
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
host_impl_->PinchGestureEnd();
+ host_impl_->ScrollEnd();
DrawOneFrame();
// The scroll delta is not scaled because the main thread did not scale.
@@ -1826,9 +1865,11 @@
LayerImpl* grand_child = child->children()[0];
// Set new page scale on impl thread by pinching.
+ host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
host_impl_->PinchGestureBegin();
host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
host_impl_->PinchGestureEnd();
+ host_impl_->ScrollEnd();
DrawOneFrame();
EXPECT_EQ(1.f, root->contents_scale_x());
diff --git a/cc/trees/layer_tree_host_unittest_delegated.cc b/cc/trees/layer_tree_host_unittest_delegated.cc
index 08ba3e0..d489313 100644
--- a/cc/trees/layer_tree_host_unittest_delegated.cc
+++ b/cc/trees/layer_tree_host_unittest_delegated.cc
@@ -4,14 +4,18 @@
#include "cc/trees/layer_tree_host.h"
+#include "base/bind.h"
#include "cc/layers/delegated_renderer_layer.h"
#include "cc/layers/delegated_renderer_layer_client.h"
#include "cc/layers/delegated_renderer_layer_impl.h"
+#include "cc/output/compositor_frame.h"
+#include "cc/output/compositor_frame_ack.h"
#include "cc/output/delegated_frame_data.h"
#include "cc/quads/shared_quad_state.h"
#include "cc/quads/texture_draw_quad.h"
#include "cc/test/fake_delegated_renderer_layer.h"
#include "cc/test/fake_delegated_renderer_layer_impl.h"
+#include "cc/test/fake_output_surface.h"
#include "cc/test/layer_tree_test.h"
#include "cc/trees/layer_tree_impl.h"
#include "gpu/GLES2/gl2extchromium.h"
@@ -35,6 +39,49 @@
return frame.Pass();
}
+ scoped_ptr<DelegatedFrameData> CreateInvalidFrameData(
+ gfx::Rect root_output_rect,
+ gfx::Rect root_damage_rect) {
+ scoped_ptr<DelegatedFrameData> frame(new DelegatedFrameData);
+
+ scoped_ptr<RenderPass> root_pass(RenderPass::Create());
+ root_pass->SetNew(RenderPass::Id(1, 1),
+ root_output_rect,
+ root_damage_rect,
+ gfx::Transform());
+
+ scoped_ptr<SharedQuadState> shared_quad_state = SharedQuadState::Create();
+
+ gfx::Rect rect = root_output_rect;
+ gfx::Rect opaque_rect = root_output_rect;
+ // An invalid resource id! The resource isn't part of the frame.
+ unsigned resource_id = 5;
+ bool premultiplied_alpha = false;
+ gfx::PointF uv_top_left = gfx::PointF(0.f, 0.f);
+ gfx::PointF uv_bottom_right = gfx::PointF(1.f, 1.f);
+ SkColor background_color = 0;
+ float vertex_opacity[4] = {1.f, 1.f, 1.f, 1.f};
+ bool flipped = false;
+
+ scoped_ptr<TextureDrawQuad> invalid_draw_quad = TextureDrawQuad::Create();
+ invalid_draw_quad->SetNew(shared_quad_state.get(),
+ rect,
+ opaque_rect,
+ resource_id,
+ premultiplied_alpha,
+ uv_top_left,
+ uv_bottom_right,
+ background_color,
+ vertex_opacity,
+ flipped);
+ root_pass->quad_list.push_back(invalid_draw_quad.PassAs<DrawQuad>());
+
+ root_pass->shared_quad_state_list.push_back(shared_quad_state.Pass());
+
+ frame->render_pass_list.push_back(root_pass.Pass());
+ return frame.Pass();
+ }
+
void AddTransferableResource(DelegatedFrameData* frame,
ResourceProvider::ResourceId resource_id) {
TransferableResource resource;
@@ -65,6 +112,54 @@
scoped_ptr<DelegatedFrameData> frame(new DelegatedFrameData);
return frame.Pass();
}
+
+
+ static ResourceProvider::ResourceId AppendResourceId(
+ std::vector<ResourceProvider::ResourceId>* resources_in_last_sent_frame,
+ ResourceProvider::ResourceId resource_id) {
+ resources_in_last_sent_frame->push_back(resource_id);
+ return resource_id;
+ }
+
+ void ReturnUnusedResourcesFromParent(LayerTreeHostImpl* host_impl) {
+ DelegatedFrameData* delegated_frame_data =
+ output_surface()->last_sent_frame().delegated_frame_data.get();
+ if (!delegated_frame_data)
+ return;
+
+ std::vector<ResourceProvider::ResourceId> resources_in_last_sent_frame;
+ for (size_t i = 0; i < delegated_frame_data->render_pass_list.size(); ++i) {
+ RenderPass* pass = delegated_frame_data->render_pass_list.at(i);
+ for (size_t j = 0; j < pass->quad_list.size(); ++j) {
+ DrawQuad* quad = pass->quad_list[j];
+ quad->IterateResources(base::Bind(&AppendResourceId,
+ &resources_in_last_sent_frame));
+ }
+ }
+
+ std::vector<ResourceProvider::ResourceId> resources_to_return;
+
+ const TransferableResourceArray& resources_held_by_parent =
+ output_surface()->resources_held_by_parent();
+ for (size_t i = 0; i < resources_held_by_parent.size(); ++i) {
+ ResourceProvider::ResourceId resource_in_parent =
+ resources_held_by_parent[i].id;
+ bool resource_in_parent_is_not_part_of_frame =
+ std::find(resources_in_last_sent_frame.begin(),
+ resources_in_last_sent_frame.end(),
+ resource_in_parent) == resources_in_last_sent_frame.end();
+ if (resource_in_parent_is_not_part_of_frame)
+ resources_to_return.push_back(resource_in_parent);
+ }
+
+ if (resources_to_return.empty())
+ return;
+
+ CompositorFrameAck ack;
+ for (size_t i = 0; i < resources_to_return.size(); ++i)
+ output_surface()->ReturnResource(resources_to_return[i], &ack);
+ host_impl->OnSwapBuffersComplete(&ack);
+ }
};
class LayerTreeHostDelegatedTestCaseSingleDelegatedLayer
@@ -267,13 +362,18 @@
gfx::Rect(5, 5, 1, 1)));
break;
case 13:
+ // An invalid frame isn't used, so it should not cause damage.
+ delegated_->SetFrameData(CreateInvalidFrameData(gfx::Rect(0, 0, 10, 10),
+ gfx::Rect(5, 5, 1, 1)));
+ break;
+ case 14:
// Should create gfx::Rect(1, 1, 2, 2) of damage. The frame size is
// 5x5 and the display size is now set to 10x10, so this should result
// in a gfx::Rect(2, 2, 4, 4) damage rect.
delegated_->SetFrameData(CreateFrameData(gfx::Rect(0, 0, 5, 5),
gfx::Rect(1, 1, 2, 2)));
break;
- case 14:
+ case 15:
// Should create zero damage.
layer_tree_host()->SetNeedsCommit();
break;
@@ -352,10 +452,14 @@
damage_rect.ToString());
break;
case 13:
- EXPECT_EQ(gfx::RectF(2.f, 2.f, 4.f, 4.f).ToString(),
+ EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
damage_rect.ToString());
break;
case 14:
+ EXPECT_EQ(gfx::RectF(2.f, 2.f, 4.f, 4.f).ToString(),
+ damage_rect.ToString());
+ break;
+ case 15:
EXPECT_EQ(gfx::RectF(0.f, 0.f, 0.f, 0.f).ToString(),
damage_rect.ToString());
EndTest();
@@ -479,7 +583,7 @@
PostSetNeedsCommitToMainThread();
}
- virtual void DidCommit() OVERRIDE {
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
scoped_ptr<DelegatedFrameData> frame;
TransferableResourceArray resources;
@@ -495,6 +599,11 @@
delegated_->SetFrameData(frame.Pass());
break;
case 2:
+ // Retrieve unused resources to the main thread.
+ // TODO(danakj): Shouldn't need to commit to get resources.
+ layer_tree_host()->SetNeedsCommit();
+ return;
+ case 3:
// All of the resources are in use.
delegated_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
@@ -506,7 +615,12 @@
AddTransferableResource(frame.get(), 444);
delegated_->SetFrameData(frame.Pass());
break;
- case 3:
+ case 4:
+ // Retrieve unused resources to the main thread.
+ // TODO(danakj): Shouldn't need to commit to get resources.
+ layer_tree_host()->SetNeedsCommit();
+ return;
+ case 5:
// 555 is no longer in use.
delegated_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(1u, resources.size());
@@ -516,7 +630,12 @@
frame = CreateFrameData(gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1));
delegated_->SetFrameData(frame.Pass());
break;
- case 4:
+ case 6:
+ // Postpone collecting resources for a frame. They should still be there
+ // the next frame.
+ layer_tree_host()->SetNeedsCommit();
+ return;
+ case 7:
// 444 and 999 are no longer in use.
delegated_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(2u, resources.size());
@@ -537,11 +656,15 @@
EXPECT_TRUE(empty_resources.empty());
}
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+ bool result) OVERRIDE {
+ ReturnUnusedResourcesFromParent(host_impl);
+ }
+
virtual void AfterTest() OVERRIDE {}
};
-// Enable this for delegating renderer. crbug.com/239290
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
+SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostDelegatedTestReturnUnusedResources);
class LayerTreeHostDelegatedTestReusedResources
@@ -551,7 +674,7 @@
PostSetNeedsCommitToMainThread();
}
- virtual void DidCommit() OVERRIDE {
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
scoped_ptr<DelegatedFrameData> frame;
TransferableResourceArray resources;
@@ -569,6 +692,11 @@
delegated_->SetFrameData(frame.Pass());
break;
case 2:
+ // Retrieve unused resources to the main thread.
+ // TODO(danakj): Shouldn't need to commit to get resources.
+ layer_tree_host()->SetNeedsCommit();
+ return;
+ case 3:
// All of the resources are in use.
delegated_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
@@ -588,7 +716,12 @@
AddTextureQuad(frame.get(), 444);
delegated_->SetFrameData(frame.Pass());
break;
- case 3:
+ case 4:
+ // Retrieve unused resources to the main thread.
+ // TODO(danakj): Shouldn't need to commit to get resources.
+ layer_tree_host()->SetNeedsCommit();
+ return;
+ case 5:
// The 999 resource is the only unused one.
delegated_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(1u, resources.size());
@@ -598,12 +731,15 @@
}
}
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+ bool result) OVERRIDE {
+ ReturnUnusedResourcesFromParent(host_impl);
+ }
+
virtual void AfterTest() OVERRIDE {}
};
-// Enable this for delegating renderer. crbug.com/239290
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
- LayerTreeHostDelegatedTestReusedResources);
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestReusedResources);
class LayerTreeHostDelegatedTestFrameBeforeAck
: public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
@@ -612,7 +748,7 @@
PostSetNeedsCommitToMainThread();
}
- virtual void DidCommit() OVERRIDE {
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
scoped_ptr<DelegatedFrameData> frame;
TransferableResourceArray resources;
@@ -630,6 +766,11 @@
delegated_->SetFrameData(frame.Pass());
break;
case 2:
+ // Retrieve unused resources to the main thread.
+ // TODO(danakj): Shouldn't need to commit to get resources.
+ layer_tree_host()->SetNeedsCommit();
+ return;
+ case 3:
// All of the resources are in use.
delegated_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
@@ -645,7 +786,12 @@
// The parent compositor (this one) does a commit.
break;
- case 3:
+ case 4:
+ // Retrieve unused resources to the main thread.
+ // TODO(danakj): Shouldn't need to commit to get resources.
+ layer_tree_host()->SetNeedsCommit();
+ return;
+ case 5:
delegated_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(2u, resources.size());
if (resources[0].id == 555) {
@@ -668,7 +814,7 @@
}
virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
- if (host_impl->active_tree()->source_frame_number() != 3)
+ if (host_impl->active_tree()->source_frame_number() != 5)
return;
LayerImpl* root_impl = host_impl->active_tree()->root_layer();
@@ -697,12 +843,15 @@
EndTest();
}
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+ bool result) OVERRIDE {
+ ReturnUnusedResourcesFromParent(host_impl);
+ }
+
virtual void AfterTest() OVERRIDE {}
};
-// Enable this for delegating renderer. crbug.com/239290
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
- LayerTreeHostDelegatedTestFrameBeforeAck);
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestFrameBeforeAck);
class LayerTreeHostDelegatedTestFrameBeforeTakeResources
: public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
@@ -711,7 +860,7 @@
PostSetNeedsCommitToMainThread();
}
- virtual void DidCommit() OVERRIDE {
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
scoped_ptr<DelegatedFrameData> frame;
TransferableResourceArray resources;
@@ -729,6 +878,11 @@
delegated_->SetFrameData(frame.Pass());
break;
case 2:
+ // Retrieve unused resources to the main thread.
+ // TODO(danakj): Shouldn't need to commit to get resources.
+ layer_tree_host()->SetNeedsCommit();
+ return;
+ case 3:
// All of the resources are in use.
delegated_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
@@ -744,7 +898,12 @@
// The parent compositor (this one) does a commit.
break;
- case 3:
+ case 4:
+ // Retrieve unused resources to the main thread.
+ // TODO(danakj): Shouldn't need to commit to get resources.
+ layer_tree_host()->SetNeedsCommit();
+ return;
+ case 5:
// The child compositor sends a frame before taking resources back
// from the previous commit. This frame makes use of the resources 555
// and 444, which were just released during commit.
@@ -758,7 +917,12 @@
delegated_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
break;
- case 4:
+ case 6:
+ // Retrieve unused resources to the main thread.
+ // TODO(danakj): Shouldn't need to commit to get resources.
+ layer_tree_host()->SetNeedsCommit();
+ return;
+ case 7:
delegated_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
EndTest();
@@ -767,7 +931,7 @@
}
virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
- if (host_impl->active_tree()->source_frame_number() != 3)
+ if (host_impl->active_tree()->source_frame_number() != 5)
return;
LayerImpl* root_impl = host_impl->active_tree()->root_layer();
@@ -803,11 +967,15 @@
EXPECT_EQ(map.find(444)->second, quad3->resource_id);
}
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+ bool result) OVERRIDE {
+ ReturnUnusedResourcesFromParent(host_impl);
+ }
+
virtual void AfterTest() OVERRIDE {}
};
-// Enable this for delegating renderer. crbug.com/239290
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
+SINGLE_AND_MULTI_THREAD_TEST_F(
LayerTreeHostDelegatedTestFrameBeforeTakeResources);
class LayerTreeHostDelegatedTestBadFrame
@@ -817,7 +985,7 @@
PostSetNeedsCommitToMainThread();
}
- virtual void DidCommit() OVERRIDE {
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
scoped_ptr<DelegatedFrameData> frame;
TransferableResourceArray resources;
@@ -833,6 +1001,11 @@
delegated_->SetFrameData(frame.Pass());
break;
case 2:
+ // Retrieve unused resources to the main thread.
+ // TODO(danakj): Shouldn't need to commit to get resources.
+ layer_tree_host()->SetNeedsCommit();
+ return;
+ case 3:
// All of the resources are in use.
delegated_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
@@ -851,7 +1024,12 @@
// The parent compositor (this one) does a commit.
break;
- case 3:
+ case 4:
+ // Retrieve unused resources to the main thread.
+ // TODO(danakj): Shouldn't need to commit to get resources.
+ layer_tree_host()->SetNeedsCommit();
+ return;
+ case 5:
// The bad frame's resource is given back to the child compositor.
delegated_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(1u, resources.size());
@@ -862,7 +1040,12 @@
AddTextureQuad(frame.get(), 999);
delegated_->SetFrameData(frame.Pass());
break;
- case 4:
+ case 6:
+ // Retrieve unused resources to the main thread.
+ // TODO(danakj): Shouldn't need to commit to get resources.
+ layer_tree_host()->SetNeedsCommit();
+ return;
+ case 7:
// The unused 555 from the last good frame is now released.
delegated_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(1u, resources.size());
@@ -873,10 +1056,13 @@
}
}
- virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
+ virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
+ bool result) OVERRIDE {
if (host_impl->active_tree()->source_frame_number() < 1)
return;
+ ReturnUnusedResourcesFromParent(host_impl);
+
LayerImpl* root_impl = host_impl->active_tree()->root_layer();
FakeDelegatedRendererLayerImpl* delegated_impl =
static_cast<FakeDelegatedRendererLayerImpl*>(root_impl->children()[0]);
@@ -907,7 +1093,7 @@
EXPECT_EQ(map.find(555)->second, quad2->resource_id);
break;
}
- case 2: {
+ case 3: {
// We only keep resources from the last valid frame.
EXPECT_EQ(2u, map.size());
EXPECT_EQ(1u, map.count(999));
@@ -929,7 +1115,14 @@
EXPECT_EQ(map.find(555)->second, quad2->resource_id);
break;
}
- case 3: {
+ case 5:
+ // Resources given to our parent compositor will be returned now, but
+ // the DelegatedRendererLayerImpl doesn't know about it until the next
+ // commit.
+ // TODO(danakj): Shouldn't need a commit to return resources to the
+ // DelegatedRendererLayerImpl or to the main thread.
+ break;
+ case 6: {
// We have the new good frame with just 999 in it.
EXPECT_EQ(1u, map.size());
EXPECT_EQ(1u, map.count(999));
@@ -950,9 +1143,7 @@
virtual void AfterTest() OVERRIDE {}
};
-// Enable this for delegating renderer. crbug.com/239290
-SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
- LayerTreeHostDelegatedTestBadFrame);
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestBadFrame);
class LayerTreeHostDelegatedTestUnnamedResource
: public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
@@ -1077,13 +1268,7 @@
class LayerTreeHostDelegatedTestResourceSentToParent
: public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
public:
- virtual void BeginTest() OVERRIDE {
- // Prevent drawing with resources that are sent to the grandparent.
- layer_tree_host()->SetViewportSize(gfx::Size());
- PostSetNeedsCommitToMainThread();
- }
-
- virtual void DidCommit() OVERRIDE {
+ virtual void DidCommitAndDrawFrame() OVERRIDE {
scoped_ptr<DelegatedFrameData> frame;
TransferableResourceArray resources;
@@ -1113,6 +1298,8 @@
delegated_->TakeUnusedResourcesForChildCompositor(&resources);
EXPECT_EQ(0u, resources.size());
+ // The impl side will get back the resource at some point.
+ // TODO(danakj): The test should work without this.
layer_tree_host()->SetNeedsCommit();
break;
case 4:
@@ -1148,15 +1335,7 @@
EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(999)->second));
EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second));
- // The 999 resource is sent to a grandparent compositor.
- ResourceProvider::ResourceIdArray resources_for_parent;
- resources_for_parent.push_back(map.find(999)->second);
- TransferableResourceArray transferable_resources;
- host_impl->resource_provider()->PrepareSendToParent(
- resources_for_parent, &transferable_resources);
-
- resource_in_grandparent = transferable_resources[0];
- EXPECT_EQ(map.find(999)->second, resource_in_grandparent.id);
+ // The 999 resource will be sent to a grandparent compositor.
break;
}
case 2: {
@@ -1164,17 +1343,14 @@
EXPECT_EQ(1u, map.count(999));
EXPECT_EQ(1u, map.count(555));
- /// 999 is in the parent, so not held by delegated renderer layer.
+ // 999 is in the parent, so not held by delegated renderer layer.
EXPECT_EQ(1u, delegated_impl->Resources().size());
EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second));
// Receive 999 back from the grandparent.
- EXPECT_EQ(map.find(999)->second, resource_in_grandparent.id);
- TransferableResourceArray transferable_resources;
- transferable_resources.push_back(resource_in_grandparent);
-
- host_impl->resource_provider()->ReceiveFromParent(
- transferable_resources);
+ CompositorFrameAck ack;
+ output_surface()->ReturnResource(map.find(999)->second, &ack);
+ host_impl->OnSwapBuffersComplete(&ack);
break;
}
case 3:
@@ -1184,6 +1360,7 @@
EXPECT_EQ(1u, delegated_impl->Resources().size());
EXPECT_EQ(1u, delegated_impl->Resources().count(map.find(555)->second));
+ break;
}
}
@@ -1192,7 +1369,8 @@
TransferableResource resource_in_grandparent;
};
-SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDelegatedTestResourceSentToParent);
+SINGLE_AND_MULTI_THREAD_DELEGATING_RENDERER_TEST_F(
+ LayerTreeHostDelegatedTestResourceSentToParent);
class LayerTreeHostDelegatedTestCommitWithoutTake
: public LayerTreeHostDelegatedTestCaseSingleDelegatedLayer {
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index 5705788..a0bd4bf 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -112,7 +112,11 @@
TRACE_EVENT0("cc", "ThreadProxy::CompositeAndReadback");
DCHECK(IsMainThread());
DCHECK(layer_tree_host_);
- DCHECK(!defer_commits_);
+
+ if (defer_commits_) {
+ TRACE_EVENT0("cc", "CompositeAndReadback_DeferCommit");
+ return false;
+ }
if (!layer_tree_host_->InitializeOutputSurfaceIfNeeded()) {
TRACE_EVENT0("cc", "CompositeAndReadback_EarlyOut_LR_Uninitialized");
diff --git a/chrome/VERSION b/chrome/VERSION
index 8bdd7b3..5fc8dd7 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
MAJOR=30
MINOR=0
-BUILD=1591
+BUILD=1595
PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/FindMatchRectsDetails.java b/chrome/android/java/src/org/chromium/chrome/browser/FindMatchRectsDetails.java
index a0575d3..7b2bd83 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/FindMatchRectsDetails.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/FindMatchRectsDetails.java
@@ -7,8 +7,7 @@
import android.graphics.RectF;
/**
- * Java equivalent to the C++ FindMatchRectsDetails class
- * defined in chrome/browser/ui/find_bar/find_match_rects_details.h
+ * Holds the result details of a RequestFindMatchRects reply.
*/
public class FindMatchRectsDetails {
/** Version of the the rects in this result. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerAndroid.java
new file mode 100644
index 0000000..e7696d5
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerAndroid.java
@@ -0,0 +1,190 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.autofill;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+import org.chromium.ui.WindowAndroid;
+
+/**
+ * Java-side AutofillDialog and AutofillDialogFactory interfaces, and
+ * JNI glue for C++ AutofillDialogControllerAndroid.
+ */
+@JNINamespace("autofill")
+public class AutofillDialogControllerAndroid {
+ private static AutofillDialogFactory mDialogFactory;
+
+ private int mNativeDelegate; // could be 0 after onDestroy().
+ private AutofillDialog mDialog;
+
+ /**
+ * An interface to the two possible continuations for the dialog.
+ * The dialog is expected to be dismissed when either of the calls is made.
+ */
+ public interface AutofillDialogDelegate {
+ /**
+ * Cancels the requestAutocomplete.
+ */
+ void dialogCancel();
+
+ /**
+ * Submits the data to the web-page and persists the last account/card/address choices.
+ * @param fullWallet Resulting billing/shipping information obtained from the user
+ * @param lastUsedChoiceIsAutofill Whether the last selected data source is Autofill
+ * @param lastUsedAccountName The last selected account name, or null
+ * @param guidLastUsedBilling GUID of the last selected Autofill billing address, or null
+ * @param guidLastUsedShipping GUID of the last selected Autofill shipping address, or null
+ * @param guidLastUsedCard GUID of the last selected Autofill credit card, or null
+ */
+ void dialogContinue(
+ AutofillDialogResult.ResultWallet fullWallet,
+ boolean lastUsedChoiceIsAutofill, String lastUsedAccountName,
+ String guidLastUsedBilling, String guidLastUsedShipping, String guidLastUsedCard);
+ }
+
+ /**
+ * An interface that exposes the necessary functionality for an Autofill dialog.
+ * Note that all information necessary to construct the dialog is passed to the factory.
+ */
+ public interface AutofillDialog {
+ /**
+ * Notifies the dialog that the C++ side is gone.
+ * The dialog needs to clear its reference to the no longer valid AutofillDialogDelegate.
+ */
+ void onDestroy();
+ }
+
+ /**
+ * An interface to the factory that creates Autofill dialogs.
+ */
+ public interface AutofillDialogFactory {
+ /**
+ * Creates the dialog.
+ * Reasonable attempts should be made to respect "initial choices",
+ * Initial choices don't have to be self-consistent or valid.
+ *
+ * @param delegate Continuations for the dialog
+ * @param windowAndroid Context in which the dialog should be shown
+ * @param requestFullBillingAddress Whether the full billing address is required
+ * @param requestShippingAddress Whether the shipping address is required
+ * @param requestPhoneNumbers Whether the phone numbers are required in addresses
+ * @param incognitoMode True if the dialog started from an incognito tab
+ * @param initialChoiceIsAutofill Whether the selected data source should be Autofill
+ * @param initialAccountName Account to be selected, or null
+ * @param initialBillingGuid GUID of the initial billing address selection in Autofill
+ * @param initialShippingGuid GUID of the initial shipping address selection in Autofill
+ * @param initialCardGuid GUID of the initial credit card selection in Autofill
+ * @param merchantDomain Scheme+origin for the originating web page, or null
+ * @return The Autofill dialog that would later call into the delegate, or null
+ */
+ AutofillDialog createDialog(
+ final AutofillDialogDelegate delegate,
+ final WindowAndroid windowAndroid,
+ final boolean requestFullBillingAddress, final boolean requestShippingAddress,
+ final boolean requestPhoneNumbers,
+ final boolean incognitoMode,
+ final boolean initialChoiceIsAutofill, final String initialAccountName,
+ final String initialBillingGuid, final String initialShippingGuid,
+ final String initialCardGuid,
+ final String merchantDomain);
+ }
+
+ /**
+ * Sets the factory to be used.
+ * @param factory An instance of the AutofillDialogFactory that will handle requests.
+ */
+ public static void setDialogFactory(AutofillDialogFactory factory) {
+ mDialogFactory = factory;
+ }
+
+ private AutofillDialogControllerAndroid(
+ final int nativeAutofillDialogControllerAndroid,
+ final WindowAndroid windowAndroid,
+ final boolean requestFullBillingAddress, final boolean requestShippingAddress,
+ final boolean requestPhoneNumbers,
+ final boolean incognitoMode,
+ final boolean initialChoiceIsAutofill, final String initialWalletAccountName,
+ final String initialBillingGuid, final String initialShippingGuid,
+ final String initialCardGuid,
+ final String merchantDomain) {
+ mNativeDelegate = nativeAutofillDialogControllerAndroid;
+
+ if (mDialogFactory == null) {
+ nativeDialogCancel(mNativeDelegate);
+ return;
+ }
+
+ AutofillDialogDelegate delegate = new AutofillDialogDelegate() {
+ @Override
+ public void dialogCancel() {
+ nativeDialogCancel(mNativeDelegate);
+ }
+
+ @Override
+ public void dialogContinue(
+ AutofillDialogResult.ResultWallet fullWallet,
+ boolean lastUsedChoiceIsAutofill, String lastUsedAccountName,
+ String guidLastUsedBilling, String guidLastUsedShipping,
+ String guidLastUsedCard) {
+ nativeDialogContinue(mNativeDelegate, fullWallet,
+ lastUsedChoiceIsAutofill, lastUsedAccountName,
+ guidLastUsedBilling, guidLastUsedShipping, guidLastUsedCard);
+ }
+ };
+
+ mDialog = mDialogFactory.createDialog(
+ delegate,
+ windowAndroid,
+ requestFullBillingAddress, requestShippingAddress,
+ requestPhoneNumbers,
+ incognitoMode,
+ initialChoiceIsAutofill, initialWalletAccountName,
+ initialBillingGuid, initialShippingGuid, initialCardGuid,
+ merchantDomain);
+ if (mDialog == null) {
+ nativeDialogCancel(mNativeDelegate);
+ return;
+ }
+ }
+
+ @CalledByNative
+ private static AutofillDialogControllerAndroid create(
+ final int nativeAutofillDialogControllerAndroid,
+ final WindowAndroid windowAndroid,
+ final boolean requestFullBillingAddress, final boolean requestShippingAddress,
+ final boolean requestPhoneNumbers,
+ final boolean incognitoMode,
+ final boolean initialChoiceIsAutofill, final String initialWalletAccountName,
+ final String initialBillingGuid, final String initialShippingGuid,
+ final String initialCreditCardGuid,
+ final String merchantDomain) {
+ return new AutofillDialogControllerAndroid(
+ nativeAutofillDialogControllerAndroid, windowAndroid,
+ requestFullBillingAddress, requestShippingAddress, requestPhoneNumbers,
+ incognitoMode,
+ initialChoiceIsAutofill, initialWalletAccountName,
+ initialBillingGuid, initialShippingGuid,
+ initialCreditCardGuid,
+ merchantDomain);
+ }
+
+ @CalledByNative
+ private void onDestroy() {
+ if (mNativeDelegate == 0) return;
+
+ if (mDialog != null) mDialog.onDestroy();
+
+ mDialog = null;
+ mNativeDelegate = 0;
+ }
+
+ // Calls from Java to C++ AutofillDialogControllerAndroid:
+
+ private native void nativeDialogCancel(int nativeAutofillDialogControllerAndroid);
+ private native void nativeDialogContinue(int nativeAutofillDialogControllerAndroid,
+ Object fullWallet,
+ boolean lastUsedChoiceIsAutofill, String lastUsedAccountName,
+ String guidLastUsedBilling, String guidLastUsedShipping, String guidLastUsedCard);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogResult.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogResult.java
new file mode 100644
index 0000000..92f0cd8
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogResult.java
@@ -0,0 +1,246 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.autofill;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+
+/**
+ * Java-side result of a non-cancelled AutofillDialog invocation, and
+ * JNI glue for C++ AutofillDialogResult used by AutofillDialogControllerAndroid.
+ */
+@JNINamespace("autofill")
+public class AutofillDialogResult {
+ /**
+ * Information about the credit card in the dialog result.
+ */
+ public static class ResultCard {
+ private final int mExpirationMonth;
+ private final int mExpirationYear;
+ private final String mPan;
+ private final String mCvn;
+
+ /**
+ * Creates a ResultCard.
+ * @param expirationMonth Expiration month
+ * @param expirationYear Expiration year
+ * @param pan Credit card number
+ * @param cvn Credit card verification number
+ */
+ public ResultCard(int expirationMonth, int expirationYear, String pan, String cvn) {
+ mExpirationMonth = expirationMonth;
+ mExpirationYear = expirationYear;
+ mPan = pan;
+ mCvn = cvn;
+ }
+
+ /**
+ * @return Expiration month
+ */
+ @CalledByNative("ResultCard")
+ public int getExpirationMonth() {
+ return mExpirationMonth;
+ }
+
+ /**
+ * @return Expiration year
+ */
+ @CalledByNative("ResultCard")
+ public int getExpirationYear() {
+ return mExpirationYear;
+ }
+
+ /**
+ * @return Credit card number
+ */
+ @CalledByNative("ResultCard")
+ public String getPan() {
+ return mPan;
+ }
+
+ /**
+ * @return Credit card verification number
+ */
+ @CalledByNative("ResultCard")
+ public String getCvn() {
+ return mCvn;
+ }
+ }
+
+ /**
+ * Information about an address in the dialog result.
+ */
+ public static class ResultAddress {
+ private final String mName;
+ private final String mPhoneNumber;
+ private final String mAddress1;
+ private final String mAddress2;
+ private final String mCity;
+ private final String mState;
+ private final String mPostalCode;
+ private final String mCountryCode;
+
+ /**
+ * Creates a ResultAddress.
+ * Any parameter can be empty or null.
+ * @param name Full name
+ * @param phoneNumber Phone number
+ * @param address1 Address line 1
+ * @param address2 Address line 2
+ * @param city City
+ * @param state State
+ * @param postalCode Postal code
+ * @param countryCode Country code
+ */
+ public ResultAddress(
+ String name, String phoneNumber,
+ String address1, String address2,
+ String city, String state, String postalCode,
+ String countryCode) {
+ mName = name;
+ mPhoneNumber = phoneNumber;
+ mAddress1 = address1;
+ mAddress2 = address2;
+ mCity = city;
+ mState = state;
+ mPostalCode = postalCode;
+ mCountryCode = countryCode;
+ }
+
+ /**
+ * @return Full name
+ */
+ @CalledByNative("ResultAddress")
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * @return Phone number
+ */
+ @CalledByNative("ResultAddress")
+ public String getPhoneNumber() {
+ return mPhoneNumber;
+ }
+
+ /**
+ * @return Address line 1
+ */
+ @CalledByNative("ResultAddress")
+ public String getAddress1() {
+ return mAddress1;
+ }
+
+ /**
+ * @return Address line 2
+ */
+ @CalledByNative("ResultAddress")
+ public String getAddress2() {
+ return mAddress2;
+ }
+
+ /**
+ * @return City
+ */
+ @CalledByNative("ResultAddress")
+ public String getCity() {
+ return mCity;
+ }
+
+ /**
+ * @return State
+ */
+ @CalledByNative("ResultAddress")
+ public String getState() {
+ return mState;
+ }
+
+ /**
+ * @return Postal code
+ */
+ @CalledByNative("ResultAddress")
+ public String getPostalCode() {
+ return mPostalCode;
+ }
+
+ /**
+ * @return Country code
+ */
+ @CalledByNative("ResultAddress")
+ public String getCountryCode() {
+ return mCountryCode;
+ }
+ }
+
+ /**
+ * A response from the dialog.
+ */
+ public static class ResultWallet {
+ private final String mEmail;
+ private final String mGoogleTransactionId;
+ private final ResultCard mCard;
+ private final ResultAddress mBillingAddress;
+ private final ResultAddress mShippingAddress;
+
+ /**
+ * Creates a ResultWallet.
+ * Any fields could be empty or null.
+ * @param email Email address
+ * @param googleTransactionId Google transaction ID if any
+ * @param card Information about the credit card
+ * @param billingAddress Information about the billing address
+ * @param shippingAddress Information about the shipping address
+ */
+ public ResultWallet(
+ String email, String googleTransactionId,
+ ResultCard card, ResultAddress billingAddress, ResultAddress shippingAddress) {
+ mEmail = email;
+ mGoogleTransactionId = googleTransactionId;
+ mCard = card;
+ mBillingAddress = billingAddress;
+ mShippingAddress = shippingAddress;
+ }
+
+ /**
+ * @return Email address
+ */
+ @CalledByNative("ResultWallet")
+ public String getEmail() {
+ return mEmail;
+ }
+
+ /**
+ * @return Google transaction ID if any
+ */
+ @CalledByNative("ResultWallet")
+ public String getGoogleTransactionId() {
+ return mGoogleTransactionId;
+ }
+
+ /**
+ * @return Credit card information, or null
+ */
+ @CalledByNative("ResultWallet")
+ public ResultCard getCard() {
+ return mCard;
+ }
+
+ /**
+ * @return Billing address information, or null
+ */
+ @CalledByNative("ResultWallet")
+ public ResultAddress getBillingAddress() {
+ return mBillingAddress;
+ }
+
+ /**
+ * @return Shipping address information, or null
+ */
+ @CalledByNative("ResultWallet")
+ public ResultAddress getShippingAddress() {
+ return mShippingAddress;
+ }
+ }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java
index f539e1b..ee26e4c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java
@@ -115,7 +115,10 @@
}
}
- public int getSearchEngine() {
+ /**
+ * @return The default search engine index (e.g., 0, 1, 2,...).
+ */
+ public int getDefaultSearchEngineIndex() {
ThreadUtils.assertOnUiThread();
return nativeGetDefaultSearchProvider(mNativeTemplateUrlServiceAndroid);
}
@@ -125,7 +128,7 @@
*/
public TemplateUrl getDefaultSearchEngineTemplateUrl() {
return nativeGetPrepopulatedTemplateUrlAt(
- mNativeTemplateUrlServiceAndroid, getSearchEngine());
+ mNativeTemplateUrlServiceAndroid, getDefaultSearchEngineIndex());
}
public void setSearchEngine(int selectedIndex) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceTest.java
index 04c8965..e3b44d8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/search_engines/TemplateUrlServiceTest.java
@@ -66,7 +66,7 @@
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override
public void run() {
- searchEngineIndex.set(templateUrlService.getSearchEngine());
+ searchEngineIndex.set(templateUrlService.getDefaultSearchEngineIndex());
}
});
assertEquals(0, searchEngineIndex.get());
@@ -80,7 +80,7 @@
assertTrue("There must be more than one search engine to change searchEngines",
searchEngines.size() > 1);
templateUrlService.setSearchEngine(1);
- searchEngineIndex.set(templateUrlService.getSearchEngine());
+ searchEngineIndex.set(templateUrlService.getDefaultSearchEngineIndex());
}
});
assertEquals(1, searchEngineIndex.get());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ModalDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ModalDialogTest.java
index ecefa99..beb56fd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ModalDialogTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ModalDialogTest.java
@@ -14,6 +14,7 @@
import android.widget.EditText;
import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.UrlUtils;
import org.chromium.chrome.browser.JavascriptAppModalDialog;
@@ -170,8 +171,9 @@
* Verifies beforeunload dialogs are shown and they block/allow navigation
* as appropriate.
*/
- @MediumTest
- @Feature({"Browser", "Main"})
+ //@MediumTest
+ //@Feature({"Browser", "Main"})
+ @DisabledTest //crbug/270593
public void testBeforeUnloadDialog()
throws InterruptedException, TimeoutException, ExecutionException {
loadUrlWithSanitization(BEFORE_UNLOAD_URL);
diff --git a/chrome/android/testshell/testshell_tab.cc b/chrome/android/testshell/testshell_tab.cc
index 92a35c2..656bc31 100644
--- a/chrome/android/testshell/testshell_tab.cc
+++ b/chrome/android/testshell/testshell_tab.cc
@@ -89,6 +89,10 @@
return false;
}
+void TestShellTab::OnNewTabPageReady() {
+ NOTIMPLEMENTED();
+}
+
void TestShellTab::RunExternalProtocolDialog(const GURL& url) {
NOTIMPLEMENTED();
}
diff --git a/chrome/android/testshell/testshell_tab.h b/chrome/android/testshell/testshell_tab.h
index 0f79de4..bb06ad9 100644
--- a/chrome/android/testshell/testshell_tab.h
+++ b/chrome/android/testshell/testshell_tab.h
@@ -65,6 +65,7 @@
virtual void ShowSyncSettings() OVERRIDE;
virtual void ShowTermsOfService() OVERRIDE;
virtual bool ShouldWelcomePageLinkToTermsOfService() OVERRIDE;
+ virtual void OnNewTabPageReady() OVERRIDE;
virtual void RunExternalProtocolDialog(const GURL& url) OVERRIDE;
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc
index 1daec10..4825c3f 100644
--- a/chrome/app/chrome_main_delegate.cc
+++ b/chrome/app/chrome_main_delegate.cc
@@ -5,6 +5,7 @@
#include "chrome/app/chrome_main_delegate.h"
#include "base/command_line.h"
+#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/stats_counters.h"
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 027556d..3fc23f4 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -471,6 +471,15 @@
<message name="IDS_CREATE_LOCALLY_MANAGED_USER_NO_MANAGER_TEXT" desc="Text shown when supervised user can be created, but no users that can be manager exist.">
At least one account must exist on this device before creating a supervised user.
</message>
+ <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_TITLE" desc="Supervised user dialog, intro page, title">
+ What is a supervised user?
+ </message>
+ <message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_ALTERNATE_TEXT" desc="Supervised user dialog, intro page, first paragraph">
+ A supervised user can explore the web with your guidance. As the manager of a supervised user, you can
+ <ph name="BEGIN_BOLD"><strong></ph>allow or prohibit<ph name="END_BOLD"></strong></ph> certain websites,
+ <ph name="BEGIN_BOLD"><strong></ph>review<ph name="END_BOLD"></strong></ph> websites the supervised user has visited, and
+ <ph name="BEGIN_BOLD"><strong></ph>manage<ph name="END_BOLD"></strong></ph> other settings.
+ </message>
<message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_1" desc="Supervised user dialog, intro page, first paragraph">
A supervised user can explore the web with your guidance. As the manager of a supervised user in Chrome, you can:
</message>
@@ -485,8 +494,7 @@
</message>
<message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_2" desc="Supervised user dialog, intro page, second paragraph">
Creating a supervised user does not create a Google Account, and their settings
- and data will not follow them to other devices with Chrome Sync. Currently,
- a supervised user applies only to this installation of Chrome, on this device.
+ and data will not follow them to other devices with Chrome Sync. A supervised user applies only to this device.
</message>
<message name="IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_3" desc="Supervised user dialog, intro page, third paragraph">
After you create a new supervised user, you can manage the settings at any time from any device at <ph name="MANAGEMENT_URL">$1<ex>www.example.com</ex></ph>.
@@ -501,7 +509,7 @@
Enter password
</message>
<message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_ACCOUNT_NAME_TITLE" desc="Supervised user dialog, new user page, title for name of new user">
- Create an name -
+ Create a name -
</message>
<message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_ACCOUNT_NAME_EXPLANATION" desc="Supervised user dialog, new user page, explanation for name of new user">
This supervised user will be managed by <ph name="MANAGER_EMAIL">$1<ex>john.doe@example.com</ex></ph>.
@@ -596,16 +604,19 @@
Retry
</message>
<message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_AUTH_PROGRESS_MESSAGE" desc="Text shown next to progress indicator upon manager authentication.">
- Authenticating...
+ Authenticating
</message>
<message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_CREATION_PROGRESS_MESSAGE" desc="Text shown next to progress indicator upon supervised user creation.">
- Creating profile...
+ Creating supervised user
</message>
<message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_CREATION_TIMEOUT_MESSAGE" desc="Text shown at the place of progess indicator if creation takes too long and should be cancelled.">
Profile takes too long to create. You may want to cancel process and retry later.
</message>
<message name="IDS_USER_IS_LOCALLY_MANAGED_BY_NOTICE" desc="Text for notifications showing that this user is locally managed">
- This supervised user is managed by <ph name="USER_DISPLAY_NAME">$1<ex>John</ex></ph>. Usage and browsing history can be viewed by the manager.
+ This user is supervised by <ph name="MANAGER_EMAIL">$1<ex>user@example.com</ex></ph>. Usage and history from this user can be reviewed by the manager on chrome.com.
+ </message>
+ <message name="IDS_SUPERVISED_USER_EXPIRED_TOKEN_WARNING" desc="Warning text that is shown on login screen trying to sign in as a supervised user that has expired token">
+ This supervised user may have been deleted or disabled by the manager. Please contact the manager if you would like to continue signing in as this user.
</message>
<message name="IDS_LOGIN_POD_USER_REMOVE_WARNING" desc="Text shown as a warning when attempting to remove supervised user.">
All files and local data associated with the supervised user will be permanently
@@ -975,15 +986,6 @@
<message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_STANDARD_ORIENTATION" desc="The default value of display orientation option item.">
Standard
</message>
- <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION_90" desc="The value of display orientation option item: 90-degree rotated">
- 90°
- </message>
- <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION_180" desc="The value of display orientation option item: 180-degree rotated">
- 180°
- </message>
- <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION_270" desc="The value of display orientation option item: 270-degree rotated">
- 270°
- </message>
<message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_CALIBRATING_OVERSCAN" desc="Button label to start calibrating the overscan preference.">
Adjust...
</message>
@@ -1616,6 +1618,19 @@
This SIM card is disabled and cannot be used. Please contact your service provider for a replacement.
</message>
+ <message name="IDS_SLOW_DISABLE" desc="The text of the button that disables performance collection for feedback reports">
+ Disable performance data collection
+ </message>
+ <message name="IDS_SLOW_ENABLE" desc="The text of the button that enables performance collection for feedback reports">
+ Enable performance data collection
+ </message>
+ <message name="IDS_SLOW_DESCRIPTION" desc="The description of the performance tracing feature for feedback reports.">
+ Enabling collection of performance data will help Google improve the system over time. No data is sent until you file a feedback report (Alt-Shift-I) and include performance data. You can return to this screen to disable collection at any time.
+ </message>
+ <message name="IDS_SLOW_WARNING" desc="The warning that informs users that enabling this can have a negative effect on their performance">
+ <ph name="BEGIN_BOLD"><strong></ph>Note:<ph name="END_BOLD"></strong></ph> Only enable if you know what you are doing or if you have been asked to do so, as collection of data may reduce performance.
+ </message>
+
<message name="IDS_EULA_BACK_BUTTON" desc="Back button shown on EULA screen.">
Back
</message>
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index 8dacb67..9e97135 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -909,6 +909,9 @@
<message name="IDS_AUTOFILL_DIALOG_SAVE_LOCALLY_TOOLTIP" desc="Tooltip which explains function of checkbox that controls whether info the user types into the autofill dialog is saved by chrome.">
Chromium will securely store your information so you don't need to type it in again, but you will still need to verify your card's security code for future payments.
</message>
+ <message name="IDS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_TITLE" desc="Title text of the new credit card bubble informing a user their billing information has been saved in chrome.">
+ Your billing details have been saved in Chromium.
+ </message>
<!-- Network Error Pages -->
<message name="IDS_ERRORPAGES_SUGGESTION_NETWORK_PREDICTION_BODY" desc="When a page fails to load, sometimes we suggest disabling predicting network actions. These are details below a header.">
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index ce595e8..9dfe704 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -4786,6 +4786,9 @@
<message name="IDS_EXTENSION_WARNINGS_CREDENTIALS_CONFLICT" desc="Warning message which indicates that two or more extensions tried to modify a network request in a conflicting way and the modification of this extension was ignored">
This extension failed to provide credentials to a network request because another extension (<ph name="EXTENSION_NAME">$1<ex>My Cool Extension</ex></ph>) provided different credentials.
</message>
+ <message name="IDS_EXTENSION_WARNINGS_DOWNLOAD_FILENAME_CONFLICT" desc="Warning message which indicates that two or more extensions tried to determine the filename of a downloaded file in a conflicting way and the modification of this extension was ignored">
+ This extension failed to name the download "<ph name="ATTEMPTED_FILENAME">$1<ex>apple.png</ex></ph>" because another extension (<ph name="EXTENSION_NAME">$2<ex>My Cool Extension</ex></ph>) determined a different filename "<ph name="ACTUAL_FILENAME">$3<ex>banana.png</ex></ph>".
+ </message>
<!-- External extension install alerts -->
<!-- TODO(mpcomplete): We may need to change Chrome to
@@ -5753,6 +5756,12 @@
<message name="IDS_FLAGS_ENABLE_PANELS_DESCRIPTION" desc="Description for the flag to enable Panel windows.">
Enable Panel windows that open outside of the browser frame. Attempts to open a Panel will open a popup instead if not enabled. Panels are always enabled on the dev and canary channels.
</message>
+ <message name="IDS_FLAGS_ENABLE_HTML_IMPORTS_NAME" desc="Enable HTML Imports.">
+ Enable HTML Imports
+ </message>
+ <message name="IDS_FLAGS_ENABLE_HTML_IMPORTS_DESCRIPTION" desc="Description of 'Enable HTML Imports' flag.">
+ Enabling this option allows web applications to load HTML Imports.
+ </message>
<message name="IDS_FLAGS_ENABLE_WEBGL_NAME" desc="Name of the 'Enable WebGL' lab.">
Enable WebGL
</message>
@@ -7207,6 +7216,9 @@
<message name="IDS_IMPORT_FROM_SAFARI" desc="browser combo box: Safari">
Safari
</message>
+ <message name="IDS_IMPORT_FROM_BOOKMARKS_HTML_FILE" desc="browser combo box: Bookmarks HTML File">
+ Bookmarks HTML File
+ </message>
<message name="IDS_IMPORT_ITEMS_LABEL" desc="Label before item select checkboxes">
Select items to import:
</message>
@@ -7232,6 +7244,9 @@
<message name="IDS_IMPORT_COMMIT" desc="Text for OK button on dialog">
Import
</message>
+ <message name="IDS_IMPORT_CHOOSE_FILE" desc="Text for the Choose File on dialog">
+ Choose File
+ </message>
<message name="IDS_IMPORTER_GOOGLE_LOGIN_TEXT" desc="The message to be displayed on dialog">
In order to import Toolbar bookmarks into Chrome, you must be signed in to your Google account. Please sign in and try to import again.
@@ -7239,6 +7254,10 @@
<message name="IDS_IMPORT_NO_PROFILE_FOUND" desc="Message displayed when we do not find any supported browser to import from.">
No supported browser found
</message>
+ <message name="IDS_IMPORT_PASSWORD_KEYCHAIN_WARNING" desc="Message displayed at the bottom of the Import Dialog for Safari on Mac OS">
+ Passwords saved in the Mac OS X Keychain will be used to help you sign in without typing.
+ </message>
+
<!-- Import progress popup -->
<message name="IDS_IMPORT_PROGRESS_TITLE" desc="Title for the importing progress dialog">
@@ -7333,6 +7352,9 @@
<message name="IDS_FEEDBACK_SAVED_SCREENSHOTS" desc="Radio button for including the last screen image on the bug report dialog box">
Send a saved screen shot
</message>
+ <message name="IDS_FEEDBACK_INCLUDE_PERFORMANCE_TRACE_CHECKBOX" desc="Checkbox for including system information on the bug report dialog box">
+ Send performance trace data
+ </message>
<message name="IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX" desc="Checkbox for including system information on the bug report dialog box">
Send system information
</message>
@@ -7461,6 +7483,9 @@
<message name="IDS_BLOCK_INTERSTITIAL_MESSAGE" desc="A message for the supervised user when they attempt to visit a site that is not permitted by the manager.">
Oops, looks like you need permission from <ph name="NAME">$1<ex>John Doe</ex></ph> to access this page.
</message>
+ <message name="IDS_BLOCK_INTERSTITIAL_MESSAGE_ACCESS_REQUESTS_DISABLED" desc="A message for the supervised user when they attempt to visit a site that is not permitted by the manager (and they can't ask for permission).">
+ Oops, looks like you don't have permission to access this page.
+ </message>
<message name="IDS_BACK_BUTTON" desc="A button for going back to the last safe url after being blocked.">
Go back
</message>
@@ -9762,6 +9787,12 @@
<message name="IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARD_NUMBER" desc="The placeholder/label text for credit card number in the requestAutocomplete dialog.">
Card number
</message>
+ <message name="IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_MONTH" desc="The placeholder/label text for credit card expiration month in the requestAutocomplete dialog.">
+ Month
+ </message>
+ <message name="IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_YEAR" desc="The placeholder/label text for credit card expiration year in the requestAutocomplete dialog.">
+ Year
+ </message>
<message name="IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC" desc="The placeholder/label text for credit card verification code in the requestAutocomplete dialog.">
CVC
</message>
@@ -9795,12 +9826,18 @@
<message name="IDS_AUTOFILL_DIALOG_TITLE" desc="Title for autofill dialog which asks user to input address + payment info.">
Pay
</message>
- <message name="IDS_AUTOFILL_DIALOG_PAY_WITHOUT_WALLET" desc="This text is shown in a payment method chooser when a user is forced to pay without Google Wallet because the service is unavailable.">
- Chrome Autofill
+ <message name="IDS_AUTOFILL_DIALOG_PAY_WITHOUT_WALLET" desc="This text is shown in a payment method chooser as a way for a user to pay with local Chrome Autofill data instead of using Wallet.">
+ Disable Google Wallet
+ </message>
+ <message name="IDS_AUTOFILL_DIALOG_PAYING_WITHOUT_WALLET" desc="This text is shown as the click target for a dormant payment method chooser when using Chrome Autofill data instead of Wallet.">
+ Google Wallet disabled
</message>
<message name="IDS_AUTOFILL_DIALOG_SIGN_IN" desc="This link text is shown when the user is not signed into a GAIA account.">
Sign in to pay with Google Wallet
</message>
+ <message name="IDS_AUTOFILL_DIALOG_CANCEL_SIGN_IN" desc="This link text is shown when the user is signing into a GAIA account as a way to cancel sign in.">
+ Back
+ </message>
<message name="IDS_AUTOFILL_DIALOG_GOOGLE_WALLET" desc="The menu item that allows a user to select Google Wallet as their payment backend.">
Google Wallet
</message>
@@ -9861,6 +9898,15 @@
<message name="IDS_AUTOFILL_WALLET_BUYER_ACCOUNT_ERROR" desc="Text explaining that the user's Wallet account cannot be used.">
There's something wrong with your Google Wallet account [12].
</message>
+ <message name="IDS_AUTOFILL_WALLET_BUYER_COUNTRY_NOT_SUPPORTED" desc="Text explaining that the user's Wallet Buyer Legal Address has a country which is unsupported.">
+ lorem ipsum - unsupported buyer bla.
+ </message>
+ <message name="IDS_AUTOFILL_WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS" desc="Text explaining that Google Wallet failed/pending Know Your Customer (KYC) check, and would require user to call Google Wallet.">
+ lorem ipsum - kyc.
+ </message>
+ <message name="IDS_AUTOFILL_WALLET_UNSUPPORTED_MERCHANT" desc="Text explaining that the merchant is blacklisted for Google Wallet Chrome Payments due to compliance violation.">
+ lorem ipsum - unsupported_merchant.
+ </message>
<message name="IDS_AUTOFILL_WALLET_UPGRADE_CHROME_ERROR" desc="Text explaining that user must upgrade Chrome to use Wallet.">
You must upgrade Chrome to use Google Wallet [<ph name="ERROR_CODE">$1<ex>54</ex></ph>].
</message>
@@ -10048,14 +10094,14 @@
No, Thanks
</message>
- <!-- Autofill dialog post-submit bubble -->
- <message name="IDS_AUTOFILL_CREDIT_CARD_BUBBLE_GENERATED_TITLE" desc="Title of a bubble shown directly after a new card has been generated via Online Wallet using the Autofill dialog.">
+ <!-- Autofill dialog post-submit bubbles -->
+ <message name="IDS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_TITLE" desc="Title of a bubble shown directly after a new card has been generated via Online Wallet using the Autofill dialog.">
Google Wallet is protecting your card
</message>
- <message name="IDS_AUTOFILL_CREDIT_CARD_BUBBLE_GENERATED_TEXT" desc="Text in the bubble explaining that a temporary card has been generated for the user's security by Google Wallet.">
+ <message name="IDS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_CONTENTS" desc="Text in the bubble explaining that a temporary card has been generated for the user's security by Google Wallet.">
Don't worry, this purchase will still be charged to your |$1|. Your card has been protected with the Google Wallet Virtual Online Card (|$2|), this number will appear on your receipt.
</message>
- <message name="IDS_AUTOFILL_CREDIT_CARD_BUBBLE_MANAGE_CARDS" desc="The text of a link at the bottom of the autofill dialog bubble that sends users to a Google Wallet billing/card management page.">
+ <message name="IDS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_LINK" desc="The text of a link at the bottom of the autofill dialog bubble that sends users to a Google Wallet billing/card management page.">
Manage Saved Cards
</message>
@@ -12001,6 +12047,9 @@
<message name="IDS_FILE_BROWSER_REMOVE_FOLDER_SHORTCUT_BUTTON_LABEL" desc="Menu item label, unpinning the selected folder from the left nav.">
Remove shortcut
</message>
+ <message name="IDS_FILE_BROWSER_SHORTCUT_TARGET_UNAVAILABLE" desc="The message which is shown when the user selects a shortcut to a missing folder and ask whether to remove said shortcut.">
+ The folder referred by this shortcut has been changed or deleted. Do you want to remove it?
+ </message>
<message name="IDS_FILE_BROWSER_SHARE_BUTTON_LABEL" desc="Menu item label, showing dialog to share the selected file.">
Share
</message>
@@ -13060,7 +13109,7 @@
<message name="IDS_TRANSLATE_INFOBAR_BEFORE_MESSAGE" desc="Message that page is in specified language and ask if should translate">
This page is in<ph name="original_language">$1<ex>French</ex></ph>Would you like to translate it?
</message>
- <if expr="is_android">
+ <if expr="is_android or pp_ifdef('ios')">
<message name="IDS_TRANSLATE_INFOBAR_BEFORE_MESSAGE_MOBILE" desc="Mobile: Message that page is in specified language and ask if should translate.">
Translate from <ph name="original_language">$1<ex>French</ex></ph> to <ph name="target_language">$2<ex>English</ex></ph>?
</message>
@@ -13086,7 +13135,7 @@
<message name="IDS_TRANSLATE_INFOBAR_AFTER_MESSAGE_AUTODETERMINED_SOURCE_LANGUAGE" desc="Message that page has been translated to another with server side auto language detection">
This page has been translated to <ph name="target_language">$1<ex>German</ex></ph>
</message>
- <if expr="is_android">
+ <if expr="is_android or pp_ifdef('ios')">
<message name="IDS_TRANSLATE_INFOBAR_AFTER_MESSAGE_MOBILE" desc="Mobile: Message that page has been translated from one language to another">
This page has been translated to <ph name="target_language">$1<ex>German</ex></ph>
</message>
@@ -13112,7 +13161,7 @@
<message name="IDS_TRANSLATE_INFOBAR_UNSUPPORTED_PAGE_LANGUAGE" desc="Error message shown when the translate server translated the page and returned the page was in a language the browser does not know.">
This page has been translated from an unknown language to <ph name="language_language">$1<ex>English</ex></ph>
</message>
- <if expr="is_android">
+ <if expr="is_android or pp_ifdef('ios')">
<message name="IDS_TRANSLATE_INFOBAR_ERROR_MOBILE" desc="Mobile: Translate Error message">
The translation to <ph name="target_language">$1<ex>German</ex></ph> failed.
</message>
@@ -13585,7 +13634,7 @@
The following sites have been blocked from tracking your location on this page:
</message>
<message name="IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR" desc="Hint text for the geolocation bubble informing user they must reload the page for the Clear settings command to take effect.">
- Settings will be cleared on next reload
+ Settings will be cleared on next reload.
</message>
<message name="IDS_GEOLOCATION_BUBBLE_CLEAR_LINK" desc="Link on the geolocation bubble that resets the list of allowed and blocked sites.">
Clear these settings for future visits
@@ -13613,8 +13662,6 @@
<message name="IDS_MIDI_SYSEX_ASK_RADIO" desc="A radio button in Content Settings dialog to allow a site to query the permision to access MIDI devices with system exclusive messages.">
Ask me when a site wants to use system exclusive messages to access MIDI devices (recommended)
</message>
-
- <!-- Web MIDI messages -->
<message name="IDS_MIDI_SYSEX_INFOBAR_QUESTION" desc="Question asked on the info bar whenever URL wants to access MIDI devices with system exclusive messages.">
<ph name="URL">
$1<ex>www.google.com</ex>
@@ -13626,11 +13673,34 @@
<message name="IDS_MIDI_SYSEX_DENY_BUTTON" desc="A button in MIDI access infobar for denying full access to MIDI devices for a given domain.">
Deny
</message>
+ <message name="IDS_MIDI_SYSEX_ALLOWED_TOOLTIP" desc="Location bar icon tooltip text when a page is allowed to use MIDI system exclusive messages.">
+ This page has full control of MIDI devices.
+ </message>
+ <message name="IDS_MIDI_SYSEX_BLOCKED_TOOLTIP" desc="Location bar icon tooltip text when a page is blocked from using MIDI system exclusive messages.">
+ This page has been blocked from having full control of MIDI devices.
+ </message>
+ <message name="IDS_MIDI_SYSEX_BUBBLE_ALLOWED" desc="Title of the MIDI bubble where system exclusive messages are allowed.">
+ This site has full control of MIDI devices.
+ </message>
+ <message name="IDS_MIDI_SYSEX_BUBBLE_DENIED" desc="Title of the MIDI bubble where system exclusive messages are blocked.">
+ This site has been blocked from having full control of MIDI devices.
+ </message>
+ <message name="IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR" desc="Hint text for the MIDI bubble informing user they must reload the page for the Clear settings command to take effect.">
+ Settings will be cleared on next reload.
+ </message>
+ <message name="IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK" desc="Link on the MIDI bubble that resets the list of allowed and blocked sites.">
+ Clear these settings for future visits
+ </message>
+ <message name="IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK" desc="Link on the MIDI bubble that opens up the Content Settings management dialog.">
+ Manage MIDI settings...
+ </message>
+ <!-- Protocol Handler -->
<message name="IDS_REGISTER_PROTOCOL_HANDLER_TOOLTIP" desc="Location bar icon tooltip text when a page wants to use registerProtocolHandler.">
This page wants to install a service handler.
</message>
+ <!-- Media Stream -->
<message name="IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK" desc="Link on the media (camera and microphone) bubble that opens up the Content Settings management dialog for media settings.">
Manage media settings...
</message>
@@ -14163,6 +14233,10 @@
<message name="IDS_PROFILES_CREATE_MANAGED_SIGNED_IN_LABEL" desc="Label for the 'Supervised user' checkbox in the create-profile dialog when the current user is signed in. This will be followed by a 'Learn more' link.">
This is a supervised user managed by <ph name="CUSTODIAN_EMAIL">$1<ex>user@gmail.com</ex>.</ph>
</message>
+ <message name="IDS_PROFILES_CREATE_MANAGED_ACCOUNT_DETAILS_OUT_OF_DATE_LABEL" desc="Label for the 'Supervised user' checkbox in the create-profile dialog when the current user is signed in, but their login information is invalid. This will be followed by a 'Sign in again' link.">
+ This is a supervised user managed by <ph name="CUSTODIAN_EMAIL">$1<ex>user@gmail.com</ex>.</ph>
+Your account sign-in details are out of date.
+ </message>
<message name="IDS_PROFILES_CREATE_MANAGED_NOT_SIGNED_IN_LABEL" desc="Label for the (disabled) 'Supervised user' checkbox in the create-profile dialog when the current user is not signed in. This will be followed by a 'Sign in now' link.">
This is a supervised user who will be managed by you.
You need to be signed in to use this feature.
@@ -14170,8 +14244,11 @@
<message name="IDS_PROFILES_CREATE_MANAGED_NOT_SIGNED_IN_LINK" desc="Text for the sign-in promo link, shown after the (disabled) 'Supervised user' checkbox in the create-profile dialog when the current user is not signed in.">
Sign in now
</message>
+ <message name="IDS_PROFILES_CREATE_MANAGED_ACCOUNT_SIGN_IN_AGAIN_LINK" desc="Text for the sign-in promo link, shown after the message telling the user that their sign-in credentials are out of date in the create supervised user dialog.">
+ Sign in again
+ </message>
<message name="IDS_PROFILES_CREATE_MANAGED_FROM_EXISTING_LABEL" desc="Label for the 'Select an exisiting managed user' checkbox. During managed user creation a custodian will have an option to select an existing managed profile rather creating a new one.">
- Select an existing managed user:
+ Select an existing managed user:
</message>
<message name="IDS_PROFILES_CREATE_SHORTCUT_CHECKBOX" desc="Create Shortcut checkbox when creating a new profile">
Create a desktop shortcut for this user
@@ -14217,7 +14294,7 @@
</message>
<if expr="not is_android and not pp_ifdef('ios') and not pp_ifdef('chromeos')">
- <!-- User chooser web UI -->
+ <!-- User manager web UI -->
<if expr="pp_ifdef('use_titlecase')">
<message name="IDS_ADD_USER_BUTTON" desc="Text shown on an add user button on login/locker screen">
Add User
@@ -14246,6 +14323,9 @@
Remove this user
</message>
</if>
+ <message name="IDS_USER_MANAGER_SCREEN_TITLE" desc="String to be displayed in the title bar of the user manager page">
+ User Manager
+ </message>
<message name="IDS_GO_INCOGNITO_BUTTON" desc="Text shown on Chrome OS login screen button that launches guest session. Should be short.">
Browse as Guest
</message>
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index 663bc97..10e8dc7 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -833,7 +833,9 @@
<message name="IDS_AUTOFILL_DIALOG_SAVE_LOCALLY_TOOLTIP" desc="Tooltip which explains function of checkbox that controls whether info the user types into the autofill dialog is saved by chrome.">
Chrome will securely store your information so you don't need to type it in again, but you will still need to verify your card's security code for future payments.
</message>
-
+ <message name="IDS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_TITLE" desc="Title text of the new credit card bubble informing a user their billing information has been saved in chrome.">
+ Your billing details have been saved in Chrome.
+ </message>
<!-- Network Error Pages -->
<message name="IDS_ERRORPAGES_SUGGESTION_NETWORK_PREDICTION_BODY" desc="When a page fails to load, sometimes we suggest disabling predicting network actions. These are details below a header.">
diff --git a/chrome/app/nibs/ContentBlockedMIDISysEx.xib b/chrome/app/nibs/ContentBlockedMIDISysEx.xib
new file mode 100644
index 0000000..915253a
--- /dev/null
+++ b/chrome/app/nibs/ContentBlockedMIDISysEx.xib
@@ -0,0 +1,848 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">1050</int>
+ <string key="IBDocument.SystemVersion">12E55</string>
+ <string key="IBDocument.InterfaceBuilderVersion">3084</string>
+ <string key="IBDocument.AppKitVersion">1187.39</string>
+ <string key="IBDocument.HIToolboxVersion">626.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="NS.object.0">3084</string>
+ </object>
+ <object class="NSArray" key="IBDocument.IntegratedClassDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>NSBox</string>
+ <string>NSButton</string>
+ <string>NSButtonCell</string>
+ <string>NSCustomObject</string>
+ <string>NSCustomView</string>
+ <string>NSView</string>
+ <string>NSWindowTemplate</string>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+ <integer value="1" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSCustomObject" id="1001">
+ <string key="NSClassName">ContentSettingBubbleController</string>
+ </object>
+ <object class="NSCustomObject" id="1003">
+ <string key="NSClassName">FirstResponder</string>
+ </object>
+ <object class="NSCustomObject" id="1004">
+ <string key="NSClassName">NSApplication</string>
+ </object>
+ <object class="NSWindowTemplate" id="1005">
+ <int key="NSWindowStyleMask">15</int>
+ <int key="NSWindowBacking">2</int>
+ <string key="NSWindowRect">{{196, 422}, {316, 88}}</string>
+ <int key="NSWTFlags">536873984</int>
+ <string key="NSWindowTitle">Window</string>
+ <string key="NSWindowClass">InfoBubbleWindow</string>
+ <nil key="NSViewClass"/>
+ <nil key="NSUserInterfaceItemIdentifier"/>
+ <object class="NSView" key="NSWindowView" id="1006">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">256</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSCustomView" id="301729179">
+ <reference key="NSNextResponder" ref="1006"/>
+ <int key="NSvFlags">274</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSBox" id="913795455">
+ <reference key="NSNextResponder" ref="301729179"/>
+ <int key="NSvFlags">34</int>
+ <string key="NSFrame">{{20, 43}, {276, 5}}</string>
+ <reference key="NSSuperview" ref="301729179"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="730386640"/>
+ <string key="NSOffsets">{0, 0}</string>
+ <object class="NSTextFieldCell" key="NSTitleCell">
+ <int key="NSCellFlags">67108864</int>
+ <int key="NSCellFlags2">0</int>
+ <string key="NSContents">Box</string>
+ <object class="NSFont" key="NSSupport">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">13</double>
+ <int key="NSfFlags">1044</int>
+ </object>
+ <object class="NSColor" key="NSBackgroundColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">textBackgroundColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ </object>
+ <object class="NSColor" key="NSTextColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MCAwLjgwMDAwMDAxAA</bytes>
+ </object>
+ </object>
+ <int key="NSBorderType">3</int>
+ <int key="NSBoxType">2</int>
+ <int key="NSTitlePosition">0</int>
+ <bool key="NSTransparent">NO</bool>
+ </object>
+ <object class="NSCustomView" id="730386640">
+ <reference key="NSNextResponder" ref="301729179"/>
+ <int key="NSvFlags">294</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSButton" id="91589614">
+ <reference key="NSNextResponder" ref="730386640"/>
+ <int key="NSvFlags">292</int>
+ <string key="NSFrame">{{15, 13}, {115, 28}}</string>
+ <reference key="NSSuperview" ref="730386640"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="395762087"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="319182835">
+ <int key="NSCellFlags">67108864</int>
+ <int key="NSCellFlags2">134348800</int>
+ <string key="NSContents">^IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK</string>
+ <object class="NSFont" key="NSSupport" id="26">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">11</double>
+ <int key="NSfFlags">3100</int>
+ </object>
+ <reference key="NSControlView" ref="91589614"/>
+ <int key="NSButtonFlags">-2038284288</int>
+ <int key="NSButtonFlags2">129</int>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent"/>
+ <int key="NSPeriodicDelay">200</int>
+ <int key="NSPeriodicInterval">25</int>
+ </object>
+ <bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+ </object>
+ </object>
+ <string key="NSFrameSize">{192, 37}</string>
+ <reference key="NSSuperview" ref="301729179"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="91589614"/>
+ <string key="NSClassName">GTMWidthBasedTweaker</string>
+ </object>
+ <object class="NSCustomView" id="395762087">
+ <reference key="NSNextResponder" ref="301729179"/>
+ <int key="NSvFlags">291</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSButton" id="433059244">
+ <reference key="NSNextResponder" ref="395762087"/>
+ <int key="NSvFlags">289</int>
+ <string key="NSFrame">{{40, 13}, {68, 28}}</string>
+ <reference key="NSSuperview" ref="395762087"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="255173005">
+ <int key="NSCellFlags">67108864</int>
+ <int key="NSCellFlags2">134348800</int>
+ <string key="NSContents">^IDS_DONE</string>
+ <reference key="NSSupport" ref="26"/>
+ <reference key="NSControlView" ref="433059244"/>
+ <int key="NSButtonFlags">-2038284288</int>
+ <int key="NSButtonFlags2">129</int>
+ <string key="NSAlternateContents"/>
+ <string type="base64-UTF8" key="NSKeyEquivalent">DQ</string>
+ <int key="NSPeriodicDelay">200</int>
+ <int key="NSPeriodicInterval">25</int>
+ </object>
+ <bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+ </object>
+ </object>
+ <string key="NSFrame">{{193, 0}, {123, 37}}</string>
+ <reference key="NSSuperview" ref="301729179"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="433059244"/>
+ <string key="NSClassName">GTMWidthBasedTweaker</string>
+ </object>
+ <object class="NSCustomView" id="1034822360">
+ <reference key="NSNextResponder" ref="301729179"/>
+ <int key="NSvFlags">290</int>
+ <string key="NSFrame">{{20, 54}, {276, 14}}</string>
+ <reference key="NSSuperview" ref="301729179"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="913795455"/>
+ <string key="NSClassName">NSView</string>
+ </object>
+ </object>
+ <string key="NSFrameSize">{316, 88}</string>
+ <reference key="NSSuperview" ref="1006"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="1034822360"/>
+ <string key="NSClassName">InfoBubbleView</string>
+ </object>
+ </object>
+ <string key="NSFrameSize">{316, 88}</string>
+ <reference key="NSSuperview"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="301729179"/>
+ </object>
+ <string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+ <string key="NSMaxSize">{10000000000000, 10000000000000}</string>
+ <bool key="NSWindowIsRestorable">YES</bool>
+ </object>
+ <object class="NSCustomObject" id="670916757">
+ <string key="NSClassName">ChromeUILocalizer</string>
+ </object>
+ <object class="NSCustomObject" id="684547419">
+ <string key="NSClassName">GTMUILocalizerAndLayoutTweaker</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">window</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="1005"/>
+ </object>
+ <int key="connectionID">3</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">bubble_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="301729179"/>
+ </object>
+ <int key="connectionID">5</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">manageBlocking:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="91589614"/>
+ </object>
+ <int key="connectionID">25</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">closeBubble:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="433059244"/>
+ </object>
+ <int key="connectionID">26</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">contentsContainer_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="1034822360"/>
+ </object>
+ <int key="connectionID">43</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">manageButton_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="91589614"/>
+ </object>
+ <int key="connectionID">45</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">doneButton_</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="433059244"/>
+ </object>
+ <int key="connectionID">46</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="1005"/>
+ <reference key="destination" ref="1001"/>
+ </object>
+ <int key="connectionID">6</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">localizer_</string>
+ <reference key="source" ref="684547419"/>
+ <reference key="destination" ref="670916757"/>
+ </object>
+ <int key="connectionID">22</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">uiObject_</string>
+ <reference key="source" ref="684547419"/>
+ <reference key="destination" ref="1005"/>
+ </object>
+ <int key="connectionID">23</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <object class="NSArray" key="object" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="1001"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="1003"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">First Responder</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-3</int>
+ <reference key="object" ref="1004"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">Application</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">1</int>
+ <reference key="object" ref="1005"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1006"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="1006"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="301729179"/>
+ </object>
+ <reference key="parent" ref="1005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">4</int>
+ <reference key="object" ref="301729179"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="913795455"/>
+ <reference ref="395762087"/>
+ <reference ref="730386640"/>
+ <reference ref="1034822360"/>
+ </object>
+ <reference key="parent" ref="1006"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">20</int>
+ <reference key="object" ref="670916757"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">21</int>
+ <reference key="object" ref="684547419"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">19</int>
+ <reference key="object" ref="913795455"/>
+ <reference key="parent" ref="301729179"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">29</int>
+ <reference key="object" ref="395762087"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="433059244"/>
+ </object>
+ <reference key="parent" ref="301729179"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">17</int>
+ <reference key="object" ref="433059244"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="255173005"/>
+ </object>
+ <reference key="parent" ref="395762087"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">18</int>
+ <reference key="object" ref="255173005"/>
+ <reference key="parent" ref="433059244"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">28</int>
+ <reference key="object" ref="730386640"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="91589614"/>
+ </object>
+ <reference key="parent" ref="301729179"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">15</int>
+ <reference key="object" ref="91589614"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="319182835"/>
+ </object>
+ <reference key="parent" ref="730386640"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">16</int>
+ <reference key="object" ref="319182835"/>
+ <reference key="parent" ref="91589614"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">42</int>
+ <reference key="object" ref="1034822360"/>
+ <reference key="parent" ref="301729179"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.IBPluginDependency</string>
+ <string>-2.IBPluginDependency</string>
+ <string>-3.IBPluginDependency</string>
+ <string>1.IBPluginDependency</string>
+ <string>1.IBWindowTemplateEditedContentRect</string>
+ <string>1.NSWindowTemplate.visibleAtLaunch</string>
+ <string>15.IBPluginDependency</string>
+ <string>16.IBPluginDependency</string>
+ <string>17.IBPluginDependency</string>
+ <string>18.IBPluginDependency</string>
+ <string>19.IBPluginDependency</string>
+ <string>2.IBPluginDependency</string>
+ <string>20.IBPluginDependency</string>
+ <string>21.IBPluginDependency</string>
+ <string>28.IBPluginDependency</string>
+ <string>29.IBPluginDependency</string>
+ <string>4.IBPluginDependency</string>
+ <string>42.IBPluginDependency</string>
+ </object>
+ <object class="NSArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{333, 411}, {316, 88}}</string>
+ <boolean value="NO"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <reference key="dict.values" ref="0"/>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <reference key="dict.values" ref="0"/>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">46</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">BaseBubbleController</string>
+ <string key="superclassName">NSWindowController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <string key="NS.key.0">bubble_</string>
+ <string key="NS.object.0">InfoBubbleView</string>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <string key="NS.key.0">bubble_</string>
+ <object class="IBToOneOutletInfo" key="NS.object.0">
+ <string key="name">bubble_</string>
+ <string key="candidateClassName">InfoBubbleView</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/BaseBubbleController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">ChromeEventProcessingWindow</string>
+ <string key="superclassName">UnderlayOpenGLHostingWindow</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/ChromeEventProcessingWindow.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">ChromeUILocalizer</string>
+ <string key="superclassName">GTMUILocalizer</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/ChromeUILocalizer.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">ContentSettingBubbleController</string>
+ <string key="superclassName">BaseBubbleController</string>
+ <object class="NSMutableDictionary" key="actions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>allowBlockToggled:</string>
+ <string>closeBubble:</string>
+ <string>learnMoreLinkClicked:</string>
+ <string>load:</string>
+ <string>loadAllPlugins:</string>
+ <string>manageBlocking:</string>
+ <string>showMoreInfo:</string>
+ </object>
+ <object class="NSArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>id</string>
+ <string>id</string>
+ <string>id</string>
+ <string>id</string>
+ <string>id</string>
+ <string>id</string>
+ <string>id</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="actionInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>allowBlockToggled:</string>
+ <string>closeBubble:</string>
+ <string>learnMoreLinkClicked:</string>
+ <string>load:</string>
+ <string>loadAllPlugins:</string>
+ <string>manageBlocking:</string>
+ <string>showMoreInfo:</string>
+ </object>
+ <object class="NSArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBActionInfo">
+ <string key="name">allowBlockToggled:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ <object class="IBActionInfo">
+ <string key="name">closeBubble:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ <object class="IBActionInfo">
+ <string key="name">learnMoreLinkClicked:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ <object class="IBActionInfo">
+ <string key="name">load:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ <object class="IBActionInfo">
+ <string key="name">loadAllPlugins:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ <object class="IBActionInfo">
+ <string key="name">manageBlocking:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ <object class="IBActionInfo">
+ <string key="name">showMoreInfo:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>allowBlockRadioGroup_</string>
+ <string>blockedResourcesField_</string>
+ <string>contentsContainer_</string>
+ <string>doneButton_</string>
+ <string>infoButton_</string>
+ <string>loadAllPluginsButton_</string>
+ <string>loadButton_</string>
+ <string>manageButton_</string>
+ <string>titleLabel_</string>
+ </object>
+ <object class="NSArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>NSMatrix</string>
+ <string>NSTextField</string>
+ <string>NSView</string>
+ <string>NSButton</string>
+ <string>NSButton</string>
+ <string>NSButton</string>
+ <string>NSButton</string>
+ <string>NSButton</string>
+ <string>NSTextField</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>allowBlockRadioGroup_</string>
+ <string>blockedResourcesField_</string>
+ <string>contentsContainer_</string>
+ <string>doneButton_</string>
+ <string>infoButton_</string>
+ <string>loadAllPluginsButton_</string>
+ <string>loadButton_</string>
+ <string>manageButton_</string>
+ <string>titleLabel_</string>
+ </object>
+ <object class="NSArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBToOneOutletInfo">
+ <string key="name">allowBlockRadioGroup_</string>
+ <string key="candidateClassName">NSMatrix</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">blockedResourcesField_</string>
+ <string key="candidateClassName">NSTextField</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">contentsContainer_</string>
+ <string key="candidateClassName">NSView</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">doneButton_</string>
+ <string key="candidateClassName">NSButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">infoButton_</string>
+ <string key="candidateClassName">NSButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">loadAllPluginsButton_</string>
+ <string key="candidateClassName">NSButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">loadButton_</string>
+ <string key="candidateClassName">NSButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">manageButton_</string>
+ <string key="candidateClassName">NSButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">titleLabel_</string>
+ <string key="candidateClassName">NSTextField</string>
+ </object>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/ContentSettingBubbleController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">GTMUILocalizer</string>
+ <string key="superclassName">NSObject</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>otherObjectToLocalize_</string>
+ <string>owner_</string>
+ <string>yetAnotherObjectToLocalize_</string>
+ </object>
+ <object class="NSArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>id</string>
+ <string>id</string>
+ <string>id</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>otherObjectToLocalize_</string>
+ <string>owner_</string>
+ <string>yetAnotherObjectToLocalize_</string>
+ </object>
+ <object class="NSArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBToOneOutletInfo">
+ <string key="name">otherObjectToLocalize_</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">owner_</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">yetAnotherObjectToLocalize_</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/GTMUILocalizer.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">GTMUILocalizerAndLayoutTweaker</string>
+ <string key="superclassName">NSObject</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>localizerOwner_</string>
+ <string>localizer_</string>
+ <string>uiObject_</string>
+ </object>
+ <object class="NSArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>id</string>
+ <string>GTMUILocalizer</string>
+ <string>id</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>localizerOwner_</string>
+ <string>localizer_</string>
+ <string>uiObject_</string>
+ </object>
+ <object class="NSArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBToOneOutletInfo">
+ <string key="name">localizerOwner_</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">localizer_</string>
+ <string key="candidateClassName">GTMUILocalizer</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">uiObject_</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/GTMUILocalizerAndLayoutTweaker.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">GTMWidthBasedTweaker</string>
+ <string key="superclassName">NSView</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>viewToResize_</string>
+ <string>viewToSlideAndResize_</string>
+ <string>viewToSlide_</string>
+ </object>
+ <object class="NSArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>id</string>
+ <string>NSView</string>
+ <string>NSView</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>viewToResize_</string>
+ <string>viewToSlideAndResize_</string>
+ <string>viewToSlide_</string>
+ </object>
+ <object class="NSArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBToOneOutletInfo">
+ <string key="name">viewToResize_</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">viewToSlideAndResize_</string>
+ <string key="candidateClassName">NSView</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">viewToSlide_</string>
+ <string key="candidateClassName">NSView</string>
+ </object>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/GTMWidthBasedTweaker.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">InfoBubbleView</string>
+ <string key="superclassName">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/InfoBubbleView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">InfoBubbleWindow</string>
+ <string key="superclassName">ChromeEventProcessingWindow</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/InfoBubbleWindow.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UnderlayOpenGLHostingWindow</string>
+ <string key="superclassName">NSWindow</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/UnderlayOpenGLHostingWindow.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
+ <integer value="1050" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+ <integer value="3000" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ </data>
+</archive>
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index a59a81a..09f2cd0 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -52,7 +52,6 @@
# TODO(stuartmorgan): Remove these by refactoring necessary code out of
# webkit/. See crbug.com/146251
# DO NOT ADD ANY MORE ITEMS TO THE LIST BELOW!
- "+webkit/plugins", # Defines some types that are marshalled over IPC.
# TODO(kinuko): Remove all other webkit/* dependencies after we cleaned
# up webkit/. crbug.com/239710
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index cffd974..71e06a1 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1178,12 +1178,6 @@
kOsCrOS,
SINGLE_VALUE_TYPE(chromeos::switches::kUseNewNetworkConfigurationHandlers),
},
- { "use-new-network-connection-handler",
- IDS_FLAGS_CHROMEOS_USE_NEW_NETWORK_CONNECTION_HANDLER_NAME,
- IDS_FLAGS_CHROMEOS_USE_NEW_NETWORK_CONNECTION_HANDLER_DESCRIPTION,
- kOsCrOS,
- SINGLE_VALUE_TYPE(chromeos::switches::kUseNewNetworkConnectionHandler),
- },
{
"ash-audio-device-menu",
IDS_FLAGS_ASH_AUDIO_DEVICE_MENU_NAME,
@@ -1545,6 +1539,13 @@
SINGLE_VALUE_TYPE(switches::kEnableWebGLDraftExtensions)
},
{
+ "enable-html-imports",
+ IDS_FLAGS_ENABLE_HTML_IMPORTS_NAME,
+ IDS_FLAGS_ENABLE_HTML_IMPORTS_DESCRIPTION,
+ kOsAll,
+ SINGLE_VALUE_TYPE(switches::kEnableHTMLImports)
+ },
+ {
"high-dpi-support",
IDS_FLAGS_HIDPI_NAME,
IDS_FLAGS_HIDPI_DESCRIPTION,
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc
index 5b6c457..1675c62 100644
--- a/chrome/browser/android/chrome_jni_registrar.cc
+++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -27,6 +27,8 @@
#include "chrome/browser/signin/android_profile_oauth2_token_service.h"
#include "chrome/browser/speech/tts_android.h"
#include "chrome/browser/sync/profile_sync_service_android.h"
+#include "chrome/browser/ui/android/autofill/autofill_dialog_controller_android.h"
+#include "chrome/browser/ui/android/autofill/autofill_dialog_result.h"
#include "chrome/browser/ui/android/autofill/autofill_popup_view_android.h"
#include "chrome/browser/ui/android/chrome_http_auth_handler.h"
#include "chrome/browser/ui/android/javascript_app_modal_dialog_android.h"
@@ -54,6 +56,11 @@
{ "AndroidProfileOAuth2TokenService",
AndroidProfileOAuth2TokenService::Register },
{ "ApplicationLifetime", RegisterApplicationLifetimeAndroid },
+ { "AutofillDialogControllerAndroid",
+ autofill::AutofillDialogControllerAndroid::
+ RegisterAutofillDialogControllerAndroid },
+ { "AutofillDialogResult",
+ autofill::AutofillDialogResult::RegisterAutofillDialogResult },
{ "AutofillPopup",
autofill::AutofillPopupViewAndroid::RegisterAutofillPopupViewAndroid },
{ "CertificateViewer", RegisterCertificateViewer },
diff --git a/chrome/browser/android/chrome_web_contents_delegate_android.cc b/chrome/browser/android/chrome_web_contents_delegate_android.cc
index 5b3c747..0eb1157 100644
--- a/chrome/browser/android/chrome_web_contents_delegate_android.cc
+++ b/chrome/browser/android/chrome_web_contents_delegate_android.cc
@@ -9,7 +9,6 @@
#include "chrome/browser/file_select_helper.h"
#include "chrome/browser/media/media_capture_devices_dispatcher.h"
#include "chrome/browser/ui/app_modal_dialogs/javascript_dialog_manager.h"
-#include "chrome/browser/ui/find_bar/find_match_rects_details.h"
#include "chrome/browser/ui/find_bar/find_notification_details.h"
#include "chrome/browser/ui/find_bar/find_tab_helper.h"
#include "content/public/browser/notification_details.h"
@@ -163,12 +162,6 @@
int version,
const std::vector<gfx::RectF>& rects,
const gfx::RectF& active_rect) {
- FindMatchRectsDetails match_rects(version, rects, active_rect);
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_FIND_MATCH_RECTS_AVAILABLE,
- content::Source<WebContents>(web_contents),
- content::Details<FindMatchRectsDetails>(&match_rects));
-
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
if (obj.is_null())
@@ -178,17 +171,17 @@
ScopedJavaLocalRef<jobject> details_object =
Java_ChromeWebContentsDelegateAndroid_createFindMatchRectsDetails(
env,
- match_rects.version(),
- match_rects.rects().size(),
- CreateJavaRectF(env, match_rects.active_rect()).obj());
+ version,
+ rects.size(),
+ CreateJavaRectF(env, active_rect).obj());
// Add the rects
- for (size_t i = 0; i < match_rects.rects().size(); ++i) {
+ for (size_t i = 0; i < rects.size(); ++i) {
Java_ChromeWebContentsDelegateAndroid_setMatchRectByIndex(
env,
details_object.obj(),
i,
- CreateJavaRectF(env, match_rects.rects()[i]).obj());
+ CreateJavaRectF(env, rects[i]).obj());
}
Java_ChromeWebContentsDelegateAndroid_onFindMatchRectsAvailable(
diff --git a/chrome/browser/android/tab_android.h b/chrome/browser/android/tab_android.h
index 3c6f0c1..19d8f25 100644
--- a/chrome/browser/android/tab_android.h
+++ b/chrome/browser/android/tab_android.h
@@ -75,6 +75,9 @@
// of service and the privacy notice.
virtual bool ShouldWelcomePageLinkToTermsOfService() = 0;
+ // Called to notify that the new tab page has completely rendered.
+ virtual void OnNewTabPageReady() = 0;
+
// Called when the common ExternalProtocolHandler wants to
// run the external protocol dialog.
// TODO(jknotten): Remove this method. Making it non-abstract, so that
diff --git a/chrome/browser/app_controller_mac.h b/chrome/browser/app_controller_mac.h
index 4ea1356..46d8a05 100644
--- a/chrome/browser/app_controller_mac.h
+++ b/chrome/browser/app_controller_mac.h
@@ -81,9 +81,6 @@
scoped_ptr<PrefChangeRegistrar> profilePrefRegistrar_;
PrefChangeRegistrar localPrefRegistrar_;
-
- // The main menu item showing the name of a currently focused packaged app.
- base::scoped_nsobject<NSMenuItem> appMenuItem_;
}
@property(readonly, nonatomic) BOOL startupComplete;
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm
index 859a539..b2d30cd 100644
--- a/chrome/browser/app_controller_mac.mm
+++ b/chrome/browser/app_controller_mac.mm
@@ -5,7 +5,7 @@
#import "chrome/browser/app_controller_mac.h"
#include "apps/app_shim/extension_app_shim_handler_mac.h"
-#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/command_line.h"
@@ -28,7 +28,6 @@
#include "chrome/browser/download/download_service_factory.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/printing/print_dialog_cloud.h"
@@ -73,7 +72,6 @@
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/cloud_print/cloud_print_class_mac.h"
-#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/mac/app_mode_common.h"
#include "chrome/common/pref_names.h"
@@ -199,7 +197,6 @@
- (BOOL)shouldQuitWithInProgressDownloads;
- (void)executeApplication:(id)sender;
- (void)profileWasRemoved:(const base::FilePath&)profilePath;
-- (void)showOrHideMenuItemsForPackagedApp:(NSNotification*)notification;
@end
class AppControllerProfileObserver : public ProfileInfoCacheObserver {
@@ -315,12 +312,6 @@
// Set up the command updater for when there are no windows open
[self initMenuState];
- [[NSNotificationCenter defaultCenter]
- addObserver:self
- selector:@selector(showOrHideMenuItemsForPackagedApp:)
- name:NSWindowDidBecomeMainNotification
- object:nil];
-
// Initialize the Profile menu.
[self initProfileMenu];
}
@@ -388,7 +379,7 @@
}
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)app {
- using extensions::ShellWindowRegistry;
+ using apps::ShellWindowRegistry;
// If there are no windows, quit immediately.
if (chrome::BrowserIterator().done() &&
@@ -1345,15 +1336,18 @@
[item setEnabled:[self validateUserInterfaceItem:item]];
[dockMenu addItem:item];
- titleStr = l10n_util::GetNSStringWithFixup(IDS_NEW_INCOGNITO_WINDOW_MAC);
- item.reset(
- [[NSMenuItem alloc] initWithTitle:titleStr
- action:@selector(commandFromDock:)
- keyEquivalent:@""]);
- [item setTarget:self];
- [item setTag:IDC_NEW_INCOGNITO_WINDOW];
- [item setEnabled:[self validateUserInterfaceItem:item]];
- [dockMenu addItem:item];
+ // |profile| can be NULL during unit tests.
+ if (!profile || !profile->IsManaged()) {
+ titleStr = l10n_util::GetNSStringWithFixup(IDS_NEW_INCOGNITO_WINDOW_MAC);
+ item.reset(
+ [[NSMenuItem alloc] initWithTitle:titleStr
+ action:@selector(commandFromDock:)
+ keyEquivalent:@""]);
+ [item setTarget:self];
+ [item setTag:IDC_NEW_INCOGNITO_WINDOW];
+ [item setEnabled:[self validateUserInterfaceItem:item]];
+ [dockMenu addItem:item];
+ }
// TODO(rickcam): Mock out BackgroundApplicationListModel, then add unit
// tests which use the mock in place of the profile-initialized model.
@@ -1420,52 +1414,6 @@
WorkAreaChanged());
}
-// If the window is an app window, show the menu bar for that app, otherwise
-// restore the Chrome menu bar.
-- (void)showOrHideMenuItemsForPackagedApp:(NSNotification*)notification {
- NSMenu* mainMenu = [NSApp mainMenu];
- apps::ShellWindow* shellWindow =
- extensions::ShellWindowRegistry::GetShellWindowForNativeWindowAnyProfile(
- [notification object]);
-
- if (!shellWindow) {
- if (!appMenuItem_)
- return;
-
- [mainMenu removeItem:appMenuItem_];
- appMenuItem_.reset();
-
- // Restore the Chrome main menu bar.
- for (NSMenuItem* item in [mainMenu itemArray])
- [item setHidden:NO];
-
- return;
- }
-
- const extensions::Extension* app = shellWindow->extension();
- NSString* appId = base::SysUTF8ToNSString(app->id());
- NSString* title = base::SysUTF8ToNSString(app->name());
-
- if (appMenuItem_) {
- if ([[appMenuItem_ title] isEqualToString:appId])
- return;
-
- [mainMenu removeItem:appMenuItem_];
- } else {
- // Hide everything and add a menu item for the app.
- for (NSMenuItem* item in [mainMenu itemArray])
- [item setHidden:YES];
- }
-
- appMenuItem_.reset(
- [[NSMenuItem alloc] initWithTitle:appId
- action:nil
- keyEquivalent:@""]);
- base::scoped_nsobject<NSMenu> appMenu([[NSMenu alloc] initWithTitle:title]);
- [appMenuItem_ setSubmenu:appMenu];
- [mainMenu addItem:appMenuItem_];
-}
-
@end // @implementation AppController
//---------------------------------------------------------------------------
diff --git a/chrome/browser/app_controller_mac_browsertest.mm b/chrome/browser/app_controller_mac_browsertest.mm
index 02059a5..4e66e35 100644
--- a/chrome/browser/app_controller_mac_browsertest.mm
+++ b/chrome/browser/app_controller_mac_browsertest.mm
@@ -4,20 +4,20 @@
#import <Cocoa/Cocoa.h>
+#include "apps/shell_window_registry.h"
#include "base/command_line.h"
#include "base/mac/scoped_nsobject.h"
-#include "base/strings/sys_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#import "chrome/browser/app_controller_mac.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/extensions/platform_app_browsertest_util.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#import "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/web_contents.h"
@@ -55,72 +55,6 @@
EXPECT_EQ(1u, active_browser_list_->size());
}
-// Test that focusing an app window changes the menu bar.
-IN_PROC_BROWSER_TEST_F(AppControllerPlatformAppBrowserTest,
- PlatformAppFocusUpdatesMenuBar) {
- base::scoped_nsobject<AppController> app_controller(
- [[AppController alloc] init]);
-
- // Start two apps and wait for them to be launched.
- ExtensionTestMessageListener listener_1("Launched", false);
- const extensions::Extension* app_1 =
- InstallAndLaunchPlatformApp("minimal_id");
- ASSERT_TRUE(listener_1.WaitUntilSatisfied());
- ExtensionTestMessageListener listener_2("Launched", false);
- const extensions::Extension* app_2 =
- InstallAndLaunchPlatformApp("minimal");
- ASSERT_TRUE(listener_2.WaitUntilSatisfied());
-
- NSMenu* main_menu = [NSApp mainMenu];
- NSUInteger initial_menu_item_count = [[main_menu itemArray] count];
-
- // When an app is focused, all Chrome menu items should be hidden, and a menu
- // item for the app should be added.
- apps::ShellWindow* app_1_shell_window =
- extensions::ShellWindowRegistry::Get(profile())->
- GetShellWindowsForApp(app_1->id()).front();
- [[NSNotificationCenter defaultCenter]
- postNotificationName:NSWindowDidBecomeMainNotification
- object:app_1_shell_window->GetNativeWindow()];
- NSArray* item_array = [main_menu itemArray];
- EXPECT_EQ(initial_menu_item_count + 1, [item_array count]);
- for (NSUInteger i = 0; i < initial_menu_item_count; ++i)
- EXPECT_TRUE([[item_array objectAtIndex:i] isHidden]);
- NSMenuItem* last_item = [item_array lastObject];
- EXPECT_EQ(app_1->id(), base::SysNSStringToUTF8([last_item title]));
- EXPECT_EQ(app_1->name(),
- base::SysNSStringToUTF8([[last_item submenu] title]));
- EXPECT_FALSE([last_item isHidden]);
-
- // When another app is focused, the menu item for the app should change.
- apps::ShellWindow* app_2_shell_window =
- extensions::ShellWindowRegistry::Get(profile())->
- GetShellWindowsForApp(app_2->id()).front();
- [[NSNotificationCenter defaultCenter]
- postNotificationName:NSWindowDidBecomeMainNotification
- object:app_2_shell_window->GetNativeWindow()];
- item_array = [main_menu itemArray];
- EXPECT_EQ(initial_menu_item_count + 1, [item_array count]);
- for (NSUInteger i = 0; i < initial_menu_item_count; ++i)
- EXPECT_TRUE([[item_array objectAtIndex:i] isHidden]);
- last_item = [item_array lastObject];
- EXPECT_EQ(app_2->id(), base::SysNSStringToUTF8([last_item title]));
- EXPECT_EQ(app_2->name(),
- base::SysNSStringToUTF8([[last_item submenu] title]));
- EXPECT_FALSE([last_item isHidden]);
-
- // When Chrome is focused, the menu item for the app should be removed.
- NSWindow* browser_native_window =
- active_browser_list_->get(0)->window()->GetNativeWindow();
- [[NSNotificationCenter defaultCenter]
- postNotificationName:NSWindowDidBecomeMainNotification
- object:browser_native_window];
- item_array = [main_menu itemArray];
- EXPECT_EQ(initial_menu_item_count, [item_array count]);
- for (NSUInteger i = 0; i < initial_menu_item_count; ++i)
- EXPECT_FALSE([[item_array objectAtIndex:i] isHidden]);
-}
-
IN_PROC_BROWSER_TEST_F(AppControllerPlatformAppBrowserTest,
ActivationFocusesBrowserWindow) {
base::scoped_nsobject<AppController> app_controller(
@@ -131,7 +65,7 @@
InstallAndLaunchPlatformApp("minimal");
ASSERT_TRUE(listener.WaitUntilSatisfied());
- NSWindow* app_window = extensions::ShellWindowRegistry::Get(profile())->
+ NSWindow* app_window = apps::ShellWindowRegistry::Get(profile())->
GetShellWindowsForApp(app->id()).front()->GetNativeWindow();
NSWindow* browser_window = browser()->window()->GetNativeWindow();
diff --git a/chrome/browser/apps/shortcut_manager.cc b/chrome/browser/apps/shortcut_manager.cc
index 914d1fd..539cf65 100644
--- a/chrome/browser/apps/shortcut_manager.cc
+++ b/chrome/browser/apps/shortcut_manager.cc
@@ -63,9 +63,9 @@
weak_factory_(this) {
// Use of g_browser_process requires that we are either on the UI thread, or
// there are no threads initialized (such as in unit tests).
- DCHECK(
- !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
- content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK(!content::BrowserThread::IsThreadInitialized(
+ content::BrowserThread::UI) ||
+ content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
content::Source<Profile>(profile_));
diff --git a/chrome/browser/autocomplete/autocomplete_controller.cc b/chrome/browser/autocomplete/autocomplete_controller.cc
index ee39845..492533a 100644
--- a/chrome/browser/autocomplete/autocomplete_controller.cc
+++ b/chrome/browser/autocomplete/autocomplete_controller.cc
@@ -543,10 +543,11 @@
!match.search_terms_args->assisted_query_stats.empty()) {
TemplateURLRef::SearchTermsArgs search_terms_args(*match.search_terms_args);
search_terms_args.assisted_query_stats += base::StringPrintf(
- ".%" PRId64 "j%d",
+ ".%" PRId64 "j%dj%d",
query_formulation_time.InMilliseconds(),
search_provider_ &&
- search_provider_->field_trial_triggered_in_session());
+ search_provider_->field_trial_triggered_in_session(),
+ input_.current_page_classification());
destination_url = GURL(template_url->url_ref().
ReplaceSearchTerms(search_terms_args));
}
diff --git a/chrome/browser/autocomplete/autocomplete_input.h b/chrome/browser/autocomplete/autocomplete_input.h
index 0ebc17d..3aba2d1 100644
--- a/chrome/browser/autocomplete/autocomplete_input.h
+++ b/chrome/browser/autocomplete/autocomplete_input.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
#include "base/strings/string16.h"
#include "url/gurl.h"
#include "url/url_parse.h"
@@ -68,6 +69,10 @@
// The new tab page in which this omnibox interaction first started
// with the user having focus in the fakebox.
INSTANT_NEW_TAB_PAGE_WITH_FAKEBOX_AS_STARTING_FOCUS = 8,
+ // The user is on a search result page that's not doing search term
+ // replacement, meaning the URL of the page should've appeared in the
+ // omnibox before the user started editing it, not the search terms.
+ SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT = 9
};
AutocompleteInput();
@@ -217,6 +222,8 @@
void Clear();
private:
+ FRIEND_TEST_ALL_PREFIXES(AutocompleteProviderTest, GetDestinationURL);
+
// NOTE: Whenever adding a new field here, please make sure to update Clear()
// method.
string16 text_;
diff --git a/chrome/browser/autocomplete/autocomplete_provider_unittest.cc b/chrome/browser/autocomplete/autocomplete_provider_unittest.cc
index 8b56cbb..7f59752 100644
--- a/chrome/browser/autocomplete/autocomplete_provider_unittest.cc
+++ b/chrome/browser/autocomplete/autocomplete_provider_unittest.cc
@@ -628,7 +628,7 @@
"chrome.0.69i57j69i58j5l2j0l3j69i59";
url = controller_->GetDestinationURL(match,
base::TimeDelta::FromMilliseconds(2456));
- EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j0&", url.path());
+ EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j0j0&", url.path());
// Test field trial triggered bit set.
controller_->search_provider_->field_trial_triggered_in_session_ = true;
@@ -636,5 +636,22 @@
controller_->search_provider_->field_trial_triggered_in_session());
url = controller_->GetDestinationURL(match,
base::TimeDelta::FromMilliseconds(2456));
- EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j1&", url.path());
+ EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j1j0&", url.path());
+
+ // Test page classification set.
+ controller_->input_.current_page_classification_ = AutocompleteInput::OTHER;
+ controller_->search_provider_->field_trial_triggered_in_session_ = false;
+ EXPECT_FALSE(
+ controller_->search_provider_->field_trial_triggered_in_session());
+ url = controller_->GetDestinationURL(match,
+ base::TimeDelta::FromMilliseconds(2456));
+ EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j0j4&", url.path());
+
+ // Test page classification and field trial triggered set.
+ controller_->search_provider_->field_trial_triggered_in_session_ = true;
+ EXPECT_TRUE(
+ controller_->search_provider_->field_trial_triggered_in_session());
+ url = controller_->GetDestinationURL(match,
+ base::TimeDelta::FromMilliseconds(2456));
+ EXPECT_EQ("//aqs=chrome.0.69i57j69i58j5l2j0l3j69i59.2456j1j4&", url.path());
}
diff --git a/chrome/browser/autocomplete/autocomplete_result.cc b/chrome/browser/autocomplete/autocomplete_result.cc
index 7238c1e..832be73 100644
--- a/chrome/browser/autocomplete/autocomplete_result.cc
+++ b/chrome/browser/autocomplete/autocomplete_result.cc
@@ -11,9 +11,60 @@
#include "chrome/browser/autocomplete/autocomplete_input.h"
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "chrome/browser/autocomplete/autocomplete_provider.h"
+#include "chrome/browser/omnibox/omnibox_field_trial.h"
#include "chrome/browser/search/search.h"
#include "chrome/common/autocomplete_match_type.h"
+namespace {
+
+// This class implements a special version of AutocompleteMatch::MoreRelevant
+// that allows matches of particular types to be demoted in AutocompleteResult.
+class CompareWithDemoteByType {
+ public:
+ CompareWithDemoteByType(
+ AutocompleteInput::PageClassification current_page_classification);
+
+ // Returns the relevance score of |match| demoted appropriately by
+ // |demotions_by_type_|.
+ int GetDemotedRelevance(const AutocompleteMatch& match);
+
+ // Comparison function.
+ bool operator()(const AutocompleteMatch& elem1,
+ const AutocompleteMatch& elem2);
+
+ private:
+ OmniboxFieldTrial::DemotionMultipliers demotions_;
+};
+
+CompareWithDemoteByType::CompareWithDemoteByType(
+ AutocompleteInput::PageClassification current_page_classification) {
+ OmniboxFieldTrial::GetDemotionsByType(current_page_classification,
+ &demotions_);
+}
+
+int CompareWithDemoteByType::GetDemotedRelevance(
+ const AutocompleteMatch& match) {
+ OmniboxFieldTrial::DemotionMultipliers::const_iterator demotion_it =
+ demotions_.find(match.type);
+ return (demotion_it == demotions_.end()) ?
+ match.relevance : (match.relevance * demotion_it->second);
+}
+
+bool CompareWithDemoteByType::operator()(const AutocompleteMatch& elem1,
+ const AutocompleteMatch& elem2) {
+ // Compute demoted relevance scores for each match.
+ const int demoted_relevance1 = GetDemotedRelevance(elem1);
+ const int demoted_relevance2 = GetDemotedRelevance(elem2);
+ // For equal-relevance matches, we sort alphabetically, so that providers
+ // who return multiple elements at the same priority get a "stable" sort
+ // across multiple updates.
+ return (demoted_relevance1 == demoted_relevance2) ?
+ (elem1.contents < elem2.contents) :
+ (demoted_relevance1 > demoted_relevance2);
+}
+
+}; // namespace
+
// static
const size_t AutocompleteResult::kMaxMatches = 6;
const int AutocompleteResult::kLowestDefaultScore = 1200;
@@ -70,7 +121,8 @@
old_matches.BuildProviderToMatches(&old_matches_per_provider);
for (ProviderToMatches::const_iterator i(old_matches_per_provider.begin());
i != old_matches_per_provider.end(); ++i) {
- MergeMatchesByProvider(i->second, matches_per_provider[i->first]);
+ MergeMatchesByProvider(input.current_page_classification(),
+ i->second, matches_per_provider[i->first]);
}
SortAndCull(input, profile);
@@ -102,9 +154,16 @@
matches_.end());
// Sort and trim to the most relevant kMaxMatches matches.
- const size_t num_matches = std::min(kMaxMatches, matches_.size());
- std::partial_sort(matches_.begin(), matches_.begin() + num_matches,
- matches_.end(), &AutocompleteMatch::MoreRelevant);
+ size_t max_num_matches = std::min(kMaxMatches, matches_.size());
+ CompareWithDemoteByType comparing_object(input.current_page_classification());
+ std::partial_sort(matches_.begin(), matches_.begin() + max_num_matches,
+ matches_.end(), comparing_object);
+ // In the process of trimming, drop all matches with a demoted relevance
+ // score of 0.
+ size_t num_matches;
+ for (num_matches = 0u; (num_matches < max_num_matches) &&
+ (comparing_object.GetDemotedRelevance(*match_at(num_matches)) > 0);
+ ++num_matches) {}
matches_.resize(num_matches);
default_match_ = begin();
@@ -221,13 +280,16 @@
alternate_nav_url_ = rhs.alternate_nav_url_;
}
-void AutocompleteResult::AddMatch(const AutocompleteMatch& match) {
+void AutocompleteResult::AddMatch(
+ AutocompleteInput::PageClassification page_classification,
+ const AutocompleteMatch& match) {
DCHECK(default_match_ != end());
DCHECK_EQ(AutocompleteMatch::SanitizeString(match.contents), match.contents);
DCHECK_EQ(AutocompleteMatch::SanitizeString(match.description),
match.description);
+ CompareWithDemoteByType comparing_object(page_classification);
ACMatches::iterator insertion_point =
- std::upper_bound(begin(), end(), match, &AutocompleteMatch::MoreRelevant);
+ std::upper_bound(begin(), end(), match, comparing_object);
matches_difference_type default_offset = default_match_ - begin();
if ((insertion_point - begin()) <= default_offset)
++default_offset;
@@ -251,8 +313,10 @@
return false;
}
-void AutocompleteResult::MergeMatchesByProvider(const ACMatches& old_matches,
- const ACMatches& new_matches) {
+void AutocompleteResult::MergeMatchesByProvider(
+ AutocompleteInput::PageClassification page_classification,
+ const ACMatches& old_matches,
+ const ACMatches& new_matches) {
if (new_matches.size() >= old_matches.size())
return;
@@ -271,7 +335,7 @@
AutocompleteMatch match = *i;
match.relevance = std::min(max_relevance, match.relevance);
match.from_previous = true;
- AddMatch(match);
+ AddMatch(page_classification, match);
delta--;
}
}
diff --git a/chrome/browser/autocomplete/autocomplete_result.h b/chrome/browser/autocomplete/autocomplete_result.h
index a622d1b..69bdbed 100644
--- a/chrome/browser/autocomplete/autocomplete_result.h
+++ b/chrome/browser/autocomplete/autocomplete_result.h
@@ -10,6 +10,7 @@
#include <map>
#include "base/basictypes.h"
+#include "chrome/browser/autocomplete/autocomplete_input.h"
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "url/gurl.h"
@@ -166,15 +167,18 @@
// Adds a single match. The match is inserted at the appropriate position
// based on relevancy and display order. This is ONLY for use after
// SortAndCull() has been invoked, and preserves default_match_.
- void AddMatch(const AutocompleteMatch& match);
+ void AddMatch(AutocompleteInput::PageClassification page_classification,
+ const AutocompleteMatch& match);
// Populates |provider_to_matches| from |matches_|.
void BuildProviderToMatches(ProviderToMatches* provider_to_matches) const;
// Copies matches into this result. |old_matches| gives the matches from the
// last result, and |new_matches| the results from this result.
- void MergeMatchesByProvider(const ACMatches& old_matches,
- const ACMatches& new_matches);
+ void MergeMatchesByProvider(
+ AutocompleteInput::PageClassification page_classification,
+ const ACMatches& old_matches,
+ const ACMatches& new_matches);
ACMatches matches_;
diff --git a/chrome/browser/autocomplete/autocomplete_result_unittest.cc b/chrome/browser/autocomplete/autocomplete_result_unittest.cc
index 3038c27..1e8900f 100644
--- a/chrome/browser/autocomplete/autocomplete_result_unittest.cc
+++ b/chrome/browser/autocomplete/autocomplete_result_unittest.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/autocomplete/autocomplete_result.h"
+#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -13,6 +14,9 @@
#include "chrome/browser/search_engines/template_url_prepopulate_data.h"
#include "chrome/browser/search_engines/template_url_service.h"
#include "chrome/browser/search_engines/template_url_service_test_util.h"
+#include "chrome/common/autocomplete_match_type.h"
+#include "chrome/common/metrics/entropy_provider.h"
+#include "chrome/common/metrics/variations/variations_util.h"
#include "chrome/test/base/testing_profile.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -30,7 +34,14 @@
int relevance;
};
- AutocompleteResultTest() {}
+ AutocompleteResultTest() {
+ // Destroy the existing FieldTrialList before creating a new one to avoid
+ // a DCHECK.
+ field_trial_list_.reset();
+ field_trial_list_.reset(new base::FieldTrialList(
+ new metrics::SHA1EntropyProvider("foo")));
+ chrome_variations::testing::ClearAllVariationParams();
+ }
virtual void SetUp() OVERRIDE {
#if defined(OS_ANDROID)
@@ -69,6 +80,8 @@
TemplateURLServiceTestUtil test_util_;
private:
+ scoped_ptr<base::FieldTrialList> field_trial_list_;
+
DISALLOW_COPY_AND_ASSIGN(AutocompleteResultTest);
};
@@ -148,6 +161,7 @@
// Swap with a single match.
ACMatches matches;
AutocompleteMatch match;
+ match.relevance = 1;
AutocompleteInput input(ASCIIToUTF16("a"), string16::npos, string16(), GURL(),
AutocompleteInput::INVALID_SPEC, false, false, false,
AutocompleteInput::ALL_MATCHES);
@@ -292,3 +306,69 @@
result.match_at(2)->destination_url.spec());
EXPECT_EQ(900, result.match_at(2)->relevance);
}
+
+TEST_F(AutocompleteResultTest, SortAndCullWithDemotionsByType) {
+ // Add some matches.
+ ACMatches matches;
+ {
+ AutocompleteMatch match;
+ match.destination_url = GURL("http://history-url/");
+ match.relevance = 1400;
+ match.type = AutocompleteMatchType::HISTORY_URL;
+ matches.push_back(match);
+ }
+ {
+ AutocompleteMatch match;
+ match.destination_url = GURL("http://search-what-you-typed/");
+ match.relevance = 1300;
+ match.type = AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED;
+ matches.push_back(match);
+ }
+ {
+ AutocompleteMatch match;
+ match.destination_url = GURL("http://history-title/");
+ match.relevance = 1200;
+ match.type = AutocompleteMatchType::HISTORY_TITLE;
+ matches.push_back(match);
+ }
+ {
+ AutocompleteMatch match;
+ match.destination_url = GURL("http://search-history/");
+ match.relevance = 500;
+ match.type = AutocompleteMatchType::SEARCH_HISTORY;
+ matches.push_back(match);
+ }
+
+ // Add a rule demoting history-url and killing history-title.
+ // Must be the same as kBundledExperimentFieldTrialName
+ // defined in omnibox_field_trial.cc.
+ const std::string kTrialName = "OmniboxBundledExperimentV1";
+ // Must be the same as kDemoteByTypeRule defined in
+ // omnibox_field_trial.cc.
+ const std::string kRuleName = "DemoteByType";
+ {
+ std::map<std::string, std::string> params;
+ params[kRuleName + ":3:*"] = "1:50,7:100,2:0"; // 3 == HOMEPAGE
+ ASSERT_TRUE(chrome_variations::AssociateVariationParams(
+ kTrialName, "A", params));
+ }
+ base::FieldTrialList::CreateFieldTrial(kTrialName, "A");
+
+ AutocompleteResult result;
+ result.AppendMatches(matches);
+ AutocompleteInput input(string16(), string16::npos, string16(), GURL(),
+ AutocompleteInput::HOMEPAGE, false, false, false,
+ AutocompleteInput::ALL_MATCHES);
+ result.SortAndCull(input, test_util_.profile());
+
+ // Check the new ordering. The history-title results should be omitted.
+ // We cannot check relevance scores because the matches are sorted by
+ // demoted relevance but the actual relevance scores are not modified.
+ ASSERT_EQ(3u, result.size());
+ EXPECT_EQ("http://search-what-you-typed/",
+ result.match_at(0)->destination_url.spec());
+ EXPECT_EQ("http://history-url/",
+ result.match_at(1)->destination_url.spec());
+ EXPECT_EQ("http://search-history/",
+ result.match_at(2)->destination_url.spec());
+}
diff --git a/chrome/browser/autocomplete/search_provider.cc b/chrome/browser/autocomplete/search_provider.cc
index d4245fd..b5a6f48 100644
--- a/chrome/browser/autocomplete/search_provider.cc
+++ b/chrome/browser/autocomplete/search_provider.cc
@@ -32,10 +32,13 @@
#include "chrome/browser/omnibox/omnibox_field_trial.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/search.h"
-#include "chrome/browser/search_engines/search_engine_type.h"
#include "chrome/browser/search_engines/template_url_prepopulate_data.h"
#include "chrome/browser/search_engines/template_url_service.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_instant_controller.h"
+#include "chrome/browser/ui/search/instant_controller.h"
#include "chrome/common/net/url_fixer_upper.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
@@ -250,8 +253,7 @@
providers_(TemplateURLServiceFactory::GetForProfile(profile)),
suggest_results_pending_(0),
field_trial_triggered_(false),
- field_trial_triggered_in_session_(false),
- omnibox_start_margin_(-1) {
+ field_trial_triggered_in_session_(false) {
}
// static
@@ -369,10 +371,6 @@
field_trial_triggered_in_session_ = false;
}
-void SearchProvider::SetOmniboxStartMargin(int omnibox_start_margin) {
- omnibox_start_margin_ = omnibox_start_margin;
-}
-
SearchProvider::~SearchProvider() {
}
@@ -834,6 +832,7 @@
// Bail if the suggestion URL is invalid with the given replacements.
TemplateURLRef::SearchTermsArgs search_term_args(input.text());
search_term_args.cursor_position = input.cursor_position();
+ search_term_args.page_classification = input.current_page_classification();
GURL suggest_url(template_url->suggestions_url_ref().ReplaceSearchTerms(
search_term_args));
if (!suggest_url.is_valid())
@@ -1382,11 +1381,26 @@
int accepted_suggestion,
bool is_keyword,
MatchMap* map) {
+ // On non-mobile, ask the instant controller for the appropriate start margin.
+ // On mobile the start margin is unused, so leave the value as default there.
+ int omnibox_start_margin = chrome::kDisableStartMargin;
+#if !defined(OS_ANDROID) && !defined(IOS)
+ if (chrome::IsInstantExtendedAPIEnabled()) {
+ Browser* browser =
+ chrome::FindBrowserWithProfile(profile_, chrome::GetActiveDesktop());
+ if (browser && browser->instant_controller() &&
+ browser->instant_controller()->instant()) {
+ omnibox_start_margin =
+ browser->instant_controller()->instant()->omnibox_bounds().x();
+ }
+ }
+#endif // !defined(OS_ANDROID) && !defined(IOS)
+
const TemplateURL* template_url = is_keyword ?
providers_.GetKeywordProviderURL() : providers_.GetDefaultProviderURL();
AutocompleteMatch match = CreateSearchSuggestion(this, relevance, type,
template_url, query_string, input_text, input_, is_keyword,
- accepted_suggestion, omnibox_start_margin_,
+ accepted_suggestion, omnibox_start_margin,
!is_keyword || providers_.default_provider().empty());
if (!match.destination_url.is_valid())
return;
diff --git a/chrome/browser/autocomplete/search_provider.h b/chrome/browser/autocomplete/search_provider.h
index 74c5e7e..5f25f35 100644
--- a/chrome/browser/autocomplete/search_provider.h
+++ b/chrome/browser/autocomplete/search_provider.h
@@ -94,9 +94,6 @@
virtual void AddProviderInfo(ProvidersInfo* provider_info) const OVERRIDE;
virtual void ResetSession() OVERRIDE;
- // Update the omnibox start margin used to generate search suggestion URLs.
- void SetOmniboxStartMargin(int omnibox_start_margin);
-
bool field_trial_triggered_in_session() const {
return field_trial_triggered_in_session_;
}
@@ -527,9 +524,6 @@
// session.
bool field_trial_triggered_in_session_;
- // Start margin of the omnibox. Used to construct search URLs.
- int omnibox_start_margin_;
-
// If true, search history query suggestions will score low enough that
// they will not be inlined.
bool prevent_search_history_inlining_;
diff --git a/chrome/browser/autocomplete/shortcuts_provider.cc b/chrome/browser/autocomplete/shortcuts_provider.cc
index cf121be..06f3455 100644
--- a/chrome/browser/autocomplete/shortcuts_provider.cc
+++ b/chrome/browser/autocomplete/shortcuts_provider.cc
@@ -54,8 +54,7 @@
: AutocompleteProvider(listener, profile,
AutocompleteProvider::TYPE_SHORTCUTS),
languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)),
- initialized_(false),
- max_relevance_(AutocompleteResult::kLowestDefaultScore - 1) {
+ initialized_(false) {
scoped_refptr<history::ShortcutsBackend> backend =
ShortcutsBackendFactory::GetForProfile(profile_);
if (backend.get()) {
@@ -63,9 +62,6 @@
if (backend->initialized())
initialized_ = true;
}
- int max_relevance;
- if (OmniboxFieldTrial::ShortcutsScoringMaxRelevance(&max_relevance))
- max_relevance_ = max_relevance;
}
void ShortcutsProvider::Start(const AutocompleteInput& input,
@@ -157,12 +153,17 @@
string16 term_string(base::i18n::ToLower(input.text()));
DCHECK(!term_string.empty());
+ int max_relevance;
+ if (!OmniboxFieldTrial::ShortcutsScoringMaxRelevance(
+ input.current_page_classification(), &max_relevance))
+ max_relevance = AutocompleteResult::kLowestDefaultScore - 1;
+
for (history::ShortcutsBackend::ShortcutMap::const_iterator it =
FindFirstMatch(term_string, backend.get());
it != backend->shortcuts_map().end() &&
StartsWith(it->first, term_string, true); ++it) {
// Don't return shortcuts with zero relevance.
- int relevance = CalculateScore(term_string, it->second);
+ int relevance = CalculateScore(term_string, it->second, max_relevance);
if (relevance)
matches_.push_back(ShortcutToACMatch(relevance, term_string, it->second));
}
@@ -177,7 +178,7 @@
// Reset relevance scores to guarantee no results are given an
// inlineable score and all scores are decreasing (but not do assign
// any scores below 1).
- int max_relevance = AutocompleteResult::kLowestDefaultScore - 1;
+ max_relevance = AutocompleteResult::kLowestDefaultScore - 1;
for (ACMatches::iterator it = matches_.begin(); it != matches_.end(); ++it) {
max_relevance = std::min(max_relevance, it->relevance);
it->relevance = max_relevance;
@@ -338,7 +339,8 @@
int ShortcutsProvider::CalculateScore(
const string16& terms,
- const history::ShortcutsBackend::Shortcut& shortcut) {
+ const history::ShortcutsBackend::Shortcut& shortcut,
+ int max_relevance) {
DCHECK(!terms.empty());
DCHECK_LE(terms.length(), shortcut.text.length());
@@ -348,7 +350,7 @@
// directly. This makes sense since the first characters typed are much more
// important for determining how likely it is a user wants a particular
// shortcut than are the remaining continued characters.
- double base_score = max_relevance_ *
+ double base_score = max_relevance *
sqrt(static_cast<double>(terms.length()) / shortcut.text.length());
// Then we decay this by half each week.
diff --git a/chrome/browser/autocomplete/shortcuts_provider.h b/chrome/browser/autocomplete/shortcuts_provider.h
index 11f0b0a..89dcc3c 100644
--- a/chrome/browser/autocomplete/shortcuts_provider.h
+++ b/chrome/browser/autocomplete/shortcuts_provider.h
@@ -96,17 +96,11 @@
int CalculateScore(
const string16& terms,
- const history::ShortcutsBackend::Shortcut& shortcut);
+ const history::ShortcutsBackend::Shortcut& shortcut,
+ int max_relevance);
std::string languages_;
bool initialized_;
-
- // The maximum relevance that can be assigned in CalculateScore().
- // Note that if the final assigned relevance is at least
- // AutocompleteResult::kLowestDefaultScore, the relevance will be
- // demoted to less than that number because ShortcutsProvider isn't
- // allowed to inline.
- int max_relevance_;
};
#endif // CHROME_BROWSER_AUTOCOMPLETE_SHORTCUTS_PROVIDER_H_
diff --git a/chrome/browser/autocomplete/shortcuts_provider_unittest.cc b/chrome/browser/autocomplete/shortcuts_provider_unittest.cc
index 73699db..a6fef30 100644
--- a/chrome/browser/autocomplete/shortcuts_provider_unittest.cc
+++ b/chrome/browser/autocomplete/shortcuts_provider_unittest.cc
@@ -21,6 +21,7 @@
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "chrome/browser/autocomplete/autocomplete_provider.h"
#include "chrome/browser/autocomplete/autocomplete_provider_listener.h"
+#include "chrome/browser/autocomplete/autocomplete_result.h"
#include "chrome/browser/history/history_service.h"
#include "chrome/browser/history/in_memory_url_index.h"
#include "chrome/browser/history/shortcuts_backend.h"
@@ -574,37 +575,38 @@
spans_description, base::Time::Now(), 1);
// Maximal score.
+ const int max_relevance = AutocompleteResult::kLowestDefaultScore - 1;
const int kMaxScore = provider_->CalculateScore(
- ASCIIToUTF16("test"), shortcut);
+ ASCIIToUTF16("test"), shortcut, max_relevance);
// Score decreases as percent of the match is decreased.
int score_three_quarters =
- provider_->CalculateScore(ASCIIToUTF16("tes"), shortcut);
+ provider_->CalculateScore(ASCIIToUTF16("tes"), shortcut, max_relevance);
EXPECT_LT(score_three_quarters, kMaxScore);
int score_one_half =
- provider_->CalculateScore(ASCIIToUTF16("te"), shortcut);
+ provider_->CalculateScore(ASCIIToUTF16("te"), shortcut, max_relevance);
EXPECT_LT(score_one_half, score_three_quarters);
int score_one_quarter =
- provider_->CalculateScore(ASCIIToUTF16("t"), shortcut);
+ provider_->CalculateScore(ASCIIToUTF16("t"), shortcut, max_relevance);
EXPECT_LT(score_one_quarter, score_one_half);
// Should decay with time - one week.
shortcut.last_access_time = base::Time::Now() - base::TimeDelta::FromDays(7);
int score_week_old =
- provider_->CalculateScore(ASCIIToUTF16("test"), shortcut);
+ provider_->CalculateScore(ASCIIToUTF16("test"), shortcut, max_relevance);
EXPECT_LT(score_week_old, kMaxScore);
// Should decay more in two weeks.
shortcut.last_access_time = base::Time::Now() - base::TimeDelta::FromDays(14);
int score_two_weeks_old =
- provider_->CalculateScore(ASCIIToUTF16("test"), shortcut);
+ provider_->CalculateScore(ASCIIToUTF16("test"), shortcut, max_relevance);
EXPECT_LT(score_two_weeks_old, score_week_old);
// But not if it was activly clicked on. 2 hits slow decaying power.
shortcut.number_of_hits = 2;
shortcut.last_access_time = base::Time::Now() - base::TimeDelta::FromDays(14);
int score_popular_two_weeks_old =
- provider_->CalculateScore(ASCIIToUTF16("test"), shortcut);
+ provider_->CalculateScore(ASCIIToUTF16("test"), shortcut, max_relevance);
EXPECT_LT(score_two_weeks_old, score_popular_two_weeks_old);
// But still decayed.
EXPECT_LT(score_popular_two_weeks_old, kMaxScore);
@@ -613,7 +615,7 @@
shortcut.number_of_hits = 3;
shortcut.last_access_time = base::Time::Now() - base::TimeDelta::FromDays(14);
int score_more_popular_two_weeks_old =
- provider_->CalculateScore(ASCIIToUTF16("test"), shortcut);
+ provider_->CalculateScore(ASCIIToUTF16("test"), shortcut, max_relevance);
EXPECT_LT(score_two_weeks_old, score_more_popular_two_weeks_old);
EXPECT_LT(score_popular_two_weeks_old, score_more_popular_two_weeks_old);
// But still decayed.
diff --git a/chrome/browser/autofill/autofill_browsertest.cc b/chrome/browser/autofill/autofill_browsertest.cc
index b1cda4b..4498d2d 100644
--- a/chrome/browser/autofill/autofill_browsertest.cc
+++ b/chrome/browser/autofill/autofill_browsertest.cc
@@ -20,8 +20,6 @@
#include "chrome/browser/infobars/confirm_infobar_delegate.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/translate/translate_infobar_delegate.h"
-#include "chrome/browser/translate/translate_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -31,9 +29,6 @@
#include "chrome/test/base/ui_test_utils.h"
#include "components/autofill/content/browser/autofill_driver_impl.h"
#include "components/autofill/core/browser/autofill_common_test.h"
-#include "components/autofill/core/browser/autofill_external_delegate.h"
-#include "components/autofill/core/browser/autofill_manager.h"
-#include "components/autofill/core/browser/autofill_manager_test_delegate.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/personal_data_manager.h"
@@ -55,69 +50,6 @@
namespace autofill {
-static const char* kDataURIPrefix = "data:text/html;charset=utf-8,";
-static const char* kTestFormString =
- "<form action=\"http://www.example.com/\" method=\"POST\">"
- "<label for=\"firstname\">First name:</label>"
- " <input type=\"text\" id=\"firstname\""
- " onFocus=\"domAutomationController.send(true)\"><br>"
- "<label for=\"lastname\">Last name:</label>"
- " <input type=\"text\" id=\"lastname\"><br>"
- "<label for=\"address1\">Address line 1:</label>"
- " <input type=\"text\" id=\"address1\"><br>"
- "<label for=\"address2\">Address line 2:</label>"
- " <input type=\"text\" id=\"address2\"><br>"
- "<label for=\"city\">City:</label>"
- " <input type=\"text\" id=\"city\"><br>"
- "<label for=\"state\">State:</label>"
- " <select id=\"state\">"
- " <option value=\"\" selected=\"yes\">--</option>"
- " <option value=\"CA\">California</option>"
- " <option value=\"TX\">Texas</option>"
- " </select><br>"
- "<label for=\"zip\">ZIP code:</label>"
- " <input type=\"text\" id=\"zip\"><br>"
- "<label for=\"country\">Country:</label>"
- " <select id=\"country\">"
- " <option value=\"\" selected=\"yes\">--</option>"
- " <option value=\"CA\">Canada</option>"
- " <option value=\"US\">United States</option>"
- " </select><br>"
- "<label for=\"phone\">Phone number:</label>"
- " <input type=\"text\" id=\"phone\"><br>"
- "</form>";
-
-class AutofillManagerTestDelegateImpl
- : public autofill::AutofillManagerTestDelegate {
- public:
- AutofillManagerTestDelegateImpl() {}
-
- virtual void DidPreviewFormData() OVERRIDE {
- loop_runner_->Quit();
- }
-
- virtual void DidFillFormData() OVERRIDE {
- loop_runner_->Quit();
- }
-
- virtual void DidShowSuggestions() OVERRIDE {
- loop_runner_->Quit();
- }
-
- void Reset() {
- loop_runner_ = new content::MessageLoopRunner();
- }
-
- void Wait() {
- loop_runner_->Run();
- }
-
- private:
- scoped_refptr<content::MessageLoopRunner> loop_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(AutofillManagerTestDelegateImpl);
-};
-
class WindowedPersonalDataManagerObserver
: public PersonalDataManagerObserver,
public content::NotificationObserver {
@@ -181,39 +113,6 @@
InfoBarService* infobar_service_;
};
-class TestAutofillExternalDelegate : public AutofillExternalDelegate {
- public:
- TestAutofillExternalDelegate(content::WebContents* web_contents,
- AutofillManager* autofill_manager,
- AutofillDriver* autofill_driver)
- : AutofillExternalDelegate(web_contents, autofill_manager,
- autofill_driver),
- keyboard_listener_(NULL) {
- }
- virtual ~TestAutofillExternalDelegate() {}
-
- virtual void OnPopupShown(content::KeyboardListener* listener) OVERRIDE {
- AutofillExternalDelegate::OnPopupShown(listener);
- keyboard_listener_ = listener;
- }
-
- virtual void OnPopupHidden(content::KeyboardListener* listener) OVERRIDE {
- keyboard_listener_ = NULL;
- AutofillExternalDelegate::OnPopupHidden(listener);
- }
-
- content::KeyboardListener* keyboard_listener() {
- return keyboard_listener_;
- }
-
- private:
- // The popup that is currently registered as a keyboard listener, or NULL if
- // there is none.
- content::KeyboardListener* keyboard_listener_;
-
- DISALLOW_COPY_AND_ASSIGN(TestAutofillExternalDelegate);
-};
-
class AutofillTest : public InProcessBrowserTest {
protected:
AutofillTest() {}
@@ -221,19 +120,6 @@
virtual void SetUpOnMainThread() OVERRIDE {
// Don't want Keychain coming up on Mac.
test::DisableSystemServices(browser()->profile());
-
- // When testing the native UI, hook up a test external delegate, which
- // allows us to forward keyboard events to the popup directly.
- content::WebContents* web_contents =
- browser()->tab_strip_model()->GetActiveWebContents();
- AutofillDriverImpl* autofill_driver =
- AutofillDriverImpl::FromWebContents(web_contents);
- AutofillManager* autofill_manager = autofill_driver->autofill_manager();
- scoped_ptr<AutofillExternalDelegate> external_delegate(
- new TestAutofillExternalDelegate(web_contents, autofill_manager,
- autofill_driver));
- autofill_driver->SetAutofillExternalDelegate(external_delegate.Pass());
- autofill_manager->SetTestDelegate(&test_delegate_);
}
virtual void CleanUpOnMainThread() OVERRIDE {
@@ -249,21 +135,6 @@
return PersonalDataManagerFactory::GetForProfile(browser()->profile());
}
- void CreateTestProfile() {
- AutofillProfile profile;
- test::SetProfileInfo(
- &profile, "Milton", "C.", "Waddams",
- "red.swingline@initech.com", "Initech", "4120 Freidrich Lane",
- "Basement", "Austin", "Texas", "78744", "US", "5125551234");
-
- WindowedPersonalDataManagerObserver observer(browser());
- personal_data_manager()->AddProfile(profile);
-
- // AddProfile is asynchronous. Wait for it to finish before continuing the
- // tests.
- observer.Wait();
- }
-
void SetProfiles(std::vector<AutofillProfile>* profiles) {
WindowedPersonalDataManagerObserver observer(browser());
personal_data_manager()->SetProfiles(profiles);
@@ -319,18 +190,6 @@
FillFormAndSubmit("autofill_creditcard_form.html", data);
}
- // Populates a webpage form using autofill data and keypress events.
- // This function focuses the specified input field in the form, and then
- // sends keypress events to the tab to cause the form to be populated.
- void PopulateForm(const std::string& field_id) {
- std::string js("document.getElementById('" + field_id + "').focus();");
- ASSERT_TRUE(content::ExecuteScript(render_view_host(), js));
-
- SendKeyToPageAndWait(ui::VKEY_DOWN);
- SendKeyToPopupAndWait(ui::VKEY_DOWN);
- SendKeyToPopupAndWait(ui::VKEY_RETURN);
- }
-
// Aggregate profiles from forms into Autofill preferences. Returns the number
// of parsed profiles.
int AggregateProfilesIntoAutofillPrefs(const std::string& filename) {
@@ -387,65 +246,6 @@
GetRenderViewHost();
}
- void SimulateURLFetch(bool success) {
- net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
- ASSERT_TRUE(fetcher);
- net::URLRequestStatus status;
- status.set_status(success ? net::URLRequestStatus::SUCCESS :
- net::URLRequestStatus::FAILED);
-
- std::string script = " var google = {};"
- "google.translate = (function() {"
- " return {"
- " TranslateService: function() {"
- " return {"
- " isAvailable : function() {"
- " return true;"
- " },"
- " restore : function() {"
- " return;"
- " },"
- " getDetectedLanguage : function() {"
- " return \"ja\";"
- " },"
- " translatePage : function(originalLang, targetLang,"
- " onTranslateProgress) {"
- " document.getElementsByTagName(\"body\")[0].innerHTML = '" +
- std::string(kTestFormString) +
- " ';"
- " onTranslateProgress(100, true, false);"
- " }"
- " };"
- " }"
- " };"
- "})();";
-
- fetcher->set_url(fetcher->GetOriginalURL());
- fetcher->set_status(status);
- fetcher->set_response_code(success ? 200 : 500);
- fetcher->SetResponseString(script);
- fetcher->delegate()->OnURLFetchComplete(fetcher);
- }
-
- void FocusFirstNameField() {
- LOG(WARNING) << "Clicking on the tab.";
- content::SimulateMouseClick(
- browser()->tab_strip_model()->GetActiveWebContents(),
- 0,
- WebKit::WebMouseEvent::ButtonLeft);
-
- LOG(WARNING) << "Focusing the first name field.";
- bool result = false;
- ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
- render_view_host(),
- "if (document.readyState === 'complete')"
- " document.getElementById('firstname').focus();"
- "else"
- " domAutomationController.send(false);",
- &result));
- ASSERT_TRUE(result);
- }
-
void ExpectFilledTestForm() {
ExpectFieldValue("firstname", "Milton");
ExpectFieldValue("lastname", "Waddams");
@@ -458,528 +258,10 @@
ExpectFieldValue("phone", "5125551234");
}
- void SendKeyToPageAndWait(ui::KeyboardCode key) {
- test_delegate_.Reset();
- content::SimulateKeyPress(
- browser()->tab_strip_model()->GetActiveWebContents(),
- key, false, false, false, false);
- test_delegate_.Wait();
- }
-
- void SendKeyToPopupAndWait(ui::KeyboardCode key) {
- // When testing the native UI, route popup-targeted key presses via the
- // external delegate.
- content::NativeWebKeyboardEvent event;
- event.windowsKeyCode = key;
- test_delegate_.Reset();
- external_delegate()->keyboard_listener()->HandleKeyPressEvent(event);
- test_delegate_.Wait();
- }
-
- void TryBasicFormFill() {
- FocusFirstNameField();
-
- // Start filling the first name field with "M" and wait for the popup to be
- // shown.
- LOG(WARNING) << "Typing 'M' to bring up the Autofill popup.";
- SendKeyToPageAndWait(ui::VKEY_M);
-
- // Press the down arrow to select the suggestion and preview the autofilled
- // form.
- LOG(WARNING) << "Simulating down arrow press to initiate Autofill preview.";
- SendKeyToPopupAndWait(ui::VKEY_DOWN);
-
- // The previewed values should not be accessible to JavaScript.
- ExpectFieldValue("firstname", "M");
- ExpectFieldValue("lastname", std::string());
- ExpectFieldValue("address1", std::string());
- ExpectFieldValue("address2", std::string());
- ExpectFieldValue("city", std::string());
- ExpectFieldValue("state", std::string());
- ExpectFieldValue("zip", std::string());
- ExpectFieldValue("country", std::string());
- ExpectFieldValue("phone", std::string());
- // TODO(isherman): It would be nice to test that the previewed values are
- // displayed: http://crbug.com/57220
-
- // Press Enter to accept the autofill suggestions.
- LOG(WARNING) << "Simulating Return press to fill the form.";
- SendKeyToPopupAndWait(ui::VKEY_RETURN);
-
- // The form should be filled.
- ExpectFilledTestForm();
- }
-
- TestAutofillExternalDelegate* external_delegate() {
- content::WebContents* web_contents =
- browser()->tab_strip_model()->GetActiveWebContents();
- AutofillDriverImpl* autofill_driver =
- AutofillDriverImpl::FromWebContents(web_contents);
- return static_cast<TestAutofillExternalDelegate*>(
- autofill_driver->autofill_external_delegate());
- }
-
- AutofillManagerTestDelegateImpl test_delegate_;
-
private:
net::TestURLFetcherFactory url_fetcher_factory_;
};
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_BasicFormFill BasicFormFill
-#else
-#define MAYBE_BasicFormFill DISABLED_BasicFormFill
-#endif
-// Test that basic form fill is working.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_BasicFormFill) {
- CreateTestProfile();
-
- // Load the test page.
- ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
- GURL(std::string(kDataURIPrefix) + kTestFormString)));
-
- // Invoke Autofill.
- TryBasicFormFill();
-}
-
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_AutofillViaDownArrow AutofillViaDownArrow
-#else
-#define MAYBE_AutofillViaDownArrow DISABLED_AutofillViaDownArrow
-#endif
-// Test that form filling can be initiated by pressing the down arrow.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_AutofillViaDownArrow) {
- CreateTestProfile();
-
- // Load the test page.
- ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
- GURL(std::string(kDataURIPrefix) + kTestFormString)));
-
- // Focus a fillable field.
- FocusFirstNameField();
-
- // Press the down arrow to initiate Autofill and wait for the popup to be
- // shown.
- SendKeyToPageAndWait(ui::VKEY_DOWN);
-
- // Press the down arrow to select the suggestion and preview the autofilled
- // form.
- SendKeyToPopupAndWait(ui::VKEY_DOWN);
-
- // Press Enter to accept the autofill suggestions.
- SendKeyToPopupAndWait(ui::VKEY_RETURN);
-
- // The form should be filled.
- ExpectFilledTestForm();
-}
-
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_OnChangeAfterAutofill OnChangeAfterAutofill
-#else
-#define MAYBE_OnChangeAfterAutofill DISABLED_OnChangeAfterAutofill
-#endif
-// Test that a JavaScript onchange event is fired after auto-filling a form.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_OnChangeAfterAutofill) {
- CreateTestProfile();
-
- const char* kOnChangeScript =
- "<script>"
- "focused_fired = false;"
- "unfocused_fired = false;"
- "changed_select_fired = false;"
- "unchanged_select_fired = false;"
- "document.getElementById('firstname').onchange = function() {"
- " focused_fired = true;"
- "};"
- "document.getElementById('lastname').onchange = function() {"
- " unfocused_fired = true;"
- "};"
- "document.getElementById('state').onchange = function() {"
- " changed_select_fired = true;"
- "};"
- "document.getElementById('country').onchange = function() {"
- " unchanged_select_fired = true;"
- "};"
- "document.getElementById('country').value = 'US';"
- "</script>";
-
- // Load the test page.
- ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
- GURL(std::string(kDataURIPrefix) + kTestFormString + kOnChangeScript)));
-
- // Invoke Autofill.
- FocusFirstNameField();
-
- // Start filling the first name field with "M" and wait for the popup to be
- // shown.
- SendKeyToPageAndWait(ui::VKEY_M);
-
- // Press the down arrow to select the suggestion and preview the autofilled
- // form.
- SendKeyToPopupAndWait(ui::VKEY_DOWN);
-
- // Press Enter to accept the autofill suggestions.
- SendKeyToPopupAndWait(ui::VKEY_RETURN);
-
- // The form should be filled.
- ExpectFilledTestForm();
-
- // The change event should have already fired for unfocused fields, both of
- // <input> and of <select> type. However, it should not yet have fired for the
- // focused field.
- bool focused_fired = false;
- bool unfocused_fired = false;
- bool changed_select_fired = false;
- bool unchanged_select_fired = false;
- ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
- render_view_host(),
- "domAutomationController.send(focused_fired);",
- &focused_fired));
- ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
- render_view_host(),
- "domAutomationController.send(unfocused_fired);",
- &unfocused_fired));
- ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
- render_view_host(),
- "domAutomationController.send(changed_select_fired);",
- &changed_select_fired));
- ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
- render_view_host(),
- "domAutomationController.send(unchanged_select_fired);",
- &unchanged_select_fired));
- EXPECT_FALSE(focused_fired);
- EXPECT_TRUE(unfocused_fired);
- EXPECT_TRUE(changed_select_fired);
- EXPECT_FALSE(unchanged_select_fired);
-
- // Unfocus the first name field. Its change event should fire.
- ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
- render_view_host(),
- "document.getElementById('firstname').blur();"
- "domAutomationController.send(focused_fired);", &focused_fired));
- EXPECT_TRUE(focused_fired);
-}
-
-// Test that we can autofill forms distinguished only by their |id| attribute.
-// DISABLED: http://crbug.com/150084
-IN_PROC_BROWSER_TEST_F(AutofillTest, DISABLED_AutofillFormsDistinguishedById) {
- CreateTestProfile();
-
- // Load the test page.
- const std::string kURL =
- std::string(kDataURIPrefix) + kTestFormString +
- "<script>"
- "var mainForm = document.forms[0];"
- "mainForm.id = 'mainForm';"
- "var newForm = document.createElement('form');"
- "newForm.action = mainForm.action;"
- "newForm.method = mainForm.method;"
- "newForm.id = 'newForm';"
- "mainForm.parentNode.insertBefore(newForm, mainForm);"
- "</script>";
- ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), GURL(kURL)));
-
- // Invoke Autofill.
- TryBasicFormFill();
-}
-
-// Test that we properly autofill forms with repeated fields.
-// In the wild, the repeated fields are typically either email fields
-// (duplicated for "confirmation"); or variants that are hot-swapped via
-// JavaScript, with only one actually visible at any given time.
-// DISABLED: http://crbug.com/150084
-IN_PROC_BROWSER_TEST_F(AutofillTest, DISABLED_AutofillFormWithRepeatedField) {
- CreateTestProfile();
-
- // Load the test page.
- ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
- GURL(std::string(kDataURIPrefix) +
- "<form action=\"http://www.example.com/\" method=\"POST\">"
- "<label for=\"firstname\">First name:</label>"
- " <input type=\"text\" id=\"firstname\""
- " onFocus=\"domAutomationController.send(true)\"><br>"
- "<label for=\"lastname\">Last name:</label>"
- " <input type=\"text\" id=\"lastname\"><br>"
- "<label for=\"address1\">Address line 1:</label>"
- " <input type=\"text\" id=\"address1\"><br>"
- "<label for=\"address2\">Address line 2:</label>"
- " <input type=\"text\" id=\"address2\"><br>"
- "<label for=\"city\">City:</label>"
- " <input type=\"text\" id=\"city\"><br>"
- "<label for=\"state\">State:</label>"
- " <select id=\"state\">"
- " <option value=\"\" selected=\"yes\">--</option>"
- " <option value=\"CA\">California</option>"
- " <option value=\"TX\">Texas</option>"
- " </select><br>"
- "<label for=\"state_freeform\" style=\"display:none\">State:</label>"
- " <input type=\"text\" id=\"state_freeform\""
- " style=\"display:none\"><br>"
- "<label for=\"zip\">ZIP code:</label>"
- " <input type=\"text\" id=\"zip\"><br>"
- "<label for=\"country\">Country:</label>"
- " <select id=\"country\">"
- " <option value=\"\" selected=\"yes\">--</option>"
- " <option value=\"CA\">Canada</option>"
- " <option value=\"US\">United States</option>"
- " </select><br>"
- "<label for=\"phone\">Phone number:</label>"
- " <input type=\"text\" id=\"phone\"><br>"
- "</form>")));
-
- // Invoke Autofill.
- TryBasicFormFill();
- ExpectFieldValue("state_freeform", std::string());
-}
-
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_AutofillFormWithNonAutofillableField \
- AutofillFormWithNonAutofillableField
-#else
-#define MAYBE_AutofillFormWithNonAutofillableField \
- DISABLED_AutofillFormWithNonAutofillableField
-#endif
-
-// Test that we properly autofill forms with non-autofillable fields.
-IN_PROC_BROWSER_TEST_F(AutofillTest,
- MAYBE_AutofillFormWithNonAutofillableField) {
- CreateTestProfile();
-
- // Load the test page.
- ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
- GURL(std::string(kDataURIPrefix) +
- "<form action=\"http://www.example.com/\" method=\"POST\">"
- "<label for=\"firstname\">First name:</label>"
- " <input type=\"text\" id=\"firstname\""
- " onFocus=\"domAutomationController.send(true)\"><br>"
- "<label for=\"middlename\">Middle name:</label>"
- " <input type=\"text\" id=\"middlename\" autocomplete=\"off\" /><br>"
- "<label for=\"lastname\">Last name:</label>"
- " <input type=\"text\" id=\"lastname\"><br>"
- "<label for=\"address1\">Address line 1:</label>"
- " <input type=\"text\" id=\"address1\"><br>"
- "<label for=\"address2\">Address line 2:</label>"
- " <input type=\"text\" id=\"address2\"><br>"
- "<label for=\"city\">City:</label>"
- " <input type=\"text\" id=\"city\"><br>"
- "<label for=\"state\">State:</label>"
- " <select id=\"state\">"
- " <option value=\"\" selected=\"yes\">--</option>"
- " <option value=\"CA\">California</option>"
- " <option value=\"TX\">Texas</option>"
- " </select><br>"
- "<label for=\"zip\">ZIP code:</label>"
- " <input type=\"text\" id=\"zip\"><br>"
- "<label for=\"country\">Country:</label>"
- " <select id=\"country\">"
- " <option value=\"\" selected=\"yes\">--</option>"
- " <option value=\"CA\">Canada</option>"
- " <option value=\"US\">United States</option>"
- " </select><br>"
- "<label for=\"phone\">Phone number:</label>"
- " <input type=\"text\" id=\"phone\"><br>"
- "</form>")));
-
- // Invoke Autofill.
- TryBasicFormFill();
-}
-
-// Test that we can Autofill dynamically generated forms.
-// DISABLED: http://crbug.com/150084
-IN_PROC_BROWSER_TEST_F(AutofillTest, DISABLED_DynamicFormFill) {
- CreateTestProfile();
-
- // Load the test page.
- ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
- GURL(std::string(kDataURIPrefix) +
- "<form id=\"form\" action=\"http://www.example.com/\""
- " method=\"POST\"></form>"
- "<script>"
- "function AddElement(name, label) {"
- " var form = document.getElementById('form');"
- ""
- " var label_text = document.createTextNode(label);"
- " var label_element = document.createElement('label');"
- " label_element.setAttribute('for', name);"
- " label_element.appendChild(label_text);"
- " form.appendChild(label_element);"
- ""
- " if (name === 'state' || name === 'country') {"
- " var select_element = document.createElement('select');"
- " select_element.setAttribute('id', name);"
- " select_element.setAttribute('name', name);"
- ""
- " /* Add an empty selected option. */"
- " var default_option = new Option('--', '', true);"
- " select_element.appendChild(default_option);"
- ""
- " /* Add the other options. */"
- " if (name == 'state') {"
- " var option1 = new Option('California', 'CA');"
- " select_element.appendChild(option1);"
- " var option2 = new Option('Texas', 'TX');"
- " select_element.appendChild(option2);"
- " } else {"
- " var option1 = new Option('Canada', 'CA');"
- " select_element.appendChild(option1);"
- " var option2 = new Option('United States', 'US');"
- " select_element.appendChild(option2);"
- " }"
- ""
- " form.appendChild(select_element);"
- " } else {"
- " var input_element = document.createElement('input');"
- " input_element.setAttribute('id', name);"
- " input_element.setAttribute('name', name);"
- ""
- " /* Add the onFocus listener to the 'firstname' field. */"
- " if (name === 'firstname') {"
- " input_element.setAttribute("
- " 'onFocus', 'domAutomationController.send(true)');"
- " }"
- ""
- " form.appendChild(input_element);"
- " }"
- ""
- " form.appendChild(document.createElement('br'));"
- "};"
- ""
- "function BuildForm() {"
- " var elements = ["
- " ['firstname', 'First name:'],"
- " ['lastname', 'Last name:'],"
- " ['address1', 'Address line 1:'],"
- " ['address2', 'Address line 2:'],"
- " ['city', 'City:'],"
- " ['state', 'State:'],"
- " ['zip', 'ZIP code:'],"
- " ['country', 'Country:'],"
- " ['phone', 'Phone number:'],"
- " ];"
- ""
- " for (var i = 0; i < elements.length; i++) {"
- " var name = elements[i][0];"
- " var label = elements[i][1];"
- " AddElement(name, label);"
- " }"
- "};"
- "</script>")));
-
- // Dynamically construct the form.
- ASSERT_TRUE(content::ExecuteScript(render_view_host(), "BuildForm();"));
-
- // Invoke Autofill.
- TryBasicFormFill();
-}
-
-// Test that form filling works after reloading the current page.
-// This test brought to you by http://crbug.com/69204
-#if defined(OS_MACOSX)
-// Now flaky on everything but mac.
-// http://crbug.com/150084
-#define MAYBE_AutofillAfterReload AutofillAfterReload
-#else
-#define MAYBE_AutofillAfterReload DISABLED_AutofillAfterReload
-#endif
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_AutofillAfterReload) {
- LOG(WARNING) << "Creating test profile.";
- CreateTestProfile();
-
- // Load the test page.
- LOG(WARNING) << "Bringing browser window to front.";
- LOG(WARNING) << "Navigating to URL.";
- ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
- GURL(std::string(kDataURIPrefix) + kTestFormString)));
-
- // Reload the page.
- LOG(WARNING) << "Reloading the page.";
- content::WebContents* web_contents =
- browser()->tab_strip_model()->GetActiveWebContents();
- web_contents->GetController().Reload(false);
- content::WaitForLoadStop(web_contents);
-
- // Invoke Autofill.
- LOG(WARNING) << "Trying to fill the form.";
- TryBasicFormFill();
-}
-
-// DISABLED: http://crbug.com/150084
-IN_PROC_BROWSER_TEST_F(AutofillTest, DISABLED_AutofillAfterTranslate) {
- CreateTestProfile();
-
- GURL url(std::string(kDataURIPrefix) +
- "<form action=\"http://www.example.com/\" method=\"POST\">"
- "<label for=\"fn\">なまえ</label>"
- " <input type=\"text\" id=\"fn\""
- " onFocus=\"domAutomationController.send(true)\""
- "><br>"
- "<label for=\"ln\">みょうじ</label>"
- " <input type=\"text\" id=\"ln\"><br>"
- "<label for=\"a1\">Address line 1:</label>"
- " <input type=\"text\" id=\"a1\"><br>"
- "<label for=\"a2\">Address line 2:</label>"
- " <input type=\"text\" id=\"a2\"><br>"
- "<label for=\"ci\">City:</label>"
- " <input type=\"text\" id=\"ci\"><br>"
- "<label for=\"st\">State:</label>"
- " <select id=\"st\">"
- " <option value=\"\" selected=\"yes\">--</option>"
- " <option value=\"CA\">California</option>"
- " <option value=\"TX\">Texas</option>"
- " </select><br>"
- "<label for=\"z\">ZIP code:</label>"
- " <input type=\"text\" id=\"z\"><br>"
- "<label for=\"co\">Country:</label>"
- " <select id=\"co\">"
- " <option value=\"\" selected=\"yes\">--</option>"
- " <option value=\"CA\">Canada</option>"
- " <option value=\"US\">United States</option>"
- " </select><br>"
- "<label for=\"ph\">Phone number:</label>"
- " <input type=\"text\" id=\"ph\"><br>"
- "</form>");
- ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), url));
-
- // Get translation bar.
- LanguageDetectionDetails details;
- details.adopted_language = "ja";
- content::RenderViewHostTester::TestOnMessageReceived(
- render_view_host(),
- ChromeViewHostMsg_TranslateLanguageDetermined(0, details, true));
- TranslateInfoBarDelegate* delegate = InfoBarService::FromWebContents(
- browser()->tab_strip_model()->GetActiveWebContents())->infobar_at(0)->
- AsTranslateInfoBarDelegate();
- ASSERT_TRUE(delegate);
- EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE,
- delegate->infobar_type());
-
- // Simulate translation button press.
- delegate->Translate();
-
- // Simulate the translate script being retrieved.
- // Pass fake google.translate lib as the translate script.
- SimulateURLFetch(true);
-
- content::WindowedNotificationObserver translation_observer(
- chrome::NOTIFICATION_PAGE_TRANSLATED,
- content::NotificationService::AllSources());
-
- // Simulate translation to kick onTranslateElementLoad.
- // But right now, the call stucks here.
- // Once click the text field, it starts again.
- ASSERT_TRUE(content::ExecuteScript(
- render_view_host(), "cr.googleTranslate.onTranslateElementLoad();"));
-
- // Simulate the render notifying the translation has been done.
- translation_observer.Wait();
-
- TryBasicFormFill();
-}
-
// Test filling profiles with unicode strings and crazy characters.
// TODO(isherman): rewrite as unit test under PersonalDataManagerTest.
IN_PROC_BROWSER_TEST_F(AutofillTest, FillProfileCrazyCharacters) {
@@ -1273,52 +555,6 @@
ASSERT_TRUE(personal_data_manager()->GetProfiles().empty());
}
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_ComparePhoneNumbers ComparePhoneNumbers
-#else
-#define MAYBE_ComparePhoneNumbers DISABLED_ComparePhoneNumbers
-#endif
-// Test phone fields parse correctly from a given profile.
-// The high level key presses execute the following: Select the first text
-// field, invoke the autofill popup list, select the first profile within the
-// list, and commit to the profile to populate the form.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_ComparePhoneNumbers) {
- ASSERT_TRUE(test_server()->Start());
-
- AutofillProfile profile;
- profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bob"));
- profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith"));
- profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1234 H St."));
- profile.SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("San Jose"));
- profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("CA"));
- profile.SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("95110"));
- profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("1-408-555-4567"));
- SetProfile(profile);
-
- GURL url = test_server()->GetURL("files/autofill/form_phones.html");
- ui_test_utils::NavigateToURL(browser(), url);
- PopulateForm("NAME_FIRST");
-
- ExpectFieldValue("NAME_FIRST", "Bob");
- ExpectFieldValue("NAME_LAST", "Smith");
- ExpectFieldValue("ADDRESS_HOME_LINE1", "1234 H St.");
- ExpectFieldValue("ADDRESS_HOME_CITY", "San Jose");
- ExpectFieldValue("ADDRESS_HOME_STATE", "CA");
- ExpectFieldValue("ADDRESS_HOME_ZIP", "95110");
- ExpectFieldValue("PHONE_HOME_WHOLE_NUMBER", "14085554567");
- ExpectFieldValue("PHONE_HOME_CITY_CODE-1", "408");
- ExpectFieldValue("PHONE_HOME_CITY_CODE-2", "408");
- ExpectFieldValue("PHONE_HOME_NUMBER", "5554567");
- ExpectFieldValue("PHONE_HOME_NUMBER_3-1", "555");
- ExpectFieldValue("PHONE_HOME_NUMBER_3-2", "555");
- ExpectFieldValue("PHONE_HOME_NUMBER_4-1", "4567");
- ExpectFieldValue("PHONE_HOME_NUMBER_4-2", "4567");
- ExpectFieldValue("PHONE_HOME_EXT-1", std::string());
- ExpectFieldValue("PHONE_HOME_EXT-2", std::string());
- ExpectFieldValue("PHONE_HOME_COUNTRY_CODE-1", "1");
-}
-
// Test profile is saved if phone number is valid in selected country.
// The data file contains two profiles with valid phone numbers and two
// profiles with invalid phone numbers from their respective country.
@@ -1432,129 +668,6 @@
infobar_count());
}
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_NoAutofillForReadOnlyFields NoAutofillForReadOnlyFields
-#else
-#define MAYBE_NoAutofillForReadOnlyFields DISABLED_NoAutofillForReadOnlyFields
-#endif
-// Test that Autofill does not fill in read-only fields.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_NoAutofillForReadOnlyFields) {
- ASSERT_TRUE(test_server()->Start());
-
- std::string addr_line1("1234 H St.");
-
- AutofillProfile profile;
- profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bob"));
- profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith"));
- profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16("bsmith@gmail.com"));
- profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16(addr_line1));
- profile.SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("San Jose"));
- profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("CA"));
- profile.SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("95110"));
- profile.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Company X"));
- profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("408-871-4567"));
- SetProfile(profile);
-
- GURL url = test_server()->GetURL("files/autofill/read_only_field_test.html");
- ui_test_utils::NavigateToURL(browser(), url);
- PopulateForm("firstname");
-
- ExpectFieldValue("email", std::string());
- ExpectFieldValue("address", addr_line1);
-}
-
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_FormFillableOnReset FormFillableOnReset
-#else
-#define MAYBE_FormFillableOnReset DISABLED_FormFillableOnReset
-#endif
-// Test form is fillable from a profile after form was reset.
-// Steps:
-// 1. Fill form using a saved profile.
-// 2. Reset the form.
-// 3. Fill form using a saved profile.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_FormFillableOnReset) {
- ASSERT_TRUE(test_server()->Start());
-
- CreateTestProfile();
-
- GURL url = test_server()->GetURL("files/autofill/autofill_test_form.html");
- ui_test_utils::NavigateToURL(browser(), url);
- PopulateForm("NAME_FIRST");
-
- ASSERT_TRUE(content::ExecuteScript(
- browser()->tab_strip_model()->GetActiveWebContents(),
- "document.getElementById('testform').reset()"));
-
- PopulateForm("NAME_FIRST");
-
- ExpectFieldValue("NAME_FIRST", "Milton");
- ExpectFieldValue("NAME_LAST", "Waddams");
- ExpectFieldValue("EMAIL_ADDRESS", "red.swingline@initech.com");
- ExpectFieldValue("ADDRESS_HOME_LINE1", "4120 Freidrich Lane");
- ExpectFieldValue("ADDRESS_HOME_CITY", "Austin");
- ExpectFieldValue("ADDRESS_HOME_STATE", "Texas");
- ExpectFieldValue("ADDRESS_HOME_ZIP", "78744");
- ExpectFieldValue("ADDRESS_HOME_COUNTRY", "United States");
- ExpectFieldValue("PHONE_HOME_WHOLE_NUMBER", "5125551234");
-}
-
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_DistinguishMiddleInitialWithinName \
- DistinguishMiddleInitialWithinName
-#else
-#define MAYBE_DistinguishMiddleInitialWithinName \
- DISABLED_DistinguishMiddleInitialWithinName
-#endif
-// Test Autofill distinguishes a middle initial in a name.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_DistinguishMiddleInitialWithinName) {
- ASSERT_TRUE(test_server()->Start());
-
- CreateTestProfile();
-
- GURL url = test_server()->GetURL(
- "files/autofill/autofill_middleinit_form.html");
- ui_test_utils::NavigateToURL(browser(), url);
- PopulateForm("NAME_FIRST");
-
- ExpectFieldValue("NAME_MIDDLE", "C");
-}
-
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_MultipleEmailFilledByOneUserGesture \
- MultipleEmailFilledByOneUserGesture
-#else
-#define MAYBE_MultipleEmailFilledByOneUserGesture \
- DISABLED_MultipleEmailFilledByOneUserGesture
-#endif
-// Test forms with multiple email addresses are filled properly.
-// Entire form should be filled with one user gesture.
-IN_PROC_BROWSER_TEST_F(AutofillTest,
- MAYBE_MultipleEmailFilledByOneUserGesture) {
- ASSERT_TRUE(test_server()->Start());
-
- std::string email("bsmith@gmail.com");
-
- AutofillProfile profile;
- profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bob"));
- profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith"));
- profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16(email));
- profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("4088714567"));
- SetProfile(profile);
-
- GURL url = test_server()->GetURL(
- "files/autofill/autofill_confirmemail_form.html");
- ui_test_utils::NavigateToURL(browser(), url);
- PopulateForm("NAME_FIRST");
-
- ExpectFieldValue("EMAIL_CONFIRM", email);
- // TODO(isherman): verify entire form.
-}
-
// Test profile not aggregated if email found in non-email field.
IN_PROC_BROWSER_TEST_F(AutofillTest, ProfileWithEmailInOtherFieldNotSaved) {
ASSERT_TRUE(test_server()->Start());
@@ -1573,123 +686,6 @@
ASSERT_EQ(0u, personal_data_manager()->GetProfiles().size());
}
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_FormFillLatencyAfterSubmit FormFillLatencyAfterSubmit
-#else
-#define MAYBE_FormFillLatencyAfterSubmit DISABLED_FormFillLatencyAfterSubmit
-#endif
-// Test latency time on form submit with lots of stored Autofill profiles.
-// This test verifies when a profile is selected from the Autofill dictionary
-// that consists of thousands of profiles, the form does not hang after being
-// submitted.
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_FormFillLatencyAfterSubmit) {
- ASSERT_TRUE(test_server()->Start());
-
- std::vector<std::string> cities;
- cities.push_back("San Jose");
- cities.push_back("San Francisco");
- cities.push_back("Sacramento");
- cities.push_back("Los Angeles");
-
- std::vector<std::string> streets;
- streets.push_back("St");
- streets.push_back("Ave");
- streets.push_back("Ln");
- streets.push_back("Ct");
-
- const int kNumProfiles = 1500;
- base::Time start_time = base::Time::Now();
- std::vector<AutofillProfile> profiles;
- for (int i = 0; i < kNumProfiles; i++) {
- AutofillProfile profile;
- string16 name(base::IntToString16(i));
- string16 email(name + ASCIIToUTF16("@example.com"));
- string16 street = ASCIIToUTF16(
- base::IntToString(base::RandInt(0, 10000)) + " " +
- streets[base::RandInt(0, streets.size() - 1)]);
- string16 city = ASCIIToUTF16(cities[base::RandInt(0, cities.size() - 1)]);
- string16 zip(base::IntToString16(base::RandInt(0, 10000)));
- profile.SetRawInfo(NAME_FIRST, name);
- profile.SetRawInfo(EMAIL_ADDRESS, email);
- profile.SetRawInfo(ADDRESS_HOME_LINE1, street);
- profile.SetRawInfo(ADDRESS_HOME_CITY, city);
- profile.SetRawInfo(ADDRESS_HOME_STATE, WideToUTF16(L"CA"));
- profile.SetRawInfo(ADDRESS_HOME_ZIP, zip);
- profile.SetRawInfo(ADDRESS_HOME_COUNTRY, WideToUTF16(L"US"));
- profiles.push_back(profile);
- }
- SetProfiles(&profiles);
- // TODO(isherman): once we're sure this test doesn't timeout on any bots, this
- // can be removd.
- LOG(INFO) << "Created " << kNumProfiles << " profiles in " <<
- (base::Time::Now() - start_time).InSeconds() << " seconds.";
-
- GURL url = test_server()->GetURL(
- "files/autofill/latency_after_submit_test.html");
- ui_test_utils::NavigateToURL(browser(), url);
- PopulateForm("NAME_FIRST");
-
- content::WindowedNotificationObserver load_stop_observer(
- content::NOTIFICATION_LOAD_STOP,
- content::Source<content::NavigationController>(
- &browser()->tab_strip_model()->GetActiveWebContents()->
- GetController()));
-
- ASSERT_TRUE(content::ExecuteScript(
- render_view_host(),
- "document.getElementById('testform').submit();"));
- // This will ensure the test didn't hang.
- load_stop_observer.Wait();
-}
-
-// http://crbug.com/150084
-#if defined(OS_MACOSX)
-#define MAYBE_DisableAutocompleteWhileFilling DisableAutocompleteWhileFilling
-#else
-#define MAYBE_DisableAutocompleteWhileFilling \
- DISABLED_DisableAutocompleteWhileFilling
-#endif
-// Test that Chrome doesn't crash when autocomplete is disabled while the user
-// is interacting with the form. This is a regression test for
-// http://crbug.com/160476
-IN_PROC_BROWSER_TEST_F(AutofillTest, MAYBE_DisableAutocompleteWhileFilling) {
- CreateTestProfile();
-
- // Load the test page.
- ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
- GURL(std::string(kDataURIPrefix) + kTestFormString)));
-
- // Invoke Autofill: Start filling the first name field with "M" and wait for
- // the popup to be shown.
- FocusFirstNameField();
- SendKeyToPageAndWait(ui::VKEY_M);
-
- // Now that the popup with suggestions is showing, disable autocomplete for
- // the active field.
- ASSERT_TRUE(content::ExecuteScript(
- render_view_host(),
- "document.querySelector('input').autocomplete = 'off';"));
-
- // Press the down arrow to select the suggestion and attempt to preview the
- // autofilled form.
- content::NativeWebKeyboardEvent event;
- event.windowsKeyCode = ui::VKEY_DOWN;
- external_delegate()->keyboard_listener()->HandleKeyPressEvent(event);
-
- // Wait for any IPCs to complete by performing an action that generates an
- // IPC that's easy to wait for. Chrome shouldn't crash.
- bool result = false;
- ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
- render_view_host(),
- "var city = document.getElementById('city');"
- "city.onfocus = function() { domAutomationController.send(true); };"
- "city.focus()",
- &result));
- ASSERT_TRUE(result);
- SendKeyToPageAndWait(ui::VKEY_A);
-}
-
// Test that profiles merge for aggregated data with same address.
// The criterion for when two profiles are expected to be merged is when their
// 'Address Line 1' and 'City' data match. When two profiles are merged, any
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc
index 8f4f6e6..50e84ae 100644
--- a/chrome/browser/autofill/autofill_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -2,16 +2,32 @@
// 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 <string>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/rand_util.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
#include "chrome/browser/autofill/personal_data_manager_factory.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/infobars/confirm_infobar_delegate.h"
+#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/translate/translate_infobar_delegate.h"
+#include "chrome/browser/translate/translate_manager.h"
#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/render_messages.h"
#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/test_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/autofill/content/browser/autofill_driver_impl.h"
#include "components/autofill/core/browser/autofill_common_test.h"
@@ -21,22 +37,56 @@
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/personal_data_manager_observer.h"
+#include "components/autofill/core/browser/validation.h"
+#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_renderer_host.h"
#include "content/public/test/test_utils.h"
+#include "net/url_request/test_url_fetcher_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/keycodes/keyboard_codes.h"
-// TODO(csharp): Most of this file was just copied from autofill_browsertests.cc
-// The repeated code should be moved into a helper file, instead of being
-// repeated.
-
namespace autofill {
+static const char* kDataURIPrefix = "data:text/html;charset=utf-8,";
+static const char* kTestFormString =
+ "<form action=\"http://www.example.com/\" method=\"POST\">"
+ "<label for=\"firstname\">First name:</label>"
+ " <input type=\"text\" id=\"firstname\""
+ " onFocus=\"domAutomationController.send(true)\"><br>"
+ "<label for=\"lastname\">Last name:</label>"
+ " <input type=\"text\" id=\"lastname\"><br>"
+ "<label for=\"address1\">Address line 1:</label>"
+ " <input type=\"text\" id=\"address1\"><br>"
+ "<label for=\"address2\">Address line 2:</label>"
+ " <input type=\"text\" id=\"address2\"><br>"
+ "<label for=\"city\">City:</label>"
+ " <input type=\"text\" id=\"city\"><br>"
+ "<label for=\"state\">State:</label>"
+ " <select id=\"state\">"
+ " <option value=\"\" selected=\"yes\">--</option>"
+ " <option value=\"CA\">California</option>"
+ " <option value=\"TX\">Texas</option>"
+ " </select><br>"
+ "<label for=\"zip\">ZIP code:</label>"
+ " <input type=\"text\" id=\"zip\"><br>"
+ "<label for=\"country\">Country:</label>"
+ " <select id=\"country\">"
+ " <option value=\"\" selected=\"yes\">--</option>"
+ " <option value=\"CA\">Canada</option>"
+ " <option value=\"US\">United States</option>"
+ " </select><br>"
+ "<label for=\"phone\">Phone number:</label>"
+ " <input type=\"text\" id=\"phone\"><br>"
+ "</form>";
+
// AutofillManagerTestDelegateImpl --------------------------------------------
@@ -48,17 +98,14 @@
// autofill::AutofillManagerTestDelegate:
virtual void DidPreviewFormData() OVERRIDE {
- LOG(INFO) << "DidPreviewFormData";
loop_runner_->Quit();
}
virtual void DidFillFormData() OVERRIDE {
- LOG(INFO) << "DidFillFormData";
loop_runner_->Quit();
}
virtual void DidShowSuggestions() OVERRIDE {
- LOG(INFO) << "DidShowSuggestions";
loop_runner_->Quit();
}
@@ -67,7 +114,6 @@
}
void Wait() {
- LOG(INFO) << "Wait";
loop_runner_->Run();
}
@@ -251,6 +297,30 @@
observer.Wait();
}
+ void SetProfiles(std::vector<AutofillProfile>* profiles) {
+ WindowedPersonalDataManagerObserver observer(browser());
+ GetPersonalDataManager()->SetProfiles(profiles);
+ observer.Wait();
+ }
+
+ void SetProfile(const AutofillProfile& profile) {
+ std::vector<AutofillProfile> profiles;
+ profiles.push_back(profile);
+ SetProfiles(&profiles);
+ }
+
+ // Populates a webpage form using autofill data and keypress events.
+ // This function focuses the specified input field in the form, and then
+ // sends keypress events to the tab to cause the form to be populated.
+ void PopulateForm(const std::string& field_id) {
+ std::string js("document.getElementById('" + field_id + "').focus();");
+ ASSERT_TRUE(content::ExecuteScript(GetRenderViewHost(), js));
+
+ SendKeyToPageAndWait(ui::VKEY_DOWN);
+ SendKeyToPopupAndWait(ui::VKEY_DOWN);
+ SendKeyToPopupAndWait(ui::VKEY_RETURN);
+ }
+
void ExpectFieldValue(const std::string& field_name,
const std::string& expected_value) {
std::string value;
@@ -262,8 +332,47 @@
EXPECT_EQ(expected_value, value);
}
+ void SimulateURLFetch(bool success) {
+ net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
+ ASSERT_TRUE(fetcher);
+ net::URLRequestStatus status;
+ status.set_status(success ? net::URLRequestStatus::SUCCESS :
+ net::URLRequestStatus::FAILED);
+
+ std::string script = " var google = {};"
+ "google.translate = (function() {"
+ " return {"
+ " TranslateService: function() {"
+ " return {"
+ " isAvailable : function() {"
+ " return true;"
+ " },"
+ " restore : function() {"
+ " return;"
+ " },"
+ " getDetectedLanguage : function() {"
+ " return \"ja\";"
+ " },"
+ " translatePage : function(originalLang, targetLang,"
+ " onTranslateProgress) {"
+ " document.getElementsByTagName(\"body\")[0].innerHTML = '" +
+ std::string(kTestFormString) +
+ " ';"
+ " onTranslateProgress(100, true, false);"
+ " }"
+ " };"
+ " }"
+ " };"
+ "})();";
+
+ fetcher->set_url(fetcher->GetOriginalURL());
+ fetcher->set_status(status);
+ fetcher->set_response_code(success ? 200 : 500);
+ fetcher->SetResponseString(script);
+ fetcher->delegate()->OnURLFetchComplete(fetcher);
+ }
+
void FocusFirstNameField() {
- LOG(WARNING) << "Focusing the first name field.";
bool result = false;
ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
GetRenderViewHost(),
@@ -288,8 +397,6 @@
}
void SendKeyToPageAndWait(ui::KeyboardCode key) {
- LOG(INFO) << "SendKeyToPageAndWait";
-
test_delegate_.Reset();
content::SimulateKeyPress(
browser()->tab_strip_model()->GetActiveWebContents(),
@@ -307,60 +414,92 @@
test_delegate_.Wait();
}
+ void TryBasicFormFill() {
+ FocusFirstNameField();
+
+ // Start filling the first name field with "M" and wait for the popup to be
+ // shown.
+ SendKeyToPageAndWait(ui::VKEY_M);
+
+ // Press the down arrow to select the suggestion and preview the autofilled
+ // form.
+ SendKeyToPopupAndWait(ui::VKEY_DOWN);
+
+ // The previewed values should not be accessible to JavaScript.
+ ExpectFieldValue("firstname", "M");
+ ExpectFieldValue("lastname", std::string());
+ ExpectFieldValue("address1", std::string());
+ ExpectFieldValue("address2", std::string());
+ ExpectFieldValue("city", std::string());
+ ExpectFieldValue("state", std::string());
+ ExpectFieldValue("zip", std::string());
+ ExpectFieldValue("country", std::string());
+ ExpectFieldValue("phone", std::string());
+ // TODO(isherman): It would be nice to test that the previewed values are
+ // displayed: http://crbug.com/57220
+
+ // Press Enter to accept the autofill suggestions.
+ SendKeyToPopupAndWait(ui::VKEY_RETURN);
+
+ // The form should be filled.
+ ExpectFilledTestForm();
+ }
+
private:
AutofillManagerTestDelegateImpl test_delegate_;
+ net::TestURLFetcherFactory url_fetcher_factory_;
+
DISALLOW_COPY_AND_ASSIGN(AutofillInteractiveTest);
};
-
-// Actual tests ---------------------------------------------------------------
-
-// Potentially flaky, see http://crbug.com/150084
-IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, DISABLED_AutofillSelectViaTab) {
+// Test that basic form fill is working.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, BasicFormFill) {
CreateTestProfile();
// Load the test page.
- const char kDataURIPrefix[] = "data:text/html;charset=utf-8,";
- const char kTestFormString[] =
- "<form action=\"http://www.example.com/\" method=\"POST\">"
- "<label for=\"firstname\">First name:</label>"
- " <input type=\"text\" id=\"firstname\""
- " onFocus=\"domAutomationController.send(true)\"><br>"
- "<label for=\"lastname\">Last name:</label>"
- " <input type=\"text\" id=\"lastname\"><br>"
- "<label for=\"address1\">Address line 1:</label>"
- " <input type=\"text\" id=\"address1\"><br>"
- "<label for=\"address2\">Address line 2:</label>"
- " <input type=\"text\" id=\"address2\"><br>"
- "<label for=\"city\">City:</label>"
- " <input type=\"text\" id=\"city\"><br>"
- "<label for=\"state\">State:</label>"
- " <select id=\"state\">"
- " <option value=\"\" selected=\"yes\">--</option>"
- " <option value=\"CA\">California</option>"
- " <option value=\"TX\">Texas</option>"
- " </select><br>"
- "<label for=\"zip\">ZIP code:</label>"
- " <input type=\"text\" id=\"zip\"><br>"
- "<label for=\"country\">Country:</label>"
- " <select id=\"country\">"
- " <option value=\"\" selected=\"yes\">--</option>"
- " <option value=\"CA\">Canada</option>"
- " <option value=\"US\">United States</option>"
- " </select><br>"
- "<label for=\"phone\">Phone number:</label>"
- " <input type=\"text\" id=\"phone\"><br>"
- "</form>";
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+ GURL(std::string(kDataURIPrefix) + kTestFormString)));
+
+ // Invoke Autofill.
+ TryBasicFormFill();
+}
+
+// Test that form filling can be initiated by pressing the down arrow.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillViaDownArrow) {
+ CreateTestProfile();
+
+ // Load the test page.
ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
GURL(std::string(kDataURIPrefix) + kTestFormString)));
// Focus a fillable field.
FocusFirstNameField();
- // Enable all logging to help track down the flakiness.
- // TODO(csharp): Remove once this flakiness is fixed.
- logging::SetMinLogLevel(0);
+ // Press the down arrow to initiate Autofill and wait for the popup to be
+ // shown.
+ SendKeyToPageAndWait(ui::VKEY_DOWN);
+
+ // Press the down arrow to select the suggestion and preview the autofilled
+ // form.
+ SendKeyToPopupAndWait(ui::VKEY_DOWN);
+
+ // Press Enter to accept the autofill suggestions.
+ SendKeyToPopupAndWait(ui::VKEY_RETURN);
+
+ // The form should be filled.
+ ExpectFilledTestForm();
+}
+
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillSelectViaTab) {
+ CreateTestProfile();
+
+ // Load the test page.
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+ GURL(std::string(kDataURIPrefix) + kTestFormString)));
+
+ // Focus a fillable field.
+ FocusFirstNameField();
// Press the down arrow to initiate Autofill and wait for the popup to be
// shown.
@@ -377,4 +516,631 @@
ExpectFilledTestForm();
}
+// Test that a JavaScript onchange event is fired after auto-filling a form.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, OnChangeAfterAutofill) {
+ CreateTestProfile();
+
+ const char* kOnChangeScript =
+ "<script>"
+ "focused_fired = false;"
+ "unfocused_fired = false;"
+ "changed_select_fired = false;"
+ "unchanged_select_fired = false;"
+ "document.getElementById('firstname').onchange = function() {"
+ " focused_fired = true;"
+ "};"
+ "document.getElementById('lastname').onchange = function() {"
+ " unfocused_fired = true;"
+ "};"
+ "document.getElementById('state').onchange = function() {"
+ " changed_select_fired = true;"
+ "};"
+ "document.getElementById('country').onchange = function() {"
+ " unchanged_select_fired = true;"
+ "};"
+ "document.getElementById('country').value = 'US';"
+ "</script>";
+
+ // Load the test page.
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+ GURL(std::string(kDataURIPrefix) + kTestFormString + kOnChangeScript)));
+
+ // Invoke Autofill.
+ FocusFirstNameField();
+
+ // Start filling the first name field with "M" and wait for the popup to be
+ // shown.
+ SendKeyToPageAndWait(ui::VKEY_M);
+
+ // Press the down arrow to select the suggestion and preview the autofilled
+ // form.
+ SendKeyToPopupAndWait(ui::VKEY_DOWN);
+
+ // Press Enter to accept the autofill suggestions.
+ SendKeyToPopupAndWait(ui::VKEY_RETURN);
+
+ // The form should be filled.
+ ExpectFilledTestForm();
+
+ // The change event should have already fired for unfocused fields, both of
+ // <input> and of <select> type. However, it should not yet have fired for the
+ // focused field.
+ bool focused_fired = false;
+ bool unfocused_fired = false;
+ bool changed_select_fired = false;
+ bool unchanged_select_fired = false;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ GetRenderViewHost(),
+ "domAutomationController.send(focused_fired);",
+ &focused_fired));
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ GetRenderViewHost(),
+ "domAutomationController.send(unfocused_fired);",
+ &unfocused_fired));
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ GetRenderViewHost(),
+ "domAutomationController.send(changed_select_fired);",
+ &changed_select_fired));
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ GetRenderViewHost(),
+ "domAutomationController.send(unchanged_select_fired);",
+ &unchanged_select_fired));
+ EXPECT_FALSE(focused_fired);
+ EXPECT_TRUE(unfocused_fired);
+ EXPECT_TRUE(changed_select_fired);
+ EXPECT_FALSE(unchanged_select_fired);
+
+ // Unfocus the first name field. Its change event should fire.
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ GetRenderViewHost(),
+ "document.getElementById('firstname').blur();"
+ "domAutomationController.send(focused_fired);", &focused_fired));
+ EXPECT_TRUE(focused_fired);
+}
+
+// Test that we can autofill forms distinguished only by their |id| attribute.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
+ AutofillFormsDistinguishedById) {
+ CreateTestProfile();
+
+ // Load the test page.
+ const std::string kURL =
+ std::string(kDataURIPrefix) + kTestFormString +
+ "<script>"
+ "var mainForm = document.forms[0];"
+ "mainForm.id = 'mainForm';"
+ "var newForm = document.createElement('form');"
+ "newForm.action = mainForm.action;"
+ "newForm.method = mainForm.method;"
+ "newForm.id = 'newForm';"
+ "mainForm.parentNode.insertBefore(newForm, mainForm);"
+ "</script>";
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), GURL(kURL)));
+
+ // Invoke Autofill.
+ TryBasicFormFill();
+}
+
+// Test that we properly autofill forms with repeated fields.
+// In the wild, the repeated fields are typically either email fields
+// (duplicated for "confirmation"); or variants that are hot-swapped via
+// JavaScript, with only one actually visible at any given time.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillFormWithRepeatedField) {
+ CreateTestProfile();
+
+ // Load the test page.
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+ GURL(std::string(kDataURIPrefix) +
+ "<form action=\"http://www.example.com/\" method=\"POST\">"
+ "<label for=\"firstname\">First name:</label>"
+ " <input type=\"text\" id=\"firstname\""
+ " onFocus=\"domAutomationController.send(true)\"><br>"
+ "<label for=\"lastname\">Last name:</label>"
+ " <input type=\"text\" id=\"lastname\"><br>"
+ "<label for=\"address1\">Address line 1:</label>"
+ " <input type=\"text\" id=\"address1\"><br>"
+ "<label for=\"address2\">Address line 2:</label>"
+ " <input type=\"text\" id=\"address2\"><br>"
+ "<label for=\"city\">City:</label>"
+ " <input type=\"text\" id=\"city\"><br>"
+ "<label for=\"state\">State:</label>"
+ " <select id=\"state\">"
+ " <option value=\"\" selected=\"yes\">--</option>"
+ " <option value=\"CA\">California</option>"
+ " <option value=\"TX\">Texas</option>"
+ " </select><br>"
+ "<label for=\"state_freeform\" style=\"display:none\">State:</label>"
+ " <input type=\"text\" id=\"state_freeform\""
+ " style=\"display:none\"><br>"
+ "<label for=\"zip\">ZIP code:</label>"
+ " <input type=\"text\" id=\"zip\"><br>"
+ "<label for=\"country\">Country:</label>"
+ " <select id=\"country\">"
+ " <option value=\"\" selected=\"yes\">--</option>"
+ " <option value=\"CA\">Canada</option>"
+ " <option value=\"US\">United States</option>"
+ " </select><br>"
+ "<label for=\"phone\">Phone number:</label>"
+ " <input type=\"text\" id=\"phone\"><br>"
+ "</form>")));
+
+ // Invoke Autofill.
+ TryBasicFormFill();
+ ExpectFieldValue("state_freeform", std::string());
+}
+
+// Test that we properly autofill forms with non-autofillable fields.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
+ AutofillFormWithNonAutofillableField) {
+ CreateTestProfile();
+
+ // Load the test page.
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+ GURL(std::string(kDataURIPrefix) +
+ "<form action=\"http://www.example.com/\" method=\"POST\">"
+ "<label for=\"firstname\">First name:</label>"
+ " <input type=\"text\" id=\"firstname\""
+ " onFocus=\"domAutomationController.send(true)\"><br>"
+ "<label for=\"middlename\">Middle name:</label>"
+ " <input type=\"text\" id=\"middlename\" autocomplete=\"off\" /><br>"
+ "<label for=\"lastname\">Last name:</label>"
+ " <input type=\"text\" id=\"lastname\"><br>"
+ "<label for=\"address1\">Address line 1:</label>"
+ " <input type=\"text\" id=\"address1\"><br>"
+ "<label for=\"address2\">Address line 2:</label>"
+ " <input type=\"text\" id=\"address2\"><br>"
+ "<label for=\"city\">City:</label>"
+ " <input type=\"text\" id=\"city\"><br>"
+ "<label for=\"state\">State:</label>"
+ " <select id=\"state\">"
+ " <option value=\"\" selected=\"yes\">--</option>"
+ " <option value=\"CA\">California</option>"
+ " <option value=\"TX\">Texas</option>"
+ " </select><br>"
+ "<label for=\"zip\">ZIP code:</label>"
+ " <input type=\"text\" id=\"zip\"><br>"
+ "<label for=\"country\">Country:</label>"
+ " <select id=\"country\">"
+ " <option value=\"\" selected=\"yes\">--</option>"
+ " <option value=\"CA\">Canada</option>"
+ " <option value=\"US\">United States</option>"
+ " </select><br>"
+ "<label for=\"phone\">Phone number:</label>"
+ " <input type=\"text\" id=\"phone\"><br>"
+ "</form>")));
+
+ // Invoke Autofill.
+ TryBasicFormFill();
+}
+
+// Test that we can Autofill dynamically generated forms.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, DynamicFormFill) {
+ CreateTestProfile();
+
+ // Load the test page.
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+ GURL(std::string(kDataURIPrefix) +
+ "<form id=\"form\" action=\"http://www.example.com/\""
+ " method=\"POST\"></form>"
+ "<script>"
+ "function AddElement(name, label) {"
+ " var form = document.getElementById('form');"
+ ""
+ " var label_text = document.createTextNode(label);"
+ " var label_element = document.createElement('label');"
+ " label_element.setAttribute('for', name);"
+ " label_element.appendChild(label_text);"
+ " form.appendChild(label_element);"
+ ""
+ " if (name === 'state' || name === 'country') {"
+ " var select_element = document.createElement('select');"
+ " select_element.setAttribute('id', name);"
+ " select_element.setAttribute('name', name);"
+ ""
+ " /* Add an empty selected option. */"
+ " var default_option = new Option('--', '', true);"
+ " select_element.appendChild(default_option);"
+ ""
+ " /* Add the other options. */"
+ " if (name == 'state') {"
+ " var option1 = new Option('California', 'CA');"
+ " select_element.appendChild(option1);"
+ " var option2 = new Option('Texas', 'TX');"
+ " select_element.appendChild(option2);"
+ " } else {"
+ " var option1 = new Option('Canada', 'CA');"
+ " select_element.appendChild(option1);"
+ " var option2 = new Option('United States', 'US');"
+ " select_element.appendChild(option2);"
+ " }"
+ ""
+ " form.appendChild(select_element);"
+ " } else {"
+ " var input_element = document.createElement('input');"
+ " input_element.setAttribute('id', name);"
+ " input_element.setAttribute('name', name);"
+ ""
+ " /* Add the onFocus listener to the 'firstname' field. */"
+ " if (name === 'firstname') {"
+ " input_element.setAttribute("
+ " 'onFocus', 'domAutomationController.send(true)');"
+ " }"
+ ""
+ " form.appendChild(input_element);"
+ " }"
+ ""
+ " form.appendChild(document.createElement('br'));"
+ "};"
+ ""
+ "function BuildForm() {"
+ " var elements = ["
+ " ['firstname', 'First name:'],"
+ " ['lastname', 'Last name:'],"
+ " ['address1', 'Address line 1:'],"
+ " ['address2', 'Address line 2:'],"
+ " ['city', 'City:'],"
+ " ['state', 'State:'],"
+ " ['zip', 'ZIP code:'],"
+ " ['country', 'Country:'],"
+ " ['phone', 'Phone number:'],"
+ " ];"
+ ""
+ " for (var i = 0; i < elements.length; i++) {"
+ " var name = elements[i][0];"
+ " var label = elements[i][1];"
+ " AddElement(name, label);"
+ " }"
+ "};"
+ "</script>")));
+
+ // Dynamically construct the form.
+ ASSERT_TRUE(content::ExecuteScript(GetRenderViewHost(), "BuildForm();"));
+
+ // Invoke Autofill.
+ TryBasicFormFill();
+}
+
+// Test that form filling works after reloading the current page.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, AutofillAfterReload) {
+ CreateTestProfile();
+
+ // Load the test page.
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+ GURL(std::string(kDataURIPrefix) + kTestFormString)));
+
+ // Reload the page.
+ content::WebContents* web_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ web_contents->GetController().Reload(false);
+ content::WaitForLoadStop(web_contents);
+
+ // Invoke Autofill.
+ TryBasicFormFill();
+}
+
+// DISABLED: http://crbug.com/150084
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
+ DISABLED_AutofillAfterTranslate) {
+ CreateTestProfile();
+
+ GURL url(std::string(kDataURIPrefix) +
+ "<form action=\"http://www.example.com/\" method=\"POST\">"
+ "<label for=\"fn\">なまえ</label>"
+ " <input type=\"text\" id=\"fn\""
+ " onFocus=\"domAutomationController.send(true)\""
+ "><br>"
+ "<label for=\"ln\">みょうじ</label>"
+ " <input type=\"text\" id=\"ln\"><br>"
+ "<label for=\"a1\">Address line 1:</label>"
+ " <input type=\"text\" id=\"a1\"><br>"
+ "<label for=\"a2\">Address line 2:</label>"
+ " <input type=\"text\" id=\"a2\"><br>"
+ "<label for=\"ci\">City:</label>"
+ " <input type=\"text\" id=\"ci\"><br>"
+ "<label for=\"st\">State:</label>"
+ " <select id=\"st\">"
+ " <option value=\"\" selected=\"yes\">--</option>"
+ " <option value=\"CA\">California</option>"
+ " <option value=\"TX\">Texas</option>"
+ " </select><br>"
+ "<label for=\"z\">ZIP code:</label>"
+ " <input type=\"text\" id=\"z\"><br>"
+ "<label for=\"co\">Country:</label>"
+ " <select id=\"co\">"
+ " <option value=\"\" selected=\"yes\">--</option>"
+ " <option value=\"CA\">Canada</option>"
+ " <option value=\"US\">United States</option>"
+ " </select><br>"
+ "<label for=\"ph\">Phone number:</label>"
+ " <input type=\"text\" id=\"ph\"><br>"
+ "</form>");
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), url));
+
+ // Get translation bar.
+ LanguageDetectionDetails details;
+ details.adopted_language = "ja";
+ content::RenderViewHostTester::TestOnMessageReceived(
+ GetRenderViewHost(),
+ ChromeViewHostMsg_TranslateLanguageDetermined(0, details, true));
+ TranslateInfoBarDelegate* delegate = InfoBarService::FromWebContents(
+ browser()->tab_strip_model()->GetActiveWebContents())->infobar_at(0)->
+ AsTranslateInfoBarDelegate();
+ ASSERT_TRUE(delegate);
+ EXPECT_EQ(TranslateInfoBarDelegate::BEFORE_TRANSLATE,
+ delegate->infobar_type());
+
+ // Simulate translation button press.
+ delegate->Translate();
+
+ // Simulate the translate script being retrieved.
+ // Pass fake google.translate lib as the translate script.
+ SimulateURLFetch(true);
+
+ content::WindowedNotificationObserver translation_observer(
+ chrome::NOTIFICATION_PAGE_TRANSLATED,
+ content::NotificationService::AllSources());
+
+ // Simulate translation to kick onTranslateElementLoad.
+ // But right now, the call stucks here.
+ // Once click the text field, it starts again.
+ ASSERT_TRUE(content::ExecuteScript(
+ GetRenderViewHost(), "cr.googleTranslate.onTranslateElementLoad();"));
+
+ // Simulate the render notifying the translation has been done.
+ translation_observer.Wait();
+
+ TryBasicFormFill();
+}
+
+// Test phone fields parse correctly from a given profile.
+// The high level key presses execute the following: Select the first text
+// field, invoke the autofill popup list, select the first profile within the
+// list, and commit to the profile to populate the form.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, ComparePhoneNumbers) {
+ ASSERT_TRUE(test_server()->Start());
+
+ AutofillProfile profile;
+ profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bob"));
+ profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith"));
+ profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1234 H St."));
+ profile.SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("San Jose"));
+ profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("CA"));
+ profile.SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("95110"));
+ profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("1-408-555-4567"));
+ SetProfile(profile);
+
+ GURL url = test_server()->GetURL("files/autofill/form_phones.html");
+ ui_test_utils::NavigateToURL(browser(), url);
+ PopulateForm("NAME_FIRST");
+
+ ExpectFieldValue("NAME_FIRST", "Bob");
+ ExpectFieldValue("NAME_LAST", "Smith");
+ ExpectFieldValue("ADDRESS_HOME_LINE1", "1234 H St.");
+ ExpectFieldValue("ADDRESS_HOME_CITY", "San Jose");
+ ExpectFieldValue("ADDRESS_HOME_STATE", "CA");
+ ExpectFieldValue("ADDRESS_HOME_ZIP", "95110");
+ ExpectFieldValue("PHONE_HOME_WHOLE_NUMBER", "14085554567");
+ ExpectFieldValue("PHONE_HOME_CITY_CODE-1", "408");
+ ExpectFieldValue("PHONE_HOME_CITY_CODE-2", "408");
+ ExpectFieldValue("PHONE_HOME_NUMBER", "5554567");
+ ExpectFieldValue("PHONE_HOME_NUMBER_3-1", "555");
+ ExpectFieldValue("PHONE_HOME_NUMBER_3-2", "555");
+ ExpectFieldValue("PHONE_HOME_NUMBER_4-1", "4567");
+ ExpectFieldValue("PHONE_HOME_NUMBER_4-2", "4567");
+ ExpectFieldValue("PHONE_HOME_EXT-1", std::string());
+ ExpectFieldValue("PHONE_HOME_EXT-2", std::string());
+ ExpectFieldValue("PHONE_HOME_COUNTRY_CODE-1", "1");
+}
+
+// Test that Autofill does not fill in read-only fields.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, NoAutofillForReadOnlyFields) {
+ ASSERT_TRUE(test_server()->Start());
+
+ std::string addr_line1("1234 H St.");
+
+ AutofillProfile profile;
+ profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bob"));
+ profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith"));
+ profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16("bsmith@gmail.com"));
+ profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16(addr_line1));
+ profile.SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("San Jose"));
+ profile.SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("CA"));
+ profile.SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("95110"));
+ profile.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Company X"));
+ profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("408-871-4567"));
+ SetProfile(profile);
+
+ GURL url = test_server()->GetURL("files/autofill/read_only_field_test.html");
+ ui_test_utils::NavigateToURL(browser(), url);
+ PopulateForm("firstname");
+
+ ExpectFieldValue("email", std::string());
+ ExpectFieldValue("address", addr_line1);
+}
+
+// Test form is fillable from a profile after form was reset.
+// Steps:
+// 1. Fill form using a saved profile.
+// 2. Reset the form.
+// 3. Fill form using a saved profile.
+// Flakily times out: http://crbug.com/270341
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, DISABLED_FormFillableOnReset) {
+ ASSERT_TRUE(test_server()->Start());
+
+ CreateTestProfile();
+
+ GURL url = test_server()->GetURL("files/autofill/autofill_test_form.html");
+ ui_test_utils::NavigateToURL(browser(), url);
+ PopulateForm("NAME_FIRST");
+
+ ASSERT_TRUE(content::ExecuteScript(
+ browser()->tab_strip_model()->GetActiveWebContents(),
+ "document.getElementById('testform').reset()"));
+
+ PopulateForm("NAME_FIRST");
+
+ ExpectFieldValue("NAME_FIRST", "Milton");
+ ExpectFieldValue("NAME_LAST", "Waddams");
+ ExpectFieldValue("EMAIL_ADDRESS", "red.swingline@initech.com");
+ ExpectFieldValue("ADDRESS_HOME_LINE1", "4120 Freidrich Lane");
+ ExpectFieldValue("ADDRESS_HOME_CITY", "Austin");
+ ExpectFieldValue("ADDRESS_HOME_STATE", "Texas");
+ ExpectFieldValue("ADDRESS_HOME_ZIP", "78744");
+ ExpectFieldValue("ADDRESS_HOME_COUNTRY", "United States");
+ ExpectFieldValue("PHONE_HOME_WHOLE_NUMBER", "5125551234");
+}
+
+// Test Autofill distinguishes a middle initial in a name.
+// Flakily times out: http://crbug.com/270341
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
+ DISABLED_DistinguishMiddleInitialWithinName) {
+ ASSERT_TRUE(test_server()->Start());
+
+ CreateTestProfile();
+
+ GURL url = test_server()->GetURL(
+ "files/autofill/autofill_middleinit_form.html");
+ ui_test_utils::NavigateToURL(browser(), url);
+ PopulateForm("NAME_FIRST");
+
+ ExpectFieldValue("NAME_MIDDLE", "C");
+}
+
+// Test forms with multiple email addresses are filled properly.
+// Entire form should be filled with one user gesture.
+// Flakily times out: http://crbug.com/270341
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
+ DISABLED_MultipleEmailFilledByOneUserGesture) {
+ ASSERT_TRUE(test_server()->Start());
+
+ std::string email("bsmith@gmail.com");
+
+ AutofillProfile profile;
+ profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Bob"));
+ profile.SetRawInfo(NAME_LAST, ASCIIToUTF16("Smith"));
+ profile.SetRawInfo(EMAIL_ADDRESS, ASCIIToUTF16(email));
+ profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("4088714567"));
+ SetProfile(profile);
+
+ GURL url = test_server()->GetURL(
+ "files/autofill/autofill_confirmemail_form.html");
+ ui_test_utils::NavigateToURL(browser(), url);
+ PopulateForm("NAME_FIRST");
+
+ ExpectFieldValue("EMAIL_CONFIRM", email);
+ // TODO(isherman): verify entire form.
+}
+
+// http://crbug.com/150084
+#if defined(OS_MACOSX)
+#define MAYBE_FormFillLatencyAfterSubmit FormFillLatencyAfterSubmit
+#else
+#define MAYBE_FormFillLatencyAfterSubmit DISABLED_FormFillLatencyAfterSubmit
+#endif
+// Test latency time on form submit with lots of stored Autofill profiles.
+// This test verifies when a profile is selected from the Autofill dictionary
+// that consists of thousands of profiles, the form does not hang after being
+// submitted.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
+ MAYBE_FormFillLatencyAfterSubmit) {
+ ASSERT_TRUE(test_server()->Start());
+
+ std::vector<std::string> cities;
+ cities.push_back("San Jose");
+ cities.push_back("San Francisco");
+ cities.push_back("Sacramento");
+ cities.push_back("Los Angeles");
+
+ std::vector<std::string> streets;
+ streets.push_back("St");
+ streets.push_back("Ave");
+ streets.push_back("Ln");
+ streets.push_back("Ct");
+
+ const int kNumProfiles = 1500;
+ base::Time start_time = base::Time::Now();
+ std::vector<AutofillProfile> profiles;
+ for (int i = 0; i < kNumProfiles; i++) {
+ AutofillProfile profile;
+ string16 name(base::IntToString16(i));
+ string16 email(name + ASCIIToUTF16("@example.com"));
+ string16 street = ASCIIToUTF16(
+ base::IntToString(base::RandInt(0, 10000)) + " " +
+ streets[base::RandInt(0, streets.size() - 1)]);
+ string16 city = ASCIIToUTF16(cities[base::RandInt(0, cities.size() - 1)]);
+ string16 zip(base::IntToString16(base::RandInt(0, 10000)));
+ profile.SetRawInfo(NAME_FIRST, name);
+ profile.SetRawInfo(EMAIL_ADDRESS, email);
+ profile.SetRawInfo(ADDRESS_HOME_LINE1, street);
+ profile.SetRawInfo(ADDRESS_HOME_CITY, city);
+ profile.SetRawInfo(ADDRESS_HOME_STATE, WideToUTF16(L"CA"));
+ profile.SetRawInfo(ADDRESS_HOME_ZIP, zip);
+ profile.SetRawInfo(ADDRESS_HOME_COUNTRY, WideToUTF16(L"US"));
+ profiles.push_back(profile);
+ }
+ SetProfiles(&profiles);
+ // TODO(isherman): once we're sure this test doesn't timeout on any bots, this
+ // can be removd.
+ LOG(INFO) << "Created " << kNumProfiles << " profiles in " <<
+ (base::Time::Now() - start_time).InSeconds() << " seconds.";
+
+ GURL url = test_server()->GetURL(
+ "files/autofill/latency_after_submit_test.html");
+ ui_test_utils::NavigateToURL(browser(), url);
+ PopulateForm("NAME_FIRST");
+
+ content::WindowedNotificationObserver load_stop_observer(
+ content::NOTIFICATION_LOAD_STOP,
+ content::Source<content::NavigationController>(
+ &browser()->tab_strip_model()->GetActiveWebContents()->
+ GetController()));
+
+ ASSERT_TRUE(content::ExecuteScript(
+ GetRenderViewHost(),
+ "document.getElementById('testform').submit();"));
+ // This will ensure the test didn't hang.
+ load_stop_observer.Wait();
+}
+
+// Test that Chrome doesn't crash when autocomplete is disabled while the user
+// is interacting with the form. This is a regression test for
+// http://crbug.com/160476
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
+ DisableAutocompleteWhileFilling) {
+ CreateTestProfile();
+
+ // Load the test page.
+ ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(),
+ GURL(std::string(kDataURIPrefix) + kTestFormString)));
+
+ // Invoke Autofill: Start filling the first name field with "M" and wait for
+ // the popup to be shown.
+ FocusFirstNameField();
+ SendKeyToPageAndWait(ui::VKEY_M);
+
+ // Now that the popup with suggestions is showing, disable autocomplete for
+ // the active field.
+ ASSERT_TRUE(content::ExecuteScript(
+ GetRenderViewHost(),
+ "document.querySelector('input').autocomplete = 'off';"));
+
+ // Press the down arrow to select the suggestion and attempt to preview the
+ // autofilled form.
+ content::NativeWebKeyboardEvent event;
+ event.windowsKeyCode = ui::VKEY_DOWN;
+ GetExternalDelegate()->keyboard_listener()->HandleKeyPressEvent(event);
+
+ // Wait for any IPCs to complete by performing an action that generates an
+ // IPC that's easy to wait for. Chrome shouldn't crash.
+ bool result = false;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ GetRenderViewHost(),
+ "var city = document.getElementById('city');"
+ "city.onfocus = function() { domAutomationController.send(true); };"
+ "city.focus()",
+ &result));
+ ASSERT_TRUE(result);
+ SendKeyToPageAndWait(ui::VKEY_A);
+}
+
} // namespace autofill
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc
index a6a3aa6..6bf6afa 100644
--- a/chrome/browser/automation/testing_automation_provider.cc
+++ b/chrome/browser/automation/testing_automation_provider.cc
@@ -3500,11 +3500,10 @@
// If the given path has a 'crx' extension, assume it is a packed extension
// and install it. Otherwise load it as an unpacked extension.
if (extension_path.MatchesExtension(FILE_PATH_LITERAL(".crx"))) {
- ExtensionInstallPrompt* client = (with_ui ?
- new ExtensionInstallPrompt(tab) :
- NULL);
+ scoped_ptr<ExtensionInstallPrompt> client(
+ with_ui ? new ExtensionInstallPrompt(tab) : NULL);
scoped_refptr<extensions::CrxInstaller> installer(
- extensions::CrxInstaller::Create(service, client));
+ extensions::CrxInstaller::Create(service, client.Pass()));
if (!with_ui)
installer->set_allow_silent_install(true);
installer->set_install_cause(extension_misc::INSTALL_CAUSE_AUTOMATION);
diff --git a/chrome/browser/bookmarks/bookmark_model_test_utils.cc b/chrome/browser/bookmarks/bookmark_model_test_utils.cc
index f04a6b5..485872e 100644
--- a/chrome/browser/bookmarks/bookmark_model_test_utils.cc
+++ b/chrome/browser/bookmarks/bookmark_model_test_utils.cc
@@ -115,7 +115,6 @@
const BookmarkNode* node,
const std::string& model_string) {
DCHECK(node);
- const std::string folder_tell(":[");
std::string::size_type start_pos = 0;
std::string::size_type end_pos =
AddNodesFromString(model, node, model_string, start_pos);
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 82aa66b..1f9c3fd 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -70,10 +70,8 @@
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/chrome_manifest_handlers.h"
+#include "chrome/common/extensions/chrome_extensions_client.h"
#include "chrome/common/extensions/extension_l10n_util.h"
-#include "chrome/common/extensions/permissions/chrome_api_permissions.h"
-#include "chrome/common/extensions/permissions/permissions_info.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/switch_utils.h"
#include "chrome/common/url_constants.h"
@@ -184,9 +182,8 @@
InitIdleMonitor();
#endif
- extensions::PermissionsInfo::GetInstance()->InitializeWithDelegate(
- extensions::ChromeAPIPermissions());
- extensions::RegisterChromeManifestHandlers();
+ extensions::ExtensionsClient::Set(
+ extensions::ChromeExtensionsClient::GetInstance());
extension_event_router_forwarder_ = new extensions::EventRouterForwarder;
ExtensionRendererState::GetInstance()->Init();
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index d6e5804..6d6a0b9 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -318,6 +318,8 @@
<include name="IDR_SIM_UNLOCK_HTML" file="resources\chromeos\sim_unlock.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_WRENCH_MENU_CSS" file="resources\chromeos\wrench_menu.css" flattenhtml="true" type="BINDATA" />
<include name="IDR_WRENCH_MENU_JS" file="resources\chromeos\wrench_menu.js" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_SLOW_HTML" file="resources\chromeos\slow.html" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_SLOW_JS" file="resources\chromeos\slow.js" type="BINDATA" />
</if>
<if expr="pp_ifdef('file_manager_extension')">
<include name="IDR_FILEMANAGER_MANIFEST" file="resources\file_manager\manifest.json" type="BINDATA" />
@@ -355,8 +357,8 @@
<include name="IDR_SET_AS_DEFAULT_BROWSER_HTML" file="resources\set_as_default_browser.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
</if>
<if expr="not is_android and not pp_ifdef('ios') and not pp_ifdef('chromeos')">
- <include name="IDR_USER_CHOOSER_JS" file="resources\user_chooser\user_chooser.js" flattenhtml="true" type="BINDATA" />
- <include name="IDR_USER_CHOOSER_HTML" file="resources\user_chooser\user_chooser.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
+ <include name="IDR_USER_MANAGER_JS" file="resources\user_manager\user_manager.js" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_USER_MANAGER_HTML" file="resources\user_manager\user_manager.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
</if>
<include name="IDR_MANAGED_MODE_BLOCK_INTERSTITIAL_HTML" file="resources\managed_mode_block_interstitial.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_PROFILE_SIGNIN_CONFIRMATION_HTML" file="resources\profile_signin_confirmation.html" type="BINDATA" />
diff --git a/chrome/browser/browsing_data/browsing_data_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_helper_unittest.cc
index 2186b44..5fe25ce 100644
--- a/chrome/browser/browsing_data/browsing_data_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_helper_unittest.cc
@@ -75,8 +75,8 @@
EXPECT_FALSE(IsWebScheme(chrome::kChromeInternalScheme));
EXPECT_FALSE(IsWebScheme(chrome::kChromeUIScheme));
EXPECT_FALSE(IsWebScheme(chrome::kJavaScriptScheme));
- EXPECT_FALSE(IsWebScheme(chrome::kMailToScheme));
- EXPECT_FALSE(IsWebScheme(chrome::kMetadataScheme));
+ EXPECT_FALSE(IsWebScheme(content::kMailToScheme));
+ EXPECT_FALSE(IsWebScheme(content::kMetadataScheme));
EXPECT_FALSE(IsWebScheme(content::kSwappedOutScheme));
EXPECT_FALSE(IsWebScheme(content::kViewSourceScheme));
}
@@ -100,8 +100,8 @@
EXPECT_FALSE(IsExtensionScheme(chrome::kChromeInternalScheme));
EXPECT_FALSE(IsExtensionScheme(chrome::kChromeUIScheme));
EXPECT_FALSE(IsExtensionScheme(chrome::kJavaScriptScheme));
- EXPECT_FALSE(IsExtensionScheme(chrome::kMailToScheme));
- EXPECT_FALSE(IsExtensionScheme(chrome::kMetadataScheme));
+ EXPECT_FALSE(IsExtensionScheme(content::kMailToScheme));
+ EXPECT_FALSE(IsExtensionScheme(content::kMetadataScheme));
EXPECT_FALSE(IsExtensionScheme(content::kSwappedOutScheme));
EXPECT_FALSE(IsExtensionScheme(content::kViewSourceScheme));
}
diff --git a/chrome/browser/browsing_data/browsing_data_remover.cc b/chrome/browser/browsing_data/browsing_data_remover.cc
index 008d5cf..0512a67 100644
--- a/chrome/browser/browsing_data/browsing_data_remover.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover.cc
@@ -25,6 +25,7 @@
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/io_thread.h"
#include "chrome/browser/nacl_host/nacl_browser.h"
+#include "chrome/browser/nacl_host/pnacl_host.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/net/predictor.h"
#include "chrome/browser/password_manager/password_store.h"
@@ -169,10 +170,12 @@
waiting_for_clear_network_predictor_(false),
waiting_for_clear_networking_history_(false),
waiting_for_clear_plugin_data_(false),
+ waiting_for_clear_pnacl_cache_(false),
waiting_for_clear_quota_managed_data_(false),
waiting_for_clear_server_bound_certs_(false),
waiting_for_clear_session_storage_(false),
waiting_for_clear_shader_cache_(false),
+ waiting_for_clear_webrtc_identity_store_(false),
remove_mask_(0),
remove_origin_(GURL()),
origin_set_mask_(0) {
@@ -529,6 +532,12 @@
BrowserThread::IO, FROM_HERE,
base::Bind(&BrowsingDataRemover::ClearNaClCacheOnIOThread,
base::Unretained(this)));
+
+ waiting_for_clear_pnacl_cache_ = true;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&BrowsingDataRemover::ClearPnaclCacheOnIOThread,
+ base::Unretained(this), delete_begin_, delete_end_));
#endif
// The PrerenderManager may have a page actively being prerendered, which
@@ -545,6 +554,15 @@
content::RecordAction(UserMetricsAction("ClearBrowsingData_ShaderCache"));
ClearShaderCacheOnUIThread();
+
+ waiting_for_clear_webrtc_identity_store_ = true;
+ BrowserContext::GetDefaultStoragePartition(profile_)->ClearDataForRange(
+ content::StoragePartition::REMOVE_DATA_MASK_WEBRTC_IDENTITY,
+ content::StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
+ delete_begin_,
+ delete_end_,
+ base::Bind(&BrowsingDataRemover::OnClearWebRTCIdentityStore,
+ base::Unretained(this)));
}
#if defined(ENABLE_PLUGINS)
@@ -617,24 +635,22 @@
}
bool BrowsingDataRemover::AllDone() {
- return registrar_.IsEmpty() &&
- !waiting_for_clear_autofill_origin_urls_ &&
- !waiting_for_clear_cache_ &&
- !waiting_for_clear_nacl_cache_ &&
- !waiting_for_clear_cookies_count_&&
- !waiting_for_clear_history_ &&
- !waiting_for_clear_local_storage_ &&
- !waiting_for_clear_logged_in_predictor_ &&
- !waiting_for_clear_session_storage_ &&
- !waiting_for_clear_networking_history_ &&
- !waiting_for_clear_server_bound_certs_ &&
- !waiting_for_clear_plugin_data_ &&
- !waiting_for_clear_quota_managed_data_ &&
- !waiting_for_clear_content_licenses_ &&
- !waiting_for_clear_form_ &&
- !waiting_for_clear_hostname_resolution_cache_ &&
- !waiting_for_clear_network_predictor_ &&
- !waiting_for_clear_shader_cache_;
+ return registrar_.IsEmpty() && !waiting_for_clear_autofill_origin_urls_ &&
+ !waiting_for_clear_cache_ && !waiting_for_clear_nacl_cache_ &&
+ !waiting_for_clear_cookies_count_ && !waiting_for_clear_history_ &&
+ !waiting_for_clear_local_storage_ &&
+ !waiting_for_clear_logged_in_predictor_ &&
+ !waiting_for_clear_session_storage_ &&
+ !waiting_for_clear_networking_history_ &&
+ !waiting_for_clear_server_bound_certs_ &&
+ !waiting_for_clear_plugin_data_ &&
+ !waiting_for_clear_pnacl_cache_ &&
+ !waiting_for_clear_quota_managed_data_ &&
+ !waiting_for_clear_content_licenses_ && !waiting_for_clear_form_ &&
+ !waiting_for_clear_hostname_resolution_cache_ &&
+ !waiting_for_clear_network_predictor_ &&
+ !waiting_for_clear_shader_cache_ &&
+ !waiting_for_clear_webrtc_identity_store_;
}
void BrowsingDataRemover::Observe(int type,
@@ -886,6 +902,36 @@
base::Bind(&BrowsingDataRemover::ClearedNaClCacheOnIOThread,
base::Unretained(this)));
}
+
+void BrowsingDataRemover::ClearedPnaclCache() {
+ // This function should be called on the UI thread.
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ waiting_for_clear_pnacl_cache_ = false;
+
+ NotifyAndDeleteIfDone();
+}
+
+void BrowsingDataRemover::ClearedPnaclCacheOnIOThread() {
+ // This function should be called on the IO thread.
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // Notify the UI thread that we are done.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&BrowsingDataRemover::ClearedPnaclCache,
+ base::Unretained(this)));
+}
+
+void BrowsingDataRemover::ClearPnaclCacheOnIOThread(base::Time begin,
+ base::Time end) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ PnaclHost::GetInstance()->ClearTranslationCacheEntriesBetween(
+ begin, end,
+ base::Bind(&BrowsingDataRemover::ClearedPnaclCacheOnIOThread,
+ base::Unretained(this)));
+}
#endif
void BrowsingDataRemover::ClearLocalStorageOnUIThread() {
@@ -1123,3 +1169,9 @@
waiting_for_clear_autofill_origin_urls_ = false;
NotifyAndDeleteIfDone();
}
+
+void BrowsingDataRemover::OnClearWebRTCIdentityStore() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ waiting_for_clear_webrtc_identity_store_ = false;
+ NotifyAndDeleteIfDone();
+}
diff --git a/chrome/browser/browsing_data/browsing_data_remover.h b/chrome/browser/browsing_data/browsing_data_remover.h
index af1b441..be29059 100644
--- a/chrome/browser/browsing_data/browsing_data_remover.h
+++ b/chrome/browser/browsing_data/browsing_data_remover.h
@@ -288,6 +288,16 @@
// Invoked on the IO thread to delete the NaCl cache.
void ClearNaClCacheOnIOThread();
+
+ // Callback for when the PNaCl translation cache has been deleted. Invokes
+ // NotifyAndDeleteIfDone.
+ void ClearedPnaclCache();
+
+ // Invokes ClearedPnaclCacheOn on the UI thread.
+ void ClearedPnaclCacheOnIOThread();
+
+ // Invoked on the IO thread to delete entries in the PNaCl translation cache.
+ void ClearPnaclCacheOnIOThread(base::Time begin, base::Time end);
#endif
// Invoked on the UI thread to delete local storage.
@@ -361,6 +371,9 @@
// Invoked on the IO thread to delete from the shader cache.
void ClearShaderCacheOnUIThread();
+ // Callback on UI thread when the WebRTC identities are cleared.
+ void OnClearWebRTCIdentityStore();
+
// Returns true if we're all done.
bool AllDone();
@@ -421,10 +434,12 @@
bool waiting_for_clear_network_predictor_;
bool waiting_for_clear_networking_history_;
bool waiting_for_clear_plugin_data_;
+ bool waiting_for_clear_pnacl_cache_;
bool waiting_for_clear_quota_managed_data_;
bool waiting_for_clear_server_bound_certs_;
bool waiting_for_clear_session_storage_;
bool waiting_for_clear_shader_cache_;
+ bool waiting_for_clear_webrtc_identity_store_;
// Tracking how many origins need to be deleted, and whether we're finished
// gathering origins.
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index bc285f0..26155b1 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -91,7 +91,6 @@
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/renderer_host/chrome_render_view_host_observer.h"
-#include "chrome/browser/search_engines/search_engine_type.h"
#include "chrome/browser/service/service_process_control.h"
#include "chrome/browser/shell_integration.h"
#include "chrome/browser/three_d_api_observer.h"
@@ -689,17 +688,17 @@
bool is_first_run = first_run::IsChromeFirstRun();
-// CurrentProcessInfo::CreationTime() is currently only implemented on Mac and
-// Windows.
-#if defined(OS_MACOSX) || defined(OS_WIN)
- const base::Time* process_creation_time =
+// CurrentProcessInfo::CreationTime() is currently only implemented on some
+// platforms.
+#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
+ const base::Time process_creation_time =
base::CurrentProcessInfo::CreationTime();
- if (!is_first_run && process_creation_time) {
+ if (!is_first_run && !process_creation_time.is_null()) {
RecordPreReadExperimentTime("Startup.BrowserMessageLoopStartTime",
- base::Time::Now() - *process_creation_time);
+ base::Time::Now() - process_creation_time);
}
-#endif // defined(OS_MACOSX) || defined(OS_WIN)
+#endif // defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
// Record collected startup metrics.
startup_metric_utils::OnBrowserStartupComplete(is_first_run);
diff --git a/chrome/browser/chrome_browser_main_linux.cc b/chrome/browser/chrome_browser_main_linux.cc
index 299154d..2e6ad60 100644
--- a/chrome/browser/chrome_browser_main_linux.cc
+++ b/chrome/browser/chrome_browser_main_linux.cc
@@ -23,6 +23,7 @@
#include "chromeos/chromeos_switches.h"
#else
#include "chrome/browser/storage_monitor/storage_monitor_linux.h"
+#include "chrome/browser/sxs_linux.h"
#include "content/public/browser/browser_thread.h"
#endif
@@ -113,6 +114,11 @@
content::BrowserThread::PostTask(content::BrowserThread::FILE,
FROM_HERE,
base::Bind(&GetLinuxDistroCallback));
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&sxs_linux::AddChannelMarkToUserDataDir));
#endif
if (IsCrashReportingEnabled(local_state()))
diff --git a/chrome/browser/chrome_browser_main_mac.mm b/chrome/browser/chrome_browser_main_mac.mm
index 3d41c65..07f250c 100644
--- a/chrome/browser/chrome_browser_main_mac.mm
+++ b/chrome/browser/chrome_browser_main_mac.mm
@@ -229,7 +229,7 @@
[[KeystoneGlue defaultKeystoneGlue] registerWithKeystone];
// Disk image installation is sort of a first-run task, so it shares the
- // kNoFirstRun switch.
+ // no first run switches.
//
// This needs to be done after the resource bundle is initialized (for
// access to localizations in the UI) and after Keystone is initialized
@@ -240,7 +240,7 @@
// anyone tries doing anything silly like firing off an import job, and
// before anything creating preferences like Local State in order for the
// relaunched installed application to still consider itself as first-run.
- if (!parsed_command_line().HasSwitch(switches::kNoFirstRun)) {
+ if (!first_run::IsFirstRunSuppressed(parsed_command_line())) {
if (MaybeInstallFromDiskImage()) {
// The application was installed and the installed copy has been
// launched. This process is now obsolete. Exit.
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 22947f0..4700b5a 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -140,7 +140,6 @@
#include "ui/message_center/message_center_util.h"
#include "webkit/browser/fileapi/external_mount_points.h"
#include "webkit/common/webpreferences.h"
-#include "webkit/plugins/plugin_switches.h"
#if defined(OS_WIN)
#include "chrome/browser/chrome_browser_main_win.h"
diff --git a/chrome/browser/chrome_notification_types.h b/chrome/browser/chrome_notification_types.h
index a4b5adc..f6ecc44 100644
--- a/chrome/browser/chrome_notification_types.h
+++ b/chrome/browser/chrome_notification_types.h
@@ -150,17 +150,6 @@
// starting and finishing all painting.
NOTIFICATION_INITIAL_NEW_TAB_UI_LOAD,
-#if defined(OS_ANDROID)
- // Indicates that the new tab page is ready. This is different than
- // NOTIFICATION_INITIAL_NEW_TAB_UI_LOAD as the NTP might do some more in-page
- // navigations after it's done loading, potentially causing flakyness in tests
- // that would navigate as soon as the NTP is done loading.
- // When this notification happen, it guarantees the page is not going to do
- // any further navigation.
- // The source is the WebContents containing the NTP.
- NOTIFICATION_NEW_TAB_READY,
-#endif
-
// Used to fire notifications about how long various events took to
// complete. E.g., this is used to get more fine grained timings from the
// new tab page. The source is a WebContents and the details is a
@@ -204,14 +193,6 @@
// match was found or not found.
NOTIFICATION_FIND_RESULT_AVAILABLE,
-#if defined(OS_ANDROID)
- // This notification is sent when the match rects of a find-in-page search
- // are available. The source is a Source<WebContents>. Details encompass a
- // FindMatchRectsDetails object that contains the result version and the
- // rects information.
- NOTIFICATION_FIND_MATCH_RECTS_AVAILABLE,
-#endif
-
// BackgroundContents ------------------------------------------------------
// A new background contents was opened by script. The source is the parent
@@ -355,9 +336,6 @@
// Task Manager ------------------------------------------------------------
- // Sent when WebUI TaskManager opens and is ready for showing tasks.
- NOTIFICATION_TASK_MANAGER_WINDOW_READY,
-
// The TaskManagerChildProcessResourceProvider collects the list of child
// processes when StartUpdating is called. This data is collected on the IO
// thread and passed back to the UI thread. Once all entries are added to the
@@ -493,9 +471,6 @@
// UpdatedExtensionPermissionsInfo, and the source is a Profile.
NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
- // Sent when an extension install turns out to not be a theme.
- NOTIFICATION_NO_THEME_DETECTED,
-
// Sent when new extensions are installed, or existing extensions are updated.
// The details are an InstalledExtensionInfo, and the source is a Profile.
NOTIFICATION_EXTENSION_INSTALLED,
@@ -657,31 +632,6 @@
// found update.
NOTIFICATION_EXTENSION_UPDATE_FOUND,
- // Component Updater -------------------------------------------------------
- //
- // The component updater notifications are deprecated and they will be
- // removed soon.
- //
- // Sent when the component updater starts doing update checks. If no
- // component has been registered for update this notification is not
- // generated. The source is the component updater itself and there are
- // no details.
- NOTIFICATION_COMPONENT_UPDATER_STARTED,
-
- // Sent when the component updater is going to take a long nap. The
- // source is the component updater itself and there are no details.
- NOTIFICATION_COMPONENT_UPDATER_SLEEPING,
-
- // Sent when there is a new version of a registered component. After
- // the notification is send the component will be downloaded. The source
- // is the id of the component and there are no details.
- NOTIFICATION_COMPONENT_UPDATE_FOUND,
-
- // Send when the new component has been downloaded and an installation
- // or upgrade is about to be attempted. The source is the id of the
- // component and there are no details.
- NOTIFICATION_COMPONENT_UPDATE_READY,
-
// Desktop Notifications ---------------------------------------------------
// This notification is sent when a balloon is connected to a renderer
@@ -923,39 +873,19 @@
// notification.
NOTIFICATION_LOGIN_WEBUI_LOADED,
- // Sent when the login screen has loaded in retail mode. The first paint event
- // after this fires NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE.
- NOTIFICATION_DEMO_WEBUI_LOADED,
-
- // Sent when the user images on the WebUI login screen have all been loaded.
- // "Normal boot" i.e. for the device with at least one user would generate
- // this one on boot. First paint event after this fires
- // NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE.
- NOTIFICATION_LOGIN_USER_IMAGES_LOADED,
-
// Sent when a network error message is displayed on the WebUI login screen.
// First paint event of this fires NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE.
NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
- // Sent when the first OOBE screen has been displayed. Note that the screen
- // may not be fully rendered at this point. First paint event after this fires
- // NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE.
- NOTIFICATION_WIZARD_FIRST_SCREEN_SHOWN,
-
// Sent when the specific part of login/lock WebUI is considered to be
// visible. That moment is tracked as the first paint event after one of the:
- // 1. NOTIFICATION_LOGIN_USER_IMAGES_LOADED
- // 2. NOTIFICATION_LOGIN_WEBUI_LOADED
- // 3. NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN
- // 4. NOTIFICATION_WIZARD_FIRST_SCREEN_SHOWN
- // 5. NOTIFICATION_DEMO_WEBUI_LOADED
+ // 1. NOTIFICATION_LOGIN_WEBUI_LOADED
+ // 2. NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN
//
// Possible series of notifications:
// 1. Boot into fresh OOBE
- // NOTIFICATION_WIZARD_FIRST_SCREEN_SHOWN
// NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
// 2. Boot into user pods list (normal boot). Same for lock screen.
- // NOTIFICATION_LOGIN_USER_IMAGES_LOADED
// NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
// 3. Boot into GAIA sign in UI (user pods display disabled or no users):
// if no network is connected or flaky network
@@ -964,7 +894,6 @@
// NOTIFICATION_LOGIN_WEBUI_LOADED
// NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
// 4. Boot into retail mode
- // NOTIFICATION_DEMO_WEBUI_LOADED
// NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE
// 5. Boot into kiosk mode
// NOTIFICATION_KIOSK_APP_LAUNCHED
@@ -1055,9 +984,6 @@
// menu has been created and shown.
NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_SHOWN,
- // Send when a context menu is closed.
- NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_CLOSED,
-
// Sent when the Instant Controller determines whether an Instant tab supports
// the Instant API or not.
NOTIFICATION_INSTANT_TAB_SUPPORT_DETERMINED,
@@ -1111,9 +1037,6 @@
NOTIFICATION_ASH_SESSION_ENDED,
#endif
- // Sent when a new web store promo has been loaded.
- NOTIFICATION_WEB_STORE_PROMO_LOADED,
-
// Protocol Handler Registry -----------------------------------------------
// Sent when a ProtocolHandlerRegistry is changed. The source is the profile.
NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
diff --git a/chrome/browser/chrome_plugin_browsertest.cc b/chrome/browser/chrome_plugin_browsertest.cc
index 5386e42..e9f3be6 100644
--- a/chrome/browser/chrome_plugin_browsertest.cc
+++ b/chrome/browser/chrome_plugin_browsertest.cc
@@ -21,13 +21,13 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/plugin_service.h"
+#include "content/public/common/content_constants.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/process_type.h"
#include "content/public/common/webplugininfo.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "net/base/net_util.h"
-#include "webkit/plugins/plugin_constants.h"
using content::BrowserThread;
@@ -109,7 +109,7 @@
std::vector<content::WebPluginInfo> plugins = GetPlugins();
for (std::vector<content::WebPluginInfo>::const_iterator it =
plugins.begin(); it != plugins.end(); ++it) {
- if (it->name == ASCIIToUTF16(kFlashPluginName))
+ if (it->name == ASCIIToUTF16(content::kFlashPluginName))
paths->push_back(it->path);
}
}
diff --git a/chrome/browser/chrome_process_finder_win.cc b/chrome/browser/chrome_process_finder_win.cc
index e1d66ee..da0f7ae 100644
--- a/chrome/browser/chrome_process_finder_win.cc
+++ b/chrome/browser/chrome_process_finder_win.cc
@@ -149,7 +149,7 @@
command_line.AppendSwitchASCII(
switches::kOriginalProcessStartTime,
base::Int64ToString(
- base::CurrentProcessInfo::CreationTime()->ToInternalValue()));
+ base::CurrentProcessInfo::CreationTime().ToInternalValue()));
if (fast_start)
command_line.AppendSwitch(switches::kFastStart);
diff --git a/chrome/browser/chromeos/app_mode/app_session_lifetime.cc b/chrome/browser/chromeos/app_mode/app_session_lifetime.cc
index 48514f0..e140e88 100644
--- a/chrome/browser/chromeos/app_mode/app_session_lifetime.cc
+++ b/chrome/browser/chromeos/app_mode/app_session_lifetime.cc
@@ -4,17 +4,17 @@
#include "chrome/browser/chromeos/app_mode/app_session_lifetime.h"
+#include "apps/shell_window_registry.h"
#include "base/basictypes.h"
#include "base/lazy_instance.h"
#include "base/prefs/pref_service.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_update_service.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/policy/browser_policy_connector.h"
#include "chrome/common/pref_names.h"
-using extensions::ShellWindowRegistry;
+using apps::ShellWindowRegistry;
namespace chromeos {
@@ -35,7 +35,7 @@
}
private:
- // extensions::ShellWindowRegistry::Observer overrides:
+ // apps::ShellWindowRegistry::Observer overrides:
virtual void OnShellWindowAdded(apps::ShellWindow* shell_window) OVERRIDE {}
virtual void OnShellWindowIconChanged(apps::ShellWindow* shell_window)
OVERRIDE {}
@@ -46,7 +46,7 @@
}
}
- extensions::ShellWindowRegistry* window_registry_;
+ apps::ShellWindowRegistry* window_registry_;
DISALLOW_COPY_AND_ASSIGN(AppWindowWatcher);
};
diff --git a/chrome/browser/chromeos/background/ash_user_wallpaper_delegate.cc b/chrome/browser/chromeos/background/ash_user_wallpaper_delegate.cc
index 16709fb..f931995 100644
--- a/chrome/browser/chromeos/background/ash_user_wallpaper_delegate.cc
+++ b/chrome/browser/chromeos/background/ash_user_wallpaper_delegate.cc
@@ -28,7 +28,8 @@
bool IsNormalWallpaperChange() {
if (chromeos::LoginState::Get()->IsUserLoggedIn() ||
- !CommandLine::ForCurrentProcess()->HasSwitch(switches::kFirstBoot) ||
+ !CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kFirstExecAfterBoot) ||
WizardController::IsZeroDelayEnabled() ||
!CommandLine::ForCurrentProcess()->HasSwitch(switches::kLoginManager)) {
return true;
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index e87caf6..d6a251e 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -32,6 +32,7 @@
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/contacts/contact_manager.h"
#include "chrome/browser/chromeos/cros/cert_library.h"
+#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/dbus/cros_dbus_service.h"
#include "chrome/browser/chromeos/display/display_configuration_observer.h"
#include "chrome/browser/chromeos/extensions/default_app_order.h"
@@ -51,9 +52,6 @@
#include "chrome/browser/chromeos/login/wallpaper_manager.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/memory/oom_priority_manager.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
-#include "chrome/browser/chromeos/net/cros_network_change_notifier_factory.h"
-#include "chrome/browser/chromeos/net/network_change_notifier_network_library.h"
#include "chrome/browser/chromeos/net/network_portal_detector.h"
#include "chrome/browser/chromeos/power/brightness_observer.h"
#include "chrome/browser/chromeos/power/idle_action_warning_observer.h"
@@ -303,12 +301,7 @@
// Initialize the network change notifier for Chrome OS. The network
// change notifier starts to monitor changes from the power manager and
// the network manager.
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- chromeos::switches::kDisableNewNetworkChangeNotifier)) {
- NetworkChangeNotifierFactoryChromeos::GetInstance()->Initialize();
- } else {
- CrosNetworkChangeNotifierFactory::GetInstance()->Init();
- }
+ NetworkChangeNotifierFactoryChromeos::GetInstance()->Initialize();
// Likewise, initialize the upgrade detector for Chrome OS. The upgrade
// detector starts to monitor changes from the update engine.
@@ -327,12 +320,9 @@
DeviceSettingsService::Get()->SetSessionManager(
DBusThreadManager::Get()->GetSessionManagerClient(),
OwnerKeyUtil::Create());
- ConnectivityStateHelper::Initialize();
}
~DBusServices() {
- ConnectivityStateHelper::Shutdown();
-
CertLibrary::Shutdown();
NetworkHandler::Shutdown();
if (network_library_initialized_)
@@ -418,18 +408,8 @@
// Replace the default NetworkChangeNotifierFactory with ChromeOS specific
// implementation. This must be done before BrowserMainLoop calls
// net::NetworkChangeNotifier::Create() in MainMessageLoopStart().
- net::NetworkChangeNotifierFactory* network_change_factory;
- // Note: At the time this is called, we have not processed about:flags
- // so this requires that the network handler flag was passed in at the command
- // line.
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- chromeos::switches::kDisableNewNetworkChangeNotifier)) {
- LOG(WARNING) << "Using new connection change notifier.";
- network_change_factory = new NetworkChangeNotifierFactoryChromeos();
- } else {
- network_change_factory = new CrosNetworkChangeNotifierFactory();
- }
- net::NetworkChangeNotifier::SetFactory(network_change_factory);
+ net::NetworkChangeNotifier::SetFactory(
+ new NetworkChangeNotifierFactoryChromeos());
ChromeBrowserMainPartsLinux::PreMainMessageLoopStart();
}
@@ -740,8 +720,6 @@
// Shutdown the network change notifier for Chrome OS. The network
// change notifier stops monitoring changes from the power manager and
// the network manager.
- if (CrosNetworkChangeNotifierFactory::GetInstance())
- CrosNetworkChangeNotifierFactory::GetInstance()->Shutdown();
if (NetworkChangeNotifierFactoryChromeos::GetInstance())
NetworkChangeNotifierFactoryChromeos::GetInstance()->Shutdown();
diff --git a/chrome/browser/chromeos/cros/network_library.cc b/chrome/browser/chromeos/cros/network_library.cc
index c84eaaa..9943d9e 100644
--- a/chrome/browser/chromeos/cros/network_library.cc
+++ b/chrome/browser/chromeos/cros/network_library.cc
@@ -15,6 +15,7 @@
#include "chrome/browser/chromeos/cros/native_network_parser.h"
#include "chrome/browser/chromeos/cros/network_library_impl_cros.h"
#include "chrome/browser/chromeos/cros/network_library_impl_stub.h"
+#include "chrome/browser/chromeos/enrollment_dialog_view.h"
#include "chrome/common/net/x509_certificate_model.h"
#include "chromeos/network/certificate_pattern.h"
#include "chromeos/network/certificate_pattern_matcher.h"
@@ -331,6 +332,10 @@
void Network::CopyCredentialsFromRemembered(Network* remembered) {
}
+void Network::SetEnrollmentDelegate(EnrollmentDelegate* delegate) {
+ enrollment_delegate_.reset(delegate);
+}
+
void Network::SetValueProperty(const char* prop, const base::Value& value) {
DCHECK(prop);
if (!EnsureRunningOnChromeOS())
@@ -419,11 +424,6 @@
void Network::set_connecting() {
state_ = STATE_CONNECT_REQUESTED;
- // Set the connecting network in NetworkStateHandler for the status area UI.
- if (NetworkHandler::IsInitialized()) {
- NetworkHandler::Get()->network_state_handler()->
- SetConnectingNetwork(service_path());
- }
}
void Network::SetProfilePath(const std::string& profile_path) {
diff --git a/chrome/browser/chromeos/cros/network_library.h b/chrome/browser/chromeos/cros/network_library.h
index ba7a6d3..e4ebbb0 100644
--- a/chrome/browser/chromeos/cros/network_library.h
+++ b/chrome/browser/chromeos/cros/network_library.h
@@ -27,9 +27,10 @@
namespace chromeos {
+class CertificatePattern;
+class EnrollmentDelegate;
class NetworkDeviceParser;
class NetworkParser;
-class CertificatePattern;
// This is the list of all implementation classes that are allowed
// access to the internals of the network library classes.
@@ -296,25 +297,6 @@
DISALLOW_COPY_AND_ASSIGN(NetworkDevice);
};
-// A virtual class that can be used to handle certificate enrollment URIs when
-// encountered. Also used by unit tests to avoid opening browser windows
-// when testing.
-class EnrollmentDelegate {
- public:
- EnrollmentDelegate() {}
- virtual ~EnrollmentDelegate() {}
-
- // Implemented to handle a given certificate enrollment URI. Returns false
- // if the enrollment URI doesn't use a scheme that we can handle, and in
- // that case, this will be called for any remaining enrollment URIs.
- // If enrollment succeeds, then the enrollment handler must run
- // |post_action| to finish connecting.
- virtual void Enroll(const std::vector<std::string>& uri_list,
- const base::Closure& post_action) = 0;
- private:
- DISALLOW_COPY_AND_ASSIGN(EnrollmentDelegate);
-};
-
// Contains data common to all network service types.
class Network {
public:
@@ -436,9 +418,7 @@
// Adopts the given enrollment handler to handle any certificate enrollment
// URIs encountered during network connection.
- void SetEnrollmentDelegate(EnrollmentDelegate* delegate) {
- enrollment_delegate_.reset(delegate);
- }
+ void SetEnrollmentDelegate(EnrollmentDelegate* delegate);
virtual bool UpdateStatus(const std::string& key,
const base::Value& value,
diff --git a/chrome/browser/chromeos/cros/network_library_unittest.cc b/chrome/browser/chromeos/cros/network_library_unittest.cc
index 06223fc..41ff24c 100644
--- a/chrome/browser/chromeos/cros/network_library_unittest.cc
+++ b/chrome/browser/chromeos/cros/network_library_unittest.cc
@@ -16,6 +16,7 @@
#include "base/path_service.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/cros/network_library_impl_stub.h"
+#include "chrome/browser/chromeos/enrollment_dialog_view.h"
#include "chrome/browser/chromeos/login/mock_user_manager.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/google_apis/test_util.h"
@@ -43,7 +44,7 @@
: did_enroll(false),
correct_args(false) {}
- virtual void Enroll(const std::vector<std::string>& uri_list,
+ virtual bool Enroll(const std::vector<std::string>& uri_list,
const base::Closure& closure) OVERRIDE {
std::vector<std::string> expected_uri_list;
expected_uri_list.push_back("http://youtu.be/dQw4w9WgXcQ");
@@ -53,6 +54,7 @@
did_enroll = true;
closure.Run();
+ return true;
}
bool did_enroll;
diff --git a/chrome/browser/chromeos/display/display_preferences.cc b/chrome/browser/chromeos/display/display_preferences.cc
index 168404c..14c18ff 100644
--- a/chrome/browser/chromeos/display/display_preferences.cc
+++ b/chrome/browser/chromeos/display/display_preferences.cc
@@ -8,6 +8,7 @@
#include "ash/display/display_layout_store.h"
#include "ash/display/display_manager.h"
#include "ash/display/display_pref_util.h"
+#include "ash/display/resolution_notification_controller.h"
#include "ash/shell.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
@@ -258,8 +259,12 @@
}
void StoreDisplayPrefs() {
- if (!IsValidUser())
+ // Do not store prefs when the confirmation dialog is shown.
+ if (!IsValidUser() ||
+ ash::Shell::GetInstance()->resolution_notification_controller()->
+ DoesNotificationTimeout()) {
return;
+ }
StoreCurrentDisplayLayoutPrefs();
StoreCurrentDisplayProperties();
StoreCurrentDisplayPowerState();
diff --git a/chrome/browser/chromeos/display/display_preferences_unittest.cc b/chrome/browser/chromeos/display/display_preferences_unittest.cc
index a319c5b..8299957 100644
--- a/chrome/browser/chromeos/display/display_preferences_unittest.cc
+++ b/chrome/browser/chromeos/display/display_preferences_unittest.cc
@@ -7,6 +7,7 @@
#include "ash/display/display_controller.h"
#include "ash/display/display_layout_store.h"
#include "ash/display/display_manager.h"
+#include "ash/display/resolution_notification_controller.h"
#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
@@ -20,6 +21,9 @@
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chromeos/display/output_configurator.h"
+#include "ui/message_center/message_center.h"
+
+using ash::internal::ResolutionNotificationController;
namespace chromeos {
namespace {
@@ -40,6 +44,7 @@
virtual void SetUp() OVERRIDE {
EXPECT_CALL(*mock_user_manager_, IsUserLoggedIn())
.WillRepeatedly(testing::Return(false));
+ EXPECT_CALL(*mock_user_manager_, Shutdown());
ash::test::AshTestBase::SetUp();
RegisterDisplayLocalStatePrefs(local_state_.registry());
TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_);
@@ -146,6 +151,8 @@
DISALLOW_COPY_AND_ASSIGN(DisplayPreferencesTest);
};
+} // namespace
+
TEST_F(DisplayPreferencesTest, PairedLayoutOverrides) {
UpdateDisplay("100x100,200x200");
int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
@@ -352,6 +359,47 @@
EXPECT_EQ(400, height);
}
+TEST_F(DisplayPreferencesTest, PreventStore) {
+ ResolutionNotificationController::SuppressTimerForTest();
+ LoggedInAsUser();
+ UpdateDisplay("400x300");
+ int64 id = ash::Shell::GetScreen()->GetPrimaryDisplay().id();
+ // Set display's resolution in single display. It creates the notification and
+ // display preferences should not stored meanwhile.
+ ash::Shell::GetInstance()->resolution_notification_controller()->
+ SetDisplayResolutionAndNotify(
+ id, gfx::Size(400, 300), gfx::Size(500, 400), base::Closure());
+ UpdateDisplay("500x400");
+
+ const base::DictionaryValue* properties =
+ local_state()->GetDictionary(prefs::kDisplayProperties);
+ const base::DictionaryValue* property = NULL;
+ EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id), &property));
+ int width = 0, height = 0;
+ EXPECT_FALSE(property->GetInteger("width", &width));
+ EXPECT_FALSE(property->GetInteger("height", &height));
+
+ // Revert the change. When timeout, 2nd button is revert.
+ message_center::MessageCenter::Get()->ClickOnNotificationButton(
+ ResolutionNotificationController::kNotificationId, 1);
+ RunAllPendingInMessageLoop();
+ EXPECT_FALSE(message_center::MessageCenter::Get()->HasNotification(
+ ResolutionNotificationController::kNotificationId));
+
+ // Once the notification is removed, the specified resolution will be stored
+ // by SetDisplayResolution.
+ ash::Shell::GetInstance()->display_manager()->SetDisplayResolution(
+ id, gfx::Size(300, 200));
+ UpdateDisplay("300x200");
+
+ property = NULL;
+ EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id), &property));
+ EXPECT_TRUE(property->GetInteger("width", &width));
+ EXPECT_TRUE(property->GetInteger("height", &height));
+ EXPECT_EQ(300, width);
+ EXPECT_EQ(200, height);
+}
+
TEST_F(DisplayPreferencesTest, StoreForSwappedDisplay) {
UpdateDisplay("100x100,200x200");
int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
@@ -445,5 +493,4 @@
ash::Shell::GetInstance()->output_configurator()->power_state());
}
-} // namespace
} // namespace chromeos
diff --git a/chrome/browser/chromeos/drive/dummy_file_system.h b/chrome/browser/chromeos/drive/dummy_file_system.h
index 191be66..c0fe931 100644
--- a/chrome/browser/chromeos/drive/dummy_file_system.h
+++ b/chrome/browser/chromeos/drive/dummy_file_system.h
@@ -58,6 +58,9 @@
const FileOperationCallback& callback) OVERRIDE {}
virtual void GetFileByPath(const base::FilePath& file_path,
const GetFileCallback& callback) OVERRIDE {}
+ virtual void GetFileByPathForSaving(
+ const base::FilePath& file_path,
+ const GetFileCallback& callback) OVERRIDE {}
virtual void GetFileContentByPath(
const base::FilePath& file_path,
const GetFileContentInitializedCallback& initialized_callback,
diff --git a/chrome/browser/chromeos/drive/fake_file_system.cc b/chrome/browser/chromeos/drive/fake_file_system.cc
index 4b6f6e4..6211872 100644
--- a/chrome/browser/chromeos/drive/fake_file_system.cc
+++ b/chrome/browser/chromeos/drive/fake_file_system.cc
@@ -134,6 +134,11 @@
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
+void FakeFileSystem::GetFileByPathForSaving(const base::FilePath& file_path,
+ const GetFileCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
+
void FakeFileSystem::GetFileContentByPath(
const base::FilePath& file_path,
const GetFileContentInitializedCallback& initialized_callback,
diff --git a/chrome/browser/chromeos/drive/fake_file_system.h b/chrome/browser/chromeos/drive/fake_file_system.h
index da005db..6b20d34 100644
--- a/chrome/browser/chromeos/drive/fake_file_system.h
+++ b/chrome/browser/chromeos/drive/fake_file_system.h
@@ -91,6 +91,8 @@
const FileOperationCallback& callback) OVERRIDE;
virtual void GetFileByPath(const base::FilePath& file_path,
const GetFileCallback& callback) OVERRIDE;
+ virtual void GetFileByPathForSaving(const base::FilePath& file_path,
+ const GetFileCallback& callback) OVERRIDE;
virtual void GetFileContentByPath(
const base::FilePath& file_path,
const GetFileContentInitializedCallback& initialized_callback,
diff --git a/chrome/browser/chromeos/drive/file_errors.cc b/chrome/browser/chromeos/drive/file_errors.cc
index 05d76f9..3778eae 100644
--- a/chrome/browser/chromeos/drive/file_errors.cc
+++ b/chrome/browser/chromeos/drive/file_errors.cc
@@ -63,6 +63,9 @@
case FILE_ERROR_NO_LOCAL_SPACE:
return "FILE_ERROR_NO_LOCAL_SPACE";
+
+ case FILE_ERROR_SERVICE_UNAVAILABLE:
+ return "FILE_ERROR_SERVICE_UNAVAILABLE";
}
NOTREACHED();
@@ -124,6 +127,9 @@
case FILE_ERROR_NO_LOCAL_SPACE:
return base::PLATFORM_FILE_ERROR_FAILED;
+
+ case FILE_ERROR_SERVICE_UNAVAILABLE:
+ return base::PLATFORM_FILE_ERROR_FAILED;
}
NOTREACHED();
@@ -141,6 +147,9 @@
return FILE_ERROR_ACCESS_DENIED;
case google_apis::HTTP_NOT_FOUND:
return FILE_ERROR_NOT_FOUND;
+ case google_apis::HTTP_INTERNAL_SERVER_ERROR:
+ case google_apis::HTTP_SERVICE_UNAVAILABLE:
+ return FILE_ERROR_SERVICE_UNAVAILABLE;
case google_apis::HTTP_NOT_IMPLEMENTED:
return FILE_ERROR_INVALID_OPERATION;
case google_apis::GDATA_CANCELLED:
diff --git a/chrome/browser/chromeos/drive/file_errors.h b/chrome/browser/chromeos/drive/file_errors.h
index 08cf5a1..4b7bc67 100644
--- a/chrome/browser/chromeos/drive/file_errors.h
+++ b/chrome/browser/chromeos/drive/file_errors.h
@@ -30,6 +30,7 @@
FILE_ERROR_INVALID_URL = -15,
FILE_ERROR_NO_CONNECTION = -16,
FILE_ERROR_NO_LOCAL_SPACE = -17,
+ FILE_ERROR_SERVICE_UNAVAILABLE = -18,
};
// Used as callbacks for file operations.
diff --git a/chrome/browser/chromeos/drive/file_system.cc b/chrome/browser/chromeos/drive/file_system.cc
index 6b89008..b6f4e93 100644
--- a/chrome/browser/chromeos/drive/file_system.cc
+++ b/chrome/browser/chromeos/drive/file_system.cc
@@ -20,6 +20,7 @@
#include "chrome/browser/chromeos/drive/file_system/create_directory_operation.h"
#include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
#include "chrome/browser/chromeos/drive/file_system/download_operation.h"
+#include "chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.h"
#include "chrome/browser/chromeos/drive/file_system/move_operation.h"
#include "chrome/browser/chromeos/drive/file_system/open_file_operation.h"
#include "chrome/browser/chromeos/drive/file_system/remove_operation.h"
@@ -208,13 +209,20 @@
cache_));
search_operation_.reset(new file_system::SearchOperation(
blocking_task_runner_.get(), scheduler_, resource_metadata_));
+ get_file_for_saving_operation_.reset(
+ new file_system::GetFileForSavingOperation(blocking_task_runner_.get(),
+ observer,
+ scheduler_,
+ resource_metadata_,
+ cache_,
+ temporary_file_directory_));
+
sync_client_.reset(new internal::SyncClient(blocking_task_runner_.get(),
observer,
scheduler_,
resource_metadata_,
cache_,
temporary_file_directory_));
-
hide_hosted_docs_ =
pref_service_->GetBoolean(prefs::kDisableDriveHostedFiles);
@@ -491,6 +499,14 @@
callback);
}
+void FileSystem::GetFileByPathForSaving(const base::FilePath& file_path,
+ const GetFileCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
+
+ get_file_for_saving_operation_->GetFileForSaving(file_path, callback);
+}
+
void FileSystem::GetFileContentByPath(
const base::FilePath& file_path,
const GetFileContentInitializedCallback& initialized_callback,
diff --git a/chrome/browser/chromeos/drive/file_system.h b/chrome/browser/chromeos/drive/file_system.h
index 5bb1ca8..dacc522 100644
--- a/chrome/browser/chromeos/drive/file_system.h
+++ b/chrome/browser/chromeos/drive/file_system.h
@@ -46,6 +46,7 @@
class CreateDirectoryOperation;
class CreateFileOperation;
class DownloadOperation;
+class GetFileForSavingOperation;
class MoveOperation;
class OpenFileOperation;
class OperationObserver;
@@ -122,6 +123,8 @@
const FileOperationCallback& callback) OVERRIDE;
virtual void GetFileByPath(const base::FilePath& file_path,
const GetFileCallback& callback) OVERRIDE;
+ virtual void GetFileByPathForSaving(const base::FilePath& file_path,
+ const GetFileCallback& callback) OVERRIDE;
virtual void GetFileContentByPath(
const base::FilePath& file_path,
const GetFileContentInitializedCallback& initialized_callback,
@@ -319,6 +322,8 @@
scoped_ptr<file_system::DownloadOperation> download_operation_;
scoped_ptr<file_system::UpdateOperation> update_operation_;
scoped_ptr<file_system::SearchOperation> search_operation_;
+ scoped_ptr<file_system::GetFileForSavingOperation>
+ get_file_for_saving_operation_;
// Note: This should remain the last member so it'll be destroyed and
// invalidate the weak pointers before any other members are destroyed.
diff --git a/chrome/browser/chromeos/drive/file_system/copy_operation.cc b/chrome/browser/chromeos/drive/file_system/copy_operation.cc
index b0d007c..a38adb5 100644
--- a/chrome/browser/chromeos/drive/file_system/copy_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/copy_operation.cc
@@ -49,6 +49,23 @@
return cache->MarkDirty(resource_id);
}
+// Gets the file size of the |local_path|, and the ResourceEntry for the parent
+// of |remote_path| to prepare the necessary information for transfer.
+FileError PrepareTransferFileFromLocalToRemote(
+ internal::ResourceMetadata* metadata,
+ const base::FilePath& local_path,
+ const base::FilePath& remote_path,
+ int64* local_file_size,
+ ResourceEntry* parent_entry) {
+ DCHECK(metadata);
+ DCHECK(local_file_size);
+ DCHECK(parent_entry);
+
+ if (!file_util::GetFileSize(local_path, local_file_size))
+ return FILE_ERROR_NOT_FOUND;
+ return metadata->GetResourceEntryByPath(remote_path.DirName(), parent_entry);
+}
+
} // namespace
CopyOperation::CopyOperation(base::SequencedTaskRunner* blocking_task_runner,
@@ -149,15 +166,25 @@
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
- // Make sure the destination directory exists.
- metadata_->GetResourceEntryByPathOnUIThread(
- remote_dest_file_path.DirName(),
+ int64* local_file_size = new int64(-1);
+ ResourceEntry* parent_entry = new ResourceEntry;
+ base::PostTaskAndReplyWithResult(
+ blocking_task_runner_.get(),
+ FROM_HERE,
+ base::Bind(&PrepareTransferFileFromLocalToRemote,
+ metadata_,
+ local_src_file_path,
+ remote_dest_file_path,
+ local_file_size,
+ parent_entry),
base::Bind(
- &CopyOperation::TransferFileFromLocalToRemoteAfterGetResourceEntry,
+ &CopyOperation::TransferFileFromLocalToRemoteAfterPrepare,
weak_ptr_factory_.GetWeakPtr(),
local_src_file_path,
remote_dest_file_path,
- callback));
+ callback,
+ base::Owned(local_file_size),
+ base::Owned(parent_entry)));
}
void CopyOperation::ScheduleTransferRegularFile(
@@ -287,8 +314,6 @@
const base::FilePath& file_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
- DCHECK_EQ(util::GetDriveMyDriveRootPath().value(),
- file_path.DirName().value());
// Return if there is an error or |dir_path| is the root directory.
if (error != FILE_ERROR_OK ||
@@ -297,6 +322,9 @@
return;
}
+ DCHECK_EQ(util::GetDriveMyDriveRootPath().value(),
+ file_path.DirName().value()) << file_path.value();
+
move_operation_->Move(file_path,
directory_path.Append(file_path.BaseName()),
callback);
@@ -424,22 +452,24 @@
ScheduleTransferRegularFile(local_file_path, remote_dest_file_path, callback);
}
-void CopyOperation::TransferFileFromLocalToRemoteAfterGetResourceEntry(
+void CopyOperation::TransferFileFromLocalToRemoteAfterPrepare(
const base::FilePath& local_src_file_path,
const base::FilePath& remote_dest_file_path,
const FileOperationCallback& callback,
- FileError error,
- scoped_ptr<ResourceEntry> entry) {
+ int64* local_file_size,
+ ResourceEntry* parent_entry,
+ FileError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null());
+ DCHECK(parent_entry);
+ DCHECK(local_file_size);
if (error != FILE_ERROR_OK) {
callback.Run(error);
return;
}
- DCHECK(entry.get());
- if (!entry->file_info().is_directory()) {
+ if (!parent_entry->file_info().is_directory()) {
// The parent of |remote_dest_file_path| is not a directory.
callback.Run(FILE_ERROR_NOT_A_DIRECTORY);
return;
@@ -456,11 +486,45 @@
remote_dest_file_path,
callback));
} else {
- ScheduleTransferRegularFile(local_src_file_path, remote_dest_file_path,
- callback);
+ // For regular files, check the server-side quota whether sufficient space
+ // is available for the file to be uploaded.
+ scheduler_->GetAboutResource(
+ base::Bind(&CopyOperation::TransferFileFromLocalToRemoteAfterGetQuota,
+ weak_ptr_factory_.GetWeakPtr(),
+ local_src_file_path,
+ remote_dest_file_path,
+ callback,
+ *local_file_size));
}
}
+void CopyOperation::TransferFileFromLocalToRemoteAfterGetQuota(
+ const base::FilePath& local_src_file_path,
+ const base::FilePath& remote_dest_file_path,
+ const FileOperationCallback& callback,
+ int64 local_file_size,
+ google_apis::GDataErrorCode status,
+ scoped_ptr<google_apis::AboutResource> about_resource) {
+ DCHECK(!callback.is_null());
+
+ FileError error = GDataToFileError(status);
+ if (error != FILE_ERROR_OK) {
+ callback.Run(error);
+ return;
+ }
+
+ DCHECK(about_resource);
+ const int64 space =
+ about_resource->quota_bytes_total() - about_resource->quota_bytes_used();
+ if (space < local_file_size) {
+ callback.Run(FILE_ERROR_NO_SERVER_SPACE);
+ return;
+ }
+
+ ScheduleTransferRegularFile(local_src_file_path, remote_dest_file_path,
+ callback);
+}
+
void CopyOperation::TransferFileForResourceId(
const base::FilePath& local_file_path,
const base::FilePath& remote_dest_file_path,
diff --git a/chrome/browser/chromeos/drive/file_system/copy_operation.h b/chrome/browser/chromeos/drive/file_system/copy_operation.h
index 9ba481d..41be0cf 100644
--- a/chrome/browser/chromeos/drive/file_system/copy_operation.h
+++ b/chrome/browser/chromeos/drive/file_system/copy_operation.h
@@ -10,6 +10,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/drive/resource_metadata.h"
+#include "chrome/browser/google_apis/drive_api_parser.h"
#include "chrome/browser/google_apis/gdata_errorcode.h"
namespace base {
@@ -154,14 +155,25 @@
const base::FilePath& local_file_path,
scoped_ptr<ResourceEntry> entry);
- // Part of TransferFileFromLocalToRemote(). Called after
- // GetResourceEntryByPath() is complete.
- void TransferFileFromLocalToRemoteAfterGetResourceEntry(
+ // Part of TransferFileFromLocalToRemote(). Called after |parent_entry| and
+ // |local_file_size| are retrieved in the blocking pool.
+ void TransferFileFromLocalToRemoteAfterPrepare(
const base::FilePath& local_src_file_path,
const base::FilePath& remote_dest_file_path,
const FileOperationCallback& callback,
- FileError error,
- scoped_ptr<ResourceEntry> entry);
+ int64* local_file_size,
+ ResourceEntry* parent_entry,
+ FileError error);
+
+ // Part of TransferFileFromLocalToRemote(). Called after the result of
+ // GetAboutResource() is avaiable.
+ void TransferFileFromLocalToRemoteAfterGetQuota(
+ const base::FilePath& local_src_file_path,
+ const base::FilePath& remote_dest_file_path,
+ const FileOperationCallback& callback,
+ int64 local_file_size,
+ google_apis::GDataErrorCode status,
+ scoped_ptr<google_apis::AboutResource> about_resource);
// Initiates transfer of |local_file_path| with |resource_id| to
// |remote_dest_file_path|. |local_file_path| must be a file from the local
diff --git a/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc
index 3451b3a..433c57d 100644
--- a/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system/copy_operation_unittest.cc
@@ -72,6 +72,43 @@
remote_dest_path.DirName()));
}
+TEST_F(CopyOperationTest, TransferFileFromLocalToRemote_QuotaCheck) {
+ const base::FilePath local_src_path = temp_dir().AppendASCII("local.txt");
+ const base::FilePath remote_dest_path(
+ FILE_PATH_LITERAL("drive/root/remote.txt"));
+
+ const size_t kFileSize = 10;
+
+ // Prepare a local file.
+ ASSERT_TRUE(
+ google_apis::test_util::WriteStringToFile(local_src_path,
+ std::string(kFileSize, 'a')));
+
+ // Set insufficient quota.
+ fake_service()->SetQuotaValue(100, 100 + kFileSize - 1);
+
+ // Transfer the local file to Drive.
+ FileError error = FILE_ERROR_FAILED;
+ operation_->TransferFileFromLocalToRemote(
+ local_src_path,
+ remote_dest_path,
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_NO_SERVER_SPACE, error);
+
+ // Set sufficient quota.
+ fake_service()->SetQuotaValue(100, 100 + kFileSize);
+
+ // Transfer the local file to Drive.
+ error = FILE_ERROR_FAILED;
+ operation_->TransferFileFromLocalToRemote(
+ local_src_path,
+ remote_dest_path,
+ google_apis::test_util::CreateCopyResultCallback(&error));
+ test_util::RunBlockingPoolTask();
+ EXPECT_EQ(FILE_ERROR_OK, error);
+}
+
TEST_F(CopyOperationTest, TransferFileFromLocalToRemote_HostedDocument) {
const base::FilePath local_src_path = temp_dir().AppendASCII("local.gdoc");
const base::FilePath remote_dest_path(FILE_PATH_LITERAL(
diff --git a/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.cc b/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.cc
new file mode 100644
index 0000000..7964876
--- /dev/null
+++ b/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.cc
@@ -0,0 +1,146 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.h"
+
+#include "base/bind.h"
+#include "chrome/browser/chromeos/drive/file_system/create_file_operation.h"
+#include "chrome/browser/chromeos/drive/file_system/download_operation.h"
+#include "chrome/browser/chromeos/drive/file_write_watcher.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
+
+namespace drive {
+namespace file_system {
+
+GetFileForSavingOperation::GetFileForSavingOperation(
+ base::SequencedTaskRunner* blocking_task_runner,
+ OperationObserver* observer,
+ JobScheduler* scheduler,
+ internal::ResourceMetadata* metadata,
+ internal::FileCache* cache,
+ const base::FilePath& temporary_file_directory)
+ : create_file_operation_(new CreateFileOperation(blocking_task_runner,
+ observer,
+ scheduler,
+ metadata,
+ cache)),
+ download_operation_(new DownloadOperation(blocking_task_runner,
+ observer,
+ scheduler,
+ metadata,
+ cache,
+ temporary_file_directory)),
+ file_write_watcher_(new internal::FileWriteWatcher(observer)),
+ cache_(cache),
+ weak_ptr_factory_(this) {
+}
+
+GetFileForSavingOperation::~GetFileForSavingOperation() {
+}
+
+void GetFileForSavingOperation::GetFileForSaving(
+ const base::FilePath& file_path,
+ const GetFileCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
+
+ create_file_operation_->CreateFile(
+ file_path,
+ false, // error_if_already_exists
+ base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterCreate,
+ weak_ptr_factory_.GetWeakPtr(),
+ file_path,
+ callback));
+}
+
+void GetFileForSavingOperation::GetFileForSavingAfterCreate(
+ const base::FilePath& file_path,
+ const GetFileCallback& callback,
+ FileError error) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
+
+ if (error != FILE_ERROR_OK) {
+ callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
+ return;
+ }
+
+ download_operation_->EnsureFileDownloadedByPath(
+ file_path,
+ ClientContext(USER_INITIATED),
+ GetFileContentInitializedCallback(),
+ google_apis::GetContentCallback(),
+ base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterDownload,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback));
+}
+
+void GetFileForSavingOperation::GetFileForSavingAfterDownload(
+ const GetFileCallback& callback,
+ FileError error,
+ const base::FilePath& cache_path,
+ scoped_ptr<ResourceEntry> entry) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
+
+ if (error != FILE_ERROR_OK) {
+ callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
+ return;
+ }
+
+ const std::string& resource_id = entry->resource_id();
+ cache_->MarkDirtyOnUIThread(
+ resource_id,
+ base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterMarkDirty,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback,
+ cache_path,
+ base::Passed(&entry)));
+}
+
+void GetFileForSavingOperation::GetFileForSavingAfterMarkDirty(
+ const GetFileCallback& callback,
+ const base::FilePath& cache_path,
+ scoped_ptr<ResourceEntry> entry,
+ FileError error) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
+
+ if (error != FILE_ERROR_OK) {
+ callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
+ return;
+ }
+
+ const std::string& resource_id = entry->resource_id();
+ file_write_watcher_->StartWatch(
+ cache_path,
+ resource_id,
+ base::Bind(&GetFileForSavingOperation::GetFileForSavingAfterWatch,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback,
+ cache_path,
+ base::Passed(&entry)));
+}
+
+void GetFileForSavingOperation::GetFileForSavingAfterWatch(
+ const GetFileCallback& callback,
+ const base::FilePath& cache_path,
+ scoped_ptr<ResourceEntry> entry,
+ bool success) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!callback.is_null());
+
+ if (!success) {
+ callback.Run(FILE_ERROR_FAILED,
+ base::FilePath(), scoped_ptr<ResourceEntry>());
+ return;
+ }
+
+ callback.Run(FILE_ERROR_OK, cache_path, entry.Pass());
+}
+
+} // namespace file_system
+} // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.h b/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.h
new file mode 100644
index 0000000..3215cc2
--- /dev/null
+++ b/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.h
@@ -0,0 +1,92 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_DRIVE_FILE_SYSTEM_GET_FILE_FOR_SAVING_OPERATION_H_
+#define CHROME_BROWSER_CHROMEOS_DRIVE_FILE_SYSTEM_GET_FILE_FOR_SAVING_OPERATION_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/chromeos/drive/file_errors.h"
+#include "chrome/browser/chromeos/drive/file_system_interface.h"
+
+namespace base {
+class FilePath;
+class SequencedTaskRunner;
+} // namespace base
+
+namespace drive {
+namespace internal {
+class FileCache;
+class FileWriteWatcher;
+class ResourceMetadata;
+} // namespace internal
+
+class JobScheduler;
+class ResourceEntry;
+
+namespace file_system {
+
+class CreateFileOperation;
+class DownloadOperation;
+class OperationObserver;
+
+// Implements GetFileForSaving() operation that prepares a local cache for
+// a Drive file whose next modification is monitored and notified to the
+// OperationObserver.
+// TODO(kinaba): crbug.com/269424: we might want to monitor all the changes
+// to the cache directory, not just the one immediately after the save dialog.
+class GetFileForSavingOperation {
+ public:
+ GetFileForSavingOperation(base::SequencedTaskRunner* blocking_task_runner,
+ OperationObserver* observer,
+ JobScheduler* scheduler,
+ internal::ResourceMetadata* metadata,
+ internal::FileCache* cache,
+ const base::FilePath& temporary_file_directory);
+ ~GetFileForSavingOperation();
+
+ // Makes sure that |file_path| in the file system is available in the local
+ // cache, and marks it as dirty. The next modification to the cache file is
+ // watched and is automatically notified to the observer. If the entry is not
+ // present in the file system, it is created.
+ void GetFileForSaving(const base::FilePath& file_path,
+ const GetFileCallback& callback);
+
+ internal::FileWriteWatcher* file_write_watcher_for_testing() {
+ return file_write_watcher_.get();
+ }
+
+ private:
+ void GetFileForSavingAfterCreate(const base::FilePath& file_path,
+ const GetFileCallback& callback,
+ FileError error);
+ void GetFileForSavingAfterDownload(const GetFileCallback& callback,
+ FileError error,
+ const base::FilePath& cache_path,
+ scoped_ptr<ResourceEntry> entry);
+ void GetFileForSavingAfterMarkDirty(const GetFileCallback& callback,
+ const base::FilePath& cache_path,
+ scoped_ptr<ResourceEntry> entry,
+ FileError error);
+ void GetFileForSavingAfterWatch(const GetFileCallback& callback,
+ const base::FilePath& cache_path,
+ scoped_ptr<ResourceEntry> entry,
+ bool success);
+
+ scoped_ptr<CreateFileOperation> create_file_operation_;
+ scoped_ptr<DownloadOperation> download_operation_;
+ scoped_ptr<internal::FileWriteWatcher> file_write_watcher_;
+ internal::FileCache* cache_;
+
+ // Note: This should remain the last member so it'll be destroyed and
+ // invalidate the weak pointers before any other members are destroyed.
+ base::WeakPtrFactory<GetFileForSavingOperation> weak_ptr_factory_;
+ DISALLOW_COPY_AND_ASSIGN(GetFileForSavingOperation);
+};
+
+} // namespace file_system
+} // namespace drive
+
+#endif // CHROME_BROWSER_CHROMEOS_DRIVE_FILE_SYSTEM_GET_FILE_FOR_SAVING_OPERATION_H_
diff --git a/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation_unittest.cc
new file mode 100644
index 0000000..08918e6
--- /dev/null
+++ b/chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation_unittest.cc
@@ -0,0 +1,158 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/drive/file_system/get_file_for_saving_operation.h"
+
+#include "base/callback.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/run_loop.h"
+#include "chrome/browser/chromeos/drive/drive.pb.h"
+#include "chrome/browser/chromeos/drive/file_errors.h"
+#include "chrome/browser/chromeos/drive/file_system/operation_test_base.h"
+#include "chrome/browser/chromeos/drive/file_write_watcher.h"
+#include "chrome/browser/google_apis/test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace drive {
+namespace file_system {
+
+namespace {
+
+// If OnCacheFileUploadNeededByOperation is called, records the resource ID and
+// calls |quit_closure|.
+class TestObserver : public OperationObserver {
+ public:
+ void set_quit_closure(const base::Closure& quit_closure) {
+ quit_closure_ = quit_closure;
+ }
+
+ const std::string& observerd_resource_id() const {
+ return observed_resource_id_;
+ }
+
+ // OperationObserver overrides.
+ virtual void OnDirectoryChangedByOperation(
+ const base::FilePath& path) OVERRIDE {}
+
+ virtual void OnCacheFileUploadNeededByOperation(
+ const std::string& resource_id) OVERRIDE {
+ observed_resource_id_ = resource_id;
+ quit_closure_.Run();
+ }
+
+ private:
+ std::string observed_resource_id_;
+ base::Closure quit_closure_;
+};
+
+} // namespace
+
+class GetFileForSavingOperationTest : public OperationTestBase {
+ protected:
+ // FileWriteWatcher requires TYPE_IO message loop to run.
+ GetFileForSavingOperationTest()
+ : OperationTestBase(content::TestBrowserThreadBundle::IO_MAINLOOP) {
+ }
+
+ virtual void SetUp() OVERRIDE {
+ OperationTestBase::SetUp();
+
+ operation_.reset(new GetFileForSavingOperation(
+ blocking_task_runner(), &observer_, scheduler(), metadata(), cache(),
+ temp_dir()));
+ operation_->file_write_watcher_for_testing()->DisableDelayForTesting();
+ }
+
+ TestObserver observer_;
+ scoped_ptr<GetFileForSavingOperation> operation_;
+};
+
+TEST_F(GetFileForSavingOperationTest, GetFileForSaving_Exist) {
+ base::FilePath drive_path(FILE_PATH_LITERAL("drive/root/File 1.txt"));
+ ResourceEntry src_entry;
+ ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(drive_path, &src_entry));
+
+ // Run the operation.
+ FileError error = FILE_ERROR_FAILED;
+ scoped_ptr<ResourceEntry> entry;
+ base::FilePath local_path;
+ operation_->GetFileForSaving(
+ drive_path,
+ google_apis::test_util::CreateCopyResultCallback(
+ &error, &local_path, &entry));
+ test_util::RunBlockingPoolTask();
+
+ // Checks that the file is retrieved.
+ EXPECT_EQ(FILE_ERROR_OK, error);
+ ASSERT_TRUE(entry);
+ EXPECT_EQ(src_entry.resource_id(), entry->resource_id());
+
+ // Checks that it presents in cache and marked dirty.
+ bool success = false;
+ FileCacheEntry cache_entry;
+ cache()->GetCacheEntryOnUIThread(
+ src_entry.resource_id(),
+ google_apis::test_util::CreateCopyResultCallback(&success, &cache_entry));
+ test_util::RunBlockingPoolTask();
+ EXPECT_TRUE(success);
+ EXPECT_TRUE(cache_entry.is_present());
+ EXPECT_TRUE(cache_entry.is_dirty());
+
+ // Write something to the cache and checks that the event is reported.
+ {
+ base::RunLoop run_loop;
+ observer_.set_quit_closure(run_loop.QuitClosure());
+ google_apis::test_util::WriteStringToFile(local_path, "hello");
+ run_loop.Run();
+ EXPECT_EQ(entry->resource_id(), observer_.observerd_resource_id());
+ }
+}
+
+TEST_F(GetFileForSavingOperationTest, GetFileForSaving_NotExist) {
+ base::FilePath drive_path(FILE_PATH_LITERAL("drive/root/NotExist.txt"));
+ ResourceEntry src_entry;
+ ASSERT_EQ(FILE_ERROR_NOT_FOUND,
+ GetLocalResourceEntry(drive_path, &src_entry));
+
+ // Run the operation.
+ FileError error = FILE_ERROR_FAILED;
+ scoped_ptr<ResourceEntry> entry;
+ base::FilePath local_path;
+ operation_->GetFileForSaving(
+ drive_path,
+ google_apis::test_util::CreateCopyResultCallback(
+ &error, &local_path, &entry));
+ test_util::RunBlockingPoolTask();
+
+ // Checks that the file is created and retrieved.
+ EXPECT_EQ(FILE_ERROR_OK, error);
+ EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(drive_path, &src_entry));
+ int64 size = -1;
+ EXPECT_TRUE(file_util::GetFileSize(local_path, &size));
+ EXPECT_EQ(0, size);
+}
+
+TEST_F(GetFileForSavingOperationTest, GetFileForSaving_Directory) {
+ base::FilePath drive_path(FILE_PATH_LITERAL("drive/root/Directory 1"));
+ ResourceEntry src_entry;
+ ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(drive_path, &src_entry));
+ ASSERT_TRUE(src_entry.file_info().is_directory());
+
+ // Run the operation.
+ FileError error = FILE_ERROR_FAILED;
+ scoped_ptr<ResourceEntry> entry;
+ base::FilePath local_path;
+ operation_->GetFileForSaving(
+ drive_path,
+ google_apis::test_util::CreateCopyResultCallback(
+ &error, &local_path, &entry));
+ test_util::RunBlockingPoolTask();
+
+ // Checks that an error is returned.
+ EXPECT_EQ(FILE_ERROR_EXISTS, error);
+}
+
+} // namespace file_system
+} // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_system/operation_test_base.cc b/chrome/browser/chromeos/drive/file_system/operation_test_base.cc
index ad1fb09..324858d 100644
--- a/chrome/browser/chromeos/drive/file_system/operation_test_base.cc
+++ b/chrome/browser/chromeos/drive/file_system/operation_test_base.cc
@@ -39,6 +39,10 @@
OperationTestBase::OperationTestBase() {
}
+OperationTestBase::OperationTestBase(int test_thread_bundle_options)
+ : thread_bundle_(test_thread_bundle_options) {
+}
+
OperationTestBase::~OperationTestBase() {
}
diff --git a/chrome/browser/chromeos/drive/file_system/operation_test_base.h b/chrome/browser/chromeos/drive/file_system/operation_test_base.h
index b8b26cc..4056455 100644
--- a/chrome/browser/chromeos/drive/file_system/operation_test_base.h
+++ b/chrome/browser/chromeos/drive/file_system/operation_test_base.h
@@ -67,6 +67,7 @@
};
OperationTestBase();
+ explicit OperationTestBase(int test_thread_bundle_options);
virtual ~OperationTestBase();
// testing::Test overrides.
diff --git a/chrome/browser/chromeos/drive/file_system_interface.h b/chrome/browser/chromeos/drive/file_system_interface.h
index 1c5865e..4df3c8f 100644
--- a/chrome/browser/chromeos/drive/file_system_interface.h
+++ b/chrome/browser/chromeos/drive/file_system_interface.h
@@ -318,15 +318,23 @@
virtual void Unpin(const base::FilePath& file_path,
const FileOperationCallback& callback) = 0;
- // Gets |file_path| from the file system. The file entry represented by
- // |file_path| needs to be present in in-memory representation of the file
- // system in order to be retrieved. If the file is not cached, the file
- // will be downloaded through GData API or Drive V2 API.
+ // Makes sure that |file_path| in the file system is available in the local
+ // cache. If the file is not cached, the file will be downloaded. The entry
+ // needs to be present in the file system.
//
- // |callback| must not be null.
+ // Returns the cache path and entry info to |callback|. It must not be null.
virtual void GetFileByPath(const base::FilePath& file_path,
const GetFileCallback& callback) = 0;
+ // Makes sure that |file_path| in the file system is available in the local
+ // cache, and mark it as dirty. The next modification to the cache file is
+ // watched and is automatically uploaded to the server. If the entry is not
+ // present in the file system, it is created.
+ //
+ // Returns the cache path and entry info to |callback|. It must not be null.
+ virtual void GetFileByPathForSaving(const base::FilePath& file_path,
+ const GetFileCallback& callback) = 0;
+
// Gets a file by the given |file_path|.
// Calls |initialized_callback| when either:
// 1) The cached file (or JSON file for hosted file) is found, or
diff --git a/chrome/browser/chromeos/drive/file_task_executor.h b/chrome/browser/chromeos/drive/file_task_executor.h
index ce9c459..69e7dad 100644
--- a/chrome/browser/chromeos/drive/file_task_executor.h
+++ b/chrome/browser/chromeos/drive/file_task_executor.h
@@ -8,6 +8,7 @@
#include <string>
#include <vector>
+#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/drive/file_errors.h"
#include "chrome/browser/chromeos/extensions/file_manager/file_tasks.h"
diff --git a/chrome/browser/chromeos/drive/file_write_watcher.h b/chrome/browser/chromeos/drive/file_write_watcher.h
index 91c947d..13523df 100644
--- a/chrome/browser/chromeos/drive/file_write_watcher.h
+++ b/chrome/browser/chromeos/drive/file_write_watcher.h
@@ -46,7 +46,7 @@
// 5 seconds has passed after the last write operation is detected.
//
// TODO(kinaba): investigate the possibility to continuously watch the whole
- // cache directory.
+ // cache directory. http://crbug.com/269424
void StartWatch(const base::FilePath& path,
const std::string& resource_id,
const StartWatchCallback& callback);
diff --git a/chrome/browser/chromeos/drive/job_scheduler.cc b/chrome/browser/chromeos/drive/job_scheduler.cc
index d9c0d61..682b3c1 100644
--- a/chrome/browser/chromeos/drive/job_scheduler.cc
+++ b/chrome/browser/chromeos/drive/job_scheduler.cc
@@ -22,9 +22,13 @@
namespace {
-const int kMaxThrottleCount = 5;
+const int kMaxThrottleCount = 4;
-const int kMaxRetryCount = kMaxThrottleCount - 1;
+// According to the API documentation, this should be the same as
+// kMaxThrottleCount (https://developers.google.com/drive/handle-errors).
+// But currently multiplied by 2 to ensure upload related jobs retried for a
+// sufficient number of times. crbug.com/269918
+const int kMaxRetryCount = 2*kMaxThrottleCount;
// Parameter struct for RunUploadNewFile.
struct UploadNewFileParams {
diff --git a/chrome/browser/chromeos/drive/resource_metadata_storage.h b/chrome/browser/chromeos/drive/resource_metadata_storage.h
index 0ad61ef..9c4621a 100644
--- a/chrome/browser/chromeos/drive/resource_metadata_storage.h
+++ b/chrome/browser/chromeos/drive/resource_metadata_storage.h
@@ -36,7 +36,10 @@
public:
// This should be incremented when incompatibility change is made to DB
// format.
- static const int kDBVersion = 7;
+ //
+ // Note: Skip '7' when incrementing this value next time. '7' has been used
+ // in the period between r208686 and r213797.
+ static const int kDBVersion = 6;
// Object to iterate over entries stored in this storage.
class Iterator {
diff --git a/chrome/browser/chromeos/drive/sync_client.cc b/chrome/browser/chromeos/drive/sync_client.cc
index c1f487b..31771d6 100644
--- a/chrome/browser/chromeos/drive/sync_client.cc
+++ b/chrome/browser/chromeos/drive/sync_client.cc
@@ -38,6 +38,9 @@
// and shorten the delay. crbug.com/134774
const int kDelaySeconds = 5;
+// The delay constant is used to delay retrying a sync task on server errors.
+const int kLongDelaySeconds = 600;
+
// Appends |resource_id| to |to_fetch| if the file is pinned but not fetched
// (not present locally), or to |to_upload| if the file is dirty but not
// uploaded.
@@ -78,6 +81,7 @@
metadata,
cache)),
delay_(base::TimeDelta::FromSeconds(kDelaySeconds)),
+ long_delay_(base::TimeDelta::FromSeconds(kLongDelaySeconds)),
weak_ptr_factory_(this) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
@@ -110,7 +114,7 @@
void SyncClient::AddFetchTask(const std::string& resource_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- AddTaskToQueue(FETCH, resource_id);
+ AddTaskToQueue(FETCH, resource_id, delay_);
}
void SyncClient::RemoveFetchTask(const std::string& resource_id) {
@@ -123,11 +127,12 @@
void SyncClient::AddUploadTask(const std::string& resource_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- AddTaskToQueue(UPLOAD, resource_id);
+ AddTaskToQueue(UPLOAD, resource_id, delay_);
}
void SyncClient::AddTaskToQueue(SyncType type,
- const std::string& resource_id) {
+ const std::string& resource_id,
+ const base::TimeDelta& delay) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// If the same task is already queued, ignore this task.
@@ -156,7 +161,7 @@
weak_ptr_factory_.GetWeakPtr(),
type,
resource_id),
- delay_);
+ delay);
}
void SyncClient::StartTask(SyncType type, const std::string& resource_id) {
@@ -205,13 +210,13 @@
for (size_t i = 0; i < to_upload->size(); ++i) {
const std::string& resource_id = (*to_upload)[i];
DVLOG(1) << "Queuing to upload: " << resource_id;
- AddTaskToQueue(UPLOAD_NO_CONTENT_CHECK, resource_id);
+ AddTaskToQueue(UPLOAD_NO_CONTENT_CHECK, resource_id, delay_);
}
for (size_t i = 0; i < to_fetch->size(); ++i) {
const std::string& resource_id = (*to_fetch)[i];
DVLOG(1) << "Queuing to fetch: " << resource_id;
- AddTaskToQueue(FETCH, resource_id);
+ AddTaskToQueue(FETCH, resource_id, delay_);
}
}
@@ -284,7 +289,7 @@
}
// Finally, adding to the queue.
- AddTaskToQueue(FETCH, resource_id);
+ AddTaskToQueue(FETCH, resource_id, delay_);
}
void SyncClient::OnFetchFileComplete(const std::string& resource_id,
@@ -308,7 +313,11 @@
break;
case FILE_ERROR_NO_CONNECTION:
// Re-queue the task so that we'll retry once the connection is back.
- AddTaskToQueue(FETCH, resource_id);
+ AddTaskToQueue(FETCH, resource_id, delay_);
+ break;
+ case FILE_ERROR_SERVICE_UNAVAILABLE:
+ // Re-queue the task so that we'll retry once the service is back.
+ AddTaskToQueue(FETCH, resource_id, long_delay_);
break;
default:
LOG(WARNING) << "Failed to fetch " << resource_id
@@ -329,7 +338,11 @@
switch (error) {
case FILE_ERROR_NO_CONNECTION:
// Re-queue the task so that we'll retry once the connection is back.
- AddTaskToQueue(UPLOAD_NO_CONTENT_CHECK, resource_id);
+ AddTaskToQueue(UPLOAD_NO_CONTENT_CHECK, resource_id, delay_);
+ break;
+ case FILE_ERROR_SERVICE_UNAVAILABLE:
+ // Re-queue the task so that we'll retry once the service is back.
+ AddTaskToQueue(UPLOAD_NO_CONTENT_CHECK, resource_id, long_delay_);
break;
default:
LOG(WARNING) << "Failed to upload " << resource_id << ": "
diff --git a/chrome/browser/chromeos/drive/sync_client.h b/chrome/browser/chromeos/drive/sync_client.h
index f5c6734..3178f5b 100644
--- a/chrome/browser/chromeos/drive/sync_client.h
+++ b/chrome/browser/chromeos/drive/sync_client.h
@@ -91,7 +91,9 @@
private:
// Adds the given task to the queue. If the same task is queued, remove the
// existing one, and adds a new one to the end of the queue.
- void AddTaskToQueue(SyncType type, const std::string& resource_id);
+ void AddTaskToQueue(SyncType type,
+ const std::string& resource_id,
+ const base::TimeDelta& delay);
// Called when a task is ready to be added to the queue.
void StartTask(SyncType type, const std::string& resource_id);
@@ -153,9 +155,12 @@
// removed before starting, they will be cancelled.
std::set<std::string> pending_fetch_list_;
- // The delay is used for delaying processing SyncTasks in DoSyncLoop().
+ // The delay is used for delaying processing tasks in AddTaskToQueue().
base::TimeDelta delay_;
+ // The delay is used for delaying retry of tasks on server errors.
+ base::TimeDelta long_delay_;
+
// 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<SyncClient> weak_ptr_factory_;
diff --git a/chrome/browser/chromeos/enrollment_dialog_view.cc b/chrome/browser/chromeos/enrollment_dialog_view.cc
index 31e3762..29cff16 100644
--- a/chrome/browser/chromeos/enrollment_dialog_view.cc
+++ b/chrome/browser/chromeos/enrollment_dialog_view.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_navigator.h"
+#include "chromeos/network/network_event_log.h"
#include "content/public/common/page_transition_types.h"
#include "extensions/common/constants.h"
#include "grit/generated_resources.h"
@@ -192,7 +193,7 @@
virtual ~DialogEnrollmentDelegate();
// EnrollmentDelegate overrides
- virtual void Enroll(const std::vector<std::string>& uri_list,
+ virtual bool Enroll(const std::vector<std::string>& uri_list,
const base::Closure& connect) OVERRIDE;
private:
@@ -212,8 +213,8 @@
DialogEnrollmentDelegate::~DialogEnrollmentDelegate() {}
-void DialogEnrollmentDelegate::Enroll(const std::vector<std::string>& uri_list,
- const base::Closure& connect) {
+bool DialogEnrollmentDelegate::Enroll(const std::vector<std::string>& uri_list,
+ const base::Closure& post_action) {
// Keep the closure for later activation if we notice that
// a certificate has been added.
@@ -229,16 +230,14 @@
EnrollmentDialogView::ShowDialog(owning_window_,
network_name_,
profile_,
- uri, connect);
- return;
+ uri, post_action);
+ return true;
}
}
- // If we didn't find a scheme we could handle, then don't continue connecting.
- // TODO(gspencer): provide a path to display this failure to the user. (but
- // for the most part they won't know what it means, since it's probably coming
- // from a policy-pushed ONC file).
- VLOG(1) << "Couldn't find usable scheme in enrollment URI(s)";
+ // No appropriate scheme was found.
+ NET_LOG_EVENT("No usable enrollment URI", network_name_);
+ return false;
}
} // namespace
diff --git a/chrome/browser/chromeos/enrollment_dialog_view.h b/chrome/browser/chromeos/enrollment_dialog_view.h
index a3cd8f0..b855cac 100644
--- a/chrome/browser/chromeos/enrollment_dialog_view.h
+++ b/chrome/browser/chromeos/enrollment_dialog_view.h
@@ -6,14 +6,31 @@
#define CHROME_BROWSER_CHROMEOS_ENROLLMENT_DIALOG_VIEW_H_
#include <string>
+#include <vector>
+#include "base/callback_forward.h"
#include "ui/gfx/native_widget_types.h"
class Profile;
namespace chromeos {
-class EnrollmentDelegate;
+// An interface that can be used to handle certificate enrollment URIs when
+// encountered. Also used by unit tests to avoid opening browser windows
+// when testing.
+class EnrollmentDelegate {
+ public:
+ EnrollmentDelegate() {}
+ virtual ~EnrollmentDelegate() {}
+
+ // Implemented to handle a given certificate enrollment URI. Returns false
+ // if the enrollment URI doesn't use a scheme that we can handle.
+ // |post_action| is called when enrollment completes.
+ virtual bool Enroll(const std::vector<std::string>& uri_list,
+ const base::Closure& post_action) = 0;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(EnrollmentDelegate);
+};
EnrollmentDelegate* CreateEnrollmentDelegate(gfx::NativeWindow owning_window,
const std::string& network_name,
diff --git a/chrome/browser/chromeos/extensions/external_cache.cc b/chrome/browser/chromeos/extensions/external_cache.cc
index 86c0f19..8174772 100644
--- a/chrome/browser/chromeos/extensions/external_cache.cc
+++ b/chrome/browser/chromeos/extensions/external_cache.cc
@@ -34,10 +34,12 @@
ExternalCache::ExternalCache(const std::string& cache_dir,
net::URLRequestContextGetter* request_context,
- Delegate* delegate)
+ Delegate* delegate,
+ bool always_check_updates)
: cache_dir_(cache_dir),
request_context_(request_context),
delegate_(delegate),
+ always_check_updates_(always_check_updates),
cached_extensions_(new base::DictionaryValue()),
weak_ptr_factory_(this),
worker_pool_token_(
@@ -54,7 +56,17 @@
void ExternalCache::UpdateExtensionsList(
scoped_ptr<base::DictionaryValue> prefs) {
extensions_ = prefs.Pass();
- CheckCacheNow();
+ if (extensions_->empty()) {
+ // Don't check cache and clear it if there are no extensions in the list.
+ // It is important case because login to supervised user shouldn't clear
+ // cache for normal users.
+ // TODO(dpolukhin): introduce reference counting to preserve cache elements
+ // when they are not needed for current user but needed for other users.
+ cached_extensions_->Clear();
+ UpdateExtensionLoader();
+ } else {
+ CheckCacheNow();
+ }
}
void ExternalCache::OnDamagedFileDetected(const base::FilePath& path) {
@@ -78,9 +90,12 @@
UpdateExtensionLoader();
// The file will be downloaded again on the next restart.
- content::BrowserThread::PostTask(
- content::BrowserThread::FILE, FROM_HERE,
- base::Bind(base::IgnoreResult(base::DeleteFile), path, true));
+ if (base::FilePath(cache_dir_).IsParent(path)) {
+ // Don't delete files out of cache_dir_.
+ content::BrowserThread::PostTask(
+ content::BrowserThread::FILE, FROM_HERE,
+ base::Bind(base::IgnoreResult(base::DeleteFile), path, true));
+ }
// Don't try to DownloadMissingExtensions() from here,
// since it can cause a fail/retry loop.
@@ -202,10 +217,10 @@
if (!file_util::CreateDirectory(dir)) {
LOG(ERROR) << "Failed to create ExternalCache directory at "
<< dir.value();
-
- // Nothing else to do. Cache won't be used.
- return;
}
+
+ // Nothing else to do. Cache won't be used.
+ return;
}
// Enumerate all the files in the cache |dir|, including directories
@@ -271,27 +286,35 @@
entry->SetString(extensions::ExternalProviderImpl::kExternalVersion,
version);
entry->SetString(extensions::ExternalProviderImpl::kExternalCrx,
- path.value());
+ path.value());
if (extension_urls::IsWebstoreUpdateUrl(GURL(update_url))) {
entry->SetBoolean(extensions::ExternalProviderImpl::kIsFromWebstore,
- true);
+ true);
}
} else if (
entry->GetString(extensions::ExternalProviderImpl::kExternalVersion,
&prev_version_string) &&
entry->GetString(extensions::ExternalProviderImpl::kExternalCrx,
&prev_crx)) {
- LOG(ERROR) << "Found two ExternalCache files for the same extension, "
- "will erase the oldest version";
Version prev_version(prev_version_string);
Version curr_version(version);
DCHECK(prev_version.IsValid());
DCHECK(curr_version.IsValid());
- if (prev_version.CompareTo(curr_version) < 0) {
- base::DeleteFile(base::FilePath(prev_crx), true /* recursive */);
+ if (prev_version.CompareTo(curr_version) <= 0) {
+ VLOG(1) << "ExternalCache found old cached version "
+ << prev_version_string << " path: " << prev_crx;
+ base::FilePath prev_crx_file(prev_crx);
+ if (dir.IsParent(prev_crx_file)) {
+ // Only delete old cached files under cache_dir_ folder.
+ base::DeleteFile(base::FilePath(prev_crx), true /* recursive */);
+ }
+ entry->SetString(extensions::ExternalProviderImpl::kExternalVersion,
+ version);
entry->SetString(extensions::ExternalProviderImpl::kExternalCrx,
path.value());
} else {
+ VLOG(1) << "ExternalCache found old cached version "
+ << version << " path: " << path.value();
base::DeleteFile(path, true /* recursive */);
}
} else {
@@ -322,12 +345,18 @@
// Check for updates for all extensions configured except for extensions
// marked as keep_if_present.
- std::string update_url;
if (downloader_ &&
- !entry->HasKey(extensions::ExternalProviderImpl::kKeepIfPresent) &&
- entry->GetString(extensions::ExternalProviderImpl::kExternalUpdateUrl,
- &update_url)) {
- downloader_->AddPendingExtension(it.key(), GURL(update_url), 0);
+ !entry->HasKey(extensions::ExternalProviderImpl::kKeepIfPresent)) {
+ GURL update_url;
+ std::string external_update_url;
+ if (entry->GetString(extensions::ExternalProviderImpl::kExternalUpdateUrl,
+ &external_update_url)) {
+ update_url = GURL(external_update_url);
+ } else if (always_check_updates_) {
+ update_url = extension_urls::GetWebstoreUpdateUrl();
+ }
+ if (update_url.is_valid())
+ downloader_->AddPendingExtension(it.key(), update_url, 0);
}
base::DictionaryValue* cached_entry = NULL;
@@ -410,9 +439,7 @@
base::DictionaryValue* entry = NULL;
std::string update_url;
- if (!extensions_->GetDictionary(id, &entry) ||
- !entry->GetString(extensions::ExternalProviderImpl::kExternalUpdateUrl,
- &update_url)) {
+ if (!extensions_->GetDictionary(id, &entry)) {
LOG(ERROR) << "ExternalCache cannot find entry for extension " << id;
return;
}
diff --git a/chrome/browser/chromeos/extensions/external_cache.h b/chrome/browser/chromeos/extensions/external_cache.h
index 2b4b4bf..07f2252 100644
--- a/chrome/browser/chromeos/extensions/external_cache.h
+++ b/chrome/browser/chromeos/extensions/external_cache.h
@@ -47,9 +47,12 @@
};
// The |request_context| is used for the update checks.
+ // By default updates are checked for the extensions with external_update_url.
+ // If |always_check_webstore| set, updates will be check for external_crx too.
ExternalCache(const std::string& cache_dir,
net::URLRequestContextGetter* request_context,
- Delegate* delegate);
+ Delegate* delegate,
+ bool always_check_updates);
virtual ~ExternalCache();
// Returns already cached extensions.
@@ -150,6 +153,9 @@
// Delegate that would like to get notifications about cache updates.
Delegate* delegate_;
+ // Updates needs to be check for the extensions with external_crx too.
+ bool always_check_updates_;
+
// This is the list of extensions currently configured.
scoped_ptr<base::DictionaryValue> extensions_;
diff --git a/chrome/browser/chromeos/extensions/external_pref_cache_loader.cc b/chrome/browser/chromeos/extensions/external_pref_cache_loader.cc
index cd02dae..470b743 100644
--- a/chrome/browser/chromeos/extensions/external_pref_cache_loader.cc
+++ b/chrome/browser/chromeos/extensions/external_pref_cache_loader.cc
@@ -38,7 +38,7 @@
if (!external_cache_.get()) {
external_cache_.reset(new ExternalCache(kPreinstalledAppsCacheDir,
g_browser_process->system_request_context(),
- this));
+ this, true));
}
external_cache_->UpdateExtensionsList(prefs_.Pass());
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.cc b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
index 58296be..df5ef07 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
@@ -21,7 +21,6 @@
#include "chrome/browser/chromeos/extensions/file_manager/mounted_disk_monitor.h"
#include "chrome/browser/chromeos/login/login_display_host_impl.h"
#include "chrome/browser/chromeos/login/screen_locker.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
#include "chrome/browser/drive/drive_service_interface.h"
#include "chrome/browser/extensions/event_names.h"
#include "chrome/browser/extensions/event_router.h"
@@ -30,12 +29,15 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "chromeos/login/login_state.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state_handler.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_source.h"
#include "webkit/common/fileapi/file_system_types.h"
#include "webkit/common/fileapi/file_system_util.h"
using chromeos::disks::DiskMountManager;
+using chromeos::NetworkHandler;
using content::BrowserThread;
using drive::DriveIntegrationService;
using drive::DriveIntegrationServiceFactory;
@@ -254,9 +256,9 @@
integration_service->job_list()->RemoveObserver(this);
}
- if (chromeos::ConnectivityStateHelper::IsInitialized()) {
- chromeos::ConnectivityStateHelper::Get()->
- RemoveNetworkManagerObserver(this);
+ if (NetworkHandler::IsInitialized()) {
+ NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
+ FROM_HERE);
}
profile_ = NULL;
}
@@ -288,9 +290,9 @@
integration_service->job_list()->AddObserver(this);
}
- if (chromeos::ConnectivityStateHelper::IsInitialized()) {
- chromeos::ConnectivityStateHelper::Get()->
- AddNetworkManagerObserver(this);
+ if (NetworkHandler::IsInitialized()) {
+ NetworkHandler::Get()->network_state_handler()->AddObserver(this,
+ FROM_HERE);
}
mounted_disk_monitor_.reset(new MountedDiskMonitor());
@@ -476,7 +478,7 @@
BroadcastEvent(event.Pass());
}
-void EventRouter::DefaultNetworkChanged() {
+void EventRouter::DefaultNetworkChanged(const chromeos::NetworkState* network) {
NetworkManagerChanged();
}
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.h b/chrome/browser/chromeos/extensions/file_manager/event_router.h
index e10e30b..ae4cc86 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.h
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.h
@@ -14,13 +14,17 @@
#include "chrome/browser/chromeos/drive/file_system_observer.h"
#include "chrome/browser/chromeos/drive/job_list.h"
#include "chrome/browser/chromeos/extensions/file_manager/file_watcher.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper_observer.h"
#include "chrome/browser/drive/drive_service_interface.h"
#include "chromeos/disks/disk_mount_manager.h"
+#include "chromeos/network/network_state_handler_observer.h"
class PrefChangeRegistrar;
class Profile;
+namespace chromeos {
+class NetworkState;
+}
+
namespace file_manager {
class DesktopNotifications;
@@ -30,7 +34,7 @@
// affecting File Manager. Dispatches appropriate File Browser events.
class EventRouter
: public chromeos::disks::DiskMountManager::Observer,
- public chromeos::ConnectivityStateHelperObserver,
+ public chromeos::NetworkStateHandlerObserver,
public drive::DriveIntegrationServiceObserver,
public drive::FileSystemObserver,
public drive::JobListObserver,
@@ -77,9 +81,10 @@
chromeos::FormatError error_code,
const std::string& device_path) OVERRIDE;
- // chromeos::ConnectivityStateHelperObserver override.
+ // chromeos::NetworkStateHandlerObserver overrides.
virtual void NetworkManagerChanged() OVERRIDE;
- virtual void DefaultNetworkChanged() OVERRIDE;
+ virtual void DefaultNetworkChanged(
+ const chromeos::NetworkState* network) OVERRIDE;
// drive::JobListObserver overrides.
virtual void OnJobAdded(const drive::JobInfo& job_info) OVERRIDE;
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.cc b/chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.cc
new file mode 100644
index 0000000..771a5ac
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.cc
@@ -0,0 +1,615 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.h"
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/i18n/case_conversion.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/chromeos/drive/file_system_util.h"
+#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
+#include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
+#include "chrome/browser/chromeos/fileapi/file_system_backend.h"
+#include "chrome/browser/extensions/event_router.h"
+#include "chrome/browser/extensions/extension_host.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/lazy_background_task_queue.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/extensions/api/file_browser_handlers/file_browser_handler.h"
+#include "chrome/common/extensions/background_info.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/child_process_security_policy.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/browser/web_contents.h"
+#include "net/base/escape.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+#include "webkit/browser/fileapi/file_system_url.h"
+
+using content::BrowserThread;
+using content::ChildProcessSecurityPolicy;
+using content::SiteInstance;
+using content::WebContents;
+using extensions::Extension;
+using fileapi::FileSystemURL;
+
+namespace file_manager {
+namespace file_browser_handlers {
+namespace {
+
+// Returns process id of the process the extension is running in.
+int ExtractProcessFromExtensionId(Profile* profile,
+ const std::string& extension_id) {
+ GURL extension_url =
+ Extension::GetBaseURLFromExtensionId(extension_id);
+ ExtensionProcessManager* manager =
+ extensions::ExtensionSystem::Get(profile)->process_manager();
+
+ SiteInstance* site_instance = manager->GetSiteInstanceForURL(extension_url);
+ if (!site_instance || !site_instance->HasProcess())
+ return -1;
+ content::RenderProcessHost* process = site_instance->GetProcess();
+
+ return process->GetID();
+}
+
+// Finds a file browser handler that matches |action_id|. Returns NULL if not
+// found.
+const FileBrowserHandler* FindFileBrowserHandlerForActionId(
+ const Extension* extension,
+ const std::string& action_id) {
+ FileBrowserHandler::List* handler_list =
+ FileBrowserHandler::GetHandlers(extension);
+ for (FileBrowserHandler::List::const_iterator handler_iter =
+ handler_list->begin();
+ handler_iter != handler_list->end();
+ ++handler_iter) {
+ if (handler_iter->get()->id() == action_id)
+ return handler_iter->get();
+ }
+ return NULL;
+}
+
+std::string EscapedUtf8ToLower(const std::string& str) {
+ string16 utf16 = UTF8ToUTF16(
+ net::UnescapeURLComponent(str, net::UnescapeRule::NORMAL));
+ return net::EscapeUrlEncodedData(
+ UTF16ToUTF8(base::i18n::ToLower(utf16)),
+ false /* do not replace space with plus */);
+}
+
+// Finds file browser handlers that can handle the |selected_file_url|.
+FileBrowserHandlerList FindFileBrowserHandlersForURL(
+ Profile* profile,
+ const GURL& selected_file_url) {
+ ExtensionService* service =
+ extensions::ExtensionSystem::Get(profile)->extension_service();
+ // In unit-tests, we may not have an ExtensionService.
+ if (!service)
+ return FileBrowserHandlerList();
+
+ // We need case-insensitive matching, and pattern in the handler is already
+ // in lower case.
+ const GURL lowercase_url(EscapedUtf8ToLower(selected_file_url.spec()));
+
+ FileBrowserHandlerList results;
+ for (ExtensionSet::const_iterator iter = service->extensions()->begin();
+ iter != service->extensions()->end();
+ ++iter) {
+ const Extension* extension = iter->get();
+ if (profile->IsOffTheRecord() &&
+ !service->IsIncognitoEnabled(extension->id()))
+ continue;
+
+ FileBrowserHandler::List* handler_list =
+ FileBrowserHandler::GetHandlers(extension);
+ if (!handler_list)
+ continue;
+ for (FileBrowserHandler::List::const_iterator handler_iter =
+ handler_list->begin();
+ handler_iter != handler_list->end();
+ ++handler_iter) {
+ const FileBrowserHandler* handler = handler_iter->get();
+ if (!handler->MatchesURL(lowercase_url))
+ continue;
+
+ results.push_back(handler_iter->get());
+ }
+ }
+ return results;
+}
+
+// Finds a file browser handler that matches |extension_id| and |action_id|
+// from |handler_list|. Returns a mutable iterator to the handler if
+// found. Returns handler_list->end() if not found.
+FileBrowserHandlerList::iterator
+FindFileBrowserHandlerForExtensionIdAndActionId(
+ FileBrowserHandlerList* handler_list,
+ const std::string& extension_id,
+ const std::string& action_id) {
+ DCHECK(handler_list);
+
+ FileBrowserHandlerList::iterator iter = handler_list->begin();
+ while (iter != handler_list->end() &&
+ !((*iter)->extension_id() == extension_id &&
+ (*iter)->id() == action_id)) {
+ ++iter;
+ }
+ return iter;
+}
+
+// This class is used to execute a file browser handler task. Here's how this
+// works:
+//
+// 1) Open the "external" file system
+// 2) Set up permissions for the target files on the external file system.
+// 3) Raise onExecute event with the action ID and entries of the target
+// files. The event will launch the file browser handler if not active.
+// 4) In the file browser handler, onExecute event is handled and executes the
+// task in JavaScript.
+//
+// That said, the class itself does not execute a task. The task will be
+// executed in JavaScript.
+class FileBrowserHandlerExecutor {
+ public:
+ FileBrowserHandlerExecutor(Profile* profile,
+ const Extension* extension,
+ int32 tab_id,
+ const std::string& action_id);
+
+ // Executes the task for each file. |done| will be run with the result.
+ void Execute(const std::vector<FileSystemURL>& file_urls,
+ const file_tasks::FileTaskFinishedCallback& done);
+
+ private:
+ // This object is responsible to delete itself.
+ virtual ~FileBrowserHandlerExecutor();
+
+ struct FileDefinition {
+ FileDefinition();
+ ~FileDefinition();
+
+ base::FilePath virtual_path;
+ base::FilePath absolute_path;
+ bool is_directory;
+ };
+
+ typedef std::vector<FileDefinition> FileDefinitionList;
+
+ // Checks legitimacy of file url and grants file RO access permissions from
+ // handler (target) extension and its renderer process.
+ static FileDefinitionList SetupFileAccessPermissions(
+ scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
+ const scoped_refptr<const Extension>& handler_extension,
+ const std::vector<FileSystemURL>& file_urls);
+
+ void DidOpenFileSystem(const std::vector<FileSystemURL>& file_urls,
+ base::PlatformFileError result,
+ const std::string& file_system_name,
+ const GURL& file_system_root);
+
+ void ExecuteDoneOnUIThread(bool success);
+ void ExecuteFileActionsOnUIThread(const std::string& file_system_name,
+ const GURL& file_system_root,
+ const FileDefinitionList& file_list);
+ void SetupPermissionsAndDispatchEvent(const std::string& file_system_name,
+ const GURL& file_system_root,
+ const FileDefinitionList& file_list,
+ int handler_pid_in,
+ extensions::ExtensionHost* host);
+
+ // Registers file permissions from |handler_host_permissions_| with
+ // ChildProcessSecurityPolicy for process with id |handler_pid|.
+ void SetupHandlerHostFileAccessPermissions(
+ const FileDefinitionList& file_list,
+ const Extension* extension,
+ int handler_pid);
+
+ Profile* profile_;
+ scoped_refptr<const Extension> extension_;
+ int32 tab_id_;
+ const std::string action_id_;
+ file_tasks::FileTaskFinishedCallback done_;
+ base::WeakPtrFactory<FileBrowserHandlerExecutor> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileBrowserHandlerExecutor);
+};
+
+FileBrowserHandlerExecutor::FileDefinition::FileDefinition()
+ : is_directory(false) {
+}
+
+FileBrowserHandlerExecutor::FileDefinition::~FileDefinition() {
+}
+
+// static
+FileBrowserHandlerExecutor::FileDefinitionList
+FileBrowserHandlerExecutor::SetupFileAccessPermissions(
+ scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
+ const scoped_refptr<const Extension>& handler_extension,
+ const std::vector<FileSystemURL>& file_urls) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DCHECK(handler_extension.get());
+
+ fileapi::ExternalFileSystemBackend* backend =
+ file_system_context_handler->external_backend();
+
+ FileDefinitionList file_list;
+ for (size_t i = 0; i < file_urls.size(); ++i) {
+ const FileSystemURL& url = file_urls[i];
+
+ // Check if this file system entry exists first.
+ base::PlatformFileInfo file_info;
+
+ base::FilePath local_path = url.path();
+ base::FilePath virtual_path = url.virtual_path();
+
+ bool is_drive_file = url.type() == fileapi::kFileSystemTypeDrive;
+ DCHECK(!is_drive_file || drive::util::IsUnderDriveMountPoint(local_path));
+
+ // If the file is under drive mount point, there is no actual file to be
+ // found on the url.path().
+ if (!is_drive_file) {
+ if (!base::PathExists(local_path) ||
+ file_util::IsLink(local_path) ||
+ !file_util::GetFileInfo(local_path, &file_info)) {
+ continue;
+ }
+ }
+
+ // Grant access to this particular file to target extension. This will
+ // ensure that the target extension can access only this FS entry and
+ // prevent from traversing FS hierarchy upward.
+ backend->GrantFileAccessToExtension(
+ handler_extension->id(), virtual_path);
+
+ // Output values.
+ FileDefinition file;
+ file.virtual_path = virtual_path;
+ file.is_directory = file_info.is_directory;
+ file.absolute_path = local_path;
+ file_list.push_back(file);
+ }
+ return file_list;
+}
+
+FileBrowserHandlerExecutor::FileBrowserHandlerExecutor(
+ Profile* profile,
+ const Extension* extension,
+ int32 tab_id,
+ const std::string& action_id)
+ : profile_(profile),
+ extension_(extension),
+ tab_id_(tab_id),
+ action_id_(action_id),
+ weak_ptr_factory_(this) {
+}
+
+FileBrowserHandlerExecutor::~FileBrowserHandlerExecutor() {}
+
+void FileBrowserHandlerExecutor::Execute(
+ const std::vector<FileSystemURL>& file_urls,
+ const file_tasks::FileTaskFinishedCallback& done) {
+ done_ = done;
+
+ // Get file system context for the extension to which onExecute event will be
+ // sent. The file access permissions will be granted to the extension in the
+ // file system context for the files in |file_urls|.
+ fileapi_util::GetFileSystemContextForExtensionId(
+ profile_, extension_->id())->OpenFileSystem(
+ Extension::GetBaseURLFromExtensionId(extension_->id()).GetOrigin(),
+ fileapi::kFileSystemTypeExternal,
+ fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
+ base::Bind(&FileBrowserHandlerExecutor::DidOpenFileSystem,
+ weak_ptr_factory_.GetWeakPtr(),
+ file_urls));
+}
+
+void FileBrowserHandlerExecutor::DidOpenFileSystem(
+ const std::vector<FileSystemURL>& file_urls,
+ base::PlatformFileError result,
+ const std::string& file_system_name,
+ const GURL& file_system_root) {
+ if (result != base::PLATFORM_FILE_OK) {
+ ExecuteDoneOnUIThread(false);
+ return;
+ }
+
+ scoped_refptr<fileapi::FileSystemContext> file_system_context(
+ fileapi_util::GetFileSystemContextForExtensionId(
+ profile_, extension_->id()));
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&SetupFileAccessPermissions,
+ file_system_context,
+ extension_,
+ file_urls),
+ base::Bind(&FileBrowserHandlerExecutor::ExecuteFileActionsOnUIThread,
+ weak_ptr_factory_.GetWeakPtr(),
+ file_system_name,
+ file_system_root));
+}
+
+void FileBrowserHandlerExecutor::ExecuteDoneOnUIThread(bool success) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (!done_.is_null())
+ done_.Run(success);
+ delete this;
+}
+
+void FileBrowserHandlerExecutor::ExecuteFileActionsOnUIThread(
+ const std::string& file_system_name,
+ const GURL& file_system_root,
+ const FileDefinitionList& file_list) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (file_list.empty()) {
+ ExecuteDoneOnUIThread(false);
+ return;
+ }
+
+ int handler_pid = ExtractProcessFromExtensionId(profile_, extension_->id());
+ if (handler_pid <= 0 &&
+ !extensions::BackgroundInfo::HasLazyBackgroundPage(extension_.get())) {
+ ExecuteDoneOnUIThread(false);
+ return;
+ }
+
+ if (handler_pid > 0) {
+ SetupPermissionsAndDispatchEvent(file_system_name, file_system_root,
+ file_list, handler_pid, NULL);
+ } else {
+ // We have to wake the handler background page before we proceed.
+ extensions::LazyBackgroundTaskQueue* queue =
+ extensions::ExtensionSystem::Get(profile_)->
+ lazy_background_task_queue();
+ if (!queue->ShouldEnqueueTask(profile_, extension_.get())) {
+ ExecuteDoneOnUIThread(false);
+ return;
+ }
+ queue->AddPendingTask(
+ profile_, extension_->id(),
+ base::Bind(
+ &FileBrowserHandlerExecutor::SetupPermissionsAndDispatchEvent,
+ weak_ptr_factory_.GetWeakPtr(),
+ file_system_name,
+ file_system_root,
+ file_list,
+ handler_pid));
+ }
+}
+
+void FileBrowserHandlerExecutor::SetupPermissionsAndDispatchEvent(
+ const std::string& file_system_name,
+ const GURL& file_system_root,
+ const FileDefinitionList& file_list,
+ int handler_pid_in,
+ extensions::ExtensionHost* host) {
+ int handler_pid = host ? host->render_process_host()->GetID() :
+ handler_pid_in;
+
+ if (handler_pid <= 0) {
+ ExecuteDoneOnUIThread(false);
+ return;
+ }
+
+ extensions::EventRouter* event_router =
+ extensions::ExtensionSystem::Get(profile_)->event_router();
+ if (!event_router) {
+ ExecuteDoneOnUIThread(false);
+ return;
+ }
+
+ SetupHandlerHostFileAccessPermissions(
+ file_list, extension_.get(), handler_pid);
+
+ scoped_ptr<ListValue> event_args(new ListValue());
+ event_args->Append(new base::StringValue(action_id_));
+ DictionaryValue* details = new DictionaryValue();
+ event_args->Append(details);
+ // Get file definitions. These will be replaced with Entry instances by
+ // dispatchEvent() method from event_binding.js.
+ ListValue* file_entries = new ListValue();
+ details->Set("entries", file_entries);
+ for (FileDefinitionList::const_iterator iter = file_list.begin();
+ iter != file_list.end();
+ ++iter) {
+ DictionaryValue* file_def = new DictionaryValue();
+ file_entries->Append(file_def);
+ file_def->SetString("fileSystemName", file_system_name);
+ file_def->SetString("fileSystemRoot", file_system_root.spec());
+ base::FilePath root(FILE_PATH_LITERAL("/"));
+ base::FilePath full_path = root.Append(iter->virtual_path);
+ file_def->SetString("fileFullPath", full_path.value());
+ file_def->SetBoolean("fileIsDirectory", iter->is_directory);
+ }
+
+ details->SetInteger("tab_id", tab_id_);
+
+ scoped_ptr<extensions::Event> event(new extensions::Event(
+ "fileBrowserHandler.onExecute", event_args.Pass()));
+ event->restrict_to_profile = profile_;
+ event_router->DispatchEventToExtension(extension_->id(), event.Pass());
+
+ ExecuteDoneOnUIThread(true);
+}
+
+void FileBrowserHandlerExecutor::SetupHandlerHostFileAccessPermissions(
+ const FileDefinitionList& file_list,
+ const Extension* extension,
+ int handler_pid) {
+ const FileBrowserHandler* action = FindFileBrowserHandlerForActionId(
+ extension_, action_id_);
+ for (FileDefinitionList::const_iterator iter = file_list.begin();
+ iter != file_list.end();
+ ++iter) {
+ if (!action)
+ continue;
+ if (action->CanRead()) {
+ content::ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
+ handler_pid, iter->absolute_path);
+ }
+ if (action->CanWrite()) {
+ content::ChildProcessSecurityPolicy::GetInstance()->
+ GrantCreateReadWriteFile(handler_pid, iter->absolute_path);
+ }
+ }
+}
+
+} // namespace
+
+bool ExecuteFileBrowserHandler(
+ Profile* profile,
+ const Extension* extension,
+ int32 tab_id,
+ const std::string& action_id,
+ const std::vector<FileSystemURL>& file_urls,
+ const file_tasks::FileTaskFinishedCallback& done) {
+ // Forbid calling undeclared handlers.
+ if (!FindFileBrowserHandlerForActionId(extension, action_id))
+ return false;
+
+ // The executor object will be self deleted on completion.
+ (new FileBrowserHandlerExecutor(
+ profile, extension, tab_id, action_id))->Execute(file_urls, done);
+ return true;
+}
+
+bool IsFallbackFileBrowserHandler(const FileBrowserHandler* handler) {
+ const std::string& extension_id = handler->extension_id();
+ return (extension_id == kFileBrowserDomain ||
+ extension_id == extension_misc::kQuickOfficeComponentExtensionId ||
+ extension_id == extension_misc::kQuickOfficeDevExtensionId ||
+ extension_id == extension_misc::kQuickOfficeExtensionId);
+}
+
+FileBrowserHandlerList FindDefaultFileBrowserHandlers(
+ Profile* profile,
+ const std::vector<base::FilePath>& file_list,
+ const FileBrowserHandlerList& common_handlers) {
+ FileBrowserHandlerList default_handlers;
+
+ std::set<std::string> default_ids;
+ for (std::vector<base::FilePath>::const_iterator it = file_list.begin();
+ it != file_list.end(); ++it) {
+ std::string task_id = file_tasks::GetDefaultTaskIdFromPrefs(
+ profile, "", it->Extension());
+ if (!task_id.empty())
+ default_ids.insert(task_id);
+ }
+
+ const FileBrowserHandler* fallback_handler = NULL;
+ // Convert the default task IDs collected above to one of the handler pointers
+ // from common_handlers.
+ for (size_t i = 0; i < common_handlers.size(); ++i) {
+ const FileBrowserHandler* handler = common_handlers[i];
+ std::string task_id = file_tasks::MakeTaskID(
+ handler->extension_id(),
+ file_tasks::kFileBrowserHandlerTaskType,
+ handler->id());
+ std::set<std::string>::iterator default_iter = default_ids.find(task_id);
+ if (default_iter != default_ids.end()) {
+ default_handlers.push_back(handler);
+ continue;
+ }
+
+ // Remember the first fallback handler.
+ if (!fallback_handler && IsFallbackFileBrowserHandler(handler))
+ fallback_handler = handler;
+ }
+
+ // If there are no default handlers found, use fallback as default.
+ if (fallback_handler && default_handlers.empty())
+ default_handlers.push_back(fallback_handler);
+
+ return default_handlers;
+}
+
+FileBrowserHandlerList FindCommonFileBrowserHandlers(
+ Profile* profile,
+ const std::vector<GURL>& file_list) {
+ FileBrowserHandlerList common_handlers;
+ for (std::vector<GURL>::const_iterator it = file_list.begin();
+ it != file_list.end(); ++it) {
+ FileBrowserHandlerList handlers =
+ FindFileBrowserHandlersForURL(profile, *it);
+ // If there is nothing to do for one file, the intersection of handlers
+ // for all files will be empty at the end, so no need to check further.
+ if (handlers.empty())
+ return FileBrowserHandlerList();
+
+ // For the very first file, just copy all the elements.
+ if (it == file_list.begin()) {
+ common_handlers = handlers;
+ } else {
+ // For all additional files, find intersection between the accumulated and
+ // file specific set.
+ FileBrowserHandlerList intersection;
+ std::set_intersection(common_handlers.begin(), common_handlers.end(),
+ handlers.begin(), handlers.end(),
+ std::back_inserter(intersection));
+ common_handlers = intersection;
+ if (common_handlers.empty())
+ return FileBrowserHandlerList();
+ }
+ }
+
+ FileBrowserHandlerList::iterator watch_iter =
+ FindFileBrowserHandlerForExtensionIdAndActionId(
+ &common_handlers, kFileBrowserDomain, kFileBrowserWatchTaskId);
+ FileBrowserHandlerList::iterator gallery_iter =
+ FindFileBrowserHandlerForExtensionIdAndActionId(
+ &common_handlers, kFileBrowserDomain, kFileBrowserGalleryTaskId);
+ if (watch_iter != common_handlers.end() &&
+ gallery_iter != common_handlers.end()) {
+ // Both "watch" and "gallery" actions are applicable which means that the
+ // selection is all videos. Showing them both is confusing, so we only keep
+ // the one that makes more sense ("watch" for single selection, "gallery"
+ // for multiple selection).
+ if (file_list.size() == 1)
+ common_handlers.erase(gallery_iter);
+ else
+ common_handlers.erase(watch_iter);
+ }
+
+ return common_handlers;
+}
+
+const FileBrowserHandler* FindFileBrowserHandlerForURLAndPath(
+ Profile* profile,
+ const GURL& url,
+ const base::FilePath& file_path) {
+ std::vector<GURL> file_urls;
+ file_urls.push_back(url);
+
+ FileBrowserHandlerList common_handlers =
+ FindCommonFileBrowserHandlers(profile, file_urls);
+ if (common_handlers.empty())
+ return NULL;
+
+ std::vector<base::FilePath> file_paths;
+ file_paths.push_back(file_path);
+
+ FileBrowserHandlerList default_handlers =
+ FindDefaultFileBrowserHandlers(profile, file_paths, common_handlers);
+
+ // If there's none, or more than one, then we don't have a canonical default.
+ if (!default_handlers.empty()) {
+ // There should not be multiple default handlers for a single URL.
+ DCHECK_EQ(1u, default_handlers.size());
+
+ return *default_handlers.begin();
+ }
+
+ // If there are no default handlers, use first handler in the list (file
+ // manager does the same in this situation). TODO(tbarzic): This is not so
+ // optimal behaviour.
+ return *common_handlers.begin();
+}
+
+} // namespace file_browser_handlers
+} // namespace file_manager
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.h b/chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.h
new file mode 100644
index 0000000..87b5c92
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.h
@@ -0,0 +1,84 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This file provides utility functions for file browser handlers.
+// https://developer.chrome.com/extensions/fileBrowserHandler.html
+
+#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILE_BROWSER_HANDLERS_H_
+#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILE_BROWSER_HANDLERS_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "chrome/browser/chromeos/extensions/file_manager/file_tasks.h"
+
+class FileBrowserHandler;
+class GURL;
+class Profile;
+
+namespace base {
+class FilePath;
+}
+
+namespace extensions {
+class Extension;
+}
+
+namespace fileapi {
+class FileSystemURL;
+}
+
+namespace file_manager {
+namespace file_browser_handlers {
+
+// Tasks are stored as a vector in order of priorities.
+typedef std::vector<const FileBrowserHandler*> FileBrowserHandlerList;
+
+// Returns true if the given file browser handler should be used as a
+// fallback. Such handlers are Files.app's internal handlers as well as quick
+// office extensions.
+bool IsFallbackFileBrowserHandler(const FileBrowserHandler* handler);
+
+// Finds file browser handlers set as default from |common_tasks| for
+// |file_list|. If no handlers are set as default, choose the the firstly
+// found fallback handler as default.
+FileBrowserHandlerList FindDefaultFileBrowserHandlers(
+ Profile* profile,
+ const std::vector<base::FilePath>& file_list,
+ const FileBrowserHandlerList& common_tasks);
+
+// Returns the list of file browser handlers that can open all files in
+// |file_list|.
+FileBrowserHandlerList FindCommonFileBrowserHandlers(
+ Profile* profile,
+ const std::vector<GURL>& file_list);
+
+// Finds a file browser handler for a file whose URL is |url| and whose path
+// is |path|. Returns the default handler if one is defined (The default
+// handler is the one that is assigned to the file manager task button by
+// default). If the default handler is not found, tries to match the url with
+// one of the file browser handlers.
+const FileBrowserHandler* FindFileBrowserHandlerForURLAndPath(
+ Profile* profile,
+ const GURL& url,
+ const base::FilePath& path);
+
+// Executes a file browser handler specified by |extension| of the given
+// action ID for |file_urls|. Returns false if undeclared handlers are
+// found. |done| is on completion. See also the comment at ExecuteFileTask()
+// for other parameters.
+bool ExecuteFileBrowserHandler(
+ Profile* profile,
+ const extensions::Extension* extension,
+ int32 tab_id,
+ const std::string& action_id,
+ const std::vector<fileapi::FileSystemURL>& file_urls,
+ const file_tasks::FileTaskFinishedCallback& done);
+
+} // namespace file_browser_handlers
+} // namespace file_manager
+
+#endif // CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILE_BROWSER_HANDLERS_H_
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_util.cc b/chrome/browser/chromeos/extensions/file_manager/file_manager_util.cc
index e38c55b..9e9d34a 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_manager_util.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_util.cc
@@ -18,7 +18,9 @@
#include "chrome/browser/chromeos/drive/drive_integration_service.h"
#include "chrome/browser/chromeos/drive/file_system.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
+#include "chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.h"
#include "chrome/browser/chromeos/extensions/file_manager/file_tasks.h"
+#include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
#include "chrome/browser/chromeos/media/media_player.h"
#include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
#include "chrome/browser/extensions/crx_installer.h"
@@ -98,15 +100,6 @@
".mhtml", ".mht", ".svg"
};
-// List of all extensions we want to be shown in histogram that keep track of
-// files that were unsuccessfully tried to be opened.
-// The list has to be synced with histogram values.
-const char* kUMATrackingExtensions[] = {
- "other", ".doc", ".docx", ".odt", ".rtf", ".pdf", ".ppt", ".pptx", ".odp",
- ".xls", ".xlsx", ".ods", ".csv", ".odf", ".rar", ".asf", ".wma", ".wmv",
- ".mov", ".mpg", ".log"
-};
-
// Returns a file manager URL for the given |path|.
GURL GetFileManagerUrl(const char* path) {
return GURL(std::string("chrome-extension://") + kFileBrowserDomain + path);
@@ -154,19 +147,6 @@
return IsPepperPluginEnabled(profile, plugin_path);
}
-// Returns index |ext| has in the |array|. If there is no |ext| in |array|, last
-// element's index is return (last element should have irrelevant value).
-int UMAExtensionIndex(const char *file_extension,
- const char** array,
- size_t array_size) {
- for (size_t i = 0; i < array_size; i++) {
- if (base::strcasecmp(file_extension, array[i]) == 0) {
- return i;
- }
- }
- return 0;
-}
-
// Convert numeric dialog type to a string.
std::string GetDialogTypeAsString(
ui::SelectFileDialog::Type dialog_type) {
@@ -238,7 +218,8 @@
scoped_refptr<extensions::CrxInstaller> installer(
extensions::CrxInstaller::Create(
service,
- new ExtensionInstallPrompt(browser->profile(), NULL, NULL)));
+ scoped_ptr<ExtensionInstallPrompt>(new ExtensionInstallPrompt(
+ browser->profile(), NULL, NULL))));
installer->set_error_on_unsupported_requirements(true);
installer->set_is_gallery_install(false);
installer->set_allow_silent_install(false);
@@ -270,22 +251,18 @@
return true;
}
-// Executes handler specified with |extension_id| and |action_id| for |url|.
+// Executes handler specified with |task| for |url|.
void ExecuteHandler(Profile* profile,
- std::string extension_id,
- std::string action_id,
- const GURL& url,
- const std::string& task_type) {
+ const file_tasks::TaskDescriptor& task,
+ const GURL& url) {
// If File Browser has not been open yet then it did not request access
// to the file system. Do it now.
if (!GrantFileSystemAccessToFileBrowser(profile))
return;
- GURL site = extensions::ExtensionSystem::Get(profile)->extension_service()->
- GetSiteForExtensionId(kFileBrowserDomain);
fileapi::FileSystemContext* file_system_context =
- BrowserContext::GetStoragePartitionForSite(profile, site)->
- GetFileSystemContext();
+ fileapi_util::GetFileSystemContextForExtensionId(
+ profile, kFileBrowserDomain);
// We are executing the task on behalf of File Browser extension.
const GURL source_url = GetFileBrowserUrl();
@@ -297,9 +274,7 @@
source_url,
kFileBrowserDomain,
0, // no tab id
- extension_id,
- task_type,
- action_id,
+ task,
urls,
file_tasks::FileTaskFinishedCallback());
}
@@ -313,10 +288,10 @@
if (!ConvertFileToFileSystemUrl(profile, path, kFileBrowserDomain, &url))
return;
- // Some values of |action_id| are not listed in the manifest and are used
- // to parameterize the behavior when opening the Files app window.
- ExecuteHandler(profile, kFileBrowserDomain, action_id, url,
- file_tasks::kTaskFile);
+ file_tasks::TaskDescriptor task(kFileBrowserDomain,
+ file_tasks::kFileBrowserHandlerTaskType,
+ action_id);
+ ExecuteHandler(profile, task, url);
}
Browser* GetBrowserForUrl(GURL target_url) {
@@ -370,11 +345,15 @@
for (FileHandlerList::iterator i = file_handlers.begin();
i != file_handlers.end(); ++i) {
const extensions::FileHandlerInfo* handler = *i;
- std::string task_id = file_tasks::MakeTaskID(extension->id(),
- file_tasks::kTaskApp, handler->id);
+ std::string task_id = file_tasks::MakeTaskID(
+ extension->id(),
+ file_tasks::kFileHandlerTaskType,
+ handler->id);
if (task_id == default_task_id) {
- ExecuteHandler(profile, extension->id(), handler->id, url,
- file_tasks::kTaskApp);
+ file_tasks::TaskDescriptor task(extension->id(),
+ file_tasks::kFileHandlerTaskType,
+ handler->id);
+ ExecuteHandler(profile, task, url);
return true;
} else if (!first_handler) {
@@ -384,8 +363,10 @@
}
}
if (first_handler) {
- ExecuteHandler(profile, extension_for_first_handler->id(),
- first_handler->id, url, file_tasks::kTaskApp);
+ file_tasks::TaskDescriptor task(extension_for_first_handler->id(),
+ file_tasks::kFileHandlerTaskType,
+ first_handler->id);
+ ExecuteHandler(profile, task, url);
return true;
}
return false;
@@ -410,15 +391,19 @@
action_id == kFileBrowserMountArchiveTaskId ||
action_id == kFileBrowserPlayTaskId ||
action_id == kFileBrowserWatchTaskId) {
- ExecuteHandler(profile, extension_id, action_id, url,
- file_tasks::kTaskFile);
+ file_tasks::TaskDescriptor task(extension_id,
+ file_tasks::kFileBrowserHandlerTaskType,
+ action_id);
+ ExecuteHandler(profile, task, url);
return true;
}
return ExecuteBuiltinHandler(browser, path);
}
- ExecuteHandler(profile, extension_id, action_id, url,
- file_tasks::kTaskFile);
+ file_tasks::TaskDescriptor task(extension_id,
+ file_tasks::kFileBrowserHandlerTaskType,
+ action_id);
+ ExecuteHandler(profile, task, url);
return true;
}
@@ -430,7 +415,6 @@
std::string mime_type = GetMimeTypeForPath(path);
std::string default_task_id = file_tasks::GetDefaultTaskIdFromPrefs(
profile, mime_type, path.Extension());
- const FileBrowserHandler* handler;
// We choose the file handler from the following in decreasing priority or
// fail if none support the file type:
@@ -440,15 +424,20 @@
// 4. non-default app
// 5. non-default extension
// Note that there can be at most one of default extension and default app.
- if (!file_tasks::GetTaskForURLAndPath(profile, url, path, &handler)) {
+ const FileBrowserHandler* handler =
+ file_browser_handlers::FindFileBrowserHandlerForURLAndPath(
+ profile, url, path);
+ if (!handler) {
return ExecuteDefaultAppHandler(
profile, path, url, mime_type, default_task_id);
}
std::string handler_task_id = file_tasks::MakeTaskID(
- handler->extension_id(), file_tasks::kTaskFile, handler->id());
+ handler->extension_id(),
+ file_tasks::kFileBrowserHandlerTaskType,
+ handler->id());
if (handler_task_id != default_task_id &&
- !file_tasks::IsFallbackTask(handler) &&
+ !file_browser_handlers::IsFallbackFileBrowserHandler(handler) &&
ExecuteDefaultAppHandler(
profile, path, url, mime_type, default_task_id)) {
return true;
@@ -740,11 +729,9 @@
return;
}
- GURL site = extensions::ExtensionSystem::Get(profile)->extension_service()->
- GetSiteForExtensionId(kFileBrowserDomain);
scoped_refptr<fileapi::FileSystemContext> file_system_context =
- BrowserContext::GetStoragePartitionForSite(profile, site)->
- GetFileSystemContext();
+ fileapi_util::GetFileSystemContextForExtensionId(
+ profile, kFileBrowserDomain);
CheckIfDirectoryExists(file_system_context, url,
base::Bind(&ContinueViewItem, profile, path));
@@ -807,13 +794,8 @@
return true;
}
- // Unknown file type. Record UMA and show an error message.
- size_t extension_index = UMAExtensionIndex(file_extension.data(),
- kUMATrackingExtensions,
- arraysize(kUMATrackingExtensions));
- UMA_HISTOGRAM_ENUMERATION("FileBrowser.OpeningFileType",
- extension_index,
- arraysize(kUMATrackingExtensions) - 1);
+ // Failed to open the file of unknown type.
+ LOG(WARNING) << "Unknown file type: " << path.value();
return false;
}
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_tasks.cc b/chrome/browser/chromeos/extensions/file_manager/file_tasks.cc
index 609cf4c..00f1cd1 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_tasks.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/file_tasks.cc
@@ -6,55 +6,36 @@
#include "apps/launcher.h"
#include "base/bind.h"
-#include "base/file_util.h"
-#include "base/i18n/case_conversion.h"
-#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/drive/file_system_util.h"
#include "chrome/browser/chromeos/drive/file_task_executor.h"
+#include "chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.h"
#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
+#include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
#include "chrome/browser/chromeos/fileapi/file_system_backend.h"
-#include "chrome/browser/extensions/event_router.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/extensions/lazy_background_task_queue.h"
-#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_tabstrip.h"
-#include "chrome/browser/ui/host_desktop.h"
-#include "chrome/common/extensions/api/file_browser_handlers/file_browser_handler.h"
-#include "chrome/common/extensions/background_info.h"
#include "chrome/common/pref_names.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/child_process_security_policy.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/site_instance.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/browser/web_contents.h"
-#include "net/base/escape.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/isolated_context.h"
-#include "webkit/common/fileapi/file_system_util.h"
-using content::BrowserContext;
-using content::BrowserThread;
-using content::ChildProcessSecurityPolicy;
-using content::SiteInstance;
-using content::WebContents;
using extensions::Extension;
using fileapi::FileSystemURL;
namespace file_manager {
namespace file_tasks {
-const char kTaskFile[] = "file";
-const char kTaskDrive[] = "drive";
-const char kTaskApp[] = "app";
+// The values "file" and "app" are confusing, but cannot be changed easily as
+// these are used in default task IDs stored in preferences.
+//
+// TODO(satorux): We should rename them to "file_browser_handler" and
+// "file_handler" respectively when switching from preferences to
+// chrome.storage crbug.com/267359
+const char kFileBrowserHandlerTaskType[] = "file";
+const char kFileHandlerTaskType[] = "app";
+const char kDriveTaskType[] = "drive";
namespace {
@@ -63,91 +44,6 @@
const size_t kDriveTaskExtensionPrefixLength =
arraysize(kDriveTaskExtensionPrefix) - 1;
-// Returns process id of the process the extension is running in.
-int ExtractProcessFromExtensionId(Profile* profile,
- const std::string& extension_id) {
- GURL extension_url =
- Extension::GetBaseURLFromExtensionId(extension_id);
- ExtensionProcessManager* manager =
- extensions::ExtensionSystem::Get(profile)->process_manager();
-
- SiteInstance* site_instance = manager->GetSiteInstanceForURL(extension_url);
- if (!site_instance || !site_instance->HasProcess())
- return -1;
- content::RenderProcessHost* process = site_instance->GetProcess();
-
- return process->GetID();
-}
-
-const FileBrowserHandler* FindFileBrowserHandler(const Extension* extension,
- const std::string& action_id) {
- FileBrowserHandler::List* handler_list =
- FileBrowserHandler::GetHandlers(extension);
- for (FileBrowserHandler::List::const_iterator action_iter =
- handler_list->begin();
- action_iter != handler_list->end();
- ++action_iter) {
- if (action_iter->get()->id() == action_id)
- return action_iter->get();
- }
- return NULL;
-}
-
-std::string EscapedUtf8ToLower(const std::string& str) {
- string16 utf16 = UTF8ToUTF16(
- net::UnescapeURLComponent(str, net::UnescapeRule::NORMAL));
- return net::EscapeUrlEncodedData(
- UTF16ToUTF8(base::i18n::ToLower(utf16)),
- false /* do not replace space with plus */);
-}
-
-bool GetFileBrowserHandlers(Profile* profile,
- const GURL& selected_file_url,
- FileBrowserHandlerList* results) {
- ExtensionService* service =
- extensions::ExtensionSystem::Get(profile)->extension_service();
- if (!service)
- return false; // In unit-tests, we may not have an ExtensionService.
-
- // We need case-insensitive matching, and pattern in the handler is already
- // in lower case.
- const GURL lowercase_url(EscapedUtf8ToLower(selected_file_url.spec()));
-
- for (ExtensionSet::const_iterator iter = service->extensions()->begin();
- iter != service->extensions()->end();
- ++iter) {
- const Extension* extension = iter->get();
- if (profile->IsOffTheRecord() &&
- !service->IsIncognitoEnabled(extension->id()))
- continue;
-
- FileBrowserHandler::List* handler_list =
- FileBrowserHandler::GetHandlers(extension);
- if (!handler_list)
- continue;
- for (FileBrowserHandler::List::const_iterator action_iter =
- handler_list->begin();
- action_iter != handler_list->end();
- ++action_iter) {
- const FileBrowserHandler* action = action_iter->get();
- if (!action->MatchesURL(lowercase_url))
- continue;
-
- results->push_back(action_iter->get());
- }
- }
- return true;
-}
-
-fileapi::FileSystemContext* GetFileSystemContextForExtension(
- Profile* profile,
- const std::string& extension_id) {
- GURL site = extensions::ExtensionSystem::Get(profile)->
- extension_service()->GetSiteForExtensionId(extension_id);
- return BrowserContext::GetStoragePartitionForSite(profile, site)->
- GetFileSystemContext();
-}
-
// Checks if the file browser extension has permissions for the files in its
// file system context.
bool FileBrowserHasAccessPermissionForFiles(
@@ -156,8 +52,8 @@
const std::string& file_browser_id,
const std::vector<FileSystemURL>& files) {
fileapi::ExternalFileSystemBackend* backend =
- GetFileSystemContextForExtension(profile, file_browser_id)->
- external_backend();
+ fileapi_util::GetFileSystemContextForExtensionId(
+ profile, file_browser_id)->external_backend();
if (!backend)
return false;
@@ -177,14 +73,6 @@
} // namespace
-bool IsFallbackTask(const FileBrowserHandler* task) {
- return (task->extension_id() == kFileBrowserDomain ||
- task->extension_id() ==
- extension_misc::kQuickOfficeComponentExtensionId ||
- task->extension_id() == extension_misc::kQuickOfficeDevExtensionId ||
- task->extension_id() == extension_misc::kQuickOfficeExtensionId);
-}
-
void UpdateDefaultTask(Profile* profile,
const std::string& task_id,
const std::set<std::string>& suffixes,
@@ -247,41 +135,39 @@
std::string MakeTaskID(const std::string& extension_id,
const std::string& task_type,
const std::string& action_id) {
- DCHECK(task_type == kTaskFile ||
- task_type == kTaskDrive ||
- task_type == kTaskApp);
+ DCHECK(task_type == kFileBrowserHandlerTaskType ||
+ task_type == kDriveTaskType ||
+ task_type == kFileHandlerTaskType);
return base::StringPrintf("%s|%s|%s",
extension_id.c_str(),
task_type.c_str(),
action_id.c_str());
}
-bool CrackTaskID(const std::string& task_id,
- std::string* extension_id,
- std::string* task_type,
- std::string* action_id) {
+std::string MakeDriveAppTaskId(const std::string& app_id) {
+ return MakeTaskID(app_id, kDriveTaskType, "open-with");
+}
+
+bool ParseTaskID(const std::string& task_id, TaskDescriptor* task) {
+ DCHECK(task);
+
std::vector<std::string> result;
int count = Tokenize(task_id, std::string("|"), &result);
- // Parse historic task_id parameters that only contain two parts. Drive tasks
- // are identified by a prefix "drive-app:" on the extension ID.
+ // Parse a legacy task ID that only contain two parts. Drive tasks are
+ // identified by a prefix "drive-app:" on the extension ID. The legacy task
+ // IDs can be stored in preferences.
+ // TODO(satorux): We should get rid of this code: crbug.com/267359.
if (count == 2) {
if (StartsWithASCII(result[0], kDriveTaskExtensionPrefix, true)) {
- if (task_type)
- *task_type = kTaskDrive;
-
- if (extension_id)
- *extension_id = result[0].substr(kDriveTaskExtensionPrefixLength);
+ task->task_type = kDriveTaskType;
+ task->app_id = result[0].substr(kDriveTaskExtensionPrefixLength);
} else {
- if (task_type)
- *task_type = kTaskFile;
-
- if (extension_id)
- *extension_id = result[0];
+ task->task_type = kFileBrowserHandlerTaskType;
+ task->app_id = result[0];
}
- if (action_id)
- *action_id = result[1];
+ task->action_id = result[1];
return true;
}
@@ -289,242 +175,21 @@
if (count != 3)
return false;
- if (extension_id)
- *extension_id = result[0];
-
- if (task_type) {
- *task_type = result[1];
- DCHECK(*task_type == kTaskFile ||
- *task_type == kTaskDrive ||
- *task_type == kTaskApp);
- }
-
- if (action_id)
- *action_id = result[2];
+ task->app_id = result[0];
+ task->task_type = result[1];
+ DCHECK(task->task_type == kFileBrowserHandlerTaskType ||
+ task->task_type == kDriveTaskType ||
+ task->task_type == kFileHandlerTaskType);
+ task->action_id = result[2];
return true;
}
-// Find a specific handler in the handler list.
-FileBrowserHandlerList::iterator FindHandler(
- FileBrowserHandlerList* handler_list,
- const std::string& extension_id,
- const std::string& id) {
- FileBrowserHandlerList::iterator iter = handler_list->begin();
- while (iter != handler_list->end() &&
- !((*iter)->extension_id() == extension_id &&
- (*iter)->id() == id)) {
- ++iter;
- }
- return iter;
-}
-
-// Given the list of selected files, returns array of file action tasks
-// that are shared between them.
-void FindDefaultTasks(Profile* profile,
- const std::vector<base::FilePath>& files_list,
- const FileBrowserHandlerList& common_tasks,
- FileBrowserHandlerList* default_tasks) {
- DCHECK(default_tasks);
- default_tasks->clear();
-
- std::set<std::string> default_ids;
- for (std::vector<base::FilePath>::const_iterator it = files_list.begin();
- it != files_list.end(); ++it) {
- std::string task_id = file_tasks::GetDefaultTaskIdFromPrefs(
- profile, "", it->Extension());
- if (!task_id.empty())
- default_ids.insert(task_id);
- }
-
- const FileBrowserHandler* fallback_task = NULL;
- // Convert the default task IDs collected above to one of the handler pointers
- // from common_tasks.
- for (FileBrowserHandlerList::const_iterator task_iter = common_tasks.begin();
- task_iter != common_tasks.end(); ++task_iter) {
- std::string task_id = MakeTaskID((*task_iter)->extension_id(), kTaskFile,
- (*task_iter)->id());
- std::set<std::string>::iterator default_iter = default_ids.find(task_id);
- if (default_iter != default_ids.end()) {
- default_tasks->push_back(*task_iter);
- continue;
- }
-
- // Remember the first fallback task.
- if (!fallback_task && IsFallbackTask(*task_iter))
- fallback_task = *task_iter;
- }
-
- // If there are no default tasks found, use fallback as default.
- if (fallback_task && default_tasks->empty())
- default_tasks->push_back(fallback_task);
-}
-
-// Given the list of selected files, returns array of context menu tasks
-// that are shared
-bool FindCommonTasks(Profile* profile,
- const std::vector<GURL>& files_list,
- FileBrowserHandlerList* common_tasks) {
- DCHECK(common_tasks);
- common_tasks->clear();
-
- FileBrowserHandlerList common_task_list;
- std::set<std::string> default_task_ids;
- for (std::vector<GURL>::const_iterator it = files_list.begin();
- it != files_list.end(); ++it) {
- FileBrowserHandlerList file_actions;
- if (!GetFileBrowserHandlers(profile, *it, &file_actions))
- return false;
- // If there is nothing to do for one file, the intersection of tasks for all
- // files will be empty at the end, and so will the default tasks.
- if (file_actions.empty())
- return true;
-
- // For the very first file, just copy all the elements.
- if (it == files_list.begin()) {
- common_task_list = file_actions;
- } else {
- // For all additional files, find intersection between the accumulated and
- // file specific set.
- FileBrowserHandlerList intersection;
- std::set_intersection(common_task_list.begin(), common_task_list.end(),
- file_actions.begin(), file_actions.end(),
- std::back_inserter(intersection));
- common_task_list = intersection;
- if (common_task_list.empty())
- return true;
- }
- }
-
- FileBrowserHandlerList::iterator watch_iter = FindHandler(
- &common_task_list, kFileBrowserDomain, kFileBrowserWatchTaskId);
- FileBrowserHandlerList::iterator gallery_iter = FindHandler(
- &common_task_list, kFileBrowserDomain, kFileBrowserGalleryTaskId);
- if (watch_iter != common_task_list.end() &&
- gallery_iter != common_task_list.end()) {
- // Both "watch" and "gallery" actions are applicable which means that the
- // selection is all videos. Showing them both is confusing, so we only keep
- // the one that makes more sense ("watch" for single selection, "gallery"
- // for multiple selection).
- if (files_list.size() == 1)
- common_task_list.erase(gallery_iter);
- else
- common_task_list.erase(watch_iter);
- }
-
- common_tasks->swap(common_task_list);
- return true;
-}
-
-bool GetTaskForURLAndPath(Profile* profile,
- const GURL& url,
- const base::FilePath& file_path,
- const FileBrowserHandler** handler) {
- std::vector<GURL> file_urls;
- file_urls.push_back(url);
-
- FileBrowserHandlerList default_tasks;
- FileBrowserHandlerList common_tasks;
- if (!FindCommonTasks(profile, file_urls, &common_tasks))
- return false;
-
- if (common_tasks.empty())
- return false;
-
- std::vector<base::FilePath> file_paths;
- file_paths.push_back(file_path);
-
- FindDefaultTasks(profile, file_paths, common_tasks, &default_tasks);
-
- // If there's none, or more than one, then we don't have a canonical default.
- if (!default_tasks.empty()) {
- // There should not be multiple default tasks for a single URL.
- DCHECK_EQ(1u, default_tasks.size());
-
- *handler = *default_tasks.begin();
- return true;
- }
-
- // If there are no default tasks, use first task in the list (file manager
- // does the same in this situation).
- // TODO(tbarzic): This is so not optimal behaviour.
- *handler = *common_tasks.begin();
- return true;
-}
-
-// ExtensionTaskExecutor executes tasks with kTaskFile type.
-class ExtensionTaskExecutor {
- public:
- ExtensionTaskExecutor(Profile* profile,
- const Extension* extension,
- int32 tab_id,
- const std::string& action_id);
-
- // Executes the task for each file. |done| will be run with the result.
- void Execute(const std::vector<FileSystemURL>& file_urls,
- const FileTaskFinishedCallback& done);
-
- private:
- // This object is responsible to delete itself.
- virtual ~ExtensionTaskExecutor();
-
- struct FileDefinition {
- FileDefinition();
- ~FileDefinition();
-
- base::FilePath virtual_path;
- base::FilePath absolute_path;
- bool is_directory;
- };
-
- typedef std::vector<FileDefinition> FileDefinitionList;
-
- // Checks legitimacy of file url and grants file RO access permissions from
- // handler (target) extension and its renderer process.
- static FileDefinitionList SetupFileAccessPermissions(
- scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
- const scoped_refptr<const Extension>& handler_extension,
- const std::vector<FileSystemURL>& file_urls);
-
- void DidOpenFileSystem(const std::vector<FileSystemURL>& file_urls,
- base::PlatformFileError result,
- const std::string& file_system_name,
- const GURL& file_system_root);
-
- void ExecuteDoneOnUIThread(bool success);
- void ExecuteFileActionsOnUIThread(const std::string& file_system_name,
- const GURL& file_system_root,
- const FileDefinitionList& file_list);
- void SetupPermissionsAndDispatchEvent(const std::string& file_system_name,
- const GURL& file_system_root,
- const FileDefinitionList& file_list,
- int handler_pid_in,
- extensions::ExtensionHost* host);
-
- // Registers file permissions from |handler_host_permissions_| with
- // ChildProcessSecurityPolicy for process with id |handler_pid|.
- void SetupHandlerHostFileAccessPermissions(
- const FileDefinitionList& file_list,
- const Extension* extension,
- int handler_pid);
-
- Profile* profile_;
- scoped_refptr<const Extension> extension_;
- int32 tab_id_;
- const std::string action_id_;
- FileTaskFinishedCallback done_;
- base::WeakPtrFactory<ExtensionTaskExecutor> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ExtensionTaskExecutor);
-};
-
bool ExecuteFileTask(Profile* profile,
const GURL& source_url,
const std::string& file_browser_id,
int32 tab_id,
- const std::string& extension_id,
- const std::string& task_type,
- const std::string& action_id,
+ const TaskDescriptor& task,
const std::vector<FileSystemURL>& file_urls,
const FileTaskFinishedCallback& done) {
if (!FileBrowserHasAccessPermissionForFiles(profile, source_url,
@@ -532,10 +197,10 @@
return false;
// drive::FileTaskExecutor is responsible to handle drive tasks.
- if (task_type == kTaskDrive) {
- DCHECK_EQ("open-with", action_id);
+ if (task.task_type == kDriveTaskType) {
+ DCHECK_EQ("open-with", task.action_id);
drive::FileTaskExecutor* executor =
- new drive::FileTaskExecutor(profile, extension_id);
+ new drive::FileTaskExecutor(profile, task.app_id);
executor->Execute(file_urls, done);
return true;
}
@@ -544,23 +209,23 @@
ExtensionService* service =
extensions::ExtensionSystem::Get(profile)->extension_service();
const Extension* extension = service ?
- service->GetExtensionById(extension_id, false) : NULL;
+ service->GetExtensionById(task.app_id, false) : NULL;
if (!extension)
return false;
// Execute the task.
- if (task_type == kTaskFile) {
- // Forbid calling undeclared handlers.
- if (!FindFileBrowserHandler(extension, action_id))
- return false;
-
- (new ExtensionTaskExecutor(
- profile, extension, tab_id, action_id))->Execute(file_urls, done);
- return true;
- } else if (task_type == kTaskApp) {
+ if (task.task_type == kFileBrowserHandlerTaskType) {
+ return file_browser_handlers::ExecuteFileBrowserHandler(
+ profile,
+ extension,
+ tab_id,
+ task.action_id,
+ file_urls,
+ done);
+ } else if (task.task_type == kFileHandlerTaskType) {
for (size_t i = 0; i != file_urls.size(); ++i) {
apps::LaunchPlatformAppWithFileHandler(
- profile, extension, action_id, file_urls[i].path());
+ profile, extension, task.action_id, file_urls[i].path());
}
if (!done.is_null())
@@ -571,242 +236,5 @@
return false;
}
-ExtensionTaskExecutor::FileDefinition::FileDefinition() : is_directory(false) {
-}
-
-ExtensionTaskExecutor::FileDefinition::~FileDefinition() {
-}
-
-// static
-ExtensionTaskExecutor::FileDefinitionList
-ExtensionTaskExecutor::SetupFileAccessPermissions(
- scoped_refptr<fileapi::FileSystemContext> file_system_context_handler,
- const scoped_refptr<const Extension>& handler_extension,
- const std::vector<FileSystemURL>& file_urls) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- DCHECK(handler_extension.get());
-
- fileapi::ExternalFileSystemBackend* backend =
- file_system_context_handler->external_backend();
-
- FileDefinitionList file_list;
- for (size_t i = 0; i < file_urls.size(); ++i) {
- const FileSystemURL& url = file_urls[i];
-
- // Check if this file system entry exists first.
- base::PlatformFileInfo file_info;
-
- base::FilePath local_path = url.path();
- base::FilePath virtual_path = url.virtual_path();
-
- bool is_drive_file = url.type() == fileapi::kFileSystemTypeDrive;
- DCHECK(!is_drive_file || drive::util::IsUnderDriveMountPoint(local_path));
-
- // If the file is under drive mount point, there is no actual file to be
- // found on the url.path().
- if (!is_drive_file) {
- if (!base::PathExists(local_path) ||
- file_util::IsLink(local_path) ||
- !file_util::GetFileInfo(local_path, &file_info)) {
- continue;
- }
- }
-
- // Grant access to this particular file to target extension. This will
- // ensure that the target extension can access only this FS entry and
- // prevent from traversing FS hierarchy upward.
- backend->GrantFileAccessToExtension(
- handler_extension->id(), virtual_path);
-
- // Output values.
- FileDefinition file;
- file.virtual_path = virtual_path;
- file.is_directory = file_info.is_directory;
- file.absolute_path = local_path;
- file_list.push_back(file);
- }
- return file_list;
-}
-
-ExtensionTaskExecutor::ExtensionTaskExecutor(
- Profile* profile,
- const Extension* extension,
- int32 tab_id,
- const std::string& action_id)
- : profile_(profile),
- extension_(extension),
- tab_id_(tab_id),
- action_id_(action_id),
- weak_ptr_factory_(this) {
-}
-
-ExtensionTaskExecutor::~ExtensionTaskExecutor() {}
-
-void ExtensionTaskExecutor::Execute(const std::vector<FileSystemURL>& file_urls,
- const FileTaskFinishedCallback& done) {
- done_ = done;
-
- // Get file system context for the extension to which onExecute event will be
- // sent. The file access permissions will be granted to the extension in the
- // file system context for the files in |file_urls|.
- GetFileSystemContextForExtension(profile_, extension_->id())->OpenFileSystem(
- Extension::GetBaseURLFromExtensionId(extension_->id()).GetOrigin(),
- fileapi::kFileSystemTypeExternal,
- fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
- base::Bind(&ExtensionTaskExecutor::DidOpenFileSystem,
- weak_ptr_factory_.GetWeakPtr(),
- file_urls));
-}
-
-void ExtensionTaskExecutor::DidOpenFileSystem(
- const std::vector<FileSystemURL>& file_urls,
- base::PlatformFileError result,
- const std::string& file_system_name,
- const GURL& file_system_root) {
- if (result != base::PLATFORM_FILE_OK) {
- ExecuteDoneOnUIThread(false);
- return;
- }
-
- scoped_refptr<fileapi::FileSystemContext> file_system_context(
- GetFileSystemContextForExtension(profile_, extension_->id()));
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::FILE,
- FROM_HERE,
- base::Bind(&SetupFileAccessPermissions,
- file_system_context,
- extension_,
- file_urls),
- base::Bind(&ExtensionTaskExecutor::ExecuteFileActionsOnUIThread,
- weak_ptr_factory_.GetWeakPtr(),
- file_system_name,
- file_system_root));
-}
-
-void ExtensionTaskExecutor::ExecuteDoneOnUIThread(bool success) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (!done_.is_null())
- done_.Run(success);
- delete this;
-}
-
-void ExtensionTaskExecutor::ExecuteFileActionsOnUIThread(
- const std::string& file_system_name,
- const GURL& file_system_root,
- const FileDefinitionList& file_list) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (file_list.empty()) {
- ExecuteDoneOnUIThread(false);
- return;
- }
-
- int handler_pid = ExtractProcessFromExtensionId(profile_, extension_->id());
- if (handler_pid <= 0 &&
- !extensions::BackgroundInfo::HasLazyBackgroundPage(extension_.get())) {
- ExecuteDoneOnUIThread(false);
- return;
- }
-
- if (handler_pid > 0) {
- SetupPermissionsAndDispatchEvent(file_system_name, file_system_root,
- file_list, handler_pid, NULL);
- } else {
- // We have to wake the handler background page before we proceed.
- extensions::LazyBackgroundTaskQueue* queue =
- extensions::ExtensionSystem::Get(profile_)->
- lazy_background_task_queue();
- if (!queue->ShouldEnqueueTask(profile_, extension_.get())) {
- ExecuteDoneOnUIThread(false);
- return;
- }
- queue->AddPendingTask(
- profile_, extension_->id(),
- base::Bind(&ExtensionTaskExecutor::SetupPermissionsAndDispatchEvent,
- weak_ptr_factory_.GetWeakPtr(),
- file_system_name,
- file_system_root,
- file_list,
- handler_pid));
- }
-}
-
-void ExtensionTaskExecutor::SetupPermissionsAndDispatchEvent(
- const std::string& file_system_name,
- const GURL& file_system_root,
- const FileDefinitionList& file_list,
- int handler_pid_in,
- extensions::ExtensionHost* host) {
- int handler_pid = host ? host->render_process_host()->GetID() :
- handler_pid_in;
-
- if (handler_pid <= 0) {
- ExecuteDoneOnUIThread(false);
- return;
- }
-
- extensions::EventRouter* event_router =
- extensions::ExtensionSystem::Get(profile_)->event_router();
- if (!event_router) {
- ExecuteDoneOnUIThread(false);
- return;
- }
-
- SetupHandlerHostFileAccessPermissions(
- file_list, extension_.get(), handler_pid);
-
- scoped_ptr<ListValue> event_args(new ListValue());
- event_args->Append(new base::StringValue(action_id_));
- DictionaryValue* details = new DictionaryValue();
- event_args->Append(details);
- // Get file definitions. These will be replaced with Entry instances by
- // dispatchEvent() method from event_binding.js.
- ListValue* files_urls = new ListValue();
- details->Set("entries", files_urls);
- for (FileDefinitionList::const_iterator iter = file_list.begin();
- iter != file_list.end();
- ++iter) {
- DictionaryValue* file_def = new DictionaryValue();
- files_urls->Append(file_def);
- file_def->SetString("fileSystemName", file_system_name);
- file_def->SetString("fileSystemRoot", file_system_root.spec());
- base::FilePath root(FILE_PATH_LITERAL("/"));
- base::FilePath full_path = root.Append(iter->virtual_path);
- file_def->SetString("fileFullPath", full_path.value());
- file_def->SetBoolean("fileIsDirectory", iter->is_directory);
- }
-
- details->SetInteger("tab_id", tab_id_);
-
- scoped_ptr<extensions::Event> event(new extensions::Event(
- "fileBrowserHandler.onExecute", event_args.Pass()));
- event->restrict_to_profile = profile_;
- event_router->DispatchEventToExtension(extension_->id(), event.Pass());
-
- ExecuteDoneOnUIThread(true);
-}
-
-void ExtensionTaskExecutor::SetupHandlerHostFileAccessPermissions(
- const FileDefinitionList& file_list,
- const Extension* extension,
- int handler_pid) {
- const FileBrowserHandler* action = FindFileBrowserHandler(extension_,
- action_id_);
- for (FileDefinitionList::const_iterator iter = file_list.begin();
- iter != file_list.end();
- ++iter) {
- if (!action)
- continue;
- if (action->CanRead()) {
- content::ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(
- handler_pid, iter->absolute_path);
- }
- if (action->CanWrite()) {
- content::ChildProcessSecurityPolicy::GetInstance()->
- GrantCreateReadWriteFile(handler_pid, iter->absolute_path);
- }
- }
-}
-
} // namespace file_tasks
} // namespace file_manager
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_tasks.h b/chrome/browser/chromeos/extensions/file_manager/file_tasks.h
index 9c05fa5..50a3e13 100644
--- a/chrome/browser/chromeos/extensions/file_manager/file_tasks.h
+++ b/chrome/browser/chromeos/extensions/file_manager/file_tasks.h
@@ -80,9 +80,10 @@
// (Files.app) and the latter looks like "419782477519" (Pixlr Editor).
//
// <task-type> is either of
-// - "file" - Files.app built-in handler
+// - "file" - File browser handler - app/extension declaring
+// "file_browser_handlers" in manifest.
+// - "app" - File handler - app declaring "file_handlers" in manifest.json.
// - "drive" - Drive App
-// - "app" - Regular Chrome Extension/App ID
//
// <task-action-id> is an ID string used for identifying actions provided
// from a single Chrome Extension/App. In other words, a single
@@ -109,15 +110,13 @@
#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILE_TASKS_H_
#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILE_TASKS_H_
+#include <set>
#include <string>
#include <vector>
+#include "base/basictypes.h"
#include "base/callback_forward.h"
-#include "base/platform_file.h"
-#include "chrome/common/extensions/extension.h"
-class Browser;
-class FileBrowserHandler;
class GURL;
class Profile;
@@ -128,20 +127,29 @@
namespace file_manager {
namespace file_tasks {
-// Tasks are stored as a vector in order of priorities.
-typedef std::vector<const FileBrowserHandler*> FileBrowserHandlerList;
+// Task types encoded in task IDs. See also the comment at the beginning of
+// the file about <task-type>.
+extern const char kFileBrowserHandlerTaskType[];
+extern const char kFileHandlerTaskType[];
+extern const char kDriveTaskType[];
-// Specifies the task type for a task id that represents some file action, Drive
-// action, or Web Intent action.
-extern const char kTaskFile[];
-extern const char kTaskDrive[];
-extern const char kTaskApp[];
+// Describes a task.
+// See the comment above for <app-id>, <task-type>, and <action-id>.
+struct TaskDescriptor {
+ TaskDescriptor(const std::string& in_app_id,
+ const std::string& in_task_type,
+ const std::string& in_action_id)
+ : app_id(in_app_id),
+ task_type(in_task_type),
+ action_id(in_action_id) {
+ }
+ TaskDescriptor() {
+ }
-void UpdateFileHandlerUsageStats(Profile* profile, const std::string& task_id);
-
-// Returns true if the task should be used as a fallback. Such tasks are
-// Files.app's internal handlers as well as quick office extensions.
-bool IsFallbackTask(const FileBrowserHandler* task);
+ std::string app_id;
+ std::string task_type;
+ std::string action_id;
+};
// Update the default file handler for the given sets of suffixes and MIME
// types.
@@ -158,58 +166,51 @@
const std::string& mime_type,
const std::string& suffix);
-// Generates task id for the action specified by the extension. The |task_type|
-// must be one of kTaskFile, kTaskDrive or kTaskApp.
+// Generates task id for the task specified by |app_id|, |task_type| and
+// |action_id|. The |task_type| must be one of kFileBrowserHandlerTaskType,
+// kDriveTaskType or kFileHandlerTaskType.
+// <app-id> is either of Chrome Extension/App ID or Drive App ID.
std::string MakeTaskID(const std::string& extension_id,
const std::string& task_type,
const std::string& action_id);
-// Extracts action, type and extension id bound to the file task ID. Either
-// |target_extension_id| or |action_id| are allowed to be NULL if caller isn't
-// interested in those values. Returns false on failure to parse.
+// Returns a task id for the Drive app with |app_id|.
+// TODO(gspencer): For now, the action id is always "open-with", but we
+// could add any actions that the drive app supports.
+std::string MakeDriveAppTaskId(const std::string& app_id);
+
+// Parses the task ID and extracts app ID, task type, and action ID into
+// |task|. On failure, returns false, and the contents of |task| are
+// undefined.
//
// See also the comment at the beginning of the file for details for how
// "task_id" looks like.
-bool CrackTaskID(const std::string& task_id,
- std::string* target_extension_id,
- std::string* task_type,
- std::string* action_id);
+bool ParseTaskID(const std::string& task_id, TaskDescriptor* task);
-// This generates a list of default tasks (tasks set as default by the user in
-// prefs) from the |common_tasks|.
-void FindDefaultTasks(Profile* profile,
- const std::vector<base::FilePath>& files_list,
- const FileBrowserHandlerList& common_tasks,
- FileBrowserHandlerList* default_tasks);
-
-// This generates list of tasks common for all files in |file_list|.
-bool FindCommonTasks(Profile* profile,
- const std::vector<GURL>& files_list,
- FileBrowserHandlerList* common_tasks);
-
-// Finds a task for a file whose URL is |url| and whose path is |path|.
-// Returns default task if one is defined (The default task is the task that is
-// assigned to file browser task button by default). If default task is not
-// found, tries to match the url with one of the builtin tasks.
-bool GetTaskForURLAndPath(Profile* profile,
- const GURL& url,
- const base::FilePath& path,
- const FileBrowserHandler** handler);
-
-// Used for returning success or failure from task executions.
-typedef base::Callback<void(bool)> FileTaskFinishedCallback;
+// The callback is used for ExecuteFileTask(). Will be called with true if
+// the file task execution is successful, or false if unsuccessful.
+typedef base::Callback<void(bool success)> FileTaskFinishedCallback;
// Executes file handler task for each element of |file_urls|.
// Returns |false| if the execution cannot be initiated. Otherwise returns
// |true| and then eventually calls |done| when all the files have been handled.
// |done| can be a null callback.
+//
+// Parameters:
+// profile - The profile used for making this function call.
+// source_url - The source URL which originates this function call.
+// tab_id - The ID of the tab which originates this function call.
+// This can be 0 if no tab is associated.
+// task - See the comment at TaskDescriptor struct.
+// file_urls - URLs of the target files.
+// done - The callback which will be called on completion.
+// The callback won't be called if the function returns
+// false.
bool ExecuteFileTask(Profile* profile,
const GURL& source_url,
const std::string& file_browser_id,
int32 tab_id,
- const std::string& extension_id,
- const std::string& task_type,
- const std::string& action_id,
+ const TaskDescriptor& task,
const std::vector<fileapi::FileSystemURL>& file_urls,
const FileTaskFinishedCallback& done);
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_tasks_unittest.cc b/chrome/browser/chromeos/extensions/file_manager/file_tasks_unittest.cc
new file mode 100644
index 0000000..c9d7146
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/file_manager/file_tasks_unittest.cc
@@ -0,0 +1,54 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/extensions/file_manager/file_tasks.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace file_manager {
+namespace file_tasks {
+
+TEST(FileManagerFileTasksTest, MakeTaskID) {
+ EXPECT_EQ("app-id|app|action-id", MakeTaskID("app-id", "app", "action-id"));
+}
+
+TEST(FileManagerFileTasksTest, MakeDriveAppTaskId) {
+ EXPECT_EQ("app-id|drive|open-with", MakeDriveAppTaskId("app-id"));
+}
+
+TEST(FileManagerFileTasksTest, ParseTaskID_Basic) {
+ TaskDescriptor task;
+ // A task ID usually has three parts.
+ EXPECT_TRUE(ParseTaskID("app-id|app|action-id", &task));
+ EXPECT_EQ("app-id", task.app_id);
+ EXPECT_EQ("app", task.task_type);
+ EXPECT_EQ("action-id", task.action_id);
+}
+
+TEST(FileManagerFileTasksTest, ParseTaskID_Legacy) {
+ TaskDescriptor task;
+ // A legacy task ID only has two parts. The task type should be to "file".
+ EXPECT_TRUE(ParseTaskID("app-id|action-id", &task));
+ EXPECT_EQ("app-id", task.app_id);
+ EXPECT_EQ("file", task.task_type);
+ EXPECT_EQ("action-id", task.action_id);
+}
+
+TEST(FileManagerFileTasksTest, ParseTaskID_LegacyDrive) {
+ TaskDescriptor task;
+ // A legacy task ID only has two parts. For Drive app, the app ID is
+ // prefixed with "drive-app:".
+ EXPECT_TRUE(ParseTaskID("drive-app:app-id|action-id", &task));
+ EXPECT_EQ("app-id", task.app_id);
+ EXPECT_EQ("drive", task.task_type);
+ EXPECT_EQ("action-id", task.action_id);
+}
+
+TEST(FileManagerFileTasksTest, ParseTaskID_Invalid) {
+ TaskDescriptor task;
+ EXPECT_FALSE(ParseTaskID("invalid", &task));
+}
+
+} // namespace file_tasks
+} // namespace file_manager.
diff --git a/chrome/browser/chromeos/extensions/file_manager/fileapi_util.cc b/chrome/browser/chromeos/extensions/file_manager/fileapi_util.cc
new file mode 100644
index 0000000..52a93e4
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/file_manager/fileapi_util.cc
@@ -0,0 +1,38 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
+
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/browser/storage_partition.h"
+#include "url/gurl.h"
+#include "webkit/browser/fileapi/file_system_context.h"
+
+namespace file_manager {
+namespace fileapi_util {
+
+fileapi::FileSystemContext* GetFileSystemContextForExtensionId(
+ Profile* profile,
+ const std::string& extension_id) {
+ GURL site = extensions::ExtensionSystem::Get(profile)->
+ extension_service()->GetSiteForExtensionId(extension_id);
+ return content::BrowserContext::GetStoragePartitionForSite(profile, site)->
+ GetFileSystemContext();
+}
+
+fileapi::FileSystemContext* GetFileSystemContextForRenderViewHost(
+ Profile* profile,
+ content::RenderViewHost* render_view_host) {
+ content::SiteInstance* site_instance = render_view_host->GetSiteInstance();
+ return content::BrowserContext::GetStoragePartition(profile, site_instance)->
+ GetFileSystemContext();
+}
+
+} // namespace fileapi_util
+} // namespace file_manager
diff --git a/chrome/browser/chromeos/extensions/file_manager/fileapi_util.h b/chrome/browser/chromeos/extensions/file_manager/fileapi_util.h
new file mode 100644
index 0000000..415fb2c
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/file_manager/fileapi_util.h
@@ -0,0 +1,40 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This file provides File API related utilities.
+
+#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILEAPI_UTIL_H_
+#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILEAPI_UTIL_H_
+
+#include <string>
+
+class Profile;
+
+namespace content {
+class RenderViewHost;
+}
+
+namespace fileapi {
+class FileSystemContext;
+}
+
+namespace file_manager {
+namespace fileapi_util {
+
+// Returns a file system context associated with the given profile and the
+// extension ID.
+fileapi::FileSystemContext* GetFileSystemContextForExtensionId(
+ Profile* profile,
+ const std::string& extension_id);
+
+// Returns a file system context associated with the given profile and the
+// render view host.
+fileapi::FileSystemContext* GetFileSystemContextForRenderViewHost(
+ Profile* profile,
+ content::RenderViewHost* render_view_host);
+
+} // namespace fileapi_util
+} // namespace file_manager
+
+#endif // CHROME_BROWSER_CHROMEOS_EXTENSIONS_FILE_MANAGER_FILEAPI_UTIL_H_
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
index f86ccff..d0d4100 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
@@ -141,9 +141,11 @@
profile_,
file_specific_info.content_mime_type(),
file_path_.Extension());
- std::string default_app_id;
- file_tasks::CrackTaskID(
- default_task_id, &default_app_id, NULL, NULL);
+ file_tasks::TaskDescriptor default_task;
+ if (!file_tasks::ParseTaskID(default_task_id, &default_task)) {
+ LOG(WARNING) << "Invalid task ID: " << default_task_id;
+ return;
+ }
ListValue* apps = new ListValue();
properties_->Set("driveApps", apps);
@@ -163,7 +165,8 @@
if (!doc_icon.is_empty())
app->SetString("docIcon", doc_icon.spec());
app->SetString("objectType", app_info->object_type);
- app->SetBoolean("isPrimary", default_app_id == app_info->app_id);
+ app->SetBoolean("isPrimary",
+ default_task.app_id == app_info->app_id);
apps->Append(app);
}
}
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 fb74bc1..c77c7c4 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
@@ -20,6 +20,7 @@
#include "chrome/browser/chromeos/extensions/file_manager/event_router.h"
#include "chrome/browser/chromeos/extensions/file_manager/file_browser_private_api.h"
#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
+#include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
#include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
#include "chrome/browser/chromeos/fileapi/file_system_backend.h"
#include "chrome/browser/profiles/profile.h"
@@ -272,10 +273,9 @@
set_log_on_completion(true);
- content::SiteInstance* site_instance = render_view_host()->GetSiteInstance();
scoped_refptr<fileapi::FileSystemContext> file_system_context =
- BrowserContext::GetStoragePartition(profile_, site_instance)->
- GetFileSystemContext();
+ fileapi_util::GetFileSystemContextForRenderViewHost(
+ profile(), render_view_host());
const GURL origin_url = source_url_.GetOrigin();
file_system_context->OpenFileSystem(
@@ -312,10 +312,9 @@
if (!args_->GetString(0, &url) || url.empty())
return false;
- content::SiteInstance* site_instance = render_view_host()->GetSiteInstance();
scoped_refptr<fileapi::FileSystemContext> file_system_context =
- BrowserContext::GetStoragePartition(profile(), site_instance)->
- GetFileSystemContext();
+ fileapi_util::GetFileSystemContextForRenderViewHost(
+ profile(), render_view_host());
FileSystemURL file_watch_url = file_system_context->CrackURL(GURL(url));
base::FilePath local_path = file_watch_url.path();
@@ -538,10 +537,10 @@
if (!args_->GetString(1, &name))
return false;
- content::SiteInstance* site_instance = render_view_host()->GetSiteInstance();
scoped_refptr<fileapi::FileSystemContext> file_system_context =
- BrowserContext::GetStoragePartition(profile(), site_instance)->
- GetFileSystemContext();
+ fileapi_util::GetFileSystemContextForRenderViewHost(
+ profile(), render_view_host());
+
fileapi::FileSystemURL filesystem_url(
file_system_context->CrackURL(GURL(parent_url)));
if (!chromeos::FileSystemBackend::CanHandleURL(filesystem_url))
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
index 6d6505e..465d4f3 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
@@ -252,6 +252,8 @@
IDS_FILE_BROWSER_CREATE_FOLDER_SHORTCUT_BUTTON_LABEL);
SET_STRING("REMOVE_FOLDER_SHORTCUT_BUTTON_LABEL",
IDS_FILE_BROWSER_REMOVE_FOLDER_SHORTCUT_BUTTON_LABEL);
+ SET_STRING("SHORTCUT_TARGET_UNAVAILABLE",
+ IDS_FILE_BROWSER_SHORTCUT_TARGET_UNAVAILABLE);
SET_STRING("SHARE_BUTTON_LABEL",
IDS_FILE_BROWSER_SHARE_BUTTON_LABEL);
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.cc
index e257dce..23f0275 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.cc
@@ -6,6 +6,7 @@
#include "chrome/browser/chromeos/drive/drive_app_registry.h"
#include "chrome/browser/chromeos/drive/drive_integration_service.h"
+#include "chrome/browser/chromeos/extensions/file_manager/file_browser_handlers.h"
#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
#include "chrome/browser/chromeos/extensions/file_manager/file_tasks.h"
#include "chrome/browser/chromeos/extensions/file_manager/private_api_util.h"
@@ -73,14 +74,6 @@
}
}
-// Returns a task id for the web app with |app_id|.
-std::string MakeWebAppTaskId(const std::string& app_id) {
- // TODO(gspencer): For now, the action id is always "open-with", but we
- // could add any actions that the drive app supports.
- return file_tasks::MakeTaskID(
- app_id, file_tasks::kTaskDrive, "open-with");
-}
-
// Gets the mime types for the given file paths.
void GetMimeTypesForFileURLs(const std::vector<base::FilePath>& file_paths,
PathAndMimeTypeSet* files) {
@@ -146,11 +139,8 @@
if (!args_->GetList(1, &files_list))
return false;
- std::string extension_id;
- std::string task_type;
- std::string action_id;
- if (!file_tasks::CrackTaskID(
- task_id, &extension_id, &task_type, &action_id)) {
+ file_tasks::TaskDescriptor task;
+ if (!file_tasks::ParseTaskID(task_id, &task)) {
LOG(WARNING) << "Invalid task " << task_id;
return false;
}
@@ -184,9 +174,7 @@
source_url(),
extension_->id(),
tab_id,
- extension_id,
- task_type,
- action_id,
+ task,
file_urls,
base::Bind(&ExecuteTaskFunction::OnTaskExecuted, this));
}
@@ -243,7 +231,7 @@
GURL icon_url = util::FindPreferredIcon(app_info.app_icons,
util::kPreferredIconSize);
task_info_map->insert(std::pair<std::string, TaskInfo>(
- MakeWebAppTaskId(app_info.app_id),
+ file_tasks::MakeDriveAppTaskId(app_info.app_id),
TaskInfo(app_info.app_name, icon_url)));
}
} else {
@@ -251,7 +239,8 @@
// based on the task id.
std::set<std::string> task_id_set;
for (size_t j = 0; j < app_info_list.size(); ++j) {
- task_id_set.insert(MakeWebAppTaskId(app_info_list[j]->app_id));
+ task_id_set.insert(
+ file_tasks::MakeDriveAppTaskId(app_info_list[j]->app_id));
}
for (TaskInfoMap::iterator iter = task_info_map->begin();
iter != task_info_map->end(); ) {
@@ -315,11 +304,7 @@
}
}
-// Find special tasks here for Drive (Blox) apps. Iterate through matching drive
-// apps and add them, with generated task ids. Extension ids will be the app_ids
-// from drive. We'll know that they are drive apps because the extension id will
-// begin with kDriveTaskExtensionPrefix.
-bool GetFileTasksFunction::FindDriveAppTasks(
+void GetFileTasksFunction::FindDriveAppTasks(
const FileInfoList& file_info_list,
ListValue* result_list,
bool* default_already_set) {
@@ -327,7 +312,7 @@
DCHECK(default_already_set);
if (file_info_list.empty())
- return true;
+ return;
drive::DriveIntegrationService* integration_service =
drive::DriveIntegrationServiceFactory::GetForProfile(profile_);
@@ -335,7 +320,7 @@
// case because there might be other extension tasks, even if we don't have
// any to add.
if (!integration_service || !integration_service->drive_app_registry())
- return true;
+ return;
drive::DriveAppRegistry* registry =
integration_service->drive_app_registry();
@@ -348,17 +333,19 @@
FindDefaultDriveTasks(file_info_list, task_info_map, &default_tasks);
CreateDriveTasks(
task_info_map, default_tasks, result_list, default_already_set);
- return true;
}
-bool GetFileTasksFunction::FindAppTasks(
+void GetFileTasksFunction::FindFileHandlerTasks(
const std::vector<base::FilePath>& file_paths,
ListValue* result_list,
bool* default_already_set) {
DCHECK(!file_paths.empty());
+ DCHECK(result_list);
+ DCHECK(default_already_set);
+
ExtensionService* service = profile_->GetExtensionService();
if (!service)
- return false;
+ return;
PathAndMimeTypeSet files;
GetMimeTypesForFileURLs(file_paths, &files);
@@ -391,7 +378,7 @@
i != file_handlers.end(); ++i) {
DictionaryValue* task = new DictionaryValue;
std::string task_id = file_tasks::MakeTaskID(
- extension->id(), file_tasks::kTaskApp, (*i)->id);
+ extension->id(), file_tasks::kFileHandlerTaskType, (*i)->id);
task->SetString("taskId", task_id);
task->SetString("title", (*i)->title);
if (!(*default_already_set) && ContainsKey(default_tasks, task_id)) {
@@ -416,8 +403,63 @@
result_list->Append(task);
}
}
+}
- return true;
+void GetFileTasksFunction::FindFileBrowserHandlerTasks(
+ const std::vector<GURL>& file_urls,
+ const std::vector<base::FilePath>& file_paths,
+ ListValue* result_list,
+ bool* default_already_set) {
+ DCHECK(!file_paths.empty());
+ DCHECK(!file_urls.empty());
+ DCHECK(result_list);
+ DCHECK(default_already_set);
+
+ file_browser_handlers::FileBrowserHandlerList common_tasks =
+ file_browser_handlers::FindCommonFileBrowserHandlers(profile_, file_urls);
+ if (common_tasks.empty())
+ return;
+ file_browser_handlers::FileBrowserHandlerList default_tasks =
+ file_browser_handlers::FindDefaultFileBrowserHandlers(
+ profile_, file_paths, common_tasks);
+
+ ExtensionService* service =
+ extensions::ExtensionSystem::Get(profile_)->extension_service();
+ for (file_browser_handlers::FileBrowserHandlerList::const_iterator iter =
+ common_tasks.begin();
+ iter != common_tasks.end();
+ ++iter) {
+ const FileBrowserHandler* handler = *iter;
+ const std::string extension_id = handler->extension_id();
+ const Extension* extension = service->GetExtensionById(extension_id, false);
+ CHECK(extension);
+ DictionaryValue* task = new DictionaryValue;
+ task->SetString("taskId", file_tasks::MakeTaskID(
+ extension_id, file_tasks::kFileBrowserHandlerTaskType, handler->id()));
+ task->SetString("title", handler->title());
+ // TODO(zelidrag): Figure out how to expose icon URL that task defined in
+ // manifest instead of the default extension icon.
+ GURL icon = extensions::ExtensionIconSource::GetIconURL(
+ extension,
+ extension_misc::EXTENSION_ICON_BITTY,
+ ExtensionIconSet::MATCH_BIGGER,
+ false, // grayscale
+ NULL); // exists
+ task->SetString("iconUrl", icon.spec());
+ task->SetBoolean("driveApp", false);
+
+ // Only set the default if there isn't already a default set.
+ if (!*default_already_set &&
+ std::find(default_tasks.begin(), default_tasks.end(), *iter) !=
+ default_tasks.end()) {
+ task->SetBoolean("isDefault", true);
+ *default_already_set = true;
+ } else {
+ task->SetBoolean("isDefault", false);
+ }
+
+ result_list->Append(task);
+ }
}
bool GetFileTasksFunction::RunImpl() {
@@ -483,72 +525,25 @@
ListValue* result_list = new ListValue();
SetResult(result_list);
- // Find the Drive apps first, because we want them to take precedence
+ // Find the Drive app tasks first, because we want them to take precedence
// when setting the default app.
bool default_already_set = false;
// Google document are not opened by drive apps but file manager.
- if (!has_google_document) {
- if (!FindDriveAppTasks(info_list, result_list, &default_already_set))
- return false;
- }
+ if (!has_google_document)
+ FindDriveAppTasks(info_list, result_list, &default_already_set);
- // Take the union of platform app file handlers, and all previous Drive
- // and extension tasks. As above, we know there aren't duplicates because
- // they're entirely different kinds of
+ // Find and append file handler tasks. We know there aren't duplicates
+ // because Drive apps and platform apps are entirely different kinds of
// tasks.
- if (!FindAppTasks(file_paths, result_list, &default_already_set))
- return false;
+ FindFileHandlerTasks(file_paths, result_list, &default_already_set);
- // Take the union of Drive and extension tasks: Because any Drive tasks we
- // found must apply to all of the files (intersection), and because the same
- // is true of the extensions, we simply take the union of two lists by adding
- // the extension tasks to the Drive task list. We know there aren't duplicates
- // because they're entirely different kinds of tasks, but there could be both
- // kinds of tasks for a file type (an image file, for instance).
- file_tasks::FileBrowserHandlerList common_tasks;
- file_tasks::FileBrowserHandlerList default_tasks;
- if (!file_tasks::FindCommonTasks(profile_, file_urls, &common_tasks))
- return false;
- file_tasks::FindDefaultTasks(profile_, file_paths,
- common_tasks, &default_tasks);
-
- ExtensionService* service =
- extensions::ExtensionSystem::Get(profile_)->extension_service();
- for (file_tasks::FileBrowserHandlerList::const_iterator iter =
- common_tasks.begin();
- iter != common_tasks.end();
- ++iter) {
- const FileBrowserHandler* handler = *iter;
- const std::string extension_id = handler->extension_id();
- const Extension* extension = service->GetExtensionById(extension_id, false);
- CHECK(extension);
- DictionaryValue* task = new DictionaryValue;
- task->SetString("taskId", file_tasks::MakeTaskID(
- extension_id, file_tasks::kTaskFile, handler->id()));
- task->SetString("title", handler->title());
- // TODO(zelidrag): Figure out how to expose icon URL that task defined in
- // manifest instead of the default extension icon.
- GURL icon = extensions::ExtensionIconSource::GetIconURL(
- extension,
- extension_misc::EXTENSION_ICON_BITTY,
- ExtensionIconSet::MATCH_BIGGER,
- false, // grayscale
- NULL); // exists
- task->SetString("iconUrl", icon.spec());
- task->SetBoolean("driveApp", false);
-
- // Only set the default if there isn't already a default set.
- if (!default_already_set &&
- std::find(default_tasks.begin(), default_tasks.end(), *iter) !=
- default_tasks.end()) {
- task->SetBoolean("isDefault", true);
- default_already_set = true;
- } else {
- task->SetBoolean("isDefault", false);
- }
-
- result_list->Append(task);
- }
+ // Find and append file browser handler tasks. We know there aren't
+ // duplicates because "file_browser_handlers" and "file_handlers" shouldn't
+ // be used in the same manifest.json.
+ FindFileBrowserHandlerTasks(file_urls,
+ file_paths,
+ result_list,
+ &default_already_set);
SendResponse(true);
return true;
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.h b/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.h
index a81bf94..4c12832 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_tasks.h
@@ -82,19 +82,36 @@
ListValue* result_list,
bool* default_already_set);
- // Find the list of drive apps that can be used with the given file types. If
- // a default task is set in the result list, then |default_already_set| is set
- // to true.
- bool FindDriveAppTasks(const FileInfoList& file_info_list,
+ // Finds the drive app tasks that can be used with the given files, and
+ // append them to the |result_list|. |*default_already_set| indicates if
+ // the |result_list| already contains the default task. If the value is
+ // false, the function will find the default task and set the value to true
+ // if found.
+ //
+ // "taskId" field in |result_list| will look like
+ // "<drive-app-id>|drive|open-with" (See also file_tasks.h).
+ // "driveApp" field in |result_list| will be set to "true".
+ void FindDriveAppTasks(const FileInfoList& file_info_list,
ListValue* result_list,
bool* default_already_set);
- // Find the list of app file handlers that can be used with the given file
- // types, appending them to the |result_list|. If a default task is set in the
- // result list, then |default_already_set| is set to true.
- bool FindAppTasks(const std::vector<base::FilePath>& file_paths,
- ListValue* result_list,
- bool* default_already_set);
+ // Find the file handler tasks (apps declaring "file_handlers" in
+ // manifest.json) that can be used with the given files, appending them to
+ // the |result_list|. See the comment at FindDriveAppTasks() about
+ // |default_already_set|
+ void FindFileHandlerTasks(const std::vector<base::FilePath>& file_paths,
+ ListValue* result_list,
+ bool* default_already_set);
+
+ // Find the file browser handler tasks (app/extensions declaring
+ // "file_browser_handlers" in manifest.json) that can be used with the
+ // given files, appending them to the |result_list|. See the comment at
+ // FindDriveAppTasks() about |default_already_set|
+ void FindFileBrowserHandlerTasks(
+ const std::vector<GURL>& file_urls,
+ const std::vector<base::FilePath>& file_paths,
+ ListValue* result_list,
+ bool* default_already_set);
};
// Implements the chrome.fileBrowserPrivate.setDefaultTask method.
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
index be35838..771b8ab 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
@@ -9,6 +9,7 @@
#include "chrome/browser/chromeos/drive/drive_integration_service.h"
#include "chrome/browser/chromeos/drive/file_errors.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
+#include "chrome/browser/chromeos/extensions/file_manager/fileapi_util.h"
#include "chrome/browser/chromeos/fileapi/file_system_backend.h"
#include "chrome/browser/extensions/extension_function_dispatcher.h"
#include "chrome/browser/extensions/extension_tab_util.h"
@@ -48,19 +49,17 @@
void GetSelectedFileInfoInternal(Profile* profile,
scoped_ptr<GetSelectedFileInfoParams> params) {
DCHECK(profile);
+ drive::DriveIntegrationService* integration_service =
+ drive::DriveIntegrationServiceFactory::GetForProfile(profile);
for (size_t i = params->selected_files.size();
i < params->file_paths.size(); ++i) {
const base::FilePath& file_path = params->file_paths[i];
- // When the caller of the select file dialog wants local file paths,
- // we should retrieve Drive files onto the local cache.
- if (params->local_path_option == NO_LOCAL_PATH_RESOLUTION ||
- !drive::util::IsUnderDriveMountPoint(file_path)) {
+
+ if (!drive::util::IsUnderDriveMountPoint(file_path)) {
params->selected_files.push_back(
ui::SelectedFileInfo(file_path, base::FilePath()));
} else {
- drive::DriveIntegrationService* integration_service =
- drive::DriveIntegrationServiceFactory::GetForProfile(profile);
// |integration_service| is NULL if Drive is disabled.
if (!integration_service) {
ContinueGetSelectedFileInfo(profile,
@@ -70,15 +69,29 @@
scoped_ptr<drive::ResourceEntry>());
return;
}
- // TODO(kinaba): crbug.com/140425 support FOR_SAVING
- DCHECK(params->local_path_option == NEED_LOCAL_PATH_FOR_OPENING);
- integration_service->file_system()->GetFileByPath(
- drive::util::ExtractDrivePath(file_path),
- base::Bind(&ContinueGetSelectedFileInfo,
- profile,
- base::Passed(¶ms)));
- return;
- }
+ // When the caller of the select file dialog wants local file paths,
+ // we should retrieve Drive files onto the local cache.
+ switch (params->local_path_option) {
+ case NO_LOCAL_PATH_RESOLUTION:
+ params->selected_files.push_back(
+ ui::SelectedFileInfo(file_path, base::FilePath()));
+ break;
+ case NEED_LOCAL_PATH_FOR_OPENING:
+ integration_service->file_system()->GetFileByPath(
+ drive::util::ExtractDrivePath(file_path),
+ base::Bind(&ContinueGetSelectedFileInfo,
+ profile,
+ base::Passed(¶ms)));
+ return; // Remaining work is done in ContinueGetSelectedFileInfo.
+ case NEED_LOCAL_PATH_FOR_SAVING:
+ integration_service->file_system()->GetFileByPathForSaving(
+ drive::util::ExtractDrivePath(file_path),
+ base::Bind(&ContinueGetSelectedFileInfo,
+ profile,
+ base::Passed(¶ms)));
+ return; // Remaining work is done in ContinueGetSelectedFileInfo.
+ }
+ }
}
params->callback.Run(params->selected_files);
}
@@ -144,10 +157,9 @@
DCHECK(render_view_host);
DCHECK(profile);
- content::SiteInstance* site_instance = render_view_host->GetSiteInstance();
scoped_refptr<fileapi::FileSystemContext> file_system_context =
- content::BrowserContext::GetStoragePartition(profile, site_instance)->
- GetFileSystemContext();
+ fileapi_util::GetFileSystemContextForRenderViewHost(
+ profile, render_view_host);
const fileapi::FileSystemURL filesystem_url(
file_system_context->CrackURL(url));
diff --git a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
index 628137f..376b90a 100644
--- a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
@@ -43,6 +43,11 @@
"/usr/share/chromeos-assets/input_methods/nacl_mozc",
},
{
+ // Google Chinese Input (zhuyin)
+ "goedamlknlnjaengojinmfgpmdjmkooo",
+ "/usr/share/chromeos-assets/input_methods/zhuyin",
+ },
+ {
// Google Chinese Input (pinyin)
"nmblnjkfdkabgdofidlkienfnnbjhnab",
"/usr/share/chromeos-assets/input_methods/pinyin",
@@ -53,11 +58,6 @@
"/usr/share/chromeos-assets/input_methods/cangjie",
},
{
- // Google Chinese Input (wubi)
- "jcffnbbngddhenhcnebafkbdomehdhpd",
- "/usr/share/chromeos-assets/input_methods/wubi",
- },
- {
// Google input tools.
"gjaehgfemfahhmlgpdfknkhdnemmolop",
"/usr/share/chromeos-assets/input_methods/input_tools",
@@ -69,6 +69,11 @@
"/usr/share/chromeos-assets/input_methods/pinyin",
},
{
+ // Open-sourced Zhuyin Chinese Input Method.
+ "ekbifjdfhkmdeeajnolmgdlmkllopefi",
+ "/usr/share/chromeos-assets/input_methods/zhuyin",
+ },
+ {
// Open-sourced Cangjie Chinese Input Method.
"aeebooiibjahgpgmhkeocbeekccfknbj",
"/usr/share/chromeos-assets/input_methods/cangjie",
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
index ad93cc8..20fba08 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -51,8 +51,12 @@
{ "mozc-dv", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_us" },
{ "pinyin", "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin" },
{ "pinyin-dv", "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin" },
+ { "mozc-chewing",
+ "_comp_ime_ekbifjdfhkmdeeajnolmgdlmkllopefizh-hant-t-i0-und "},
{ "m17n:zh:cangjie",
"_comp_ime_gjhclobljhjhgoebiipblnmdodbmpdgdzh-hant-t-i0-cangjie-1987" },
+ { "_comp_ime_jcffnbbngddhenhcnebafkbdomehdhpdzh-t-i0-wubi-1986",
+ "_comp_ime_gjhclobljhjhgoebiipblnmdodbmpdgdzh-t-i0-wubi-1986" },
// TODO(nona): Remove following migration map in M31.
{ "m17n:ta:itrans",
"_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ta_itrans" },
@@ -93,6 +97,9 @@
"_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_te_phone" },
{ "m17n:fa:isiri", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_fa" },
{ "m17n:ar:kbd", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ar" },
+ // TODO(nona): Remove following migration map in M32
+ { "m17n:zh:quick",
+ "_comp_ime_ekbifjdfhkmdeeajnolmgdlmkllopefizh-hant-t-i0-und" },
};
const struct MigrationHangulKeyboardToInputMethodID {
diff --git a/chrome/browser/chromeos/input_method/input_method_util.cc b/chrome/browser/chromeos/input_method/input_method_util.cc
index 6270f2b..fc91b63 100644
--- a/chrome/browser/chromeos/input_method/input_method_util.cc
+++ b/chrome/browser/chromeos/input_method/input_method_util.cc
@@ -53,7 +53,7 @@
"\xe6\x8b\xbc" },
{ "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin",
"\xe6\x8b\xbc" },
- { "_comp_ime_jcffnbbngddhenhcnebafkbdomehdhpdzh-t-i0-wubi-1986",
+ { "_comp_ime_gjhclobljhjhgoebiipblnmdodbmpdgdzh-t-i0-wubi-1986",
"\xe4\xba\x94" }, // U+4E94
{ "pinyin-dv", "\xe6\x8b\xbc" },
// For traditional Chinese input methods
@@ -102,7 +102,7 @@
IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_SIMPLIFIED},
{ "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin",
IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_SIMPLIFIED },
- { "_comp_ime_jcffnbbngddhenhcnebafkbdomehdhpdzh-t-i0-wubi-1986",
+ { "_comp_ime_gjhclobljhjhgoebiipblnmdodbmpdgdzh-t-i0-wubi-1986",
IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_SIMPLIFIED },
{ "_comp_ime_ekbifjdfhkmdeeajnolmgdlmkllopefizh-hant-t-i0-und",
IDS_LANGUAGES_MEDIUM_LEN_NAME_CHINESE_TRADITIONAL },
@@ -128,6 +128,8 @@
{ "ja", "us", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_us" },
{ "ja", "jp", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_jp" },
{ "zh-CN", "us", "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin" },
+ { "zh-TW", "us",
+ "_comp_ime_goedamlknlnjaengojinmfgpmdjmkooozh-hant-t-i0-und" },
{ "th", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_th" },
{ "vi", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_tcvn" },
{ "vi", "us", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_tcvn" },
diff --git a/chrome/browser/chromeos/input_method/input_method_util_unittest.cc b/chrome/browser/chromeos/input_method/input_method_util_unittest.cc
index 1a2afac..74a16b9 100644
--- a/chrome/browser/chromeos/input_method/input_method_util_unittest.cc
+++ b/chrome/browser/chromeos/input_method/input_method_util_unittest.cc
@@ -413,6 +413,18 @@
EXPECT_EQ("xkb:ru::rus", input_method_ids[1]); // Russian keyboard.
}
+// US keyboard + Traditional Chinese = US keyboard + chewing.
+TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_ZhTw) {
+ const InputMethodDescriptor* descriptor =
+ util_.GetInputMethodDescriptorFromId("xkb:us::eng"); // US keyboard.
+ ASSERT_TRUE(NULL != descriptor); // ASSERT_NE doesn't compile.
+ std::vector<std::string> input_method_ids;
+ util_.GetFirstLoginInputMethodIds("zh-TW", *descriptor, &input_method_ids);
+ ASSERT_EQ(2U, input_method_ids.size());
+ EXPECT_EQ("xkb:us::eng", input_method_ids[0]);
+ EXPECT_EQ(zhuyin_ime_id, input_method_ids[1]); // Chewing.
+}
+
// US keyboard + Thai = US keyboard + kesmanee.
TEST_F(InputMethodUtilTest, TestGetFirstLoginInputMethodIds_Us_And_Th) {
const InputMethodDescriptor* descriptor =
diff --git a/chrome/browser/chromeos/login/auth_prewarmer.cc b/chrome/browser/chromeos/login/auth_prewarmer.cc
index b7f8a59..64eb2ac 100644
--- a/chrome/browser/chromeos/login/auth_prewarmer.cc
+++ b/chrome/browser/chromeos/login/auth_prewarmer.cc
@@ -5,10 +5,12 @@
#include "chrome/browser/chromeos/login/auth_prewarmer.h"
#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/net/preconnect.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
#include "content/public/browser/browser_thread.h"
#include "google_apis/gaia/gaia_urls.h"
#include "url/gurl.h"
@@ -29,7 +31,8 @@
chrome::NOTIFICATION_PROFILE_URL_REQUEST_CONTEXT_GETTER_INITIALIZED,
content::Source<Profile>(ProfileHelper::GetSigninProfile()));
}
- ConnectivityStateHelper::Get()->RemoveNetworkManagerObserver(this);
+ NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
+ FROM_HERE);
}
void AuthPrewarmer::PrewarmAuthentication(
@@ -45,7 +48,8 @@
return;
}
if (!IsNetworkConnected())
- ConnectivityStateHelper::Get()->AddNetworkManagerObserver(this);
+ NetworkHandler::Get()->network_state_handler()->AddObserver(this,
+ FROM_HERE);
if (!GetRequestContext()) {
registrar_.Add(
this,
@@ -56,13 +60,14 @@
void AuthPrewarmer::NetworkManagerChanged() {
if (IsNetworkConnected()) {
- ConnectivityStateHelper::Get()->RemoveNetworkManagerObserver(this);
+ NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
+ FROM_HERE);
if (GetRequestContext())
DoPrewarm();
}
}
-void AuthPrewarmer::DefaultNetworkChanged() {
+void AuthPrewarmer::DefaultNetworkChanged(const NetworkState* network) {
NetworkManagerChanged();
}
@@ -106,7 +111,9 @@
}
bool AuthPrewarmer::IsNetworkConnected() const {
- return ConnectivityStateHelper::Get()->IsConnected();
+ NetworkStateHandler* nsh = NetworkHandler::Get()->network_state_handler();
+ return (nsh->ConnectedNetworkByType(NetworkStateHandler::kMatchTypeDefault) !=
+ NULL);
}
net::URLRequestContextGetter* AuthPrewarmer::GetRequestContext() const {
diff --git a/chrome/browser/chromeos/login/auth_prewarmer.h b/chrome/browser/chromeos/login/auth_prewarmer.h
index aa77fa8..861343d 100644
--- a/chrome/browser/chromeos/login/auth_prewarmer.h
+++ b/chrome/browser/chromeos/login/auth_prewarmer.h
@@ -7,7 +7,7 @@
#include "base/basictypes.h"
#include "base/callback.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper_observer.h"
+#include "chromeos/network/network_state_handler_observer.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
@@ -17,8 +17,10 @@
namespace chromeos {
+class NetworkState;
+
// Class for prewarming authentication network connection.
-class AuthPrewarmer : public ConnectivityStateHelperObserver,
+class AuthPrewarmer : public NetworkStateHandlerObserver,
public content::NotificationObserver {
public:
AuthPrewarmer();
@@ -27,9 +29,9 @@
void PrewarmAuthentication(const base::Closure& completion_callback);
private:
- // chromeos::ConnectivityStateHelperObserver overrides.
+ // chromeos::NetworkStateHandlerObserver overrides.
virtual void NetworkManagerChanged() OVERRIDE;
- virtual void DefaultNetworkChanged() OVERRIDE;
+ virtual void DefaultNetworkChanged(const NetworkState* network) OVERRIDE;
// content::NotificationObserver overrides.
virtual void Observe(int type,
diff --git a/chrome/browser/chromeos/login/captive_portal_view.cc b/chrome/browser/chromeos/login/captive_portal_view.cc
index c61b7a3..05bae47 100644
--- a/chrome/browser/chromeos/login/captive_portal_view.cc
+++ b/chrome/browser/chromeos/login/captive_portal_view.cc
@@ -7,7 +7,9 @@
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/captive_portal/captive_portal_detector.h"
#include "chrome/browser/chromeos/login/captive_portal_window_proxy.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
#include "content/public/browser/web_contents.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
@@ -47,8 +49,10 @@
string16 CaptivePortalView::GetWindowTitle() const {
string16 network_name;
- ConnectivityStateHelper* csh = ConnectivityStateHelper::Get();
- std::string default_network_name = csh->DefaultNetworkName();
+ const NetworkState* default_network =
+ NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
+ std::string default_network_name =
+ default_network ? default_network->name() : std::string();
if (!default_network_name.empty()) {
network_name = ASCIIToUTF16(default_network_name);
} else {
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc
index 94bd1b5..55cc35c 100644
--- a/chrome/browser/chromeos/login/chrome_restart_request.cc
+++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -40,7 +40,6 @@
#include "ui/gl/gl_switches.h"
#include "ui/views/corewm/corewm_switches.h"
#include "url/gurl.h"
-#include "webkit/plugins/plugin_switches.h"
using content::BrowserThread;
@@ -184,7 +183,6 @@
chromeos::switches::kLoginProfile,
chromeos::switches::kNaturalScrollDefault,
chromeos::switches::kUseNewNetworkConfigurationHandlers,
- chromeos::switches::kUseNewNetworkConnectionHandler,
gfx::switches::kEnableBrowserTextSubpixelPositioning,
gfx::switches::kEnableWebkitTextSubpixelPositioning,
views::corewm::switches::kNoDropShadows,
diff --git a/chrome/browser/chromeos/login/default_user_images.cc b/chrome/browser/chromeos/login/default_user_images.cc
index c84934a..6d325e7 100644
--- a/chrome/browser/chromeos/login/default_user_images.cc
+++ b/chrome/browser/chromeos/login/default_user_images.cc
@@ -127,7 +127,7 @@
return GetDefaultImageString(index, kDefaultUrlPrefix);
}
-bool IsDefaultImageUrl(const std::string url, int* image_id) {
+bool IsDefaultImageUrl(const std::string& url, int* image_id) {
if (url == kZeroDefaultUrl) {
*image_id = 0;
return true;
diff --git a/chrome/browser/chromeos/login/default_user_images.h b/chrome/browser/chromeos/login/default_user_images.h
index b45fac9..d30bd11 100644
--- a/chrome/browser/chromeos/login/default_user_images.h
+++ b/chrome/browser/chromeos/login/default_user_images.h
@@ -31,7 +31,7 @@
// Checks if the given URL points to one of the default images. If it is,
// returns true and its index through |image_id|. If not, returns false.
-bool IsDefaultImageUrl(const std::string url, int* image_id);
+bool IsDefaultImageUrl(const std::string& url, int* image_id);
// Returns bitmap of default user image with specified index.
const gfx::ImageSkia& GetDefaultImage(int index);
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index e6da685..f0e2e8b 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -32,7 +32,6 @@
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
@@ -135,7 +134,8 @@
is_login_in_progress_(false),
password_changed_(false),
do_auto_enrollment_(false),
- signin_screen_ready_(false) {
+ signin_screen_ready_(false),
+ network_state_helper_(new login::NetworkStateHelper) {
DCHECK(current_controller_ == NULL);
current_controller_ = this;
@@ -388,7 +388,7 @@
}
string16 ExistingUserController::GetConnectedNetworkName() {
- return GetCurrentNetworkName();
+ return network_state_helper_->GetCurrentNetworkName();
}
bool ExistingUserController::IsSigninInProgress() const {
@@ -736,7 +736,7 @@
// cached locally or the local admin account.
bool is_known_user =
UserManager::Get()->IsKnownUser(last_login_attempt_username_);
- if (!ConnectivityStateHelper::Get()->IsConnected()) {
+ if (!network_state_helper_->IsConnected()) {
if (is_known_user)
ShowError(IDS_LOGIN_ERROR_AUTHENTICATING, error);
else
@@ -1089,7 +1089,7 @@
// for end users, developers can see details string in Chrome logs.
VLOG(1) << details;
HelpAppLauncher::HelpTopic help_topic_id;
- bool is_offline = !ConnectivityStateHelper::Get()->IsConnected();
+ bool is_offline = !network_state_helper_->IsConnected();
switch (login_performer_->error().state()) {
case GoogleServiceAuthError::CONNECTION_FAILED:
help_topic_id = HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT_OFFLINE;
diff --git a/chrome/browser/chromeos/login/existing_user_controller.h b/chrome/browser/chromeos/login/existing_user_controller.h
index b249219..7a2ff11 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.h
+++ b/chrome/browser/chromeos/login/existing_user_controller.h
@@ -32,6 +32,10 @@
class CrosSettings;
class LoginDisplayHost;
+namespace login {
+class NetworkStateHelper;
+}
+
// ExistingUserController is used to handle login when someone has
// already logged into the machine.
// To use ExistingUserController create an instance of it and invoke Init.
@@ -296,6 +300,8 @@
// Timer for the interval to wait for the reboot after TPM error UI was shown.
base::OneShotTimer<ExistingUserController> reboot_timer_;
+ scoped_ptr<login::NetworkStateHelper> network_state_helper_;
+
FRIEND_TEST_ALL_PREFIXES(ExistingUserControllerTest, ExistingUserLogin);
DISALLOW_COPY_AND_ASSIGN(ExistingUserController);
diff --git a/chrome/browser/chromeos/login/helper.cc b/chrome/browser/chromeos/login/helper.cc
index ff60abe..a09f0c0 100644
--- a/chrome/browser/chromeos/login/helper.cc
+++ b/chrome/browser/chromeos/login/helper.cc
@@ -6,7 +6,9 @@
#include "ash/shell.h"
#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
@@ -26,31 +28,6 @@
return bounds;
}
-string16 GetCurrentNetworkName() {
- ConnectivityStateHelper* csh =
- ConnectivityStateHelper::Get();
-
- if (csh->IsConnectedType(flimflam::kTypeEthernet)) {
- return l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
- } else if (csh->IsConnectedType(flimflam::kTypeWifi)) {
- return UTF8ToUTF16(csh->NetworkNameForType(flimflam::kTypeWifi));
- } else if (csh->IsConnectedType(flimflam::kTypeCellular)) {
- return UTF8ToUTF16(csh->NetworkNameForType(flimflam::kTypeCellular));
- } else if (csh->IsConnectedType(flimflam::kTypeWimax)) {
- return UTF8ToUTF16(csh->NetworkNameForType(flimflam::kTypeWimax));
- } else if (csh->IsConnectingType(flimflam::kTypeEthernet)) {
- return l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
- } else if (csh->IsConnectingType(flimflam::kTypeWifi)) {
- return UTF8ToUTF16(csh->NetworkNameForType(flimflam::kTypeWifi));
- } else if (csh->IsConnectingType(flimflam::kTypeCellular)) {
- return UTF8ToUTF16(csh->NetworkNameForType(flimflam::kTypeCellular));
- } else if (csh->IsConnectingType(flimflam::kTypeWimax)) {
- return UTF8ToUTF16(csh->NetworkNameForType(flimflam::kTypeWimax));
- } else {
- return string16();
- }
-}
-
int GetCurrentUserImageSize() {
// The biggest size that the profile picture is displayed at is currently
// 220px, used for the big preview on OOBE and Change Picture options page.
@@ -62,4 +39,45 @@
ui::GetScaleFactorScale(ui::GetMaxScaleFactor());
}
+namespace login {
+
+NetworkStateHelper::NetworkStateHelper() {}
+NetworkStateHelper::~NetworkStateHelper() {}
+
+string16 NetworkStateHelper::GetCurrentNetworkName() const {
+ NetworkStateHandler* nsh = NetworkHandler::Get()->network_state_handler();
+ const NetworkState* network = nsh->ConnectedNetworkByType(
+ NetworkStateHandler::kMatchTypeNonVirtual);
+ if (network) {
+ if (network->type() == flimflam::kTypeEthernet)
+ return l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
+ return UTF8ToUTF16(network->name());
+ }
+
+ network = nsh->ConnectingNetworkByType(
+ NetworkStateHandler::kMatchTypeNonVirtual);
+ if (network) {
+ if (network->type() == flimflam::kTypeEthernet)
+ return l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
+ return UTF8ToUTF16(network->name());
+ }
+ return string16();
+}
+
+bool NetworkStateHelper::IsConnected() const {
+ chromeos::NetworkStateHandler* nsh =
+ chromeos::NetworkHandler::Get()->network_state_handler();
+ return nsh->ConnectedNetworkByType(
+ chromeos::NetworkStateHandler::kMatchTypeDefault) != NULL;
+}
+
+bool NetworkStateHelper::IsConnecting() const {
+ chromeos::NetworkStateHandler* nsh =
+ chromeos::NetworkHandler::Get()->network_state_handler();
+ return nsh->ConnectingNetworkByType(
+ chromeos::NetworkStateHandler::kMatchTypeDefault) != NULL;
+}
+
+} // namespace login
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/helper.h b/chrome/browser/chromeos/login/helper.h
index 41bc75d..543e6e5 100644
--- a/chrome/browser/chromeos/login/helper.h
+++ b/chrome/browser/chromeos/login/helper.h
@@ -26,13 +26,6 @@
// |size| is not empty. Otherwise the whole monitor is occupied.
gfx::Rect CalculateScreenBounds(const gfx::Size& size);
-// Returns name of the currently connected network.
-// If there are no connected networks, returns name of the network
-// that is in the "connecting" state. Otherwise empty string is returned.
-// If there are multiple connected networks, network priority:
-// Ethernet > WiFi > Cellular. Same for connecting network.
-string16 GetCurrentNetworkName();
-
// Returns the size of user image required for proper display under current DPI.
int GetCurrentUserImageSize();
@@ -44,6 +37,29 @@
// displayed under all possible DPI values.
const int kMaxUserImageSize = 512;
+// A helper class for easily mocking out Network*Handler calls for tests.
+class NetworkStateHelper {
+ public:
+ NetworkStateHelper();
+ virtual ~NetworkStateHelper();
+
+ // Returns name of the currently connected network.
+ // If there are no connected networks, returns name of the network
+ // that is in the "connecting" state. Otherwise empty string is returned.
+ // If there are multiple connected networks, network priority:
+ // Ethernet > WiFi > Cellular. Same for connecting network.
+ virtual string16 GetCurrentNetworkName() const;
+
+ // Returns true if the default network is in connected state.
+ virtual bool IsConnected() const;
+
+ // Returns true if the default network is in connecting state.
+ virtual bool IsConnecting() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NetworkStateHelper);
+};
+
} // namespace login
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/login_browsertest.cc b/chrome/browser/chromeos/login/login_browsertest.cc
index c1aa932..3bf47c8 100644
--- a/chrome/browser/chromeos/login/login_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_browsertest.cc
@@ -65,7 +65,6 @@
command_line->AppendSwitchASCII(
chromeos::switches::kLoginUser, "TestUser@gmail.com");
command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
- command_line->AppendSwitch(::switches::kNoFirstRun);
}
};
@@ -75,7 +74,6 @@
command_line->AppendSwitch(chromeos::switches::kGuestSession);
command_line->AppendSwitch(::switches::kIncognito);
command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
- command_line->AppendSwitch(::switches::kNoFirstRun);
}
};
diff --git a/chrome/browser/chromeos/login/login_utils_browsertest.cc b/chrome/browser/chromeos/login/login_utils_browsertest.cc
index 60923be..0b9d798 100644
--- a/chrome/browser/chromeos/login/login_utils_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_utils_browsertest.cc
@@ -23,8 +23,6 @@
#include "chrome/browser/chromeos/login/authenticator.h"
#include "chrome/browser/chromeos/login/login_status_consumer.h"
#include "chrome/browser/chromeos/login/user_manager.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
-#include "chrome/browser/chromeos/net/mock_connectivity_state_helper.h"
#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
@@ -217,9 +215,6 @@
CryptohomeLibrary::Initialize();
LoginState::Initialize();
- ConnectivityStateHelper::SetForTest(&mock_connectivity_state_helper_);
- EXPECT_CALL(mock_connectivity_state_helper_, DefaultNetworkOnline())
- .WillRepeatedly(Return(false));
mock_input_method_manager_ = new input_method::MockInputMethodManager();
input_method::InitializeForTesting(mock_input_method_manager_);
@@ -314,7 +309,6 @@
LoginUtils::Set(NULL);
input_method::Shutdown();
- ConnectivityStateHelper::SetForTest(NULL);
LoginState::Shutdown();
CryptohomeLibrary::Shutdown();
@@ -529,7 +523,6 @@
input_method::MockInputMethodManager* mock_input_method_manager_;
disks::MockDiskMountManager mock_disk_mount_manager_;
net::TestURLFetcherFactory test_url_fetcher_factory_;
- MockConnectivityStateHelper mock_connectivity_state_helper_;
cryptohome::MockAsyncMethodCaller* mock_async_method_caller_;
diff --git a/chrome/browser/chromeos/login/oauth2_login_verifier.cc b/chrome/browser/chromeos/login/oauth2_login_verifier.cc
index ab82a37..70bfc5c 100644
--- a/chrome/browser/chromeos/login/oauth2_login_verifier.cc
+++ b/chrome/browser/chromeos/login/oauth2_login_verifier.cc
@@ -11,12 +11,15 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
#include "chrome/browser/signin/profile_oauth2_token_service.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
#include "content/public/browser/browser_thread.h"
#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/gaia_urls.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
using content::BrowserThread;
@@ -50,8 +53,10 @@
// Delay the verification if the network is not connected or on a captive
// portal.
- ConnectivityStateHelper* csh = ConnectivityStateHelper::Get();
- if (!csh->DefaultNetworkOnline()) {
+ const NetworkState* default_network =
+ NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
+ if (!default_network ||
+ default_network->connection_state() == flimflam::kStatePortal) {
// If network is offline, defer the token fetching until online.
VLOG(1) << "Network is offline. Deferring OAuth2 access token fetch.";
BrowserThread::PostDelayedTask(
diff --git a/chrome/browser/chromeos/login/oauth2_token_fetcher.cc b/chrome/browser/chromeos/login/oauth2_token_fetcher.cc
index f66c1ca..31d3fd4 100644
--- a/chrome/browser/chromeos/login/oauth2_token_fetcher.cc
+++ b/chrome/browser/chromeos/login/oauth2_token_fetcher.cc
@@ -6,10 +6,13 @@
#include "base/logging.h"
#include "base/strings/string_util.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
#include "content/public/browser/browser_thread.h"
#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/google_service_auth_error.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
using content::BrowserThread;
@@ -41,8 +44,10 @@
// Delay the verification if the network is not connected or on a captive
// portal.
- ConnectivityStateHelper* csh = ConnectivityStateHelper::Get();
- if (!csh->DefaultNetworkOnline()) {
+ const NetworkState* default_network =
+ NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
+ if (!default_network ||
+ default_network->connection_state() == flimflam::kStatePortal) {
// If network is offline, defer the token fetching until online.
VLOG(1) << "Network is offline. Deferring OAuth2 token fetch.";
BrowserThread::PostDelayedTask(
@@ -61,8 +66,10 @@
auth_code_ = auth_code;
// Delay the verification if the network is not connected or on a captive
// portal.
- ConnectivityStateHelper* csh = ConnectivityStateHelper::Get();
- if (!csh->DefaultNetworkOnline()) {
+ const NetworkState* default_network =
+ NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
+ if (!default_network ||
+ default_network->connection_state() == flimflam::kStatePortal) {
// If network is offline, defer the token fetching until online.
VLOG(1) << "Network is offline. Deferring OAuth2 token fetch.";
BrowserThread::PostDelayedTask(
diff --git a/chrome/browser/chromeos/login/screens/network_screen.cc b/chrome/browser/chromeos/login/screens/network_screen.cc
index a4632b6..fd20947 100644
--- a/chrome/browser/chromeos/login/screens/network_screen.cc
+++ b/chrome/browser/chromeos/login/screens/network_screen.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/chromeos/login/screens/network_screen.h"
+#include "base/location.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
@@ -12,7 +13,8 @@
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/screens/screen_observer.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state_handler.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
@@ -36,7 +38,8 @@
: WizardScreen(screen_observer),
is_network_subscribed_(false),
continue_pressed_(false),
- actor_(actor) {
+ actor_(actor),
+ network_state_helper_(new login::NetworkStateHelper) {
DCHECK(actor_);
if (actor_)
actor_->SetDelegate(this);
@@ -73,13 +76,13 @@
}
////////////////////////////////////////////////////////////////////////////////
-// NetworkScreen, ConnectivityStateHelperObserver implementation:
+// NetworkScreen, NetworkStateHandlerObserver implementation:
void NetworkScreen::NetworkManagerChanged() {
UpdateStatus();
}
-void NetworkScreen::DefaultNetworkChanged() {
+void NetworkScreen::DefaultNetworkChanged(const NetworkState* network) {
NetworkManagerChanged();
}
@@ -100,7 +103,7 @@
}
void NetworkScreen::OnContinuePressed() {
- if (ConnectivityStateHelper::Get()->IsConnected()) {
+ if (network_state_helper_->IsConnected()) {
NotifyOnConnection();
} else {
continue_pressed_ = true;
@@ -111,17 +114,24 @@
////////////////////////////////////////////////////////////////////////////////
// NetworkScreen, private:
+void NetworkScreen::SetNetworkStateHelperForTest(
+ login::NetworkStateHelper* helper) {
+ network_state_helper_.reset(helper);
+}
+
void NetworkScreen::SubscribeNetworkNotification() {
if (!is_network_subscribed_) {
is_network_subscribed_ = true;
- ConnectivityStateHelper::Get()->AddNetworkManagerObserver(this);
+ NetworkHandler::Get()->network_state_handler()->AddObserver(
+ this, FROM_HERE);
}
}
void NetworkScreen::UnsubscribeNetworkNotification() {
if (is_network_subscribed_) {
is_network_subscribed_ = false;
- ConnectivityStateHelper::Get()->RemoveNetworkManagerObserver(this);
+ NetworkHandler::Get()->network_state_handler()->RemoveObserver(
+ this, FROM_HERE);
}
}
@@ -134,7 +144,7 @@
void NetworkScreen::OnConnectionTimeout() {
StopWaitingForConnection(network_id_);
- if (!ConnectivityStateHelper::Get()->IsConnected() && actor_) {
+ if (!network_state_helper_->IsConnected() && actor_) {
// Show error bubble.
actor_->ShowError(
l10n_util::GetStringFUTF16(
@@ -148,14 +158,14 @@
if (!actor_)
return;
- bool is_connected = ConnectivityStateHelper::Get()->IsConnected();
+ bool is_connected = network_state_helper_->IsConnected();
if (is_connected)
actor_->ClearErrors();
- string16 network_name = GetCurrentNetworkName();
+ string16 network_name = network_state_helper_->GetCurrentNetworkName();
if (is_connected) {
StopWaitingForConnection(network_name);
- } else if (ConnectivityStateHelper::Get()->IsConnecting()) {
+ } else if (network_state_helper_->IsConnecting()) {
WaitForConnection(network_name);
} else {
StopWaitingForConnection(network_id_);
@@ -163,7 +173,7 @@
}
void NetworkScreen::StopWaitingForConnection(const string16& network_id) {
- bool is_connected = ConnectivityStateHelper::Get()->IsConnected();
+ bool is_connected = network_state_helper_->IsConnected();
if (is_connected && continue_pressed_) {
NotifyOnConnection();
return;
diff --git a/chrome/browser/chromeos/login/screens/network_screen.h b/chrome/browser/chromeos/login/screens/network_screen.h
index 1a3ccf2..c8fae5c 100644
--- a/chrome/browser/chromeos/login/screens/network_screen.h
+++ b/chrome/browser/chromeos/login/screens/network_screen.h
@@ -12,12 +12,16 @@
#include "chrome/browser/chromeos/login/language_switch_menu.h"
#include "chrome/browser/chromeos/login/screens/network_screen_actor.h"
#include "chrome/browser/chromeos/login/screens/wizard_screen.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper_observer.h"
+#include "chromeos/network/network_state_handler_observer.h"
namespace chromeos {
+namespace login {
+class NetworkStateHelper;
+} // namespace login
+
class NetworkScreen : public WizardScreen,
- public ConnectivityStateHelperObserver,
+ public NetworkStateHandlerObserver,
public NetworkScreenActor::Delegate {
public:
NetworkScreen(ScreenObserver* screen_observer, NetworkScreenActor* actor);
@@ -29,9 +33,9 @@
virtual void Hide() OVERRIDE;
virtual std::string GetName() const OVERRIDE;
- // ConnectivityStateHelperObserver implementation:
+ // NetworkStateHandlerObserver implementation:
virtual void NetworkManagerChanged() OVERRIDE;
- virtual void DefaultNetworkChanged() OVERRIDE;
+ virtual void DefaultNetworkChanged(const NetworkState* network) OVERRIDE;
// NetworkScreenActor::Delegate implementation:
virtual void OnActorDestroyed(NetworkScreenActor* actor) OVERRIDE;
@@ -45,7 +49,13 @@
virtual void Refresh();
private:
+ friend class NetworkScreenTest;
FRIEND_TEST_ALL_PREFIXES(NetworkScreenTest, Timeout);
+ FRIEND_TEST_ALL_PREFIXES(NetworkScreenTest, CanConnect);
+
+ // Sets the NetworkStateHelper for use in tests. This
+ // class will take ownership of the pointed object.
+ void SetNetworkStateHelperForTest(login::NetworkStateHelper* helper);
// Subscribes to network change notifications.
void SubscribeNetworkNotification();
@@ -82,6 +92,7 @@
base::OneShotTimer<NetworkScreen> connection_timer_;
NetworkScreenActor* actor_;
+ scoped_ptr<login::NetworkStateHelper> network_state_helper_;
DISALLOW_COPY_AND_ASSIGN(NetworkScreen);
};
diff --git a/chrome/browser/chromeos/login/screens/network_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/network_screen_browsertest.cc
index dcaeda3..92b94bf 100644
--- a/chrome/browser/chromeos/login/screens/network_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/network_screen_browsertest.cc
@@ -3,12 +3,12 @@
// found in the LICENSE file.
#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/screens/mock_screen_observer.h"
#include "chrome/browser/chromeos/login/screens/network_screen.h"
#include "chrome/browser/chromeos/login/screens/wizard_screen.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h"
-#include "chrome/browser/chromeos/net/mock_connectivity_state_helper.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chromeos/dbus/fake_session_manager_client.h"
#include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h"
@@ -32,6 +32,17 @@
const ui::Event& event) OVERRIDE {}
};
+namespace login {
+
+class MockNetworkStateHelper : public NetworkStateHelper {
+ public:
+ MOCK_CONST_METHOD0(GetCurrentNetworkName, string16(void));
+ MOCK_CONST_METHOD0(IsConnected, bool(void));
+ MOCK_CONST_METHOD0(IsConnecting, bool(void));
+};
+
+} // namespace login
+
class NetworkScreenTest : public WizardInProcessBrowserTest {
public:
NetworkScreenTest(): WizardInProcessBrowserTest("network"),
@@ -47,19 +58,6 @@
DBusThreadManager::InitializeForTesting(mock_dbus_thread_manager);
fake_session_manager_client_ =
mock_dbus_thread_manager->fake_session_manager_client();
-
- mock_connectivity_state_helper_.reset(new MockConnectivityStateHelper);
- ConnectivityStateHelper::SetForTest(mock_connectivity_state_helper_.get());
- SetDefaultMockConnectivityStateHelperExpectations();
-
- cellular_.reset(new NetworkDevice("cellular"));
-
- // Minimal set of expectations needed on NetworkScreen initialization.
- // Status bar expectations are defined with RetiresOnSaturation() so
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeWifi))
- .Times(1)
- .WillRepeatedly(Return(false));
}
virtual void SetUpOnMainThread() OVERRIDE {
@@ -73,50 +71,41 @@
network_screen_);
network_screen_->screen_observer_ = mock_screen_observer_.get();
ASSERT_TRUE(network_screen_->actor() != NULL);
+
+ mock_network_state_helper_ = new login::MockNetworkStateHelper;
+ SetDefaultNetworkStateHelperExpectations();
+ network_screen_->SetNetworkStateHelperForTest(mock_network_state_helper_);
}
virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
CrosInProcessBrowserTest::TearDownInProcessBrowserTestFixture();
DBusThreadManager::Shutdown();
- ConnectivityStateHelper::SetForTest(NULL);
}
void EmulateContinueButtonExit(NetworkScreen* network_screen) {
EXPECT_CALL(*mock_screen_observer_,
OnExit(ScreenObserver::NETWORK_CONNECTED))
.Times(1);
- EXPECT_CALL(*mock_connectivity_state_helper_, IsConnected())
+ EXPECT_CALL(*mock_network_state_helper_, IsConnected())
.WillOnce(Return(true));
network_screen->OnContinuePressed();
content::RunAllPendingInMessageLoop();
}
- void SetDefaultMockConnectivityStateHelperExpectations() {
- EXPECT_CALL(*mock_connectivity_state_helper_, AddNetworkManagerObserver(_))
- .Times(AnyNumber());
- EXPECT_CALL(*mock_connectivity_state_helper_,
- RemoveNetworkManagerObserver(_))
- .Times(AnyNumber());
- EXPECT_CALL(*mock_connectivity_state_helper_, NetworkNameForType(_))
+ void SetDefaultNetworkStateHelperExpectations() {
+ EXPECT_CALL(*mock_network_state_helper_, GetCurrentNetworkName())
.Times(AnyNumber())
- .WillRepeatedly((Return("")));
- EXPECT_CALL(*mock_connectivity_state_helper_, IsConnected())
+ .WillRepeatedly((Return(string16())));
+ EXPECT_CALL(*mock_network_state_helper_, IsConnected())
.Times(AnyNumber())
.WillRepeatedly((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_, IsConnecting())
- .Times(AnyNumber())
- .WillRepeatedly((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_, IsConnectedType(_))
- .Times(AnyNumber())
- .WillRepeatedly((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_, IsConnectingType(_))
+ EXPECT_CALL(*mock_network_state_helper_, IsConnecting())
.Times(AnyNumber())
.WillRepeatedly((Return(false)));
}
scoped_ptr<MockScreenObserver> mock_screen_observer_;
- scoped_ptr<MockConnectivityStateHelper> mock_connectivity_state_helper_;
- scoped_ptr<NetworkDevice> cellular_;
+ login::MockNetworkStateHelper* mock_network_state_helper_;
NetworkScreen* network_screen_;
FakeSessionManagerClient* fake_session_manager_client_;
@@ -124,101 +113,13 @@
DISALLOW_COPY_AND_ASSIGN(NetworkScreenTest);
};
-IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Ethernet) {
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeEthernet))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeWifi))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeCellular))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectingType(flimflam::kTypeEthernet))
+IN_PROC_BROWSER_TEST_F(NetworkScreenTest, CanConnect) {
+ EXPECT_CALL(*mock_network_state_helper_, IsConnecting())
.WillOnce((Return(true)));
// EXPECT_FALSE(actor_->IsContinueEnabled());
network_screen_->NetworkManagerChanged();
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeEthernet))
- .WillOnce(Return(true));
- EXPECT_CALL(*mock_connectivity_state_helper_, IsConnected())
- .Times(2)
- .WillRepeatedly(Return(true));
- // TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
- // EXPECT_FALSE(actor_->IsContinueEnabled());
- // EXPECT_FALSE(actor_->IsConnecting());
- network_screen_->NetworkManagerChanged();
-
- // EXPECT_TRUE(actor_->IsContinueEnabled());
- EmulateContinueButtonExit(network_screen_);
- EXPECT_EQ(
- 1, fake_session_manager_client_->emit_login_prompt_ready_call_count());
-}
-
-IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Wifi) {
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeEthernet))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeWifi))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeCellular))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectingType(flimflam::kTypeEthernet))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectingType(flimflam::kTypeWifi))
- .WillOnce((Return(true)));
- // EXPECT_FALSE(actor_->IsContinueEnabled());
- network_screen_->NetworkManagerChanged();
-
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeEthernet))
- .WillOnce(Return(true));
- EXPECT_CALL(*mock_connectivity_state_helper_, IsConnected())
- .Times(2)
- .WillRepeatedly(Return(true));
- // TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
- // EXPECT_FALSE(actor_->IsContinueEnabled());
- // EXPECT_FALSE(actor_->IsConnecting());
- network_screen_->NetworkManagerChanged();
-
- // EXPECT_TRUE(actor_->IsContinueEnabled());
- EmulateContinueButtonExit(network_screen_);
- EXPECT_EQ(
- 1, fake_session_manager_client_->emit_login_prompt_ready_call_count());
-}
-
-IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Cellular) {
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeEthernet))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeWifi))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeCellular))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectingType(flimflam::kTypeEthernet))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectingType(flimflam::kTypeWifi))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectingType(flimflam::kTypeCellular))
- .WillOnce((Return(true)));
- // EXPECT_FALSE(actor_->IsContinueEnabled());
- network_screen_->NetworkManagerChanged();
-
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeEthernet))
- .WillOnce(Return(true));
- EXPECT_CALL(*mock_connectivity_state_helper_, IsConnected())
+ EXPECT_CALL(*mock_network_state_helper_, IsConnected())
.Times(2)
.WillRepeatedly(Return(true));
// TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
@@ -233,25 +134,12 @@
}
IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Timeout) {
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeEthernet))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeWifi))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectedType(flimflam::kTypeCellular))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectingType(flimflam::kTypeEthernet))
- .WillOnce((Return(false)));
- EXPECT_CALL(*mock_connectivity_state_helper_,
- IsConnectingType(flimflam::kTypeWifi))
+ EXPECT_CALL(*mock_network_state_helper_, IsConnecting())
.WillOnce((Return(true)));
// EXPECT_FALSE(actor_->IsContinueEnabled());
network_screen_->NetworkManagerChanged();
- EXPECT_CALL(*mock_connectivity_state_helper_, IsConnected())
+ EXPECT_CALL(*mock_network_state_helper_, IsConnected())
.Times(2)
.WillRepeatedly(Return(false));
// TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
diff --git a/chrome/browser/chromeos/login/user.h b/chrome/browser/chromeos/login/user.h
index 1c8fc9c..35911bb 100644
--- a/chrome/browser/chromeos/login/user.h
+++ b/chrome/browser/chromeos/login/user.h
@@ -48,22 +48,24 @@
// to by |email()|.
class User {
public:
- // The user type.
+ // The user type. Used in a histogram; do not modify existing types.
typedef enum {
// Regular user, has a user name and password.
USER_TYPE_REGULAR = 0,
// Guest user, logs in without authentication.
- USER_TYPE_GUEST,
+ USER_TYPE_GUEST = 1,
// Retail mode user, logs in without authentication. This is a special user
// type used in retail mode only.
- USER_TYPE_RETAIL_MODE,
+ USER_TYPE_RETAIL_MODE = 2,
// Public account user, logs in without authentication. Available only if
// enabled through policy.
- USER_TYPE_PUBLIC_ACCOUNT,
+ USER_TYPE_PUBLIC_ACCOUNT = 3,
// Locally managed user, logs in only with local authentication.
- USER_TYPE_LOCALLY_MANAGED,
+ USER_TYPE_LOCALLY_MANAGED = 4,
// Kiosk app robot, logs in without authentication.
- USER_TYPE_KIOSK_APP
+ USER_TYPE_KIOSK_APP = 5,
+ // Maximum histogram value.
+ NUM_USER_TYPES = 6
} UserType;
// User OAuth token status according to the last check.
diff --git a/chrome/browser/chromeos/login/user_manager_impl.cc b/chrome/browser/chromeos/login/user_manager_impl.cc
index 874e865..cdcf4bb 100644
--- a/chrome/browser/chromeos/login/user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/user_manager_impl.cc
@@ -7,7 +7,6 @@
#include <cstddef>
#include <set>
-#include "ash/shell.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/chromeos/chromeos_version.h"
@@ -15,6 +14,7 @@
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/logging.h"
+#include "base/metrics/histogram.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "base/rand_util.h"
@@ -111,6 +111,15 @@
// A dictionary that maps usernames to OAuth token presence flag.
const char kUserOAuthTokenStatus[] = "OAuthTokenStatus";
+// A string pref containing the ID of the last user who logged in if it was
+// a regular user or an empty string if it was another type of user (guest,
+// kiosk, public account, etc.).
+const char kLastLoggedInRegularUser[] = "LastLoggedInRegularUser";
+
+// Upper bound for a histogram metric reporting the amount of time between
+// one regular user logging out and a different regular user logging in.
+const int kLogoutToLoginDelayMaxSec = 1800;
+
// Callback that is called after user removal is complete.
void OnRemoveUserComplete(const std::string& user_email,
bool success,
@@ -189,6 +198,7 @@
kLocallyManagedUserCreationTransactionDisplayName, "");
registry->RegisterStringPref(
kLocallyManagedUserCreationTransactionUserId, "");
+ registry->RegisterStringPref(kLastLoggedInRegularUser, "");
registry->RegisterDictionaryPref(kUserOAuthTokenStatus);
registry->RegisterDictionaryPref(kUserDisplayName);
registry->RegisterDictionaryPref(kUserDisplayEmail);
@@ -213,7 +223,8 @@
locally_managed_users_enabled_by_policy_(false),
merge_session_state_(MERGE_STATUS_NOT_STARTED),
observed_sync_service_(NULL),
- user_image_manager_(new UserImageManagerImpl) {
+ user_image_manager_(new UserImageManagerImpl),
+ manager_creation_time_(base::TimeTicks::Now()) {
// UserManager instance should be used only on UI thread.
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
registrar_.Add(this, chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED,
@@ -317,10 +328,8 @@
User* user = FindUserInListAndModify(email);
if (user && user->GetType() == User::USER_TYPE_PUBLIC_ACCOUNT) {
PublicAccountUserLoggedIn(user);
- } else if ((user &&
- user->GetType() == User::USER_TYPE_LOCALLY_MANAGED) ||
- (!user &&
- gaia::ExtractDomainName(email) ==
+ } else if ((user && user->GetType() == User::USER_TYPE_LOCALLY_MANAGED) ||
+ (!user && gaia::ExtractDomainName(email) ==
UserManager::kLocallyManagedUserDomain)) {
LocallyManagedUserLoggedIn(email);
} else if (browser_restart && email == g_browser_process->local_state()->
@@ -347,6 +356,14 @@
logged_in_users_.insert(logged_in_users_.begin(), active_user_);
SetLRUUser(active_user_);
+ UMA_HISTOGRAM_ENUMERATION("UserManager.LoginUserType",
+ active_user_->GetType(), User::NUM_USER_TYPES);
+
+ if (active_user_->GetType() == User::USER_TYPE_REGULAR)
+ SendRegularUserLoginMetrics(email);
+ g_browser_process->local_state()->SetString(kLastLoggedInRegularUser,
+ (active_user_->GetType() == User::USER_TYPE_REGULAR) ? email : "");
+
NotifyOnLogin();
}
@@ -1064,7 +1081,7 @@
// If ephemeral users are enabled and we are on the login screen, take this
// opportunity to clean up by removing all regular users except the owner.
- if (ephemeral_users_enabled_ && !IsUserLoggedIn()) {
+ if (ephemeral_users_enabled_ && !IsUserLoggedIn()) {
ListPrefUpdate prefs_users_update(g_browser_process->local_state(),
kRegularUsers);
prefs_users_update->Clear();
@@ -1776,4 +1793,21 @@
}
}
+void UserManagerImpl::SendRegularUserLoginMetrics(const std::string& email) {
+ // If this isn't the first time Chrome was run after the system booted,
+ // assume that Chrome was restarted because a previous session ended.
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kFirstExecAfterBoot)) {
+ const std::string last_email =
+ g_browser_process->local_state()->GetString(kLastLoggedInRegularUser);
+ const base::TimeDelta time_to_login =
+ base::TimeTicks::Now() - manager_creation_time_;
+ if (!last_email.empty() && email != last_email &&
+ time_to_login.InSeconds() <= kLogoutToLoginDelayMaxSec) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("UserManager.LogoutToLoginDelay",
+ time_to_login.InSeconds(), 0, kLogoutToLoginDelayMaxSec, 50);
+ }
+ }
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/user_manager_impl.h b/chrome/browser/chromeos/login/user_manager_impl.h
index cdfe74d..577e1d6 100644
--- a/chrome/browser/chromeos/login/user_manager_impl.h
+++ b/chrome/browser/chromeos/login/user_manager_impl.h
@@ -13,6 +13,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "base/synchronization/lock.h"
+#include "base/time/time.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/user.h"
#include "chrome/browser/chromeos/login/user_image_manager_impl.h"
@@ -301,6 +302,9 @@
// Process continues till |pending_user_sessions_| map is not empty.
void RestorePendingUserSessions();
+ // Sends metrics in response to a regular user logging in.
+ void SendRegularUserLoginMetrics(const std::string& email);
+
// Interface to the signed settings store.
CrosSettings* cros_settings_;
@@ -409,6 +413,9 @@
// [user_id] > [user_id_hash]
SessionManagerClient::ActiveSessionsMap pending_user_sessions_;
+ // Time at which this object was created.
+ base::TimeTicks manager_creation_time_;
+
DISALLOW_COPY_AND_ASSIGN(UserManagerImpl);
};
diff --git a/chrome/browser/chromeos/login/webui_screen_locker.cc b/chrome/browser/chromeos/login/webui_screen_locker.cc
index c5532df..adee217 100644
--- a/chrome/browser/chromeos/login/webui_screen_locker.cc
+++ b/chrome/browser/chromeos/login/webui_screen_locker.cc
@@ -48,6 +48,7 @@
: ScreenLockerDelegate(screen_locker),
lock_ready_(false),
webui_ready_(false),
+ network_state_helper_(new login::NetworkStateHelper),
weak_factory_(this) {
set_should_emit_login_prompt_visible(false);
ash::Shell::GetInstance()->lock_state_controller()->AddObserver(this);
@@ -200,7 +201,7 @@
}
string16 WebUIScreenLocker::GetConnectedNetworkName() {
- return GetCurrentNetworkName();
+ return network_state_helper_->GetCurrentNetworkName();
}
bool WebUIScreenLocker::IsSigninInProgress() const {
diff --git a/chrome/browser/chromeos/login/webui_screen_locker.h b/chrome/browser/chromeos/login/webui_screen_locker.h
index 4da5d30..4521525 100644
--- a/chrome/browser/chromeos/login/webui_screen_locker.h
+++ b/chrome/browser/chromeos/login/webui_screen_locker.h
@@ -33,6 +33,10 @@
class WebUILoginDisplay;
struct UserContext;
+namespace login {
+class NetworkStateHelper;
+}
+
namespace test {
class WebUIScreenLockerTester;
}
@@ -135,6 +139,8 @@
// Time when lock was initiated, required for metrics.
base::TimeTicks lock_time_;
+ scoped_ptr<login::NetworkStateHelper> network_state_helper_;
+
base::WeakPtrFactory<WebUIScreenLocker> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(WebUIScreenLocker);
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index ff92afd..bc83452 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -21,7 +21,6 @@
#include "base/values.h"
#include "chrome/app/breakpad_linux.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_launcher.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
#include "chrome/browser/chromeos/customization_document.h"
@@ -60,9 +59,6 @@
#include "chromeos/dbus/session_manager_client.h"
#include "chromeos/network/network_state_handler.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/l10n/l10n_util.h"
@@ -186,10 +182,6 @@
is_out_of_box_ = true;
AdvanceToScreen(first_screen_name);
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_WIZARD_FIRST_SCREEN_SHOWN,
- content::NotificationService::AllSources(),
- content::NotificationService::NoDetails());
if (!IsMachineHWIDCorrect() && !StartupUtils::IsDeviceRegistered() &&
first_screen_name.empty())
ShowWrongHWIDScreen();
@@ -833,7 +825,9 @@
KioskAppManager::App app_data;
std::string app_id = KioskAppManager::Get()->GetAutoLaunchApp();
CHECK(KioskAppManager::Get()->GetApp(app_id, &app_data));
- ExistingUserController::current_controller()->PrepareKioskAppLaunch();
+ if (ExistingUserController::current_controller())
+ ExistingUserController::current_controller()->PrepareKioskAppLaunch();
+
// KioskAppLauncher deletes itself when done.
(new KioskAppLauncher(KioskAppManager::Get(), app_id))->Start();
}
diff --git a/chrome/browser/chromeos/mobile/mobile_activator.cc b/chrome/browser/chromeos/mobile/mobile_activator.cc
index 2c42584..3e1a82e 100644
--- a/chrome/browser/chromeos/mobile/mobile_activator.cc
+++ b/chrome/browser/chromeos/mobile/mobile_activator.cc
@@ -8,6 +8,7 @@
#include <map>
#include <string>
+#include "ash/system/chromeos/network/network_connect.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/file_util.h"
@@ -515,7 +516,8 @@
LOG(WARNING) << "Connect failed, will try again in a little bit.";
if (network) {
LOG(INFO) << "Connecting to: " << network->service_path();
- GetNetworkLibrary()->ConnectToCellularNetwork(network);
+ ash::network_connect::ConnectToNetwork(
+ network->service_path(), NULL /* no parent window */);
}
}
}
diff --git a/chrome/browser/chromeos/net/connectivity_state_helper.cc b/chrome/browser/chromeos/net/connectivity_state_helper.cc
deleted file mode 100644
index 59c626b..0000000
--- a/chrome/browser/chromeos/net/connectivity_state_helper.cc
+++ /dev/null
@@ -1,287 +0,0 @@
-// 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 "chrome/browser/chromeos/net/connectivity_state_helper.h"
-
-#include "base/command_line.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
-#include "chromeos/chromeos_switches.h"
-#include "chromeos/network/network_state.h"
-#include "chromeos/network/network_state_handler.h"
-#include "chromeos/network/network_state_handler_observer.h"
-#include "third_party/cros_system_api/dbus/service_constants.h"
-
-namespace chromeos {
-
-static ConnectivityStateHelper* g_connectivity_state_helper = NULL;
-static ConnectivityStateHelper* g_test_connectivity_state_helper = NULL;
-
-// Implementation of the connectivity state helper that uses the network
-// state handler for fetching connectivity state.
-class ConnectivityStateHelperImpl
- : public ConnectivityStateHelper,
- public NetworkStateHandlerObserver {
- public:
- ConnectivityStateHelperImpl();
- virtual ~ConnectivityStateHelperImpl();
-
- // NetworkStateHandler overrides.
- virtual bool IsConnected() OVERRIDE;
- virtual bool IsConnecting() OVERRIDE;
- virtual bool IsConnectedType(const std::string& type) OVERRIDE;
- virtual bool IsConnectingType(const std::string& type) OVERRIDE;
- virtual std::string NetworkNameForType(const std::string& type) OVERRIDE;
- virtual std::string DefaultNetworkName() OVERRIDE;
- virtual bool DefaultNetworkOnline() OVERRIDE;
- virtual void RequestScan() const OVERRIDE;
-
- // NetworkStateHandlerObserver overrides.
- virtual void NetworkManagerChanged() OVERRIDE;
- virtual void DefaultNetworkChanged(const NetworkState* network) OVERRIDE;
-
- private:
- NetworkStateHandler* network_state_handler_;
-};
-
-// Implementation of the connectivity state helper that uses the network
-// library for fetching connectivity state.
-class ConnectivityStateHelperNetworkLibrary
- : public ConnectivityStateHelper,
- public NetworkLibrary::NetworkManagerObserver {
- public:
- ConnectivityStateHelperNetworkLibrary();
- virtual ~ConnectivityStateHelperNetworkLibrary();
-
- // ConnectivityStateHelper overrides.
- virtual bool IsConnected() OVERRIDE;
- virtual bool IsConnecting() OVERRIDE;
- virtual bool IsConnectedType(const std::string& type) OVERRIDE;
- virtual bool IsConnectingType(const std::string& type) OVERRIDE;
- virtual std::string NetworkNameForType(const std::string& type) OVERRIDE;
- virtual std::string DefaultNetworkName() OVERRIDE;
- virtual bool DefaultNetworkOnline() OVERRIDE;
- virtual void RequestScan() const OVERRIDE;
-
- // NetworkLibrary::NetworkManagerObserver overrides.
- virtual void OnNetworkManagerChanged(
- NetworkLibrary* network_library) OVERRIDE;
-
- private:
- NetworkLibrary* network_library_;
-};
-
-ConnectivityStateHelper::ConnectivityStateHelper() {
-}
-
-ConnectivityStateHelper::~ConnectivityStateHelper() {
-}
-
-// static
-void ConnectivityStateHelper::Initialize() {
- CHECK(!g_connectivity_state_helper);
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- chromeos::switches::kDisableNewNetworkChangeNotifier)) {
- g_connectivity_state_helper = new ConnectivityStateHelperImpl();
- } else {
- g_connectivity_state_helper =
- new ConnectivityStateHelperNetworkLibrary();
- }
-}
-
-// static
-bool ConnectivityStateHelper::IsInitialized() {
- return g_connectivity_state_helper != NULL;
-}
-
-// static
-void ConnectivityStateHelper::Shutdown() {
- CHECK(g_connectivity_state_helper);
- delete g_connectivity_state_helper;
- g_connectivity_state_helper = NULL;
-}
-
-// static
-ConnectivityStateHelper* ConnectivityStateHelper::Get() {
- CHECK(g_connectivity_state_helper || g_test_connectivity_state_helper)
- << "ConnectivityStateHelper: Get() called before Initialize()";
- if (g_test_connectivity_state_helper)
- return g_test_connectivity_state_helper;
- return g_connectivity_state_helper;
-}
-
-// static
-void ConnectivityStateHelper::SetForTest(ConnectivityStateHelper* impl) {
- CHECK(!g_test_connectivity_state_helper || !impl);
- g_test_connectivity_state_helper = impl;
-}
-
-void ConnectivityStateHelper::AddNetworkManagerObserver(
- ConnectivityStateHelperObserver* observer) {
- connectivity_observers_.AddObserver(observer);
-}
-
-void ConnectivityStateHelper::RemoveNetworkManagerObserver(
- ConnectivityStateHelperObserver* observer) {
- connectivity_observers_.RemoveObserver(observer);
-}
-
-ConnectivityStateHelperImpl::ConnectivityStateHelperImpl() {
- network_state_handler_ = NetworkHandler::Get()->network_state_handler();
- network_state_handler_->AddObserver(this, FROM_HERE);
-}
-
-ConnectivityStateHelperImpl::~ConnectivityStateHelperImpl() {
- network_state_handler_->RemoveObserver(this, FROM_HERE);
-}
-
-bool ConnectivityStateHelperImpl::IsConnected() {
- return network_state_handler_->ConnectedNetworkByType(
- NetworkStateHandler::kMatchTypeDefault) != NULL;
-}
-
-bool ConnectivityStateHelperImpl::IsConnecting() {
- return network_state_handler_->ConnectingNetworkByType(
- NetworkStateHandler::kMatchTypeDefault) != NULL;
-}
-
-bool ConnectivityStateHelperImpl::IsConnectedType(
- const std::string& type) {
- return network_state_handler_->ConnectedNetworkByType(type) != NULL;
-}
-
-bool ConnectivityStateHelperImpl::IsConnectingType(
- const std::string& type) {
- return network_state_handler_->ConnectingNetworkByType(type) != NULL;
-}
-
-std::string ConnectivityStateHelperImpl::NetworkNameForType(
- const std::string& type) {
- const NetworkState* network = network_state_handler_->
- ConnectedNetworkByType(type);
- if (!network)
- network = network_state_handler_->ConnectingNetworkByType(type);
- return network ? network->name() : std::string();
-}
-
-std::string ConnectivityStateHelperImpl::DefaultNetworkName() {
- const NetworkState* default_network = network_state_handler_->
- DefaultNetwork();
- return default_network ? default_network->name() : std::string();
-}
-
-bool ConnectivityStateHelperImpl::DefaultNetworkOnline() {
- const NetworkState* network = network_state_handler_->DefaultNetwork();
- if (!network)
- return false;
- if (!network->IsConnectedState())
- return false;
- if (network->connection_state() == flimflam::kStatePortal)
- return false;
- return true;
-}
-
-void ConnectivityStateHelperImpl::RequestScan() const {
- network_state_handler_->RequestScan();
-}
-
-void ConnectivityStateHelperImpl::NetworkManagerChanged() {
- FOR_EACH_OBSERVER(ConnectivityStateHelperObserver, connectivity_observers_,
- NetworkManagerChanged());
-}
-
-void ConnectivityStateHelperImpl::DefaultNetworkChanged(
- const NetworkState* network) {
- FOR_EACH_OBSERVER(ConnectivityStateHelperObserver, connectivity_observers_,
- DefaultNetworkChanged());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NetworkLibrary implementation.
-//
-
-ConnectivityStateHelperNetworkLibrary::ConnectivityStateHelperNetworkLibrary() {
- network_library_ = NetworkLibrary::Get();
- network_library_->AddNetworkManagerObserver(this);
-}
-
-ConnectivityStateHelperNetworkLibrary::~ConnectivityStateHelperNetworkLibrary()
-{
- network_library_->RemoveNetworkManagerObserver(this);
-}
-
-bool ConnectivityStateHelperNetworkLibrary::IsConnected() {
- return network_library_->Connected();
-}
-
-bool ConnectivityStateHelperNetworkLibrary::IsConnecting() {
- return network_library_->Connecting();
-}
-
-bool ConnectivityStateHelperNetworkLibrary::IsConnectedType(
- const std::string& type) {
- if (type == flimflam::kTypeEthernet)
- return network_library_->ethernet_connected();
- if (type == flimflam::kTypeWifi)
- return network_library_->wifi_connected();
- if (type == flimflam::kTypeCellular)
- return network_library_->cellular_connected();
- if (type == flimflam::kTypeWimax)
- return network_library_->wimax_connected();
- return false;
-}
-
-bool ConnectivityStateHelperNetworkLibrary::IsConnectingType(
- const std::string& type) {
- if (type == flimflam::kTypeEthernet)
- return network_library_->ethernet_connecting();
- if (type == flimflam::kTypeWifi)
- return network_library_->wifi_connecting();
- if (type == flimflam::kTypeCellular)
- return network_library_->cellular_connecting();
- if (type == flimflam::kTypeWimax)
- return network_library_->wimax_connecting();
- return false;
-}
-
-std::string ConnectivityStateHelperNetworkLibrary::NetworkNameForType(
- const std::string& type) {
- if (type == flimflam::kTypeEthernet && network_library_->ethernet_network())
- return network_library_->ethernet_network()->name();
- if (type == flimflam::kTypeWifi && network_library_->wifi_network())
- return network_library_->wifi_network()->name();
- if (type == flimflam::kTypeCellular && network_library_->cellular_network())
- return network_library_->cellular_network()->name();
- if (type == flimflam::kTypeWimax && network_library_->wimax_network())
- return network_library_->wimax_network()->name();
- return std::string();
-}
-
-std::string ConnectivityStateHelperNetworkLibrary::DefaultNetworkName() {
- if (network_library_->active_network())
- return network_library_->active_network()->name();
- return std::string();
-}
-
-bool ConnectivityStateHelperNetworkLibrary::DefaultNetworkOnline() {
- const Network* active_network = network_library_->active_network();
- if (!active_network)
- return false;
- if (!active_network->connected())
- return false;
- if (active_network->restricted_pool())
- return false;
- return true;
-}
-
-void ConnectivityStateHelperNetworkLibrary::RequestScan() const {
- network_library_->RequestNetworkScan();
-}
-
-void ConnectivityStateHelperNetworkLibrary::OnNetworkManagerChanged(
- NetworkLibrary* network_library) {
- FOR_EACH_OBSERVER(ConnectivityStateHelperObserver, connectivity_observers_,
- NetworkManagerChanged());
-}
-
-} // namespace chromeos
diff --git a/chrome/browser/chromeos/net/connectivity_state_helper.h b/chrome/browser/chromeos/net/connectivity_state_helper.h
deleted file mode 100644
index d4b1201..0000000
--- a/chrome/browser/chromeos/net/connectivity_state_helper.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// 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 CHROME_BROWSER_CHROMEOS_NET_CONNECTIVITY_STATE_HELPER_H_
-#define CHROME_BROWSER_CHROMEOS_NET_CONNECTIVITY_STATE_HELPER_H_
-
-#include "base/observer_list.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
-#include "chrome/browser/chromeos/net/connectivity_state_helper_observer.h"
-#include "chromeos/network/network_state_handler.h"
-
-namespace chromeos {
-
-// This class provides an interface for consumers to query the connectivity
-// state on Chrome OS. Subclasses must implement the query methods using an
-// appropriate source (e.g. NetworkStateHandler).
-class ConnectivityStateHelper {
- public:
- virtual ~ConnectivityStateHelper();
-
- // Initializes the state helper singleton to use the default (network state
- // handler) implementation or the network library implementation based
- // on the value of command line flag.
- static void Initialize();
- static bool IsInitialized();
- static void Shutdown();
- static ConnectivityStateHelper* Get();
-
- // Sets up Get() to return |impl| for testing (e.g. with a mock
- // implementation). Call SetForTest(NUL) when |impl| is deleted.
- static void SetForTest(ConnectivityStateHelper* impl);
-
- // Returns true if in a connected state.
- virtual bool IsConnected() = 0;
-
- // Returns true if in a connecting state.
- virtual bool IsConnecting() = 0;
-
- // Returns true if there's a network of |type| in connected state.
- virtual bool IsConnectedType(const std::string& type) = 0;
-
- // Returns true if there's a network of |type| in connecting state.
- virtual bool IsConnectingType(const std::string& type) = 0;
-
- // Get the name for the primary network of type |type| which is not
- // in non-idle state (i.e. connecting or connected state).
- virtual std::string NetworkNameForType(const std::string& type) = 0;
-
- // Returns the name of the default network.
- virtual std::string DefaultNetworkName() = 0;
-
- // Returns true if we have a default network and are in online state.
- virtual bool DefaultNetworkOnline() = 0;
-
- // Request a network scan.
- virtual void RequestScan() const = 0;
-
- // Add/remove observers for listening to connection manager changes.
- virtual void AddNetworkManagerObserver(
- ConnectivityStateHelperObserver* observer);
- virtual void RemoveNetworkManagerObserver(
- ConnectivityStateHelperObserver* observer);
-
- protected:
- ConnectivityStateHelper();
- ObserverList<ConnectivityStateHelperObserver> connectivity_observers_;
-};
-
-} // namespace chromeos
-
-#endif // CHROME_BROWSER_CHROMEOS_NET_CONNECTIVITY_STATE_HELPER_H_
diff --git a/chrome/browser/chromeos/net/connectivity_state_helper_observer.h b/chrome/browser/chromeos/net/connectivity_state_helper_observer.h
deleted file mode 100644
index c907898..0000000
--- a/chrome/browser/chromeos/net/connectivity_state_helper_observer.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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 CHROME_BROWSER_CHROMEOS_NET_CONNECTIVITY_STATE_HELPER_OBSERVER_H_
-#define CHROME_BROWSER_CHROMEOS_NET_CONNECTIVITY_STATE_HELPER_OBSERVER_H_
-
-namespace chromeos {
-
-// A common observer interface used by the ConnectivityStateHelper object to
-// relay observing events received from the (older) NetworkLibrary or the (new)
-// NetworkStateHandler implementations.
-class ConnectivityStateHelperObserver {
- public:
- // Called when there's a change on the connection manager.
- virtual void NetworkManagerChanged() = 0;
-
- // Called when the default network changes.
- virtual void DefaultNetworkChanged() = 0;
-};
-
-} // namespace chromeos
-
-#endif // CHROME_BROWSER_CHROMEOS_NET_CONNECTIVITY_STATE_HELPER_OBSERVER_H_
diff --git a/chrome/browser/chromeos/net/cros_network_change_notifier_factory.cc b/chrome/browser/chromeos/net/cros_network_change_notifier_factory.cc
deleted file mode 100644
index 6941f45..0000000
--- a/chrome/browser/chromeos/net/cros_network_change_notifier_factory.cc
+++ /dev/null
@@ -1,28 +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 "chrome/browser/chromeos/net/cros_network_change_notifier_factory.h"
-
-#include "chrome/browser/chromeos/net/network_change_notifier_network_library.h"
-
-namespace chromeos {
-
-namespace {
-
-NetworkChangeNotifierNetworkLibrary* g_network_change_notifier = NULL;
-
-} // namespace
-
-net::NetworkChangeNotifier* CrosNetworkChangeNotifierFactory::CreateInstance() {
- DCHECK(!g_network_change_notifier);
- g_network_change_notifier = new NetworkChangeNotifierNetworkLibrary();
- return g_network_change_notifier;
-}
-
-// static
-NetworkChangeNotifierNetworkLibrary*
-CrosNetworkChangeNotifierFactory::GetInstance() {
- return g_network_change_notifier;
-}
-
-} // namespace net
diff --git a/chrome/browser/chromeos/net/cros_network_change_notifier_factory.h b/chrome/browser/chromeos/net/cros_network_change_notifier_factory.h
deleted file mode 100644
index b51d46f..0000000
--- a/chrome/browser/chromeos/net/cros_network_change_notifier_factory.h
+++ /dev/null
@@ -1,32 +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.
-
-#ifndef CHROME_BROWSER_CHROMEOS_NET_CROS_NETWORK_CHANGE_NOTIFIER_FACTORY_H_
-#define CHROME_BROWSER_CHROMEOS_NET_CROS_NETWORK_CHANGE_NOTIFIER_FACTORY_H_
-
-#include "base/compiler_specific.h"
-#include "net/base/network_change_notifier_factory.h"
-
-namespace chromeos {
-
-class NetworkChangeNotifierNetworkLibrary;
-
-// CrosNetworkChangeNotifierFactory creates ChromeOS-specific specialization of
-// NetworkChangeNotifier.
-class CrosNetworkChangeNotifierFactory
- : public net::NetworkChangeNotifierFactory {
- public:
- CrosNetworkChangeNotifierFactory() {}
-
- // Overrides of net::NetworkChangeNotifierFactory.
- virtual net::NetworkChangeNotifier* CreateInstance() OVERRIDE;
-
- // Gets the instance of the NetworkChangeNotifier for Chrome OS.
- // This is used for setting up the notifier at startup.
- static NetworkChangeNotifierNetworkLibrary* GetInstance();
-};
-
-} // namespace net
-
-#endif // CHROME_BROWSER_CHROMEOS_NET_CROS_NETWORK_CHANGE_NOTIFIER_FACTORY_H_
diff --git a/chrome/browser/chromeos/net/mock_connectivity_state_helper.cc b/chrome/browser/chromeos/net/mock_connectivity_state_helper.cc
deleted file mode 100644
index be9caa1..0000000
--- a/chrome/browser/chromeos/net/mock_connectivity_state_helper.cc
+++ /dev/null
@@ -1,12 +0,0 @@
-// 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 "chrome/browser/chromeos/net/mock_connectivity_state_helper.h"
-
-namespace chromeos {
-
-MockConnectivityStateHelper::MockConnectivityStateHelper() {}
-MockConnectivityStateHelper::~MockConnectivityStateHelper() {}
-
-} // namespace chromeos
diff --git a/chrome/browser/chromeos/net/mock_connectivity_state_helper.h b/chrome/browser/chromeos/net/mock_connectivity_state_helper.h
deleted file mode 100644
index cbef21d..0000000
--- a/chrome/browser/chromeos/net/mock_connectivity_state_helper.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// 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 CHROME_BROWSER_CHROMEOS_NET_MOCK_CONNECTIVITY_STATE_HELPER_H_
-#define CHROME_BROWSER_CHROMEOS_NET_MOCK_CONNECTIVITY_STATE_HELPER_H_
-
-#include "chrome/browser/chromeos/net/connectivity_state_helper.h"
-
-#include <string>
-
-#include "chrome/browser/chromeos/net/connectivity_state_helper_observer.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace chromeos {
-
-class MockConnectivityStateHelper : public ConnectivityStateHelper {
- public:
- MockConnectivityStateHelper();
- virtual ~MockConnectivityStateHelper();
- MOCK_METHOD0(IsConnected, bool(void));
- MOCK_METHOD0(IsConnecting, bool(void));
- MOCK_METHOD1(IsConnectedType, bool(const std::string&));
- MOCK_METHOD1(IsConnectingType, bool(const std::string&));
- MOCK_METHOD1(NetworkNameForType, std::string(const std::string&));
- MOCK_METHOD0(DefaultNetworkName, std::string(void));
- MOCK_METHOD0(DefaultNetworkOnline, bool(void));
- MOCK_CONST_METHOD0(RequestScan, void(void));
- MOCK_METHOD1(AddNetworkManagerObserver,
- void(ConnectivityStateHelperObserver*));
- MOCK_METHOD1(RemoveNetworkManagerObserver,
- void(ConnectivityStateHelperObserver*));
-};
-
-} // namespace chromeos
-
-#endif // CHROME_BROWSER_CHROMEOS_NET_MOCK_CONNECTIVITY_STATE_HELPER_H_
diff --git a/chrome/browser/chromeos/network_login_observer.cc b/chrome/browser/chromeos/network_login_observer.cc
index b4d4310..65cbd85 100644
--- a/chrome/browser/chromeos/network_login_observer.cc
+++ b/chrome/browser/chromeos/network_login_observer.cc
@@ -36,7 +36,7 @@
wifi->error() == ERROR_BAD_WEPKEY ||
wifi->connection_started() ||
(wifi->encrypted() && wifi->added())) {
- NetworkConfigView::Show(wifi, NULL);
+ NetworkConfigView::Show(wifi->service_path(), NULL);
return; // Only support one failure per notification.
}
}
@@ -58,7 +58,7 @@
wimax->error() == ERROR_BAD_WEPKEY ||
wimax->connection_started() ||
(wimax->passphrase_required() && wimax->added())) {
- NetworkConfigView::Show(wimax, NULL);
+ NetworkConfigView::Show(wimax->service_path(), NULL);
return; // Only support one failure per notification.
}
}
@@ -74,7 +74,7 @@
<< ", added: " << vpn->added();
// Display login dialog for any error or newly added network.
if (vpn->error() != ERROR_NO_ERROR || vpn->added()) {
- NetworkConfigView::Show(vpn, NULL);
+ NetworkConfigView::Show(vpn->service_path(), NULL);
return; // Only support one failure per notification.
}
}
diff --git a/chrome/browser/chromeos/options/network_config_view.cc b/chrome/browser/chromeos/options/network_config_view.cc
index 0a74836..257bbdc 100644
--- a/chrome/browser/chromeos/options/network_config_view.cc
+++ b/chrome/browser/chromeos/options/network_config_view.cc
@@ -12,7 +12,6 @@
#include "chrome/browser/chromeos/cros/network_property_ui_data.h"
#include "chrome/browser/chromeos/login/login_display_host_impl.h"
#include "chrome/browser/chromeos/login/user.h"
-#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/options/vpn_config_view.h"
#include "chrome/browser/chromeos/options/wifi_config_view.h"
#include "chrome/browser/chromeos/options/wimax_config_view.h"
@@ -21,7 +20,8 @@
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/host_desktop.h"
-#include "chromeos/network/managed_network_configuration_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
@@ -76,39 +76,38 @@
// static
const int ChildNetworkConfigView::kInputFieldMinWidth = 270;
-NetworkConfigView::NetworkConfigView(Network* network)
+NetworkConfigView::NetworkConfigView()
: child_config_view_(NULL),
delegate_(NULL),
advanced_button_(NULL) {
DCHECK(GetActiveDialog() == NULL);
SetActiveDialog(this);
- if (network->type() == TYPE_WIFI) {
- child_config_view_ =
- new WifiConfigView(this, static_cast<WifiNetwork*>(network));
- } else if (network->type() == TYPE_WIMAX) {
- child_config_view_ =
- new WimaxConfigView(this, static_cast<WimaxNetwork*>(network));
- } else if (network->type() == TYPE_VPN) {
- child_config_view_ =
- new VPNConfigView(this, static_cast<VirtualNetwork*>(network));
- } else {
- NOTREACHED();
- }
}
-NetworkConfigView::NetworkConfigView(ConnectionType type)
- : child_config_view_(NULL),
- delegate_(NULL),
- advanced_button_(NULL) {
- DCHECK(GetActiveDialog() == NULL);
- SetActiveDialog(this);
- if (type == TYPE_WIFI) {
- child_config_view_ = new WifiConfigView(this, false /* show_8021x */);
+void NetworkConfigView::InitWithNetworkState(const NetworkState* network) {
+ DCHECK(network);
+ std::string service_path = network->path();
+ if (network->type() == flimflam::kTypeWifi)
+ child_config_view_ = new WifiConfigView(this, service_path, false);
+ else if (network->type() == flimflam::kTypeWimax)
+ child_config_view_ = new WimaxConfigView(this, service_path);
+ else if (network->type() == flimflam::kTypeVPN)
+ child_config_view_ = new VPNConfigView(this, service_path);
+ else
+ NOTREACHED();
+}
+
+void NetworkConfigView::InitWithType(const std::string& type) {
+ if (type == flimflam::kTypeWifi) {
+ child_config_view_ = new WifiConfigView(this,
+ "" /* service_path */,
+ false /* show_8021x */);
advanced_button_ = new views::LabelButton(this, l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_ADVANCED_BUTTON));
advanced_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
- } else if (type == TYPE_VPN) {
- child_config_view_ = new VPNConfigView(this);
+ } else if (type == flimflam::kTypeVPN) {
+ child_config_view_ = new VPNConfigView(this,
+ "" /* service_path */);
} else {
NOTREACHED();
}
@@ -120,31 +119,28 @@
}
// static
-void NetworkConfigView::Show(Network* network, gfx::NativeWindow parent) {
+void NetworkConfigView::Show(const std::string& service_path,
+ gfx::NativeWindow parent) {
if (GetActiveDialog() != NULL)
return;
- NetworkConfigView* view = new NetworkConfigView(network);
+ NetworkConfigView* view = new NetworkConfigView();
+ const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path);
+ if (!network) {
+ LOG(ERROR) << "NetworkConfigView::Show called with invalid service_path";
+ return;
+ }
+ view->InitWithNetworkState(network);
view->ShowDialog(parent);
}
// static
-void NetworkConfigView::ShowForType(ConnectionType type,
+void NetworkConfigView::ShowForType(const std::string& type,
gfx::NativeWindow parent) {
if (GetActiveDialog() != NULL)
return;
- NetworkConfigView* view = new NetworkConfigView(type);
- view->ShowDialog(parent);
-}
-
-// static
-void NetworkConfigView::ShowForPath(const std::string& path,
- gfx::NativeWindow parent) {
- if (GetActiveDialog() != NULL)
- return;
- Network* network = NetworkLibrary::Get()->FindNetworkByPath(path);
- if (!network)
- return;
- NetworkConfigView* view = new NetworkConfigView(network);
+ NetworkConfigView* view = new NetworkConfigView();
+ view->InitWithType(type);
view->ShowDialog(parent);
}
@@ -219,7 +215,9 @@
RemoveChildView(child_config_view_);
delete child_config_view_;
// For now, there is only an advanced view for Wi-Fi 802.1X.
- child_config_view_ = new WifiConfigView(this, true /* show_8021x */);
+ child_config_view_ = new WifiConfigView(this,
+ "" /* service_path */,
+ true /* show_8021x */);
AddChildView(child_config_view_);
// Resize the window to be able to hold the new widgets.
gfx::Size size = views::Widget::GetLocalizedContentsSize(
@@ -271,6 +269,20 @@
window->Show();
}
+// ChildNetworkConfigView
+
+ChildNetworkConfigView::ChildNetworkConfigView(
+ NetworkConfigView* parent,
+ const std::string& service_path)
+ : parent_(parent),
+ service_path_(service_path) {
+}
+
+ChildNetworkConfigView::~ChildNetworkConfigView() {
+}
+
+// ControlledSettingIndicatorView
+
ControlledSettingIndicatorView::ControlledSettingIndicatorView()
: managed_(false),
image_view_(NULL) {
@@ -301,17 +313,6 @@
: gfx::Size();
}
-// static
-const base::DictionaryValue* NetworkConfigView::FindPolicyForActiveUser(
- const Network* network,
- onc::ONCSource* onc_source) {
- const User* user = UserManager::Get()->GetActiveUser();
- std::string username_hash = user ? user->username_hash() : std::string();
- std::string guid = network->unique_id();
- return NetworkHandler::Get()->managed_network_configuration_handler()
- ->FindPolicyByGUID(username_hash, guid, onc_source);
-}
-
void ControlledSettingIndicatorView::Layout() {
image_view_->SetBounds(0, 0, width(), height());
}
diff --git a/chrome/browser/chromeos/options/network_config_view.h b/chrome/browser/chromeos/options/network_config_view.h
index 26b3905..f51e3e7 100644
--- a/chrome/browser/chromeos/options/network_config_view.h
+++ b/chrome/browser/chromeos/options/network_config_view.h
@@ -9,7 +9,6 @@
#include "base/compiler_specific.h"
#include "base/strings/string16.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
#include "ui/gfx/native_widget_types.h" // gfx::NativeWindow
#include "ui/views/controls/button/button.h" // views::ButtonListener
#include "ui/views/window/dialog_delegate.h"
@@ -27,6 +26,7 @@
class ChildNetworkConfigView;
class NetworkPropertyUIData;
+class NetworkState;
// A dialog box for showing a password textfield.
class NetworkConfigView : public views::DialogDelegateView,
@@ -45,9 +45,10 @@
};
// Shows a network connection dialog if none is currently visible.
- static void Show(Network* network, gfx::NativeWindow parent);
- static void ShowForType(ConnectionType type, gfx::NativeWindow parent);
- static void ShowForPath(const std::string& path, gfx::NativeWindow parent);
+ static void Show(const std::string& service_path, gfx::NativeWindow parent);
+ // Shows a dialog to configure a new network. |type| must be a valid Shill
+ // 'Type' property value.
+ static void ShowForType(const std::string& type, gfx::NativeWindow parent);
// Returns corresponding native window.
gfx::NativeWindow GetNativeWindow() const;
@@ -75,10 +76,6 @@
delegate_ = delegate;
}
- static const base::DictionaryValue* FindPolicyForActiveUser(
- const Network* network,
- onc::ONCSource* onc_source);
-
protected:
// views::View overrides:
virtual void Layout() OVERRIDE;
@@ -87,12 +84,14 @@
const ViewHierarchyChangedDetails& details) OVERRIDE;
private:
- // Login dialog for known networks.
- explicit NetworkConfigView(Network* network);
- // Login dialog for new/hidden networks.
- explicit NetworkConfigView(ConnectionType type);
+ NetworkConfigView();
virtual ~NetworkConfigView();
+ // Login dialog for known networks.
+ void InitWithNetworkState(const NetworkState* network);
+ // Login dialog for new/hidden networks.
+ void InitWithType(const std::string& type);
+
// Creates and shows a dialog containing this view.
void ShowDialog(gfx::NativeWindow parent);
@@ -115,12 +114,11 @@
// methods, which are called by NetworkConfigView.
class ChildNetworkConfigView : public views::View {
public:
- ChildNetworkConfigView(NetworkConfigView* parent, Network* network)
- : service_path_(network->service_path()),
- parent_(parent) {}
- explicit ChildNetworkConfigView(NetworkConfigView* parent)
- : parent_(parent) {}
- virtual ~ChildNetworkConfigView() {}
+ // If |service_path| is NULL, a dialog for configuring a new network will
+ // be created.
+ ChildNetworkConfigView(NetworkConfigView* parent,
+ const std::string& service_path);
+ virtual ~ChildNetworkConfigView();
// Get the title to show for the dialog.
virtual string16 GetTitle() const = 0;
@@ -146,8 +144,8 @@
static const int kInputFieldMinWidth;
protected:
- std::string service_path_;
NetworkConfigView* parent_;
+ std::string service_path_;
private:
DISALLOW_COPY_AND_ASSIGN(ChildNetworkConfigView);
diff --git a/chrome/browser/chromeos/options/network_connect.cc b/chrome/browser/chromeos/options/network_connect.cc
index c44822b..a494325 100644
--- a/chrome/browser/chromeos/options/network_connect.cc
+++ b/chrome/browser/chromeos/options/network_connect.cc
@@ -12,8 +12,8 @@
#include "base/command_line.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/enrollment_dialog_view.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/options/network_config_view.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser_finder.h"
@@ -21,6 +21,13 @@
#include "chrome/browser/ui/webui/chromeos/mobile_setup_dialog.h"
#include "chrome/common/url_constants.h"
#include "chromeos/chromeos_switches.h"
+#include "chromeos/network/certificate_pattern.h"
+#include "chromeos/network/certificate_pattern_matcher.h"
+#include "chromeos/network/managed_network_configuration_handler.h"
+#include "chromeos/network/network_event_log.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
#include "content/public/browser/user_metrics.h"
#include "grit/generated_resources.h"
#include "net/base/escape.h"
@@ -28,84 +35,28 @@
#include "ui/base/l10n/l10n_util.h"
namespace chromeos {
-namespace network_connect {
namespace {
-void DoConnect(Network* network, gfx::NativeWindow parent_window) {
- NetworkLibrary* cros = NetworkLibrary::Get();
- if (network->type() == TYPE_VPN) {
- VirtualNetwork* vpn = static_cast<VirtualNetwork*>(network);
- if (vpn->NeedMoreInfoToConnect()) {
- // Show the connection UI if info for a field is missing.
- NetworkConfigView::Show(vpn, parent_window);
- } else {
- cros->ConnectToVirtualNetwork(vpn);
- // Connection failures are responsible for updating the UI, including
- // reopening dialogs.
- }
- } else if (network->type() == TYPE_WIFI) {
- WifiNetwork* wifi = static_cast<WifiNetwork*>(network);
- if (wifi->IsPassphraseRequired()) {
- // Show the connection UI if we require a passphrase.
- NetworkConfigView::Show(wifi, parent_window);
- } else {
- cros->ConnectToWifiNetwork(wifi);
- // Connection failures are responsible for updating the UI, including
- // reopening dialogs.
- }
- } else if (network->type() == TYPE_WIMAX) {
- WimaxNetwork* wimax = static_cast<WimaxNetwork*>(network);
- if (wimax->passphrase_required()) {
- // Show the connection UI if we require a passphrase.
- NetworkConfigView::Show(wimax, parent_window);
- } else {
- cros->ConnectToWimaxNetwork(wimax);
- // Connection failures are responsible for updating the UI, including
- // reopening dialogs.
- }
- } else if (network->type() == TYPE_CELLULAR) {
- CellularNetwork* cellular = static_cast<CellularNetwork*>(network);
- if (cellular->activation_state() != ACTIVATION_STATE_ACTIVATED ||
- cellular->out_of_credits()) {
- ActivateCellular(cellular->service_path());
- } else {
- cros->ConnectToCellularNetwork(cellular);
- }
- }
+void EnrollmentComplete(const std::string& service_path) {
+ NET_LOG_USER("Enrollment Complete", service_path);
}
-} // namespace
-
-void ActivateCellular(const std::string& service_path) {
- chromeos::NetworkLibrary* cros =
- chromeos::NetworkLibrary::Get();
- if (!cros->CellularDeviceUsesDirectActivation()) {
- // For non direct activation, show the mobile setup dialog which can be
- // used to activate the network.
- ShowMobileSetup(service_path);
- return;
- }
- chromeos::CellularNetwork* cellular =
- cros->FindCellularNetworkByPath(service_path);
- if (!cellular)
- return;
- if (cellular->activation_state() != chromeos::ACTIVATION_STATE_ACTIVATED)
- cellular->StartActivation();
- return;
}
+namespace network_connect {
+
void ShowMobileSetup(const std::string& service_path) {
- NetworkLibrary* cros = NetworkLibrary::Get();
- const CellularNetwork* cellular =
- cros->FindCellularNetworkByPath(service_path);
- if (cellular && !cellular->activated() &&
- cellular->activate_over_non_cellular_network() &&
- (!cros->connected_network() || !cros->connected_network()->online())) {
- NetworkTechnology technology = cellular->network_technology();
+ NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
+ const NetworkState* cellular = handler->GetNetworkState(service_path);
+ if (cellular && cellular->type() == flimflam::kTypeCellular &&
+ cellular->activation_state() != flimflam::kActivationStateActivated &&
+ cellular->activate_over_non_cellular_networks() &&
+ !handler->DefaultNetwork()) {
+ std::string technology = cellular->network_technology();
ash::NetworkObserver::NetworkType network_type =
- (technology == chromeos::NETWORK_TECHNOLOGY_LTE ||
- technology == chromeos::NETWORK_TECHNOLOGY_LTE_ADVANCED)
+ (technology == flimflam::kNetworkTechnologyLte ||
+ technology == flimflam::kNetworkTechnologyLteAdvanced)
? ash::NetworkObserver::NETWORK_CELLULAR_LTE
: ash::NetworkObserver::NETWORK_CELLULAR;
ash::Shell::GetInstance()->system_tray_notifier()->NotifySetNetworkMessage(
@@ -121,100 +72,21 @@
MobileSetupDialog::Show(service_path);
}
-ConnectResult ConnectToNetwork(const std::string& service_path,
- gfx::NativeWindow parent_window) {
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- chromeos::switches::kUseNewNetworkConnectionHandler)) {
- ash::network_connect::ConnectToNetwork(service_path);
- return CONNECT_STARTED;
- }
-
- NetworkLibrary* cros = NetworkLibrary::Get();
- Network* network = cros->FindNetworkByPath(service_path);
- if (!network)
- return NETWORK_NOT_FOUND;
-
- if (network->connecting_or_connected())
- return CONNECT_NOT_STARTED;
-
- if (network->type() == TYPE_ETHERNET)
- return CONNECT_NOT_STARTED; // Normally this shouldn't happen
-
- if (network->type() == TYPE_WIFI || network->type() == TYPE_VPN) {
- network->SetEnrollmentDelegate(chromeos::CreateEnrollmentDelegate(
- parent_window, network->name(), ProfileManager::GetLastUsedProfile()));
- network->AttemptConnection(base::Bind(&DoConnect, network, parent_window));
- return CONNECT_STARTED;
- }
-
- if (network->type() == TYPE_WIMAX) {
- WimaxNetwork* wimax = static_cast<WimaxNetwork*>(network);
- wimax->AttemptConnection(base::Bind(&DoConnect, wimax, parent_window));
- return CONNECT_STARTED;
- }
-
- if (network->type() == TYPE_CELLULAR) {
- CellularNetwork* cellular = static_cast<CellularNetwork*>(network);
- if (cellular->NeedsActivation() || cellular->out_of_credits()) {
- ActivateCellular(service_path);
- return CONNECT_STARTED;
- }
- if (cellular->activation_state() == ACTIVATION_STATE_ACTIVATING)
- return CONNECT_NOT_STARTED;
- cros->ConnectToCellularNetwork(cellular);
- return CONNECT_STARTED;
- }
-
- NOTREACHED();
- return CONNECT_NOT_STARTED;
-}
-
-void HandleUnconfiguredNetwork(const std::string& service_path,
- gfx::NativeWindow parent_window) {
- NetworkLibrary* cros = NetworkLibrary::Get();
- Network* network = cros->FindNetworkByPath(service_path);
- if (!network) {
- LOG(WARNING) << "Unknown network: " << service_path;
- return;
- }
-
- if (network->type() == TYPE_WIFI || network->type() == TYPE_VPN) {
- network->SetEnrollmentDelegate(chromeos::CreateEnrollmentDelegate(
- parent_window, network->name(), ProfileManager::GetLastUsedProfile()));
- // This will connect to the network only if the network just needs to have
- // its certificate configured. Otherwise it will show an enrollment dialog
- // if available, or call NetworkConfigView::Show().
- network->AttemptConnection(
- base::Bind(&NetworkConfigView::Show, network, parent_window));
- return;
- }
-
- if (network->type() == TYPE_WIMAX) {
- NetworkConfigView::Show(network, parent_window);
- return;
- }
-
- if (network->type() == TYPE_CELLULAR) {
- CellularNetwork* cellular = static_cast<CellularNetwork*>(network);
- if (cellular->NeedsActivation()) {
- ActivateCellular(service_path);
- return;
- } else if (cellular->out_of_credits()) {
- ShowMobileSetup(service_path);
- return;
- }
- }
-
- // No special configure or setup for |service_path|, show the settings UI.
+void ShowNetworkSettings(const std::string& service_path) {
std::string page = chrome::kInternetOptionsSubPage;
- std::string name = network->name();
- if (name.empty() && network->type() == TYPE_ETHERNET)
- name = l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
- page += base::StringPrintf(
- "?servicePath=%s&networkType=%d&networkName=%s",
- net::EscapeUrlEncodedData(service_path, true).c_str(),
- network->type(),
- net::EscapeUrlEncodedData(name, false).c_str());
+ const NetworkState* network = service_path.empty() ? NULL :
+ NetworkHandler::Get()->network_state_handler()->GetNetworkState(
+ service_path);
+ if (network) {
+ std::string name(network->name());
+ if (name.empty() && network->type() == flimflam::kTypeEthernet)
+ name = l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
+ page += base::StringPrintf(
+ "?servicePath=%s&networkType=%s&networkName=%s",
+ net::EscapeUrlEncodedData(service_path, true).c_str(),
+ net::EscapeUrlEncodedData(network->type(), true).c_str(),
+ net::EscapeUrlEncodedData(name, false).c_str());
+ }
content::RecordAction(
content::UserMetricsAction("OpenInternetOptionsDialog"));
Browser* browser = chrome::FindOrCreateTabbedBrowser(
@@ -223,5 +95,78 @@
chrome::ShowSettingsSubPage(browser, page);
}
+void HandleUnconfiguredNetwork(const std::string& service_path,
+ gfx::NativeWindow parent_window) {
+ const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path);
+ if (!network) {
+ NET_LOG_ERROR("Configuring unknown network", service_path);
+ return;
+ }
+
+ if (network->type() == flimflam::kTypeWifi) {
+ // Only show the config view for secure networks, otherwise do nothing.
+ if (network->security() != flimflam::kSecurityNone)
+ NetworkConfigView::Show(service_path, parent_window);
+ return;
+ }
+
+ if (network->type() == flimflam::kTypeWimax ||
+ network->type() == flimflam::kTypeVPN) {
+ NetworkConfigView::Show(service_path, parent_window);
+ return;
+ }
+
+ if (network->type() == flimflam::kTypeCellular) {
+ if (network->activation_state() != flimflam::kActivationStateActivated) {
+ ash::network_connect::ActivateCellular(service_path);
+ return;
+ }
+ if (network->cellular_out_of_credits()) {
+ ShowMobileSetup(service_path);
+ return;
+ }
+ // No special configure or setup for |network|, show the settings UI.
+ ShowNetworkSettings(service_path);
+ }
+ NOTREACHED();
+}
+
+bool EnrollNetwork(const std::string& service_path,
+ gfx::NativeWindow parent_window) {
+ const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path);
+ if (!network) {
+ NET_LOG_ERROR("Enrolling Unknown network", service_path);
+ return false;
+ }
+ // We skip certificate patterns for device policy ONC so that an unmanaged
+ // user can't get to the place where a cert is presented for them
+ // involuntarily.
+ if (network->ui_data().onc_source() == onc::ONC_SOURCE_DEVICE_POLICY)
+ return false;
+
+ const CertificatePattern& certificate_pattern =
+ network->ui_data().certificate_pattern();
+ if (certificate_pattern.Empty())
+ return false;
+
+ NET_LOG_USER("Enrolling", service_path);
+
+ EnrollmentDelegate* enrollment = CreateEnrollmentDelegate(
+ parent_window, network->name(), ProfileManager::GetDefaultProfile());
+ return enrollment->Enroll(certificate_pattern.enrollment_uri_list(),
+ base::Bind(&EnrollmentComplete, service_path));
+}
+
+const base::DictionaryValue* FindPolicyForActiveUser(
+ const NetworkState* network,
+ onc::ONCSource* onc_source) {
+ const User* user = UserManager::Get()->GetActiveUser();
+ std::string username_hash = user ? user->username_hash() : std::string();
+ return NetworkHandler::Get()->managed_network_configuration_handler()->
+ FindPolicyByGUID(username_hash, network->guid(), onc_source);
+}
+
} // namespace network_connect
} // namespace chromeos
diff --git a/chrome/browser/chromeos/options/network_connect.h b/chrome/browser/chromeos/options/network_connect.h
index 9872cbc..2d8acbe 100644
--- a/chrome/browser/chromeos/options/network_connect.h
+++ b/chrome/browser/chromeos/options/network_connect.h
@@ -6,46 +6,47 @@
#define CHROME_BROWSER_CHROMEOS_OPTIONS_NETWORK_CONNECT_H_
#include <string>
+#include <vector>
+#include "chromeos/network/onc/onc_constants.h"
#include "ui/gfx/native_widget_types.h" // gfx::NativeWindow
+namespace base {
+class DictionaryValue;
+}
+
namespace chromeos {
+
+class NetworkState;
+
namespace network_connect {
-enum ConnectResult {
- NETWORK_NOT_FOUND,
- CONNECT_NOT_STARTED,
- CONNECT_STARTED
-};
-
-// Activate the cellular network associated with |service_path| if direct
-// activation is supported, otherwise call ShowMobileSetup.
-void ActivateCellular(const std::string& service_path);
-
// Shows the mobile setup dialog which handles:
// * Activation for non direct-activation networks
// * Showing network plan info
void ShowMobileSetup(const std::string& service_path);
-// Attempts to connect to the network specified by |service_path|.
-// Returns one of the following results:
-// NETWORK_NOT_FOUND if the network does not exist.
-// CONNECT_NOT_STARTED if no connection attempt was started, e.g. because the
-// network is already connected, connecting, or activating.
-// CONNECT_STARTED if a connection attempt was started.
-ConnectResult ConnectToNetwork(const std::string& service_path,
- gfx::NativeWindow parent_window);
+// Shows the network settings subpage for |service_path| (or the main
+// network settings page if empty).
+void ShowNetworkSettings(const std::string& service_path);
-// Handle an unconfigured network which might do any of the following:
-// * Configure and connect to the network with a matching cert but without
-// pcks11id and tpm pin / slot configured.
-// * Show the enrollment dialog for the network.
-// * Show the configuration dialog for the network.
-// * Show the activation dialog for the network.
-// * Show the settings UI for the network.
+// Handle an unconfigured network:
+// * Show the Configure dialog for wifi/wimax/VPN
+// * Show the Activation, MobileSetup dialog, or settings page for cellular
void HandleUnconfiguredNetwork(const std::string& service_path,
gfx::NativeWindow parent_window);
+// If the network UIData has a matching enrollment URL, triggers the enrollment
+// dialog and returns true.
+bool EnrollNetwork(const std::string& service_path,
+ gfx::NativeWindow parent_window);
+
+// Looks up the policy for |network| for the current active user and sets
+// |onc_source| accordingly.
+const base::DictionaryValue* FindPolicyForActiveUser(
+ const NetworkState* network,
+ onc::ONCSource* onc_source);
+
} // namespace network_connect
} // namespace chromeos
diff --git a/chrome/browser/chromeos/options/passphrase_textfield.cc b/chrome/browser/chromeos/options/passphrase_textfield.cc
index 598d192..9cc9bd3 100644
--- a/chrome/browser/chromeos/options/passphrase_textfield.cc
+++ b/chrome/browser/chromeos/options/passphrase_textfield.cc
@@ -8,12 +8,18 @@
namespace chromeos {
-PassphraseTextfield::PassphraseTextfield(bool show_fake)
+PassphraseTextfield::PassphraseTextfield()
: Textfield(views::Textfield::STYLE_OBSCURED),
- show_fake_(show_fake),
+ show_fake_(false),
changed_(true) {
+}
+
+void PassphraseTextfield::SetShowFake(bool show_fake) {
+ show_fake_ = show_fake;
if (show_fake_)
SetFakePassphrase();
+ else
+ ClearFakePassphrase();
}
void PassphraseTextfield::OnFocus() {
diff --git a/chrome/browser/chromeos/options/passphrase_textfield.h b/chrome/browser/chromeos/options/passphrase_textfield.h
index 16d5301..1f1b590 100644
--- a/chrome/browser/chromeos/options/passphrase_textfield.h
+++ b/chrome/browser/chromeos/options/passphrase_textfield.h
@@ -13,8 +13,10 @@
class PassphraseTextfield : public views::Textfield {
public:
- // If show_already_set is true, then the text field will show a fake password.
- explicit PassphraseTextfield(bool show_fake);
+ PassphraseTextfield();
+
+ // If show_fake is true, then the text field will show a fake password.
+ void SetShowFake(bool show_fake);
// Override views::Textfield so that when focus is gained, then clear out the
// fake password if appropriate. Replace it when focus is lost if the user has
diff --git a/chrome/browser/chromeos/options/vpn_config_view.cc b/chrome/browser/chromeos/options/vpn_config_view.cc
index d8e019b..4aa6682 100644
--- a/chrome/browser/chromeos/options/vpn_config_view.cc
+++ b/chrome/browser/chromeos/options/vpn_config_view.cc
@@ -4,19 +4,25 @@
#include "chrome/browser/chromeos/options/vpn_config_view.h"
+#include "ash/system/chromeos/network/network_connect.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/enrollment_dialog_view.h"
+#include "chrome/browser/chromeos/options/network_connect.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/net/x509_certificate_model.h"
+#include "chromeos/network/network_configuration_handler.h"
+#include "chromeos/network/network_event_log.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/network_ui_data.h"
#include "chromeos/network/onc/onc_constants.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "grit/theme_resources.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/events/event.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/combobox_model.h"
@@ -35,41 +41,73 @@
// Root CA certificates that are built into Chrome use this token name.
const char* const kRootCertificateTokenName = "Builtin Object Token";
-string16 ProviderTypeToString(chromeos::ProviderType type) {
- switch (type) {
- case chromeos::PROVIDER_TYPE_L2TP_IPSEC_PSK:
+enum ProviderTypeIndex {
+ PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK = 0,
+ PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT = 1,
+ PROVIDER_TYPE_INDEX_OPEN_VPN = 2,
+ PROVIDER_TYPE_INDEX_MAX = 3,
+};
+
+string16 ProviderTypeIndexToString(int index) {
+ switch (index) {
+ case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK:
return l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_PSK);
- case chromeos::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT:
+ case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT:
return l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_USER_CERT);
- case chromeos::PROVIDER_TYPE_OPEN_VPN:
+ case PROVIDER_TYPE_INDEX_OPEN_VPN:
return l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_OPEN_VPN);
- case chromeos::PROVIDER_TYPE_MAX:
- break;
}
NOTREACHED();
return string16();
}
+int ProviderTypeToIndex(const std::string& provider_type,
+ const std::string& client_cert_id) {
+ if (provider_type == flimflam::kProviderL2tpIpsec) {
+ if (!client_cert_id.empty())
+ return PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT;
+ else
+ return PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK;
+ } else {
+ DCHECK(provider_type == flimflam::kProviderOpenVpn);
+ return PROVIDER_TYPE_INDEX_OPEN_VPN;
+ }
+}
+
// Translates the provider type to the name of the respective ONC dictionary
// containing configuration data for the type.
-std::string ProviderTypeToONCDictKey(chromeos::ProviderType type) {
- switch (type) {
- case chromeos::PROVIDER_TYPE_L2TP_IPSEC_PSK:
- case chromeos::PROVIDER_TYPE_L2TP_IPSEC_USER_CERT:
+std::string ProviderTypeIndexToONCDictKey(int provider_type_index) {
+ switch (provider_type_index) {
+ case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK:
+ case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT:
return chromeos::onc::vpn::kIPsec;
- case chromeos::PROVIDER_TYPE_OPEN_VPN:
+ case PROVIDER_TYPE_INDEX_OPEN_VPN:
return chromeos::onc::vpn::kOpenVPN;
- case chromeos::PROVIDER_TYPE_MAX:
- break;
}
-
- NOTREACHED() << "Unhandled provider type " << type;
+ NOTREACHED() << "Unhandled provider type index " << provider_type_index;
return std::string();
}
+std::string GetPemFromDictionary(
+ const base::DictionaryValue* provider_properties,
+ const std::string& key) {
+ const base::ListValue* pems = NULL;
+ if (!provider_properties->GetListWithoutPathExpansion(key, &pems))
+ return std::string();
+ std::string pem;
+ pems->GetString(0, &pem);
+ return pem;
+}
+
+void ShillError(const std::string& function,
+ const std::string& error_name,
+ scoped_ptr<base::DictionaryValue> error_data) {
+ NET_LOG_ERROR("Shill Error from VpnConfigView: " + error_name, function);
+}
+
} // namespace
namespace chromeos {
@@ -124,12 +162,11 @@
}
int ProviderTypeComboboxModel::GetItemCount() const {
- return PROVIDER_TYPE_MAX;
+ return PROVIDER_TYPE_INDEX_MAX;
}
string16 ProviderTypeComboboxModel::GetItemAt(int index) {
- ProviderType type = static_cast<ProviderType>(index);
- return ProviderTypeToString(type);
+ return ProviderTypeIndexToString(index);
}
// VpnServerCACertComboboxModel ------------------------------------------------
@@ -193,16 +230,39 @@
} // namespace internal
-VPNConfigView::VPNConfigView(NetworkConfigView* parent, VirtualNetwork* vpn)
- : ChildNetworkConfigView(parent, vpn),
- title_(0) {
- Init(vpn);
-}
-
-VPNConfigView::VPNConfigView(NetworkConfigView* parent)
- : ChildNetworkConfigView(parent),
- title_(0) {
- Init(NULL);
+VPNConfigView::VPNConfigView(NetworkConfigView* parent,
+ const std::string& service_path)
+ : ChildNetworkConfigView(parent, service_path),
+ service_text_modified_(false),
+ enable_psk_passphrase_(false),
+ enable_user_cert_(false),
+ enable_server_ca_cert_(false),
+ enable_otp_(false),
+ enable_group_name_(false),
+ title_(0),
+ layout_(NULL),
+ server_textfield_(NULL),
+ service_text_(NULL),
+ service_textfield_(NULL),
+ provider_type_combobox_(NULL),
+ provider_type_text_label_(NULL),
+ psk_passphrase_label_(NULL),
+ psk_passphrase_textfield_(NULL),
+ user_cert_label_(NULL),
+ user_cert_combobox_(NULL),
+ server_ca_cert_label_(NULL),
+ server_ca_cert_combobox_(NULL),
+ username_textfield_(NULL),
+ user_passphrase_textfield_(NULL),
+ otp_label_(NULL),
+ otp_textfield_(NULL),
+ group_name_label_(NULL),
+ group_name_textfield_(NULL),
+ save_credentials_checkbox_(NULL),
+ error_label_(NULL),
+ provider_type_index_(PROVIDER_TYPE_INDEX_MAX),
+ weak_ptr_factory_(this) {
+ Init();
}
VPNConfigView::~VPNConfigView() {
@@ -243,7 +303,9 @@
return false;
// Block login if certs are required but user has none.
- if (UserCertRequired() && (!HaveUserCerts() || !IsUserCertValid()))
+ bool cert_required =
+ GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT;
+ if (cert_required && (!HaveUserCerts() || !IsUserCertValid()))
return false;
return true;
@@ -283,15 +345,7 @@
}
void VPNConfigView::OnSelectedIndexChanged(views::Combobox* combobox) {
- if (combobox == provider_type_combobox_) {
- provider_type_ = static_cast<ProviderType>(combobox->selected_index());
- UpdateControls();
- } else if (combobox == user_cert_combobox_ ||
- combobox == server_ca_cert_combobox_) {
- // Do nothing.
- } else {
- NOTREACHED();
- }
+ UpdateControls();
UpdateErrorLabel();
UpdateCanLogin();
}
@@ -301,77 +355,35 @@
}
bool VPNConfigView::Login() {
- NetworkLibrary* cros = NetworkLibrary::Get();
if (service_path_.empty()) {
- NetworkLibrary::VPNConfigData config_data;
- switch (provider_type_) {
- case PROVIDER_TYPE_L2TP_IPSEC_PSK:
- config_data.psk = GetPSKPassphrase();
- config_data.username = GetUsername();
- config_data.user_passphrase = GetUserPassphrase();
- config_data.group_name = GetGroupName();
- break;
- case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: {
- config_data.server_ca_cert_pem = GetServerCACertPEM();
- config_data.client_cert_pkcs11_id = GetUserCertID();
- config_data.username = GetUsername();
- config_data.user_passphrase = GetUserPassphrase();
- config_data.group_name = GetGroupName();
- break;
- }
- case PROVIDER_TYPE_OPEN_VPN:
- config_data.server_ca_cert_pem = GetServerCACertPEM();
- config_data.client_cert_pkcs11_id = GetUserCertID();
- config_data.username = GetUsername();
- config_data.user_passphrase = GetUserPassphrase();
- config_data.otp = GetOTP();
- break;
- case PROVIDER_TYPE_MAX:
- break;
- }
- config_data.save_credentials = GetSaveCredentials();
- cros->ConnectToUnconfiguredVirtualNetwork(
- GetService(), GetServer(), provider_type_, config_data);
+ base::DictionaryValue properties;
+ // Identifying properties
+ properties.SetStringWithoutPathExpansion(
+ flimflam::kTypeProperty, flimflam::kTypeVPN);
+ properties.SetStringWithoutPathExpansion(
+ flimflam::kNameProperty, GetService());
+ properties.SetStringWithoutPathExpansion(
+ flimflam::kProviderHostProperty, GetServer());
+ properties.SetStringWithoutPathExpansion(
+ flimflam::kProviderTypeProperty, GetProviderTypeString());
+
+ SetConfigProperties(&properties);
+ ash::network_connect::CreateConfigurationAndConnect(
+ &properties, false /* not shared */);
} else {
- VirtualNetwork* vpn = cros->FindVirtualNetworkByPath(service_path_);
+ const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path_);
if (!vpn) {
+ // Shill no longer knows about this network (edge case).
// TODO(stevenjb): Add notification for this.
- LOG(WARNING) << "VPN no longer exists: " << service_path_;
- return true; // Close dialog.
+ NET_LOG_ERROR("Network not found", service_path_);
+ return true; // Close dialog
}
- switch (provider_type_) {
- case PROVIDER_TYPE_L2TP_IPSEC_PSK:
- vpn->SetL2TPIPsecPSKCredentials(GetPSKPassphrase(),
- GetUsername(),
- GetUserPassphrase(),
- GetGroupName());
- break;
- case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: {
- vpn->SetL2TPIPsecCertCredentials(GetUserCertID(),
- GetUsername(),
- GetUserPassphrase(),
- GetGroupName());
- break;
- }
- case PROVIDER_TYPE_OPEN_VPN: {
- vpn->SetOpenVPNCredentials(GetUserCertID(),
- GetUsername(),
- GetUserPassphrase(),
- GetOTP());
- break;
- }
- case PROVIDER_TYPE_MAX:
- break;
- }
- vpn->SetEnrollmentDelegate(
- CreateEnrollmentDelegate(GetWidget()->GetNativeWindow(),
- vpn->name(),
- ProfileManager::GetLastUsedProfile()));
- vpn->SetSaveCredentials(GetSaveCredentials());
- cros->ConnectToVirtualNetwork(vpn);
+ base::DictionaryValue properties;
+ SetConfigProperties(&properties);
+ ash::network_connect::ConfigureNetworkAndConnect(
+ service_path_, properties, false /* not shared */);
}
- // Connection failures are responsible for updating the UI, including
- // reopening dialogs.
return true; // Close dialog.
}
@@ -393,7 +405,7 @@
const std::string VPNConfigView::GetServer() const {
if (server_textfield_ != NULL)
return GetTextFromField(server_textfield_, true);
- return server_hostname_;
+ return std::string();
}
const std::string VPNConfigView::GetPSKPassphrase() const {
@@ -448,44 +460,39 @@
return save_credentials_checkbox_->checked();
}
-void VPNConfigView::Init(VirtualNetwork* vpn) {
- if (vpn) {
- ProviderType type = vpn->provider_type();
- std::string type_dict_name = ProviderTypeToONCDictKey(type);
+int VPNConfigView::GetProviderTypeIndex() const {
+ if (provider_type_combobox_)
+ return provider_type_combobox_->selected_index();
+ return provider_type_index_;
+}
- if (type == PROVIDER_TYPE_L2TP_IPSEC_PSK) {
- ParseVPNUIProperty(&ca_cert_ui_data_, vpn, type_dict_name,
- onc::ipsec::kServerCARef);
- ParseVPNUIProperty(&psk_passphrase_ui_data_, vpn, type_dict_name,
- onc::ipsec::kPSK);
- ParseVPNUIProperty(&group_name_ui_data_, vpn, type_dict_name,
- onc::ipsec::kGroup);
- } else { // OpenVPN
- ParseVPNUIProperty(&ca_cert_ui_data_, vpn, type_dict_name,
- onc::openvpn::kServerCARef);
- }
- ParseVPNUIProperty(&user_cert_ui_data_, vpn, type_dict_name,
- onc::vpn::kClientCertRef);
-
- const std::string credentials_dict_name(
- type == PROVIDER_TYPE_L2TP_IPSEC_PSK ?
- onc::vpn::kL2TP : type_dict_name);
- ParseVPNUIProperty(&username_ui_data_, vpn, credentials_dict_name,
- onc::vpn::kUsername);
- ParseVPNUIProperty(&user_passphrase_ui_data_, vpn, credentials_dict_name,
- onc::vpn::kPassword);
- ParseVPNUIProperty(&save_credentials_ui_data_, vpn, credentials_dict_name,
- onc::vpn::kSaveCredentials);
+std::string VPNConfigView::GetProviderTypeString() const {
+ int index = GetProviderTypeIndex();
+ switch (index) {
+ case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK:
+ case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT:
+ return flimflam::kProviderL2tpIpsec;
+ case PROVIDER_TYPE_INDEX_OPEN_VPN:
+ return flimflam::kProviderOpenVpn;
}
+ NOTREACHED();
+ return std::string();
+}
- views::GridLayout* layout = views::GridLayout::CreatePanel(this);
- SetLayoutManager(layout);
+void VPNConfigView::Init() {
+ const NetworkState* vpn = NULL;
+ if (!service_path_.empty()) {
+ vpn = NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path_);
+ DCHECK(vpn && vpn->type() == flimflam::kTypeVPN);
+ }
+ layout_ = views::GridLayout::CreatePanel(this);
+ SetLayoutManager(layout_);
// Observer any changes to the certificate list.
CertLibrary::Get()->AddObserver(this);
- const int column_view_set_id = 0;
- views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id);
+ views::ColumnSet* column_set = layout_->AddColumnSet(0);
// Label.
column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1,
views::GridLayout::USE_PREF, 0, 0);
@@ -501,232 +508,376 @@
// Initialize members.
service_text_modified_ = false;
- if (vpn) {
- provider_type_ = vpn->provider_type();
- // Sets enable_* based on the provider type which we use to control
- // which controls to make visible.
- UpdateControlsToEnable();
- } else {
- // Set the default provider type.
- provider_type_ = PROVIDER_TYPE_L2TP_IPSEC_PSK;
- // Provider Type is user selectable, so enable all controls during init.
- enable_psk_passphrase_ = true;
- enable_user_cert_ = true;
- enable_server_ca_cert_ = true;
- enable_otp_ = true;
- enable_group_name_ = true;
- }
-
- // Initialize the title string ID used for the dialog.
title_ = vpn ? IDS_OPTIONS_SETTINGS_JOIN_VPN : IDS_OPTIONS_SETTINGS_ADD_VPN;
+ // By default enable all controls.
+ enable_psk_passphrase_ = true;
+ enable_user_cert_ = true;
+ enable_server_ca_cert_ = true;
+ enable_otp_ = true;
+ enable_group_name_ = true;
+
// Server label and input.
// Only provide Server name when configuring a new VPN.
- if (!vpn) {
- layout->StartRow(0, column_view_set_id);
- layout->AddView(new views::Label(l10n_util::GetStringUTF16(
+ if (service_path_.empty()) {
+ layout_->StartRow(0, 0);
+ layout_->AddView(new views::Label(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVER_HOSTNAME)));
server_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
server_textfield_->SetController(this);
- layout->AddView(server_textfield_);
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+ layout_->AddView(server_textfield_);
+ layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
} else {
server_textfield_ = NULL;
}
// Service label and name or input.
- layout->StartRow(0, column_view_set_id);
- layout->AddView(new views::Label(l10n_util::GetStringUTF16(
+ layout_->StartRow(0, 0);
+ layout_->AddView(new views::Label(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVICE_NAME)));
- if (!vpn) {
+ if (service_path_.empty()) {
service_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
service_textfield_->SetController(this);
- layout->AddView(service_textfield_);
+ layout_->AddView(service_textfield_);
service_text_ = NULL;
} else {
- service_text_ = new views::Label(ASCIIToUTF16(vpn->name()));
+ service_text_ = new views::Label();
service_text_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- layout->AddView(service_text_);
+ layout_->AddView(service_text_);
service_textfield_ = NULL;
}
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+ layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
// Provider type label and select.
- layout->StartRow(0, column_view_set_id);
- layout->AddView(new views::Label(l10n_util::GetStringUTF16(
+ layout_->StartRow(0, 0);
+ layout_->AddView(new views::Label(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PROVIDER_TYPE)));
- if (!vpn) {
+ if (service_path_.empty()) {
provider_type_combobox_model_.reset(
new internal::ProviderTypeComboboxModel);
provider_type_combobox_ = new views::Combobox(
provider_type_combobox_model_.get());
provider_type_combobox_->set_listener(this);
- layout->AddView(provider_type_combobox_);
+ layout_->AddView(provider_type_combobox_);
provider_type_text_label_ = NULL;
} else {
- provider_type_text_label_ =
- new views::Label(ProviderTypeToString(provider_type_));
+ provider_type_text_label_ = new views::Label();
provider_type_text_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- layout->AddView(provider_type_text_label_);
+ layout_->AddView(provider_type_text_label_);
provider_type_combobox_ = NULL;
}
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+ layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
// PSK passphrase label, input and visible button.
- if (enable_psk_passphrase_) {
- layout->StartRow(0, column_view_set_id);
- psk_passphrase_label_ = new views::Label(l10n_util::GetStringUTF16(
- IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PSK_PASSPHRASE));
- layout->AddView(psk_passphrase_label_);
- bool has_psk_passphrase = vpn && !vpn->IsPSKPassphraseRequired();
- psk_passphrase_textfield_ = new PassphraseTextfield(has_psk_passphrase);
- psk_passphrase_textfield_->SetController(this);
- layout->AddView(psk_passphrase_textfield_);
- layout->AddView(
- new ControlledSettingIndicatorView(psk_passphrase_ui_data_));
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
- } else {
- psk_passphrase_label_ = NULL;
- psk_passphrase_textfield_ = NULL;
- }
+ layout_->StartRow(0, 0);
+ psk_passphrase_label_ = new views::Label(l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PSK_PASSPHRASE));
+ layout_->AddView(psk_passphrase_label_);
+ psk_passphrase_textfield_ = new PassphraseTextfield();
+ psk_passphrase_textfield_->SetController(this);
+ layout_->AddView(psk_passphrase_textfield_);
+ layout_->AddView(
+ new ControlledSettingIndicatorView(psk_passphrase_ui_data_));
+ layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
// Server CA certificate
- // Only provide Server CA when configuring a new VPN.
- if (!vpn) {
- layout->StartRow(0, column_view_set_id);
- server_ca_cert_label_ =
- new views::Label(l10n_util::GetStringUTF16(
- IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA));
- layout->AddView(server_ca_cert_label_);
+ if (service_path_.empty()) {
+ layout_->StartRow(0, 0);
+ server_ca_cert_label_ = new views::Label(l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA));
+ layout_->AddView(server_ca_cert_label_);
server_ca_cert_combobox_model_.reset(
new internal::VpnServerCACertComboboxModel());
server_ca_cert_combobox_ = new views::Combobox(
server_ca_cert_combobox_model_.get());
- layout->AddView(server_ca_cert_combobox_);
- layout->AddView(new ControlledSettingIndicatorView(ca_cert_ui_data_));
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+ layout_->AddView(server_ca_cert_combobox_);
+ layout_->AddView(new ControlledSettingIndicatorView(ca_cert_ui_data_));
+ layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
} else {
server_ca_cert_label_ = NULL;
server_ca_cert_combobox_ = NULL;
}
// User certificate label and input.
- if (enable_user_cert_) {
- layout->StartRow(0, column_view_set_id);
- user_cert_label_ = new views::Label(l10n_util::GetStringUTF16(
- IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT));
- layout->AddView(user_cert_label_);
- user_cert_combobox_model_.reset(
- new internal::VpnUserCertComboboxModel());
- user_cert_combobox_ = new views::Combobox(user_cert_combobox_model_.get());
- user_cert_combobox_->set_listener(this);
- layout->AddView(user_cert_combobox_);
- layout->AddView(new ControlledSettingIndicatorView(user_cert_ui_data_));
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
- } else {
- user_cert_label_ = NULL;
- user_cert_combobox_ = NULL;
- }
+ layout_->StartRow(0, 0);
+ user_cert_label_ = new views::Label(l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT));
+ layout_->AddView(user_cert_label_);
+ user_cert_combobox_model_.reset(
+ new internal::VpnUserCertComboboxModel());
+ user_cert_combobox_ = new views::Combobox(user_cert_combobox_model_.get());
+ user_cert_combobox_->set_listener(this);
+ layout_->AddView(user_cert_combobox_);
+ layout_->AddView(new ControlledSettingIndicatorView(user_cert_ui_data_));
+ layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
// Username label and input.
- layout->StartRow(0, column_view_set_id);
- layout->AddView(new views::Label(l10n_util::GetStringUTF16(
+ layout_->StartRow(0, 0);
+ layout_->AddView(new views::Label(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USERNAME)));
username_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
username_textfield_->SetController(this);
username_textfield_->SetEnabled(username_ui_data_.IsEditable());
- if (vpn && !vpn->username().empty())
- username_textfield_->SetText(UTF8ToUTF16(vpn->username()));
- layout->AddView(username_textfield_);
- layout->AddView(new ControlledSettingIndicatorView(username_ui_data_));
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+ layout_->AddView(username_textfield_);
+ layout_->AddView(new ControlledSettingIndicatorView(username_ui_data_));
+ layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
// User passphrase label, input and visble button.
- layout->StartRow(0, column_view_set_id);
- layout->AddView(new views::Label(l10n_util::GetStringUTF16(
+ layout_->StartRow(0, 0);
+ layout_->AddView(new views::Label(l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_PASSPHRASE)));
- bool has_user_passphrase = vpn && !vpn->IsUserPassphraseRequired();
- user_passphrase_textfield_ = new PassphraseTextfield(has_user_passphrase);
+ user_passphrase_textfield_ = new PassphraseTextfield();
user_passphrase_textfield_->SetController(this);
user_passphrase_textfield_->SetEnabled(user_passphrase_ui_data_.IsEditable());
- layout->AddView(user_passphrase_textfield_);
- layout->AddView(new ControlledSettingIndicatorView(user_passphrase_ui_data_));
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
+ layout_->AddView(user_passphrase_textfield_);
+ layout_->AddView(
+ new ControlledSettingIndicatorView(user_passphrase_ui_data_));
+ layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
// OTP label and input.
- if (enable_otp_) {
- layout->StartRow(0, column_view_set_id);
- otp_label_ = new views::Label(l10n_util::GetStringUTF16(
- IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_OTP));
- layout->AddView(otp_label_);
- otp_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
- otp_textfield_->SetController(this);
- layout->AddView(otp_textfield_);
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
- } else {
- otp_label_ = NULL;
- otp_textfield_ = NULL;
- }
+ layout_->StartRow(0, 0);
+ otp_label_ = new views::Label(l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_OTP));
+ layout_->AddView(otp_label_);
+ otp_textfield_ = new views::Textfield(views::Textfield::STYLE_DEFAULT);
+ otp_textfield_->SetController(this);
+ layout_->AddView(otp_textfield_);
+ layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
// Group Name label and input.
- if (enable_group_name_) {
- layout->StartRow(0, column_view_set_id);
- group_name_label_ = new views::Label(l10n_util::GetStringUTF16(
- IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_GROUP_NAME));
- layout->AddView(group_name_label_);
- group_name_textfield_ =
- new views::Textfield(views::Textfield::STYLE_DEFAULT);
- group_name_textfield_->SetController(this);
- if (vpn && !vpn->group_name().empty())
- group_name_textfield_->SetText(UTF8ToUTF16(vpn->group_name()));
- layout->AddView(group_name_textfield_);
- layout->AddView(new ControlledSettingIndicatorView(group_name_ui_data_));
- layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
- } else {
- group_name_label_ = NULL;
- group_name_textfield_ = NULL;
- }
+ layout_->StartRow(0, 0);
+ group_name_label_ = new views::Label(l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_GROUP_NAME));
+ layout_->AddView(group_name_label_);
+ group_name_textfield_ =
+ new views::Textfield(views::Textfield::STYLE_DEFAULT);
+ group_name_textfield_->SetController(this);
+ layout_->AddView(group_name_textfield_);
+ layout_->AddView(new ControlledSettingIndicatorView(group_name_ui_data_));
+ layout_->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
// Save credentials
- layout->StartRow(0, column_view_set_id);
+ layout_->StartRow(0, 0);
save_credentials_checkbox_ = new views::Checkbox(
l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SAVE_CREDENTIALS));
save_credentials_checkbox_->SetEnabled(
save_credentials_ui_data_.IsEditable());
- bool save_credentials = vpn ? vpn->save_credentials() : false;
- save_credentials_checkbox_->SetChecked(save_credentials);
- layout->SkipColumns(1);
- layout->AddView(save_credentials_checkbox_);
- layout->AddView(
+ layout_->SkipColumns(1);
+ layout_->AddView(save_credentials_checkbox_);
+ layout_->AddView(
new ControlledSettingIndicatorView(save_credentials_ui_data_));
// Error label.
- layout->StartRow(0, column_view_set_id);
- layout->SkipColumns(1);
+ layout_->StartRow(0, 0);
+ layout_->SkipColumns(1);
error_label_ = new views::Label();
error_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
error_label_->SetEnabledColor(SK_ColorRED);
- layout->AddView(error_label_);
+ layout_->AddView(error_label_);
// Set or hide the UI, update comboboxes and error labels.
Refresh();
+
+ if (vpn) {
+ NetworkHandler::Get()->network_configuration_handler()->GetProperties(
+ service_path_,
+ base::Bind(&VPNConfigView::InitFromProperties,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&VPNConfigView::GetPropertiesError,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+}
+
+void VPNConfigView::InitFromProperties(
+ const std::string& service_path,
+ const base::DictionaryValue& service_properties) {
+ const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path);
+ if (!vpn) {
+ NET_LOG_ERROR("Shill Error getting properties VpnConfigView", service_path);
+ return;
+ }
+
+ std::string provider_type, server_hostname, username, group_name;
+ bool psk_passphrase_required = false;
+ const base::DictionaryValue* provider_properties;
+ if (service_properties.GetDictionaryWithoutPathExpansion(
+ flimflam::kProviderProperty, &provider_properties)) {
+ provider_properties->GetStringWithoutPathExpansion(
+ flimflam::kTypeProperty, &provider_type);
+ provider_properties->GetStringWithoutPathExpansion(
+ flimflam::kHostProperty, &server_hostname);
+ }
+ if (provider_type == flimflam::kProviderL2tpIpsec) {
+ provider_properties->GetStringWithoutPathExpansion(
+ flimflam::kL2tpIpsecClientCertIdProperty, &client_cert_id_);
+ ca_cert_pem_ = GetPemFromDictionary(
+ provider_properties, shill::kL2tpIpsecCaCertPemProperty);
+ provider_properties->GetBooleanWithoutPathExpansion(
+ flimflam::kL2tpIpsecPskRequiredProperty, &psk_passphrase_required);
+ provider_properties->GetStringWithoutPathExpansion(
+ flimflam::kL2tpIpsecUserProperty, &username);
+ provider_properties->GetStringWithoutPathExpansion(
+ shill::kL2tpIpsecTunnelGroupProperty, &group_name);
+ } else if (provider_type == flimflam::kProviderOpenVpn) {
+ provider_properties->GetStringWithoutPathExpansion(
+ flimflam::kOpenVPNClientCertIdProperty, &client_cert_id_);
+ ca_cert_pem_ = GetPemFromDictionary(
+ provider_properties, shill::kOpenVPNCaCertPemProperty);
+ provider_properties->GetStringWithoutPathExpansion(
+ flimflam::kOpenVPNUserProperty, &username);
+ }
+ bool save_credentials = false;
+ service_properties.GetBooleanWithoutPathExpansion(
+ flimflam::kSaveCredentialsProperty, &save_credentials);
+
+ provider_type_index_ = ProviderTypeToIndex(provider_type, client_cert_id_);
+
+ if (service_text_)
+ service_text_->SetText(ASCIIToUTF16(vpn->name()));
+ if (provider_type_text_label_)
+ provider_type_text_label_->SetText(
+ ProviderTypeIndexToString(provider_type_index_));
+
+ if (server_textfield_ && !server_hostname.empty())
+ server_textfield_->SetText(UTF8ToUTF16(server_hostname));
+ if (username_textfield_ && !username.empty())
+ username_textfield_->SetText(UTF8ToUTF16(username));
+ if (group_name_textfield_ && !group_name.empty())
+ group_name_textfield_->SetText(UTF8ToUTF16(group_name));
+ if (psk_passphrase_textfield_)
+ psk_passphrase_textfield_->SetShowFake(!psk_passphrase_required);
+ if (save_credentials_checkbox_)
+ save_credentials_checkbox_->SetChecked(save_credentials);
+
+ Refresh();
+}
+
+void VPNConfigView::ParseUIProperties(const NetworkState* vpn) {
+ std::string type_dict_name =
+ ProviderTypeIndexToONCDictKey(provider_type_index_);
+ if (provider_type_index_ == PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK) {
+ ParseVPNUIProperty(vpn, type_dict_name, onc::ipsec::kServerCARef,
+ &ca_cert_ui_data_);
+ ParseVPNUIProperty(vpn, type_dict_name, onc::ipsec::kPSK,
+ &psk_passphrase_ui_data_);
+ ParseVPNUIProperty(vpn, type_dict_name, onc::ipsec::kGroup,
+ &group_name_ui_data_);
+ } else if (provider_type_index_ == PROVIDER_TYPE_INDEX_OPEN_VPN) {
+ ParseVPNUIProperty(vpn, type_dict_name, onc::openvpn::kServerCARef,
+ &ca_cert_ui_data_);
+ }
+ ParseVPNUIProperty(vpn, type_dict_name, onc::vpn::kClientCertRef,
+ &user_cert_ui_data_);
+
+ const std::string credentials_dict_name(
+ provider_type_index_ == PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK ?
+ onc::vpn::kL2TP : type_dict_name);
+ ParseVPNUIProperty(vpn, credentials_dict_name, onc::vpn::kUsername,
+ &username_ui_data_);
+ ParseVPNUIProperty(vpn, credentials_dict_name, onc::vpn::kPassword,
+ &user_passphrase_ui_data_);
+ ParseVPNUIProperty(vpn, credentials_dict_name, onc::vpn::kSaveCredentials,
+ &save_credentials_ui_data_);
+}
+
+void VPNConfigView::GetPropertiesError(
+ const std::string& error_name,
+ scoped_ptr<base::DictionaryValue> error_data) {
+ NET_LOG_ERROR("Shill Error from VpnConfigView: " + error_name, "");
+}
+
+void VPNConfigView::SetConfigProperties(
+ base::DictionaryValue* properties) {
+ int provider_type_index = GetProviderTypeIndex();
+ std::string user_passphrase = GetUserPassphrase();
+ std::string user_name = GetUsername();
+ std::string group_name = GetGroupName();
+ switch (provider_type_index) {
+ case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK: {
+ std::string psk_passphrase = GetPSKPassphrase();
+ if (!psk_passphrase.empty()) {
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kL2tpIpsecPskProperty, GetPSKPassphrase());
+ }
+ if (!group_name.empty()) {
+ properties->SetStringWithoutPathExpansion(
+ shill::kL2tpIpsecTunnelGroupProperty, group_name);
+ }
+ if (!user_name.empty()) {
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kL2tpIpsecUserProperty, user_name);
+ }
+ if (!user_passphrase.empty()) {
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kL2tpIpsecPasswordProperty, user_passphrase);
+ }
+ break;
+ }
+ case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT: {
+ std::string ca_cert_pem = GetServerCACertPEM();
+ if (!ca_cert_pem.empty()) {
+ properties->SetStringWithoutPathExpansion(
+ shill::kL2tpIpsecCaCertPemProperty, ca_cert_pem);
+ }
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kL2tpIpsecClientCertIdProperty, GetUserCertID());
+ if (!group_name.empty()) {
+ properties->SetStringWithoutPathExpansion(
+ shill::kL2tpIpsecTunnelGroupProperty, GetGroupName());
+ }
+ if (!user_name.empty()) {
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kL2tpIpsecUserProperty, user_name);
+ }
+ if (!user_passphrase.empty()) {
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kL2tpIpsecPasswordProperty, user_passphrase);
+ }
+ break;
+ }
+ case PROVIDER_TYPE_INDEX_OPEN_VPN: {
+ std::string ca_cert_pem = GetServerCACertPEM();
+ if (!ca_cert_pem.empty()) {
+ base::ListValue* pem_list = new base::ListValue;
+ pem_list->AppendString(GetServerCACertPEM());
+ properties->SetWithoutPathExpansion(
+ shill::kOpenVPNCaCertPemProperty, pem_list);
+ }
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kOpenVPNClientCertIdProperty, GetUserCertID());
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kOpenVPNUserProperty, GetUsername());
+ if (!user_passphrase.empty()) {
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kOpenVPNPasswordProperty, user_passphrase);
+ }
+ std::string otp = GetOTP();
+ if (!otp.empty()) {
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kOpenVPNOTPProperty, otp);
+ }
+ break;
+ }
+ case PROVIDER_TYPE_INDEX_MAX:
+ NOTREACHED();
+ break;
+ }
+ properties->SetBooleanWithoutPathExpansion(
+ flimflam::kSaveCredentialsProperty, GetSaveCredentials());
}
void VPNConfigView::Refresh() {
- NetworkLibrary* cros = NetworkLibrary::Get();
-
UpdateControls();
// Set certificate combo boxes.
- VirtualNetwork* vpn = cros->FindVirtualNetworkByPath(service_path_);
if (server_ca_cert_combobox_) {
server_ca_cert_combobox_->ModelChanged();
- if (enable_server_ca_cert_ &&
- (vpn && !vpn->ca_cert_pem().empty())) {
+ if (enable_server_ca_cert_ && !ca_cert_pem_.empty()) {
// Select the current server CA certificate in the combobox.
int cert_index = CertLibrary::Get()->GetCertIndexByPEM(
- CertLibrary::CERT_TYPE_SERVER_CA, vpn->ca_cert_pem());
+ CertLibrary::CERT_TYPE_SERVER_CA, ca_cert_pem_);
if (cert_index >= 0) {
// Skip item for "Default"
server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index);
@@ -740,10 +891,9 @@
if (user_cert_combobox_) {
user_cert_combobox_->ModelChanged();
- if (enable_user_cert_ &&
- (vpn && !vpn->client_cert_id().empty())) {
+ if (enable_user_cert_ && !client_cert_id_.empty()) {
int cert_index = CertLibrary::Get()->GetCertIndexByPkcs11Id(
- CertLibrary::CERT_TYPE_USER, vpn->client_cert_id());
+ CertLibrary::CERT_TYPE_USER, client_cert_id_);
if (cert_index >= 0)
user_cert_combobox_->SetSelectedIndex(cert_index);
else
@@ -757,30 +907,23 @@
}
void VPNConfigView::UpdateControlsToEnable() {
- // Set which controls are enabled.
enable_psk_passphrase_ = false;
enable_user_cert_ = false;
enable_server_ca_cert_ = false;
enable_otp_ = false;
enable_group_name_ = false;
- switch (provider_type_) {
- case PROVIDER_TYPE_L2TP_IPSEC_PSK:
- enable_psk_passphrase_ = true;
- enable_group_name_ = true;
- break;
- case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT:
- enable_server_ca_cert_ = true;
- enable_user_cert_ = HaveUserCerts();
- enable_group_name_ = true;
- break;
- case PROVIDER_TYPE_OPEN_VPN:
- enable_server_ca_cert_ = true;
- enable_user_cert_ = HaveUserCerts();
- enable_otp_ = true;
- break;
- default:
- NOTREACHED();
- break;
+ int provider_type_index = GetProviderTypeIndex();
+ if (provider_type_index == PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK) {
+ enable_psk_passphrase_ = true;
+ enable_group_name_ = true;
+ } else if (provider_type_index == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT) {
+ enable_server_ca_cert_ = true;
+ enable_user_cert_ = HaveUserCerts();
+ enable_group_name_ = true;
+ } else { // PROVIDER_TYPE_INDEX_OPEN_VPN (default)
+ enable_server_ca_cert_ = true;
+ enable_user_cert_ = HaveUserCerts();
+ enable_otp_ = true;
}
}
@@ -818,33 +961,28 @@
}
void VPNConfigView::UpdateErrorLabel() {
- NetworkLibrary* cros = NetworkLibrary::Get();
-
// Error message.
- std::string error_msg;
- if (UserCertRequired() && CertLibrary::Get()->CertificatesLoaded()) {
+ string16 error_msg;
+ bool cert_required =
+ GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT;
+ if (cert_required && CertLibrary::Get()->CertificatesLoaded()) {
if (!HaveUserCerts()) {
- error_msg = l10n_util::GetStringUTF8(
+ error_msg = l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PLEASE_INSTALL_USER_CERT);
} else if (!IsUserCertValid()) {
- error_msg = l10n_util::GetStringUTF8(
+ error_msg = l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_REQUIRE_HARDWARE_BACKED);
}
}
if (error_msg.empty() && !service_path_.empty()) {
// TODO(kuan): differentiate between bad psk and user passphrases.
- VirtualNetwork* vpn = cros->FindVirtualNetworkByPath(service_path_);
- if (vpn && vpn->failed()) {
- if (vpn->error() == ERROR_BAD_PASSPHRASE) {
- error_msg = l10n_util::GetStringUTF8(
- IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_PASSPHRASE);
- } else {
- error_msg = vpn->GetErrorString();
- }
- }
+ const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path_);
+ if (vpn && vpn->connection_state() == flimflam::kStateFailure)
+ error_msg = ash::network_connect::ErrorString(vpn->error());
}
if (!error_msg.empty()) {
- error_label_->SetText(UTF8ToUTF16(error_msg));
+ error_label_->SetText(error_msg);
error_label_->SetVisible(true);
} else {
error_label_->SetVisible(false);
@@ -855,10 +993,6 @@
parent_->GetDialogClientView()->UpdateDialogButtons();
}
-bool VPNConfigView::UserCertRequired() const {
- return provider_type_ == PROVIDER_TYPE_L2TP_IPSEC_USER_CERT;
-}
-
bool VPNConfigView::HaveUserCerts() const {
return CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER) > 0;
}
@@ -896,15 +1030,16 @@
return textfield->GetPassphrase();
}
-void VPNConfigView::ParseVPNUIProperty(NetworkPropertyUIData* property_ui_data,
- Network* network,
- const std::string& dict_key,
- const std::string& key) {
+void VPNConfigView::ParseVPNUIProperty(
+ const NetworkState* network,
+ const std::string& dict_key,
+ const std::string& key,
+ NetworkPropertyUIData* property_ui_data) {
onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
const base::DictionaryValue* onc =
- NetworkConfigView::FindPolicyForActiveUser(network, &onc_source);
+ network_connect::FindPolicyForActiveUser(network, &onc_source);
- VLOG_IF(1, !onc) << "No ONC found for VPN network " << network->unique_id();
+ VLOG_IF(1, !onc) << "No ONC found for VPN network " << network->guid();
property_ui_data->ParseOncProperty(
onc_source,
onc,
diff --git a/chrome/browser/chromeos/options/vpn_config_view.h b/chrome/browser/chromeos/options/vpn_config_view.h
index cb5f7ce..24c1a5a 100644
--- a/chrome/browser/chromeos/options/vpn_config_view.h
+++ b/chrome/browser/chromeos/options/vpn_config_view.h
@@ -18,13 +18,20 @@
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/view.h"
+namespace base {
+class DictionaryValue;
+}
+
namespace views {
class Checkbox;
+class GridLayout;
class Label;
}
namespace chromeos {
+class NetworkState;
+
namespace internal {
class ProviderTypeComboboxModel;
class VpnServerCACertComboboxModel;
@@ -38,8 +45,7 @@
public views::ComboboxListener,
public CertLibrary::Observer {
public:
- VPNConfigView(NetworkConfigView* parent, VirtualNetwork* vpn);
- explicit VPNConfigView(NetworkConfigView* parent);
+ VPNConfigView(NetworkConfigView* parent, const std::string& service_path);
virtual ~VPNConfigView();
// views::TextfieldController:
@@ -68,7 +74,17 @@
private:
// Initializes data members and create UI controls.
- void Init(VirtualNetwork* vpn);
+ void Init();
+
+ // Callback to initialize fields from uncached network properties.
+ void InitFromProperties(const std::string& service_path,
+ const base::DictionaryValue& dictionary);
+ void ParseUIProperties(const NetworkState* vpn);
+ void GetPropertiesError(const std::string& error_name,
+ scoped_ptr<base::DictionaryValue> error_data);
+
+ // Helper function to set configurable properties.
+ void SetConfigProperties(base::DictionaryValue* properties);
// Set and update all control values.
void Refresh();
@@ -81,9 +97,6 @@
// Update state of the Login button.
void UpdateCanLogin();
- // Returns true if the provider type requires a user certificate.
- bool UserCertRequired() const;
-
// Returns true if there is at least one user certificate installed.
bool HaveUserCerts() const;
@@ -109,22 +122,21 @@
const std::string GetServerCACertPEM() const;
const std::string GetUserCertID() const;
bool GetSaveCredentials() const;
+ int GetProviderTypeIndex() const;
+ std::string GetProviderTypeString() const;
// Parses a VPN UI |property| from the given |network|. |key| is the property
// name within the type-specific VPN subdictionary named |dict_key|.
- void ParseVPNUIProperty(NetworkPropertyUIData* property_ui_data,
- Network* network,
+ void ParseVPNUIProperty(const NetworkState* network,
const std::string& dict_key,
- const std::string& key);
+ const std::string& key,
+ NetworkPropertyUIData* property_ui_data);
- std::string server_hostname_;
string16 service_name_from_server_;
bool service_text_modified_;
// Initialized in Init():
- ProviderType provider_type_;
-
bool enable_psk_passphrase_;
bool enable_user_cert_;
bool enable_server_ca_cert_;
@@ -141,6 +153,7 @@
int title_;
+ views::GridLayout* layout_;
views::Textfield* server_textfield_;
views::Label* service_text_;
views::Textfield* service_textfield_;
@@ -165,6 +178,13 @@
views::Checkbox* save_credentials_checkbox_;
views::Label* error_label_;
+ // Cached VPN properties, only set when configuring an existing network.
+ int provider_type_index_;
+ std::string ca_cert_pem_;
+ std::string client_cert_id_;
+
+ base::WeakPtrFactory<VPNConfigView> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(VPNConfigView);
};
diff --git a/chrome/browser/chromeos/options/wifi_config_view.cc b/chrome/browser/chromeos/options/wifi_config_view.cc
index 211f728..9827218 100644
--- a/chrome/browser/chromeos/options/wifi_config_view.cc
+++ b/chrome/browser/chromeos/options/wifi_config_view.cc
@@ -4,19 +4,26 @@
#include "chrome/browser/chromeos/options/wifi_config_view.h"
+#include "ash/system/chromeos/network/network_connect.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/enrollment_dialog_view.h"
+#include "chrome/browser/chromeos/options/network_connect.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chromeos/login/login_state.h"
+#include "chromeos/network/network_configuration_handler.h"
+#include "chromeos/network/network_event_log.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/network_ui_data.h"
#include "chromeos/network/onc/onc_constants.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "grit/theme_resources.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/events/event.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
@@ -34,11 +41,6 @@
namespace {
-// Returns true if network is known to require 802.1x.
-bool Is8021x(const WifiNetwork* wifi) {
- return wifi && wifi->encrypted() && wifi->encryption() == SECURITY_8021X;
-}
-
// Combobox that supports a preferred width. Used by Server CA combobox
// because the strings inside it are too wide.
class ComboboxWithWidth : public views::Combobox {
@@ -85,6 +87,12 @@
PHASE_2_AUTH_INDEX_COUNT = 6
};
+void ShillError(const std::string& function,
+ const std::string& error_name,
+ scoped_ptr<base::DictionaryValue> error_data) {
+ NET_LOG_ERROR("Shill Error from WifiConfigView: " + error_name, function);
+}
+
} // namespace
namespace internal {
@@ -322,8 +330,10 @@
} // namespace internal
-WifiConfigView::WifiConfigView(NetworkConfigView* parent, WifiNetwork* wifi)
- : ChildNetworkConfigView(parent, wifi),
+WifiConfigView::WifiConfigView(NetworkConfigView* parent,
+ const std::string& service_path,
+ bool show_8021x)
+ : ChildNetworkConfigView(parent, service_path),
ssid_textfield_(NULL),
eap_method_combobox_(NULL),
phase_2_auth_label_(NULL),
@@ -343,36 +353,17 @@
passphrase_label_(NULL),
passphrase_textfield_(NULL),
passphrase_visible_button_(NULL),
- error_label_(NULL) {
- Init(wifi, Is8021x(wifi));
-}
-
-WifiConfigView::WifiConfigView(NetworkConfigView* parent, bool show_8021x)
- : ChildNetworkConfigView(parent),
- ssid_textfield_(NULL),
- eap_method_combobox_(NULL),
- phase_2_auth_label_(NULL),
- phase_2_auth_combobox_(NULL),
- user_cert_label_(NULL),
- user_cert_combobox_(NULL),
- server_ca_cert_label_(NULL),
- server_ca_cert_combobox_(NULL),
- identity_label_(NULL),
- identity_textfield_(NULL),
- identity_anonymous_label_(NULL),
- identity_anonymous_textfield_(NULL),
- save_credentials_checkbox_(NULL),
- share_network_checkbox_(NULL),
- shared_network_label_(NULL),
- security_combobox_(NULL),
- passphrase_label_(NULL),
- passphrase_textfield_(NULL),
- passphrase_visible_button_(NULL),
- error_label_(NULL) {
- Init(NULL, show_8021x);
+ error_label_(NULL),
+ weak_ptr_factory_(this) {
+ Init(show_8021x);
+ NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);
}
WifiConfigView::~WifiConfigView() {
+ if (NetworkHandler::IsInitialized()) {
+ NetworkHandler::Get()->network_state_handler()->RemoveObserver(
+ this, FROM_HERE);
+ }
CertLibrary::Get()->RemoveObserver(this);
}
@@ -541,8 +532,8 @@
// user certificates are enabled.
share_network_checkbox_->SetEnabled(false);
share_network_checkbox_->SetChecked(false);
- } else if (!LoginState::Get()->IsUserLoggedIn()) {
- // If not logged in, networks must be shared.
+ } else if (!LoginState::Get()->IsUserAuthenticated()) {
+ // If not logged in as an authenticated user, networks must be shared.
share_network_checkbox_->SetEnabled(false);
share_network_checkbox_->SetChecked(true);
} else {
@@ -552,47 +543,29 @@
}
void WifiConfigView::UpdateErrorLabel() {
- std::string error_msg;
+ base::string16 error_msg;
if (UserCertRequired() && CertLibrary::Get()->CertificatesLoaded()) {
if (!HaveUserCerts()) {
- if (!LoginState::Get()->IsUserLoggedIn()) {
- error_msg = l10n_util::GetStringUTF8(
+ if (!LoginState::Get()->IsUserAuthenticated()) {
+ error_msg = l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_LOGIN_FOR_USER_CERT);
} else {
- error_msg = l10n_util::GetStringUTF8(
+ error_msg = l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PLEASE_INSTALL_USER_CERT);
}
} else if (!IsUserCertValid()) {
- error_msg = l10n_util::GetStringUTF8(
+ error_msg = l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_REQUIRE_HARDWARE_BACKED);
}
}
if (error_msg.empty() && !service_path_.empty()) {
- NetworkLibrary* cros = NetworkLibrary::Get();
- const WifiNetwork* wifi = cros->FindWifiNetworkByPath(service_path_);
- if (wifi && wifi->failed()) {
- bool passphrase_empty = wifi->GetPassphrase().empty();
- switch (wifi->error()) {
- case ERROR_BAD_PASSPHRASE:
- if (!passphrase_empty) {
- error_msg = l10n_util::GetStringUTF8(
- IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_PASSPHRASE);
- }
- break;
- case ERROR_BAD_WEPKEY:
- if (!passphrase_empty) {
- error_msg = l10n_util::GetStringUTF8(
- IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_WEPKEY);
- }
- break;
- default:
- error_msg = wifi->GetErrorString();
- break;
- }
- }
+ const NetworkState* wifi = NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path_);
+ if (wifi && wifi->connection_state() == flimflam::kStateFailure)
+ error_msg = ash::network_connect::ErrorString(wifi->error());
}
if (!error_msg.empty()) {
- error_label_->SetText(UTF8ToUTF16(error_msg));
+ error_label_->SetText(error_msg);
error_label_->SetVisible(true);
} else {
error_label_->SetVisible(false);
@@ -651,83 +624,74 @@
}
bool WifiConfigView::Login() {
- NetworkLibrary* cros = NetworkLibrary::Get();
+ const bool share_default = true;
if (service_path_.empty()) {
- const bool share_default = true; // share networks by default
+ // Set configuration properties.
+ base::DictionaryValue properties;
+ properties.SetStringWithoutPathExpansion(
+ flimflam::kTypeProperty, flimflam::kTypeWifi);
+ properties.SetStringWithoutPathExpansion(
+ flimflam::kSSIDProperty, GetSsid());
+ properties.SetStringWithoutPathExpansion(
+ flimflam::kModeProperty, flimflam::kModeManaged);
+ properties.SetBooleanWithoutPathExpansion(
+ flimflam::kSaveCredentialsProperty, GetSaveCredentials());
+ std::string security = flimflam::kSecurityNone;
if (!eap_method_combobox_) {
// Hidden ordinary Wi-Fi connection.
- ConnectionSecurity security = SECURITY_UNKNOWN;
switch (security_combobox_->selected_index()) {
case SECURITY_INDEX_NONE:
- security = SECURITY_NONE;
+ security = flimflam::kSecurityNone;
break;
case SECURITY_INDEX_WEP:
- security = SECURITY_WEP;
+ security = flimflam::kSecurityWep;
break;
case SECURITY_INDEX_PSK:
- security = SECURITY_PSK;
+ security = flimflam::kSecurityPsk;
break;
}
- cros->ConnectToUnconfiguredWifiNetwork(
- GetSsid(),
- security,
- GetPassphrase(),
- NULL,
- GetSaveCredentials(),
- GetShareNetwork(share_default));
+ std::string passphrase = GetPassphrase();
+ if (!passphrase.empty()) {
+ properties.SetStringWithoutPathExpansion(
+ flimflam::kPassphraseProperty, GetPassphrase());
+ }
} else {
// Hidden 802.1X EAP Wi-Fi connection.
- chromeos::NetworkLibrary::EAPConfigData config_data;
- config_data.method = GetEapMethod();
- config_data.auth = GetEapPhase2Auth();
- config_data.server_ca_cert_pem = GetEapServerCaCertPEM();
- config_data.use_system_cas = GetEapUseSystemCas();
- config_data.client_cert_pkcs11_id = GetEapClientCertPkcs11Id();
- config_data.identity = GetEapIdentity();
- config_data.anonymous_identity = GetEapAnonymousIdentity();
- cros->ConnectToUnconfiguredWifiNetwork(
- GetSsid(),
- SECURITY_8021X,
- GetPassphrase(),
- &config_data,
- GetSaveCredentials(),
- GetShareNetwork(share_default));
+ security = flimflam::kSecurity8021x;
+ SetEapProperties(&properties);
}
+ properties.SetStringWithoutPathExpansion(
+ flimflam::kSecurityProperty, security);
+
+ // Configure and connect to network.
+ bool shared = GetShareNetwork(share_default);
+ ash::network_connect::CreateConfigurationAndConnect(&properties, shared);
} else {
- WifiNetwork* wifi = cros->FindWifiNetworkByPath(service_path_);
+ const NetworkState* wifi = NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path_);
if (!wifi) {
// Shill no longer knows about this wifi network (edge case).
- // TODO(stevenjb): Add a notification (chromium-os13225).
- LOG(WARNING) << "Wifi network: " << service_path_ << " no longer exists.";
- return true;
+ // TODO(stevenjb): Add notification for this.
+ NET_LOG_ERROR("Network not found", service_path_);
+ return true; // Close dialog
}
+ base::DictionaryValue properties;
if (eap_method_combobox_) {
// Visible 802.1X EAP Wi-Fi connection.
- EAPMethod method = GetEapMethod();
- DCHECK(method != EAP_METHOD_UNKNOWN);
- wifi->SetEAPMethod(method);
- wifi->SetEAPPhase2Auth(GetEapPhase2Auth());
- wifi->SetEAPServerCaCertPEM(GetEapServerCaCertPEM());
- wifi->SetEAPUseSystemCAs(GetEapUseSystemCas());
- wifi->SetEAPClientCertPkcs11Id(GetEapClientCertPkcs11Id());
- wifi->SetEAPIdentity(GetEapIdentity());
- wifi->SetEAPAnonymousIdentity(GetEapAnonymousIdentity());
- wifi->SetEAPPassphrase(GetPassphrase());
- wifi->SetSaveCredentials(GetSaveCredentials());
+ SetEapProperties(&properties);
+ properties.SetBooleanWithoutPathExpansion(
+ flimflam::kSaveCredentialsProperty, GetSaveCredentials());
} else {
// Visible ordinary Wi-Fi connection.
const std::string passphrase = GetPassphrase();
- if (passphrase != wifi->passphrase())
- wifi->SetPassphrase(passphrase);
+ if (!passphrase.empty()) {
+ properties.SetStringWithoutPathExpansion(
+ flimflam::kPassphraseProperty, passphrase);
+ }
}
- bool share_default = (wifi->profile_type() != PROFILE_USER);
- wifi->SetEnrollmentDelegate(
- CreateEnrollmentDelegate(GetWidget()->GetNativeWindow(),
- wifi->name(),
- ProfileManager::GetLastUsedProfile()));
- cros->ConnectToWifiNetwork(wifi, GetShareNetwork(share_default));
- // Connection failures are responsible for updating the UI, including
- // reopening dialogs.
+ bool share_network = GetShareNetwork(share_default);
+ ash::network_connect::ConfigureNetworkAndConnect(
+ service_path_, properties, share_network);
}
return true; // dialog will be closed
}
@@ -760,41 +724,42 @@
return share_network_checkbox_->checked();
}
-EAPMethod WifiConfigView::GetEapMethod() const {
+std::string WifiConfigView::GetEapMethod() const {
DCHECK(eap_method_combobox_);
switch (eap_method_combobox_->selected_index()) {
- case EAP_METHOD_INDEX_NONE:
- return EAP_METHOD_UNKNOWN;
case EAP_METHOD_INDEX_PEAP:
- return EAP_METHOD_PEAP;
+ return flimflam::kEapMethodPEAP;
case EAP_METHOD_INDEX_TLS:
- return EAP_METHOD_TLS;
+ return flimflam::kEapMethodTLS;
case EAP_METHOD_INDEX_TTLS:
- return EAP_METHOD_TTLS;
+ return flimflam::kEapMethodTTLS;
case EAP_METHOD_INDEX_LEAP:
- return EAP_METHOD_LEAP;
+ return flimflam::kEapMethodLEAP;
+ case EAP_METHOD_INDEX_NONE:
default:
- return EAP_METHOD_UNKNOWN;
+ return "";
}
}
-EAPPhase2Auth WifiConfigView::GetEapPhase2Auth() const {
+std::string WifiConfigView::GetEapPhase2Auth() const {
DCHECK(phase_2_auth_combobox_);
+ bool is_peap = (GetEapMethod() == flimflam::kEapMethodPEAP);
switch (phase_2_auth_combobox_->selected_index()) {
- case PHASE_2_AUTH_INDEX_AUTO:
- return EAP_PHASE_2_AUTH_AUTO;
case PHASE_2_AUTH_INDEX_MD5:
- return EAP_PHASE_2_AUTH_MD5;
+ return is_peap ? flimflam::kEapPhase2AuthPEAPMD5
+ : flimflam::kEapPhase2AuthTTLSMD5;
case PHASE_2_AUTH_INDEX_MSCHAPV2:
- return EAP_PHASE_2_AUTH_MSCHAPV2;
+ return is_peap ? flimflam::kEapPhase2AuthPEAPMSCHAPV2
+ : flimflam::kEapPhase2AuthTTLSMSCHAPV2;
case PHASE_2_AUTH_INDEX_MSCHAP:
- return EAP_PHASE_2_AUTH_MSCHAP;
+ return flimflam::kEapPhase2AuthTTLSMSCHAP;
case PHASE_2_AUTH_INDEX_PAP:
- return EAP_PHASE_2_AUTH_PAP;
+ return flimflam::kEapPhase2AuthTTLSPAP;
case PHASE_2_AUTH_INDEX_CHAP:
- return EAP_PHASE_2_AUTH_CHAP;
+ return flimflam::kEapPhase2AuthTTLSCHAP;
+ case PHASE_2_AUTH_INDEX_AUTO:
default:
- return EAP_PHASE_2_AUTH_AUTO;
+ return "";
}
}
@@ -842,6 +807,34 @@
return UTF16ToUTF8(identity_anonymous_textfield_->text());
}
+void WifiConfigView::SetEapProperties(base::DictionaryValue* properties) {
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kEapIdentityProperty, GetEapIdentity());
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kEapMethodProperty, GetEapMethod());
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kEapPhase2AuthProperty, GetEapPhase2Auth());
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kEapAnonymousIdentityProperty, GetEapAnonymousIdentity());
+
+ // shill requires both CertID and KeyID for TLS connections, despite
+ // the fact that by convention they are the same ID.
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kEapCertIdProperty, GetEapClientCertPkcs11Id());
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kEapKeyIdProperty, GetEapClientCertPkcs11Id());
+
+ properties->SetBooleanWithoutPathExpansion(
+ flimflam::kEapUseSystemCasProperty, GetEapUseSystemCas());
+ properties->SetStringWithoutPathExpansion(
+ flimflam::kEapPasswordProperty, GetPassphrase());
+
+ base::ListValue* pem_list = new base::ListValue;
+ pem_list->AppendString(GetEapServerCaCertPEM());
+ properties->SetWithoutPathExpansion(
+ shill::kEapCaCertPemProperty, pem_list);
+}
+
void WifiConfigView::Cancel() {
}
@@ -851,8 +844,13 @@
// If we are creating the "Join other network..." dialog, we will allow user
// to enter the data. And if they select the 802.1x encryption, we will show
// the 802.1x fields.
-void WifiConfigView::Init(WifiNetwork* wifi, bool show_8021x) {
+void WifiConfigView::Init(bool show_8021x) {
+ const NetworkState* wifi = NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path_);
if (wifi) {
+ DCHECK(wifi->type() == flimflam::kTypeWifi);
+ if (wifi->security() == flimflam::kSecurity8021x)
+ show_8021x = true;
ParseWiFiEAPUIProperty(&eap_method_ui_data_, wifi, onc::eap::kOuter);
ParseWiFiEAPUIProperty(&phase_2_auth_ui_data_, wifi, onc::eap::kInner);
ParseWiFiEAPUIProperty(&user_cert_ui_data_, wifi, onc::eap::kClientCertRef);
@@ -1007,8 +1005,6 @@
views::Textfield::STYLE_DEFAULT);
identity_textfield_->SetAccessibleName(identity_label_text);
identity_textfield_->SetController(this);
- if (wifi && !wifi->identity().empty())
- identity_textfield_->SetText(UTF8ToUTF16(wifi->identity()));
identity_textfield_->SetEnabled(identity_ui_data_.IsEditable());
layout->AddView(identity_textfield_);
layout->AddView(new ControlledSettingIndicatorView(identity_ui_data_));
@@ -1024,8 +1020,6 @@
passphrase_textfield_ = new views::Textfield(
views::Textfield::STYLE_OBSCURED);
passphrase_textfield_->SetController(this);
- if (wifi && !wifi->GetPassphrase().empty())
- passphrase_textfield_->SetText(UTF8ToUTF16(wifi->GetPassphrase()));
// Disable passphrase input initially for other network.
passphrase_label_->SetEnabled(wifi != NULL);
passphrase_textfield_->SetEnabled(wifi && passphrase_ui_data_.IsEditable());
@@ -1102,10 +1096,7 @@
}
// Share network
- if (!wifi ||
- (wifi->profile_type() == PROFILE_NONE &&
- wifi->IsPassphraseRequired() &&
- !wifi->RequiresUserProfile())) {
+ if (!wifi || wifi->profile_path().empty()) {
layout->StartRow(0, column_view_set_id);
share_network_checkbox_ = new views::Checkbox(
l10n_util::GetStringUTF16(
@@ -1125,111 +1116,131 @@
// Initialize the field and checkbox values.
- // After creating the fields, we set the values. Fields need to be created
- // first because RefreshEapFields() will enable/disable them as appropriate.
- if (show_8021x) {
- EAPMethod eap_method = (wifi ? wifi->eap_method() : EAP_METHOD_UNKNOWN);
- switch (eap_method) {
- case EAP_METHOD_PEAP:
- eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_PEAP);
- break;
- case EAP_METHOD_TTLS:
- eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TTLS);
- break;
- case EAP_METHOD_TLS:
- eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TLS);
- break;
- case EAP_METHOD_LEAP:
- eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_LEAP);
- break;
- default:
- break;
- }
+ if (!wifi && show_8021x)
RefreshEapFields();
- // Phase 2 authentication and anonymous identity.
- if (Phase2AuthActive()) {
- EAPPhase2Auth eap_phase_2_auth =
- (wifi ? wifi->eap_phase_2_auth() : EAP_PHASE_2_AUTH_AUTO);
- switch (eap_phase_2_auth) {
- case EAP_PHASE_2_AUTH_MD5:
- phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MD5);
- break;
- case EAP_PHASE_2_AUTH_MSCHAPV2:
- phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAPV2);
- break;
- case EAP_PHASE_2_AUTH_MSCHAP:
- phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAP);
- break;
- case EAP_PHASE_2_AUTH_PAP:
- phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_PAP);
- break;
- case EAP_PHASE_2_AUTH_CHAP:
- phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_CHAP);
- break;
- default:
- break;
- }
+ RefreshShareCheckbox();
+ UpdateErrorLabel();
- const std::string& eap_anonymous_identity =
- (wifi ? wifi->eap_anonymous_identity() : std::string());
- identity_anonymous_textfield_->SetText(
- UTF8ToUTF16(eap_anonymous_identity));
- }
-
- // Server CA certificate.
- if (CaCertActive()) {
- const std::string& ca_cert_pem =
- (wifi ? wifi->eap_server_ca_cert_pem() : std::string());
- if (ca_cert_pem.empty()) {
- if (wifi->eap_use_system_cas()) {
- // "Default".
- server_ca_cert_combobox_->SetSelectedIndex(0);
- } else {
- // "Do not check".
- server_ca_cert_combobox_->SetSelectedIndex(
- server_ca_cert_combobox_->model()->GetItemCount() - 1);
- }
- } else {
- // Select the certificate if available.
- int cert_index = CertLibrary::Get()->GetCertIndexByPEM(
- CertLibrary::CERT_TYPE_SERVER_CA, ca_cert_pem);
- if (cert_index >= 0) {
- // Skip item for "Default".
- server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index);
- }
- }
- }
-
- // User certificate.
- if (UserCertActive()) {
- const std::string& pkcs11_id =
- (wifi ? wifi->eap_client_cert_pkcs11_id() : std::string());
- if (!pkcs11_id.empty()) {
- int cert_index = CertLibrary::Get()->GetCertIndexByPkcs11Id(
- CertLibrary::CERT_TYPE_USER, pkcs11_id);
- if (cert_index >= 0) {
- user_cert_combobox_->SetSelectedIndex(cert_index);
- }
- }
- }
-
- // Identity is always active.
- const std::string& eap_identity =
- (wifi ? wifi->eap_identity() : std::string());
- identity_textfield_->SetText(UTF8ToUTF16(eap_identity));
-
- // Passphrase
- if (PassphraseActive()) {
- const std::string& eap_passphrase =
- (wifi ? wifi->eap_passphrase() : std::string());
- passphrase_textfield_->SetText(UTF8ToUTF16(eap_passphrase));
- }
-
- // Save credentials
- bool save_credentials = (wifi ? wifi->save_credentials() : false);
- save_credentials_checkbox_->SetChecked(save_credentials);
+ if (wifi) {
+ NetworkHandler::Get()->network_configuration_handler()->GetProperties(
+ service_path_,
+ base::Bind(&WifiConfigView::InitFromProperties,
+ weak_ptr_factory_.GetWeakPtr(), show_8021x),
+ base::Bind(&ShillError, "GetProperties"));
}
+}
+
+void WifiConfigView::InitFromProperties(
+ bool show_8021x,
+ const std::string& service_path,
+ const base::DictionaryValue& properties) {
+ std::string passphrase;
+ properties.GetStringWithoutPathExpansion(
+ flimflam::kPassphraseProperty, &passphrase);
+ passphrase_textfield_->SetText(UTF8ToUTF16(passphrase));
+
+ if (!show_8021x)
+ return;
+
+ // EAP Method
+ std::string eap_method;
+ properties.GetStringWithoutPathExpansion(
+ flimflam::kEapMethodProperty, &eap_method);
+ if (eap_method == flimflam::kEapMethodPEAP)
+ eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_PEAP);
+ else if (eap_method == flimflam::kEapMethodTTLS)
+ eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TTLS);
+ else if (eap_method == flimflam::kEapMethodTLS)
+ eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_TLS);
+ else if (eap_method == flimflam::kEapMethodLEAP)
+ eap_method_combobox_->SetSelectedIndex(EAP_METHOD_INDEX_LEAP);
+ RefreshEapFields();
+
+ // Phase 2 authentication and anonymous identity.
+ if (Phase2AuthActive()) {
+ std::string eap_phase_2_auth;
+ properties.GetStringWithoutPathExpansion(
+ flimflam::kEapPhase2AuthProperty, &eap_phase_2_auth);
+ if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSMD5)
+ phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MD5);
+ else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSMSCHAPV2)
+ phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAPV2);
+ else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSMSCHAP)
+ phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_MSCHAP);
+ else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSPAP)
+ phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_PAP);
+ else if (eap_phase_2_auth == flimflam::kEapPhase2AuthTTLSCHAP)
+ phase_2_auth_combobox_->SetSelectedIndex(PHASE_2_AUTH_INDEX_CHAP);
+
+ std::string eap_anonymous_identity;
+ properties.GetStringWithoutPathExpansion(
+ flimflam::kEapAnonymousIdentityProperty, &eap_anonymous_identity);
+ identity_anonymous_textfield_->SetText(UTF8ToUTF16(eap_anonymous_identity));
+ }
+
+ // Server CA certificate.
+ if (CaCertActive()) {
+ std::string eap_ca_cert_pem;
+ const base::ListValue* pems = NULL;
+ if (properties.GetListWithoutPathExpansion(
+ shill::kEapCaCertPemProperty, &pems))
+ pems->GetString(0, &eap_ca_cert_pem);
+ if (eap_ca_cert_pem.empty()) {
+ bool eap_use_system_cas = false;
+ properties.GetBooleanWithoutPathExpansion(
+ flimflam::kEapUseSystemCasProperty, &eap_use_system_cas);
+ if (eap_use_system_cas) {
+ // "Default"
+ server_ca_cert_combobox_->SetSelectedIndex(0);
+ } else {
+ // "Do not check".
+ server_ca_cert_combobox_->SetSelectedIndex(
+ server_ca_cert_combobox_->model()->GetItemCount() - 1);
+ }
+ } else {
+ // Select the certificate if available.
+ int cert_index = CertLibrary::Get()->GetCertIndexByPEM(
+ CertLibrary::CERT_TYPE_SERVER_CA, eap_ca_cert_pem);
+ if (cert_index >= 0) {
+ // Skip item for "Default".
+ server_ca_cert_combobox_->SetSelectedIndex(1 + cert_index);
+ }
+ }
+ }
+
+ // User certificate.
+ if (UserCertActive()) {
+ std::string eap_cert_id;
+ properties.GetStringWithoutPathExpansion(
+ flimflam::kEapCertIdProperty, &eap_cert_id);
+ if (!eap_cert_id.empty()) {
+ int cert_index = CertLibrary::Get()->GetCertIndexByPkcs11Id(
+ CertLibrary::CERT_TYPE_USER, eap_cert_id);
+ if (cert_index >= 0)
+ user_cert_combobox_->SetSelectedIndex(cert_index);
+ }
+ }
+
+ // Identity is always active.
+ std::string eap_identity;
+ properties.GetStringWithoutPathExpansion(
+ flimflam::kEapIdentityProperty, &eap_identity);
+ identity_textfield_->SetText(UTF8ToUTF16(eap_identity));
+
+ // Passphrase
+ if (PassphraseActive()) {
+ std::string eap_password;
+ properties.GetStringWithoutPathExpansion(
+ flimflam::kEapPasswordProperty, &eap_password);
+ passphrase_textfield_->SetText(UTF8ToUTF16(eap_password));
+ }
+
+ // Save credentials
+ bool save_credentials = false;
+ properties.GetBooleanWithoutPathExpansion(
+ flimflam::kSaveCredentialsProperty, &save_credentials);
+ save_credentials_checkbox_->SetChecked(save_credentials);
RefreshShareCheckbox();
UpdateErrorLabel();
@@ -1241,14 +1252,20 @@
view_to_focus->RequestFocus();
}
+void WifiConfigView::NetworkPropertiesUpdated(const NetworkState* network) {
+ if (network->path() != service_path_)
+ return;
+ UpdateErrorLabel();
+}
+
// static
void WifiConfigView::ParseWiFiUIProperty(
NetworkPropertyUIData* property_ui_data,
- Network* network,
+ const NetworkState* network,
const std::string& key) {
onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
const base::DictionaryValue* onc =
- NetworkConfigView::FindPolicyForActiveUser(network, &onc_source);
+ network_connect::FindPolicyForActiveUser(network, &onc_source);
property_ui_data->ParseOncProperty(
onc_source,
@@ -1259,7 +1276,7 @@
// static
void WifiConfigView::ParseWiFiEAPUIProperty(
NetworkPropertyUIData* property_ui_data,
- Network* network,
+ const NetworkState* network,
const std::string& key) {
ParseWiFiUIProperty(
property_ui_data, network,
diff --git a/chrome/browser/chromeos/options/wifi_config_view.h b/chrome/browser/chromeos/options/wifi_config_view.h
index 574072d..7956499 100644
--- a/chrome/browser/chromeos/options/wifi_config_view.h
+++ b/chrome/browser/chromeos/options/wifi_config_view.h
@@ -10,10 +10,13 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "chrome/browser/chromeos/cros/cert_library.h"
#include "chrome/browser/chromeos/cros/network_property_ui_data.h"
#include "chrome/browser/chromeos/options/network_config_view.h"
+#include "chromeos/network/network_state_handler_observer.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/models/combobox_model.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/combobox/combobox_listener.h"
@@ -28,6 +31,8 @@
namespace chromeos {
+class NetworkState;
+
namespace internal {
class EAPMethodComboboxModel;
class Phase2AuthComboboxModel;
@@ -41,32 +46,31 @@
public views::TextfieldController,
public views::ButtonListener,
public views::ComboboxListener,
- public CertLibrary::Observer {
+ public CertLibrary::Observer,
+ public NetworkStateHandlerObserver {
public:
- // Wifi login dialog for wifi network |wifi|. |wifi| must be a non NULL
- // pointer to a WifiNetwork in NetworkLibrary.
- WifiConfigView(NetworkConfigView* parent, WifiNetwork* wifi);
- // Wifi login dialog for "Joining other network..."
- WifiConfigView(NetworkConfigView* parent, bool show_8021x);
+ WifiConfigView(NetworkConfigView* parent,
+ const std::string& service_path,
+ bool show_8021x);
virtual ~WifiConfigView();
- // views::TextfieldController:
+ // views::TextfieldController
virtual void ContentsChanged(views::Textfield* sender,
const string16& new_contents) OVERRIDE;
virtual bool HandleKeyEvent(views::Textfield* sender,
const ui::KeyEvent& key_event) OVERRIDE;
- // views::ButtonListener:
+ // views::ButtonListener
virtual void ButtonPressed(views::Button* sender,
const ui::Event& event) OVERRIDE;
- // views::ComboboxListener:
+ // views::ComboboxListener
virtual void OnSelectedIndexChanged(views::Combobox* combobox) OVERRIDE;
- // CertLibrary::Observer:
+ // CertLibrary::Observer
virtual void OnCertificatesLoaded(bool initial_load) OVERRIDE;
- // ChildNetworkConfigView:
+ // ChildNetworkConfigView
virtual string16 GetTitle() const OVERRIDE;
virtual views::View* GetInitiallyFocusedView() OVERRIDE;
virtual bool CanLogin() OVERRIDE;
@@ -74,21 +78,29 @@
virtual void Cancel() OVERRIDE;
virtual void InitFocus() OVERRIDE;
+ // NetworkStateHandlerObserver
+ virtual void NetworkPropertiesUpdated(const NetworkState* network) OVERRIDE;
+
// Parses a WiFi UI |property| from the ONC associated with |network|. |key|
// is the property name within the ONC WiFi dictionary.
static void ParseWiFiUIProperty(NetworkPropertyUIData* property_ui_data,
- Network* network,
+ const NetworkState* network,
const std::string& key);
// Parses a WiFi EAP UI |property| from the ONC associated with |network|.
// |key| is the property name within the ONC WiFi.EAP dictionary.
static void ParseWiFiEAPUIProperty(NetworkPropertyUIData* property_ui_data,
- Network* network,
+ const NetworkState* network,
const std::string& key);
private:
// Initializes UI. If |show_8021x| includes 802.1x config options.
- void Init(WifiNetwork* wifi, bool show_8021x);
+ void Init(bool show_8021x);
+
+ // Callback to initialize fields from uncached network properties.
+ void InitFromProperties(bool show_8021x,
+ const std::string& service_path,
+ const base::DictionaryValue& dictionary);
// Get input values.
std::string GetSsid() const;
@@ -97,14 +109,17 @@
bool GetShareNetwork(bool share_default) const;
// Get various 802.1X EAP values from the widgets.
- EAPMethod GetEapMethod() const;
- EAPPhase2Auth GetEapPhase2Auth() const;
+ std::string GetEapMethod() const;
+ std::string GetEapPhase2Auth() const;
std::string GetEapServerCaCertPEM() const;
bool GetEapUseSystemCas() const;
std::string GetEapClientCertPkcs11Id() const;
std::string GetEapIdentity() const;
std::string GetEapAnonymousIdentity() const;
+ // Fill in |properties| with the appropriate values.
+ void SetEapProperties(base::DictionaryValue* properties);
+
// Returns true if the EAP method requires a user certificate.
bool UserCertRequired() const;
@@ -174,6 +189,8 @@
views::ToggleImageButton* passphrase_visible_button_;
views::Label* error_label_;
+ base::WeakPtrFactory<WifiConfigView> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(WifiConfigView);
};
diff --git a/chrome/browser/chromeos/options/wimax_config_view.cc b/chrome/browser/chromeos/options/wimax_config_view.cc
index 5ae075b..8ea3788 100644
--- a/chrome/browser/chromeos/options/wimax_config_view.cc
+++ b/chrome/browser/chromeos/options/wimax_config_view.cc
@@ -4,19 +4,27 @@
#include "chrome/browser/chromeos/options/wimax_config_view.h"
+#include "ash/system/chromeos/network/network_connect.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/enrollment_dialog_view.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/options/network_connect.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chromeos/login/login_state.h"
+#include "chromeos/network/network_configuration_handler.h"
+#include "chromeos/network/network_event_log.h"
+#include "chromeos/network/network_profile.h"
+#include "chromeos/network/network_profile_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/onc/onc_constants.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "grit/theme_resources.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/events/event.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
@@ -31,8 +39,19 @@
namespace chromeos {
-WimaxConfigView::WimaxConfigView(NetworkConfigView* parent, WimaxNetwork* wimax)
- : ChildNetworkConfigView(parent, wimax),
+namespace {
+
+void ShillError(const std::string& function,
+ const std::string& error_name,
+ scoped_ptr<base::DictionaryValue> error_data) {
+ NET_LOG_ERROR("Shill Error from WimaxConfigView: " + error_name, function);
+}
+
+} // namespace
+
+WimaxConfigView::WimaxConfigView(NetworkConfigView* parent,
+ const std::string& service_path)
+ : ChildNetworkConfigView(parent, service_path),
identity_label_(NULL),
identity_textfield_(NULL),
save_credentials_checkbox_(NULL),
@@ -41,8 +60,9 @@
passphrase_label_(NULL),
passphrase_textfield_(NULL),
passphrase_visible_button_(NULL),
- error_label_(NULL) {
- Init(wimax);
+ error_label_(NULL),
+ weak_ptr_factory_(this) {
+ Init();
}
WimaxConfigView::~WimaxConfigView() {
@@ -76,33 +96,15 @@
}
void WimaxConfigView::UpdateErrorLabel() {
- std::string error_msg;
+ base::string16 error_msg;
if (!service_path_.empty()) {
- NetworkLibrary* cros = NetworkLibrary::Get();
- const WimaxNetwork* wimax = cros->FindWimaxNetworkByPath(service_path_);
- if (wimax && wimax->failed()) {
- bool passphrase_empty = wimax->eap_passphrase().empty();
- switch (wimax->error()) {
- case ERROR_BAD_PASSPHRASE:
- if (!passphrase_empty) {
- error_msg = l10n_util::GetStringUTF8(
- IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_PASSPHRASE);
- }
- break;
- case ERROR_BAD_WEPKEY:
- if (!passphrase_empty) {
- error_msg = l10n_util::GetStringUTF8(
- IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_BAD_WEPKEY);
- }
- break;
- default:
- error_msg = wimax->GetErrorString();
- break;
- }
- }
+ const NetworkState* wimax = NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path_);
+ if (wimax && wimax->connection_state() == flimflam::kStateFailure)
+ error_msg = ash::network_connect::ErrorString(wimax->error());
}
if (!error_msg.empty()) {
- error_label_->SetText(UTF8ToUTF16(error_msg));
+ error_label_->SetText(error_msg);
error_label_->SetVisible(true);
} else {
error_label_->SetVisible(false);
@@ -137,26 +139,26 @@
}
bool WimaxConfigView::Login() {
- NetworkLibrary* cros = NetworkLibrary::Get();
- WimaxNetwork* wimax = cros->FindWimaxNetworkByPath(service_path_);
+ const NetworkState* wimax = NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path_);
if (!wimax) {
- // Shill no longer knows about this wimax network (edge case).
- // TODO(stevenjb): Add a notification (chromium-os13225).
- LOG(WARNING) << "Wimax network: " << service_path_ << " no longer exists.";
- return true;
+ // Shill no longer knows about this network (edge case).
+ // TODO(stevenjb): Add notification for this.
+ NET_LOG_ERROR("Network not found", service_path_);
+ return true; // Close dialog
}
- wimax->SetEAPIdentity(GetEapIdentity());
- wimax->SetEAPPassphrase(GetEapPassphrase());
- wimax->SetSaveCredentials(GetSaveCredentials());
- bool share_default = (wimax->profile_type() != PROFILE_USER);
- bool share = GetShareNetwork(share_default);
- wimax->SetEnrollmentDelegate(
- CreateEnrollmentDelegate(GetWidget()->GetNativeWindow(),
- wimax->name(),
- ProfileManager::GetLastUsedProfile()));
- cros->ConnectToWimaxNetwork(wimax, share);
- // Connection failures are responsible for updating the UI, including
- // reopening dialogs.
+ base::DictionaryValue properties;
+ properties.SetStringWithoutPathExpansion(
+ flimflam::kEapIdentityProperty, GetEapIdentity());
+ properties.SetStringWithoutPathExpansion(
+ flimflam::kEapPasswordProperty, GetEapPassphrase());
+ properties.SetBooleanWithoutPathExpansion(
+ flimflam::kSaveCredentialsProperty, GetSaveCredentials());
+
+ const bool share_default = true;
+ bool share_network = GetShareNetwork(share_default);
+ ash::network_connect::ConfigureNetworkAndConnect(
+ service_path_, properties, share_network);
return true; // dialog will be closed
}
@@ -183,8 +185,11 @@
void WimaxConfigView::Cancel() {
}
-void WimaxConfigView::Init(WimaxNetwork* wimax) {
- DCHECK(wimax);
+void WimaxConfigView::Init() {
+ const NetworkState* wimax = NetworkHandler::Get()->network_state_handler()->
+ GetNetworkState(service_path_);
+ DCHECK(wimax && wimax->type() == flimflam::kTypeWimax);
+
WifiConfigView::ParseWiFiEAPUIProperty(
&save_credentials_ui_data_, wimax, onc::eap::kSaveCredentials);
WifiConfigView::ParseWiFiEAPUIProperty(
@@ -230,8 +235,6 @@
views::Textfield::STYLE_DEFAULT);
identity_textfield_->SetAccessibleName(identity_label_text);
identity_textfield_->SetController(this);
- const std::string& eap_identity = wimax->eap_identity();
- identity_textfield_->SetText(UTF8ToUTF16(eap_identity));
identity_textfield_->SetEnabled(identity_ui_data_.IsEditable());
layout->AddView(identity_textfield_);
layout->AddView(new ControlledSettingIndicatorView(identity_ui_data_));
@@ -288,7 +291,7 @@
// Checkboxes.
- if (LoginState::Get()->IsUserLoggedIn()) {
+ if (LoginState::Get()->IsUserAuthenticated()) {
// Save credentials
layout->StartRow(0, column_view_set_id);
save_credentials_checkbox_ = new views::Checkbox(
@@ -296,23 +299,28 @@
IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SAVE_CREDENTIALS));
save_credentials_checkbox_->SetEnabled(
save_credentials_ui_data_.IsEditable());
- save_credentials_checkbox_->SetChecked(wimax->save_credentials());
layout->SkipColumns(1);
layout->AddView(save_credentials_checkbox_);
layout->AddView(
new ControlledSettingIndicatorView(save_credentials_ui_data_));
+ }
- // Share network
- if (wimax->profile_type() == PROFILE_NONE && wimax->passphrase_required()) {
- layout->StartRow(0, column_view_set_id);
- share_network_checkbox_ = new views::Checkbox(
- l10n_util::GetStringUTF16(
- IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SHARE_NETWORK));
+ // Share network
+ if (wimax->profile_path().empty()) {
+ layout->StartRow(0, column_view_set_id);
+ share_network_checkbox_ = new views::Checkbox(
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SHARE_NETWORK));
+ if (LoginState::Get()->IsUserAuthenticated()) {
+ share_network_checkbox_->SetChecked(false); // Default to unshared
share_network_checkbox_->SetEnabled(true);
- share_network_checkbox_->SetChecked(false); // Default to unshared.
- layout->SkipColumns(1);
- layout->AddView(share_network_checkbox_);
+ } else {
+ // Not logged in, must be shared
+ share_network_checkbox_->SetChecked(true);
+ share_network_checkbox_->SetEnabled(false);
}
+ layout->SkipColumns(1);
+ layout->AddView(share_network_checkbox_);
}
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
@@ -325,6 +333,32 @@
layout->AddView(error_label_);
UpdateErrorLabel();
+
+ if (wimax) {
+ NetworkHandler::Get()->network_configuration_handler()->GetProperties(
+ service_path_,
+ base::Bind(&WimaxConfigView::InitFromProperties,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&ShillError, "GetProperties"));
+ }
+}
+
+void WimaxConfigView::InitFromProperties(
+ const std::string& service_path,
+ const base::DictionaryValue& properties) {
+ // EapIdentity
+ std::string eap_identity;
+ properties.GetStringWithoutPathExpansion(
+ flimflam::kEapIdentityProperty, &eap_identity);
+ identity_textfield_->SetText(UTF8ToUTF16(eap_identity));
+
+ // Save credentials
+ if (save_credentials_checkbox_) {
+ bool save_credentials = false;
+ properties.GetBooleanWithoutPathExpansion(
+ flimflam::kSaveCredentialsProperty, &save_credentials);
+ save_credentials_checkbox_->SetChecked(save_credentials);
+ }
}
void WimaxConfigView::InitFocus() {
diff --git a/chrome/browser/chromeos/options/wimax_config_view.h b/chrome/browser/chromeos/options/wimax_config_view.h
index f76702a..baa3ae7 100644
--- a/chrome/browser/chromeos/options/wimax_config_view.h
+++ b/chrome/browser/chromeos/options/wimax_config_view.h
@@ -9,6 +9,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "chrome/browser/chromeos/options/network_config_view.h"
#include "chrome/browser/chromeos/options/wifi_config_view.h"
@@ -31,7 +32,7 @@
public:
// Wimax login dialog for wimax network |wimax|. |wimax| must be a non NULL
// pointer to a WimaxNetwork in NetworkLibrary.
- WimaxConfigView(NetworkConfigView* parent, WimaxNetwork* wimax);
+ WimaxConfigView(NetworkConfigView* parent, const std::string& service_path);
virtual ~WimaxConfigView();
// views::TextfieldController:
@@ -53,7 +54,12 @@
virtual void InitFocus() OVERRIDE;
private:
- void Init(WimaxNetwork* wimax);
+ // Initializes UI.
+ void Init();
+
+ // Callback to initialize fields from uncached network properties.
+ void InitFromProperties(const std::string& service_path,
+ const base::DictionaryValue& dictionary);
// Get input values.
std::string GetEapIdentity() const;
@@ -81,6 +87,8 @@
views::ToggleImageButton* passphrase_visible_button_;
views::Label* error_label_;
+ base::WeakPtrFactory<WimaxConfigView> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(WimaxConfigView);
};
diff --git a/chrome/browser/chromeos/policy/app_pack_updater.cc b/chrome/browser/chromeos/policy/app_pack_updater.cc
index 3aca24a..9230628 100644
--- a/chrome/browser/chromeos/policy/app_pack_updater.cc
+++ b/chrome/browser/chromeos/policy/app_pack_updater.cc
@@ -66,7 +66,7 @@
: weak_ptr_factory_(this),
created_extension_loader_(false),
install_attributes_(install_attributes),
- external_cache_(kAppPackCacheDir, request_context, this) {
+ external_cache_(kAppPackCacheDir, request_context, this, false) {
chromeos::CrosSettings::Get()->AddSettingsObserver(chromeos::kAppPack, this);
if (install_attributes_->GetMode() == DEVICE_MODE_RETAIL_KIOSK) {
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
index ff380c1..9f50d06 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
@@ -59,7 +59,7 @@
chromeos::system::StatisticsProvider* provider =
chromeos::system::StatisticsProvider::GetInstance();
if (!provider->GetMachineStatistic(key, &value))
- LOG(WARNING) << "Failed to get machine statistic " << key;
+ return std::string();
return value;
}
@@ -70,10 +70,8 @@
bool value = default_value;
chromeos::system::StatisticsProvider* provider =
chromeos::system::StatisticsProvider::GetInstance();
- if (!provider->GetMachineFlag(key, &value)) {
- LOG(WARNING) << "Failed to get machine flag " << key;
+ if (!provider->GetMachineFlag(key, &value))
return default_value;
- }
return value;
}
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service.cc b/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
index 2e63102..adcf750 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
@@ -193,13 +193,18 @@
token_service_->OnValidationComplete(token_is_valid_);
// Note: this object (which is also the Request instance) may be deleted in
// these consumer callbacks, so the callbacks must be the last line executed.
+ // Also, make copies of the parameters passed to the consumer to avoid invalid
+ // memory accesses when the consumer deletes |this| immediately.
if (!token_is_valid_) {
consumer_->OnGetTokenFailure(this, GoogleServiceAuthError(
GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
} else if (error_) {
- consumer_->OnGetTokenFailure(this, *error_.get());
+ GoogleServiceAuthError error_copy = *error_;
+ consumer_->OnGetTokenFailure(this, error_copy);
} else {
- consumer_->OnGetTokenSuccess(this, access_token_, expiration_time_);
+ std::string access_token_copy = access_token_;
+ base::Time expiration_time_copy = expiration_time_;
+ consumer_->OnGetTokenSuccess(this, access_token_copy, expiration_time_copy);
}
}
diff --git a/chrome/browser/chromeos/status/network_menu.cc b/chrome/browser/chromeos/status/network_menu.cc
index 980af04..2701f92 100644
--- a/chrome/browser/chromeos/status/network_menu.cc
+++ b/chrome/browser/chromeos/status/network_menu.cc
@@ -8,6 +8,7 @@
#include "ash/shell.h"
#include "ash/shell_delegate.h"
+#include "ash/system/chromeos/network/network_connect.h"
#include "ash/system/chromeos/network/network_icon.h"
#include "base/bind.h"
#include "base/logging.h"
@@ -17,7 +18,6 @@
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/mobile_config.h"
#include "chrome/browser/chromeos/options/network_config_view.h"
-#include "chrome/browser/chromeos/options/network_connect.h"
#include "chrome/browser/defaults.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/url_constants.h"
@@ -219,17 +219,9 @@
void NetworkMenuModel::ConnectToNetworkAt(int index) {
const std::string& service_path = menu_items_[index].service_path;
- network_connect::ConnectResult result =
- network_connect::ConnectToNetwork(
- service_path, owner_->delegate()->GetNativeWindow());
+ gfx::NativeWindow native_window = owner_->delegate()->GetNativeWindow();
+ ash::network_connect::ConnectToNetwork(service_path, native_window);
owner_->delegate()->OnConnectToNetworkRequested(service_path);
- if (result == network_connect::NETWORK_NOT_FOUND) {
- // If we are attempting to connect to a network that no longer exists,
- // display a notification.
- LOG(WARNING) << "Network does not exist to connect to: "
- << service_path;
- // TODO(stevenjb): Show notification.
- }
}
////////////////////////////////////////////////////////////////////////////////
@@ -350,7 +342,7 @@
if (type == flimflam::kTypeCellular)
ChooseMobileNetworkDialog::ShowDialog(native_window);
else
- NetworkConfigView::ShowForType(chromeos::TYPE_WIFI, native_window);
+ NetworkConfigView::ShowForType(flimflam::kTypeWifi, native_window);
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
index 764b81e..eb0b9a7 100644
--- a/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
+++ b/chrome/browser/chromeos/system/ash_system_tray_delegate.cc
@@ -72,6 +72,7 @@
#include "chrome/browser/chromeos/system/timezone_settings.h"
#include "chrome/browser/chromeos/system_key_event_listener.h"
#include "chrome/browser/drive/drive_service_interface.h"
+#include "chrome/browser/feedback/tracing_manager.h"
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/policy/browser_policy_connector.h"
@@ -463,8 +464,9 @@
virtual const string16 GetLocallyManagedUserMessage() const OVERRIDE {
if (GetUserLoginStatus() != ash::user::LOGGED_IN_LOCALLY_MANAGED)
return string16();
- return l10n_util::GetStringFUTF16(IDS_USER_IS_LOCALLY_MANAGED_BY_NOTICE,
- GetLocallyManagedUserManagerName());
+ return l10n_util::GetStringFUTF16(
+ IDS_USER_IS_LOCALLY_MANAGED_BY_NOTICE,
+ UTF8ToUTF16(GetLocallyManagedUserManager()));
}
virtual bool SystemShouldUpgrade() const OVERRIDE {
@@ -489,24 +491,7 @@
virtual void ShowNetworkSettings(const std::string& service_path) OVERRIDE {
if (!LoginState::Get()->IsUserLoggedIn())
return;
-
- std::string page = chrome::kInternetOptionsSubPage;
- const chromeos::NetworkState* network = service_path.empty() ? NULL :
- NetworkHandler::Get()->network_state_handler()->GetNetworkState(
- service_path);
- if (network) {
- std::string name(network->name());
- if (name.empty() && network->type() == flimflam::kTypeEthernet)
- name = l10n_util::GetStringUTF8(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
- page += base::StringPrintf(
- "?servicePath=%s&networkType=%s&networkName=%s",
- net::EscapeUrlEncodedData(service_path, true).c_str(),
- net::EscapeUrlEncodedData(network->type(), true).c_str(),
- net::EscapeUrlEncodedData(name, false).c_str());
- }
- content::RecordAction(
- content::UserMetricsAction("OpenInternetOptionsDialog"));
- chrome::ShowSettingsSubPage(GetAppropriateBrowser(), page);
+ network_connect::ShowNetworkSettings(service_path);
}
virtual void ShowBluetoothSettings() OVERRIDE {
@@ -519,6 +504,10 @@
kDisplaySettingsSubPageName);
}
+ virtual void ShowChromeSlow() OVERRIDE {
+ chrome::ShowSlow(GetAppropriateBrowser());
+ }
+
virtual bool ShouldShowDisplayNotification() OVERRIDE {
// Packaged app is not counted as 'last active', so if a browser opening the
// display settings is in background of a packaged app, it will return true.
@@ -767,15 +756,12 @@
network_connect::HandleUnconfiguredNetwork(network_id, GetNativeWindow());
}
- virtual void ConnectToNetwork(const std::string& network_id) OVERRIDE {
- DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
- chromeos::switches::kUseNewNetworkConnectionHandler));
- network_connect::ConnectResult result =
- network_connect::ConnectToNetwork(network_id, GetNativeWindow());
- if (result == network_connect::NETWORK_NOT_FOUND)
- ShowNetworkSettings("");
- else if (result == network_connect::CONNECT_NOT_STARTED)
- ShowNetworkSettings(network_id);
+ virtual void EnrollOrConfigureNetwork(
+ const std::string& network_id,
+ gfx::NativeWindow parent_window) OVERRIDE {
+ if (network_connect::EnrollNetwork(network_id, parent_window))
+ return;
+ network_connect::HandleUnconfiguredNetwork(network_id, parent_window);
}
virtual void ManageBluetoothDevices() OVERRIDE {
@@ -797,12 +783,16 @@
SimDialogDelegate::SIM_DIALOG_UNLOCK);
}
+ virtual void ShowMobileSetup(const std::string& network_id) OVERRIDE {
+ network_connect::ShowMobileSetup(network_id);
+ }
+
virtual void ShowOtherWifi() OVERRIDE {
- NetworkConfigView::ShowForType(chromeos::TYPE_WIFI, GetNativeWindow());
+ NetworkConfigView::ShowForType(flimflam::kTypeWifi, GetNativeWindow());
}
virtual void ShowOtherVPN() OVERRIDE {
- NetworkConfigView::ShowForType(chromeos::TYPE_VPN, GetNativeWindow());
+ NetworkConfigView::ShowForType(flimflam::kTypeVPN, GetNativeWindow());
}
virtual void ShowOtherCellular() OVERRIDE {
@@ -943,9 +933,14 @@
base::Bind(&SystemTrayDelegate::OnAccessibilityModeChanged,
base::Unretained(this),
ash::A11Y_NOTIFICATION_NONE));
+ user_pref_registrar_->Add(
+ prefs::kPerformanceTracingEnabled,
+ base::Bind(&SystemTrayDelegate::UpdatePerformanceTracing,
+ base::Unretained(this)));
UpdateClockType();
UpdateShowLogoutButtonInTray();
+ UpdatePerformanceTracing();
search_key_mapped_to_ =
profile->GetPrefs()->GetInteger(prefs::kLanguageRemapSearchKeyTo);
}
@@ -1162,6 +1157,15 @@
GetSystemTrayNotifier()->NotifyAccessibilityModeChanged(notify);
}
+ void UpdatePerformanceTracing() {
+ if (!user_pref_registrar_)
+ return;
+ bool value =
+ user_pref_registrar_->prefs()->GetBoolean(
+ prefs::kPerformanceTracingEnabled);
+ GetSystemTrayNotifier()->NotifyTracingModeChanged(value);
+ }
+
// Overridden from InputMethodManager::Observer.
virtual void InputMethodChanged(
input_method::InputMethodManager* manager, bool show_message) OVERRIDE {
@@ -1252,10 +1256,12 @@
ash::NetworkObserver::MessageType message_type,
size_t link_index) OVERRIDE {
if (message_type == ash::NetworkObserver::ERROR_OUT_OF_CREDITS) {
- const CellularNetwork* cellular =
- NetworkLibrary::Get()->cellular_network();
- if (cellular)
- ConnectToNetwork(cellular->service_path());
+ const NetworkState* cellular =
+ NetworkHandler::Get()->network_state_handler()->
+ FirstNetworkByType(flimflam::kTypeCellular);
+ std::string service_path = cellular ? cellular->path() : "";
+ ShowNetworkSettings(service_path);
+
ash::Shell::GetInstance()->system_tray_notifier()->
NotifyClearNetworkMessage(message_type);
}
diff --git a/chrome/browser/chromeos/system_logs/about_system_logs_fetcher.cc b/chrome/browser/chromeos/system_logs/about_system_logs_fetcher.cc
new file mode 100644
index 0000000..e519ddb
--- /dev/null
+++ b/chrome/browser/chromeos/system_logs/about_system_logs_fetcher.cc
@@ -0,0 +1,43 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/system_logs/about_system_logs_fetcher.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "chrome/browser/chromeos/system_logs/chrome_internal_log_source.h"
+#include "chrome/browser/chromeos/system_logs/command_line_log_source.h"
+#include "chrome/browser/chromeos/system_logs/dbus_log_source.h"
+#include "chrome/browser/chromeos/system_logs/debug_daemon_log_source.h"
+#include "chrome/browser/chromeos/system_logs/lsb_release_log_source.h"
+#include "chrome/browser/chromeos/system_logs/memory_details_log_source.h"
+#include "chrome/browser/chromeos/system_logs/network_event_log_source.h"
+#include "chrome/browser/chromeos/system_logs/touch_log_source.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
+
+namespace chromeos {
+
+AboutSystemLogsFetcher::AboutSystemLogsFetcher() {
+ // Debug Daemon data source.
+ const bool scrub_data = false;
+ data_sources_.push_back(new DebugDaemonLogSource(scrub_data));
+
+ // Chrome data sources.
+ data_sources_.push_back(new ChromeInternalLogSource());
+ data_sources_.push_back(new CommandLineLogSource());
+ data_sources_.push_back(new DBusLogSource());
+ data_sources_.push_back(new LsbReleaseLogSource());
+ data_sources_.push_back(new MemoryDetailsLogSource());
+ data_sources_.push_back(new NetworkEventLogSource());
+ data_sources_.push_back(new TouchLogSource());
+
+ num_pending_requests_ = data_sources_.size();
+}
+
+AboutSystemLogsFetcher::~AboutSystemLogsFetcher() {
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/system_logs/about_system_logs_fetcher.h b/chrome/browser/chromeos/system_logs/about_system_logs_fetcher.h
new file mode 100644
index 0000000..3c6d9ad
--- /dev/null
+++ b/chrome/browser/chromeos/system_logs/about_system_logs_fetcher.h
@@ -0,0 +1,27 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_ABOUT_SYSTEM_LOGS_FETCHER_H_
+#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_ABOUT_SYSTEM_LOGS_FETCHER_H_
+
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
+
+namespace chromeos {
+
+// The AboutAboutSystemLogsFetcher aggregates the unscrubbed logs for display
+// in the about:system page.
+class AboutSystemLogsFetcher : public SystemLogsFetcherBase {
+ public:
+ AboutSystemLogsFetcher();
+ ~AboutSystemLogsFetcher();
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(AboutSystemLogsFetcher);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_ABOUT_SYSTEM_LOGS_FETCHER_H_
+
diff --git a/chrome/browser/chromeos/system_logs/chrome_internal_log_source.cc b/chrome/browser/chromeos/system_logs/chrome_internal_log_source.cc
index 9370a61..f368097 100644
--- a/chrome/browser/chromeos/system_logs/chrome_internal_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/chrome_internal_log_source.cc
@@ -7,7 +7,6 @@
#include "base/json/json_string_value_serializer.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/profiles/profile_manager.h"
diff --git a/chrome/browser/chromeos/system_logs/chrome_internal_log_source.h b/chrome/browser/chromeos/system_logs/chrome_internal_log_source.h
index 268a3ab..1aa6546 100644
--- a/chrome/browser/chromeos/system_logs/chrome_internal_log_source.h
+++ b/chrome/browser/chromeos/system_logs/chrome_internal_log_source.h
@@ -5,7 +5,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_CHROME_INTERNAL_LOG_SOURCE_H_
#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_CHROME_INTERNAL_LOG_SOURCE_H_
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
namespace chromeos {
diff --git a/chrome/browser/chromeos/system_logs/command_line_log_source.cc b/chrome/browser/chromeos/system_logs/command_line_log_source.cc
index 43b7651..fe1a352 100644
--- a/chrome/browser/chromeos/system_logs/command_line_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/command_line_log_source.cc
@@ -33,6 +33,16 @@
command.AppendArg("--dump_server_info");
commands.push_back(std::make_pair("cras", command));
+ command = CommandLine((base::FilePath("/usr/bin/cras_test_client")));
+ command.AppendArg("--loopback_file");
+ command.AppendArg("/dev/null");
+ command.AppendArg("--rate");
+ command.AppendArg("44100");
+ command.AppendArg("--duration_seconds");
+ command.AppendArg("0.01");
+ command.AppendArg("--show_total_rms");
+ commands.push_back(std::make_pair("cras_rms", command));
+
command = CommandLine((base::FilePath("/usr/bin/printenv")));
commands.push_back(std::make_pair("env", command));
diff --git a/chrome/browser/chromeos/system_logs/command_line_log_source.h b/chrome/browser/chromeos/system_logs/command_line_log_source.h
index 4ddee4f..4dc9a98 100644
--- a/chrome/browser/chromeos/system_logs/command_line_log_source.h
+++ b/chrome/browser/chromeos/system_logs/command_line_log_source.h
@@ -5,7 +5,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_COMMAND_LINE_LOG_SOURCE_H_
#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_COMMAND_LINE_LOG_SOURCE_H_
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
namespace chromeos {
diff --git a/chrome/browser/chromeos/system_logs/dbus_log_source.cc b/chrome/browser/chromeos/system_logs/dbus_log_source.cc
index 8f92518..861f724 100644
--- a/chrome/browser/chromeos/system_logs/dbus_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/dbus_log_source.cc
@@ -4,7 +4,6 @@
#include "chrome/browser/chromeos/system_logs/dbus_log_source.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
#include "content/public/browser/browser_thread.h"
#include "dbus/dbus_statistics.h"
diff --git a/chrome/browser/chromeos/system_logs/dbus_log_source.h b/chrome/browser/chromeos/system_logs/dbus_log_source.h
index 810368d..622aa56 100644
--- a/chrome/browser/chromeos/system_logs/dbus_log_source.h
+++ b/chrome/browser/chromeos/system_logs/dbus_log_source.h
@@ -5,7 +5,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_DBUS_LOG_SOURCE_H_
#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_DBUS_LOG_SOURCE_H_
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
namespace chromeos {
diff --git a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
index feb1d8f..8a8aeb5 100644
--- a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
@@ -12,7 +12,6 @@
#include "base/memory/weak_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/chrome_switches.h"
#include "chromeos/dbus/dbus_thread_manager.h"
@@ -28,9 +27,10 @@
namespace chromeos {
-DebugDaemonLogSource::DebugDaemonLogSource()
+DebugDaemonLogSource::DebugDaemonLogSource(bool scrub)
: response_(new SystemLogsResponse()),
num_pending_requests_(0),
+ scrub_(scrub),
weak_ptr_factory_(this) {}
DebugDaemonLogSource::~DebugDaemonLogSource() {}
@@ -57,12 +57,18 @@
client->GetWiMaxStatus(base::Bind(&DebugDaemonLogSource::OnGetWiMaxStatus,
weak_ptr_factory_.GetWeakPtr()));
++num_pending_requests_;
- client->GetAllLogs(base::Bind(&DebugDaemonLogSource::OnGetLogs,
- weak_ptr_factory_.GetWeakPtr()));
- ++num_pending_requests_;
client->GetUserLogFiles(base::Bind(&DebugDaemonLogSource::OnGetUserLogFiles,
weak_ptr_factory_.GetWeakPtr()));
++num_pending_requests_;
+
+ if (scrub_) {
+ client->GetScrubbedLogs(base::Bind(&DebugDaemonLogSource::OnGetLogs,
+ weak_ptr_factory_.GetWeakPtr()));
+ } else {
+ client->GetAllLogs(base::Bind(&DebugDaemonLogSource::OnGetLogs,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+ ++num_pending_requests_;
}
void DebugDaemonLogSource::OnGetRoutes(bool succeeded,
diff --git a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h
index 8d1626c..e68e60d 100644
--- a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h
+++ b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.h
@@ -10,14 +10,14 @@
#include <vector>
#include "base/memory/weak_ptr.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
namespace chromeos {
// Gathers log data from Debug Daemon.
class DebugDaemonLogSource : public SystemLogsSource {
public:
- DebugDaemonLogSource();
+ explicit DebugDaemonLogSource(bool scrub);
virtual ~DebugDaemonLogSource();
// SystemLogsSource override:
@@ -49,6 +49,7 @@
scoped_ptr<SystemLogsResponse> response_;
SysLogsSourceCallback callback_;
int num_pending_requests_;
+ bool scrub_;
base::WeakPtrFactory<DebugDaemonLogSource> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(DebugDaemonLogSource);
diff --git a/chrome/browser/chromeos/system_logs/lsb_release_log_source.h b/chrome/browser/chromeos/system_logs/lsb_release_log_source.h
index 8680fc2..146c7532 100644
--- a/chrome/browser/chromeos/system_logs/lsb_release_log_source.h
+++ b/chrome/browser/chromeos/system_logs/lsb_release_log_source.h
@@ -4,7 +4,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_LSB_RELEASE_LOG_SOURCE_H_
#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_LSB_RELEASE_LOG_SOURCE_H_
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
namespace chromeos {
diff --git a/chrome/browser/chromeos/system_logs/memory_details_log_source.cc b/chrome/browser/chromeos/system_logs/memory_details_log_source.cc
index 75680cd..6618563 100644
--- a/chrome/browser/chromeos/system_logs/memory_details_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/memory_details_log_source.cc
@@ -4,7 +4,6 @@
#include "chrome/browser/chromeos/system_logs/memory_details_log_source.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
#include "chrome/browser/memory_details.h"
#include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/chromeos/system_logs/memory_details_log_source.h b/chrome/browser/chromeos/system_logs/memory_details_log_source.h
index c716eb5..777c576 100644
--- a/chrome/browser/chromeos/system_logs/memory_details_log_source.h
+++ b/chrome/browser/chromeos/system_logs/memory_details_log_source.h
@@ -5,7 +5,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_MEMORY_DETAILS_LOG_SOURCE_H_
#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_MEMORY_DETAILS_LOG_SOURCE_H_
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
namespace chromeos {
diff --git a/chrome/browser/chromeos/system_logs/network_event_log_source.cc b/chrome/browser/chromeos/system_logs/network_event_log_source.cc
index a0e214f..76c743b 100644
--- a/chrome/browser/chromeos/system_logs/network_event_log_source.cc
+++ b/chrome/browser/chromeos/system_logs/network_event_log_source.cc
@@ -5,7 +5,6 @@
#include "chrome/browser/chromeos/system_logs/network_event_log_source.h"
#include "base/message_loop/message_loop.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
#include "chromeos/network/network_event_log.h"
#include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/chromeos/system_logs/network_event_log_source.h b/chrome/browser/chromeos/system_logs/network_event_log_source.h
index 0c4e5e7..6df6e9a 100644
--- a/chrome/browser/chromeos/system_logs/network_event_log_source.h
+++ b/chrome/browser/chromeos/system_logs/network_event_log_source.h
@@ -5,7 +5,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_NETWORK_EVENT_LOG_SOURCE_H_
#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_NETWORK_EVENT_LOG_SOURCE_H_
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
namespace chromeos {
diff --git a/chrome/browser/chromeos/system_logs/scrubbed_system_logs_fetcher.cc b/chrome/browser/chromeos/system_logs/scrubbed_system_logs_fetcher.cc
new file mode 100644
index 0000000..5845c13
--- /dev/null
+++ b/chrome/browser/chromeos/system_logs/scrubbed_system_logs_fetcher.cc
@@ -0,0 +1,43 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/system_logs/scrubbed_system_logs_fetcher.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "chrome/browser/chromeos/system_logs/chrome_internal_log_source.h"
+#include "chrome/browser/chromeos/system_logs/command_line_log_source.h"
+#include "chrome/browser/chromeos/system_logs/dbus_log_source.h"
+#include "chrome/browser/chromeos/system_logs/debug_daemon_log_source.h"
+#include "chrome/browser/chromeos/system_logs/lsb_release_log_source.h"
+#include "chrome/browser/chromeos/system_logs/memory_details_log_source.h"
+#include "chrome/browser/chromeos/system_logs/network_event_log_source.h"
+#include "chrome/browser/chromeos/system_logs/touch_log_source.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
+
+namespace chromeos {
+
+ScrubbedSystemLogsFetcher::ScrubbedSystemLogsFetcher() {
+ // Debug Daemon data source.
+ const bool scrub_data = true;
+ data_sources_.push_back(new DebugDaemonLogSource(scrub_data));
+
+ // Chrome data sources.
+ data_sources_.push_back(new ChromeInternalLogSource());
+ data_sources_.push_back(new CommandLineLogSource());
+ data_sources_.push_back(new DBusLogSource());
+ data_sources_.push_back(new LsbReleaseLogSource());
+ data_sources_.push_back(new MemoryDetailsLogSource());
+ data_sources_.push_back(new NetworkEventLogSource());
+ data_sources_.push_back(new TouchLogSource());
+
+ num_pending_requests_ = data_sources_.size();
+}
+
+ScrubbedSystemLogsFetcher::~ScrubbedSystemLogsFetcher() {
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/system_logs/scrubbed_system_logs_fetcher.h b/chrome/browser/chromeos/system_logs/scrubbed_system_logs_fetcher.h
new file mode 100644
index 0000000..7d47151
--- /dev/null
+++ b/chrome/browser/chromeos/system_logs/scrubbed_system_logs_fetcher.h
@@ -0,0 +1,29 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SCRUBBED_SYSTEM_LOGS_FETCHER_H_
+#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SCRUBBED_SYSTEM_LOGS_FETCHER_H_
+
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
+
+namespace chromeos {
+
+// The ScrubbedSystemLogsFetcher aggregates the scrubbed logs for sending
+// with feedback reports.
+// TODO: This class needs to be expanded to provide better scrubbing of
+// system logs.
+class ScrubbedSystemLogsFetcher : public SystemLogsFetcherBase {
+ public:
+ ScrubbedSystemLogsFetcher();
+ ~ScrubbedSystemLogsFetcher();
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(ScrubbedSystemLogsFetcher);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SCRUBBED_SYSTEM_LOGS_FETCHER_H_
+
diff --git a/chrome/browser/chromeos/system_logs/system_logs_fetcher.cc b/chrome/browser/chromeos/system_logs/system_logs_fetcher_base.cc
similarity index 61%
rename from chrome/browser/chromeos/system_logs/system_logs_fetcher.cc
rename to chrome/browser/chromeos/system_logs/system_logs_fetcher_base.cc
index e34c06d..09a177b 100644
--- a/chrome/browser/chromeos/system_logs/system_logs_fetcher.cc
+++ b/chrome/browser/chromeos/system_logs/system_logs_fetcher_base.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -20,40 +20,26 @@
namespace chromeos {
-SystemLogsFetcher::SystemLogsFetcher()
+SystemLogsFetcherBase::SystemLogsFetcherBase()
: response_(new SystemLogsResponse),
- num_pending_requests_(0),
- weak_ptr_factory_(this) {
- // Debug Daemon data source.
- data_sources_.push_back(new DebugDaemonLogSource());
-
- // Chrome data sources.
- data_sources_.push_back(new ChromeInternalLogSource());
- data_sources_.push_back(new CommandLineLogSource());
- data_sources_.push_back(new DBusLogSource());
- data_sources_.push_back(new LsbReleaseLogSource());
- data_sources_.push_back(new MemoryDetailsLogSource());
- data_sources_.push_back(new NetworkEventLogSource());
- data_sources_.push_back(new TouchLogSource());
-
- num_pending_requests_ = data_sources_.size();
+ num_pending_requests_(0) {
}
-SystemLogsFetcher::~SystemLogsFetcher() {}
+SystemLogsFetcherBase::~SystemLogsFetcherBase() {}
-void SystemLogsFetcher::Fetch(const SysLogsFetcherCallback& callback) {
+void SystemLogsFetcherBase::Fetch(const SysLogsFetcherCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(callback_.is_null());
DCHECK(!callback.is_null());
callback_ = callback;
for (size_t i = 0; i < data_sources_.size(); ++i) {
- data_sources_[i]->Fetch(base::Bind(&SystemLogsFetcher::AddResponse,
- weak_ptr_factory_.GetWeakPtr()));
+ data_sources_[i]->Fetch(base::Bind(&SystemLogsFetcherBase::AddResponse,
+ AsWeakPtr()));
}
}
-void SystemLogsFetcher::AddResponse(SystemLogsResponse* response) {
+void SystemLogsFetcherBase::AddResponse(SystemLogsResponse* response) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
for (SystemLogsResponse::const_iterator it = response->begin();
diff --git a/chrome/browser/chromeos/system_logs/system_logs_fetcher.h b/chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h
similarity index 68%
rename from chrome/browser/chromeos/system_logs/system_logs_fetcher.h
rename to chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h
index 6bd5412..986b678 100644
--- a/chrome/browser/chromeos/system_logs/system_logs_fetcher.h
+++ b/chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SYSTEM_LOGS_FETCHER_H_
-#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SYSTEM_LOGS_FETCHER_H_
+#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SYSTEM_LOGS_FETCHER_BASE_H_
+#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SYSTEM_LOGS_FETCHER_BASE_H_
#include <map>
#include <string>
@@ -20,12 +20,12 @@
typedef base::Callback<void(SystemLogsResponse* response)>
SysLogsSourceCallback;
-// Callback that the SystemLogsFetcher uses to return data.
+// Callback that the SystemLogsFetcherBase uses to return data.
typedef base::Callback<void(scoped_ptr<SystemLogsResponse> response)>
SysLogsFetcherCallback;
// The SystemLogsSource provides a interface for the data sources that
-// the SystemLogsFetcher class uses to fetch logs and other
+// the SystemLogsFetcherBase class uses to fetch logs and other
// information.
class SystemLogsSource {
public:
@@ -34,13 +34,9 @@
virtual ~SystemLogsSource() {}
};
-// The SystemLogsFetcher creates a list of data sources which must be
-// classes that implement the SystemLogsSource. It's Fetch function
-// receives as a parameter a callback that takes only one parameter
-// SystemLogsResponse that is a map of keys and values.
-// Each data source also returns a SystemLogsResponse. If two data sources
-// return the same key, only the first one will be stored.
-// The class runs on the UI thread.
+// The SystemLogsFetcherBaseBase specifies an interface for LogFetcher classes.
+// Derived LogFetcher classes aggregate the logs from a list of SystemLogSource
+// classes.
//
// EXAMPLE:
// class Example {
@@ -49,17 +45,18 @@
// //do something with the logs
// }
// void GetLogs() {
-// SystemLogsFetcher* fetcher = new SystemLogsFetcher();
+// SystemLogsFetcherBase* fetcher = new SystemLogsFetcherBase();
// fetcher->Fetch(base::Bind(&Example::ProcessLogs, this));
// }
-class SystemLogsFetcher {
+class SystemLogsFetcherBase
+ : public base::SupportsWeakPtr<SystemLogsFetcherBase> {
public:
- SystemLogsFetcher();
- ~SystemLogsFetcher();
+ SystemLogsFetcherBase();
+ ~SystemLogsFetcherBase();
void Fetch(const SysLogsFetcherCallback& callback);
- private:
+ protected:
// Callback passed to all the data sources. It merges the |data| it recieves
// into response_. When all the data sources have responded, it deletes their
// objects and returns the response to the callback_. After this it
@@ -72,12 +69,12 @@
scoped_ptr<SystemLogsResponse> response_; // The actual response data.
size_t num_pending_requests_; // The number of callbacks it should get.
- base::WeakPtrFactory<SystemLogsFetcher> weak_ptr_factory_;
+ private:
- DISALLOW_COPY_AND_ASSIGN(SystemLogsFetcher);
+ DISALLOW_COPY_AND_ASSIGN(SystemLogsFetcherBase);
};
} // namespace chromeos
-#endif // CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SYSTEM_LOGS_FETCHER_H_
+#endif // CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_SYSTEM_LOGS_FETCHER_BASE_H_
diff --git a/chrome/browser/chromeos/system_logs/touch_log_source.h b/chrome/browser/chromeos/system_logs/touch_log_source.h
index d88816b..42465d3 100644
--- a/chrome/browser/chromeos/system_logs/touch_log_source.h
+++ b/chrome/browser/chromeos/system_logs/touch_log_source.h
@@ -5,7 +5,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_TOUCH_LOG_SOURCE_H_
#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_TOUCH_LOG_SOURCE_H_
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
namespace chromeos {
diff --git a/chrome/browser/component_updater/DEPS b/chrome/browser/component_updater/DEPS
index 2c90430..2bac0cf 100644
--- a/chrome/browser/component_updater/DEPS
+++ b/chrome/browser/component_updater/DEPS
@@ -1,4 +1,5 @@
include_rules = [
"+ppapi/shared_impl/ppapi_permissions.h",
+ "+ppapi/thunk",
"+third_party/widevine"
]
diff --git a/chrome/browser/component_updater/component_updater_service.cc b/chrome/browser/component_updater/component_updater_service.cc
index f595ba9..1a6f935 100644
--- a/chrome/browser/component_updater/component_updater_service.cc
+++ b/chrome/browser/component_updater/component_updater_service.cc
@@ -22,7 +22,6 @@
#include "base/strings/stringprintf.h"
#include "base/timer/timer.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/component_updater/component_patcher.h"
#include "chrome/browser/component_updater/component_unpacker.h"
#include "chrome/browser/component_updater/component_updater_ping_manager.h"
@@ -31,7 +30,6 @@
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/extensions/extension.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_service.h"
#include "content/public/browser/utility_process_host.h"
#include "content/public/browser/utility_process_host_client.h"
#include "net/base/escape.h"
@@ -398,11 +396,6 @@
NotifyComponentObservers(ComponentObserver::COMPONENT_UPDATER_STARTED, 0);
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED,
- content::Source<ComponentUpdateService>(this),
- content::NotificationService::NoDetails());
-
timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(config_->InitialDelay()),
this, &CrxUpdateService::ProcessPendingItems);
return kOk;
@@ -439,10 +432,6 @@
if (!step_delay) {
NotifyComponentObservers(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0);
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING,
- content::Source<ComponentUpdateService>(this),
- content::NotificationService::NoDetails());
// Zero is only used for unit tests.
if (0 == delay)
return;
@@ -791,11 +780,6 @@
crx->component.observer->OnEvent(
ComponentObserver::COMPONENT_UPDATE_FOUND, 0);
}
-
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND,
- content::Source<std::string>(&crx->id),
- content::NotificationService::NoDetails());
}
// All the components that are not mentioned in the manifest we
@@ -873,11 +857,6 @@
ComponentObserver::COMPONENT_UPDATE_READY, 0);
}
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_COMPONENT_UPDATE_READY,
- content::Source<std::string>(&context->id),
- content::NotificationService::NoDetails());
-
// Why unretained? See comment at top of file.
BrowserThread::PostDelayedTask(
BrowserThread::FILE,
diff --git a/chrome/browser/component_updater/pepper_flash_component_installer.cc b/chrome/browser/component_updater/pepper_flash_component_installer.cc
index d9ac58c..e463a8e 100644
--- a/chrome/browser/component_updater/pepper_flash_component_installer.cc
+++ b/chrome/browser/component_updater/pepper_flash_component_installer.cc
@@ -25,6 +25,7 @@
#include "base/version.h"
#include "build/build_config.h"
#include "chrome/browser/component_updater/component_updater_service.h"
+#include "chrome/browser/component_updater/ppapi_utils.h"
#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
@@ -32,11 +33,10 @@
#include "chrome/common/pepper_flash.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"
+#include "content/public/common/content_constants.h"
#include "content/public/common/pepper_plugin_info.h"
#include "ppapi/c/private/ppb_pdf.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
-#include "webkit/common/plugins/ppapi/ppapi_utils.h"
-#include "webkit/plugins/plugin_constants.h"
#include "flapper_version.h" // In SHARED_INTERMEDIATE_DIR.
@@ -125,7 +125,7 @@
// Returns true if the Pepper |interface_name| is implemented by this browser.
// It does not check if the interface is proxied.
bool SupportsPepperInterface(const char* interface_name) {
- if (webkit::ppapi::IsSupportedPepperInterface(interface_name))
+ if (IsSupportedPepperInterface(interface_name))
return true;
// The PDF interface is invisible to SupportsInterface() on the browser
// process because it is provided using PpapiInterfaceFactoryManager. We need
@@ -147,22 +147,22 @@
plugin_info->is_internal = false;
plugin_info->is_out_of_process = out_of_process;
plugin_info->path = flash_path;
- plugin_info->name = kFlashPluginName;
+ plugin_info->name = content::kFlashPluginName;
plugin_info->permissions = kPepperFlashPermissions;
// The description is like "Shockwave Flash 10.2 r154".
plugin_info->description = base::StringPrintf("%s %d.%d r%d",
- kFlashPluginName, ver_nums[0], ver_nums[1], ver_nums[2]);
+ content::kFlashPluginName, ver_nums[0], ver_nums[1], ver_nums[2]);
plugin_info->version = flash_version.GetString();
- content::WebPluginMimeType swf_mime_type(kFlashPluginSwfMimeType,
- kFlashPluginSwfExtension,
- kFlashPluginName);
+ content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType,
+ content::kFlashPluginSwfExtension,
+ content::kFlashPluginName);
plugin_info->mime_types.push_back(swf_mime_type);
- content::WebPluginMimeType spl_mime_type(kFlashPluginSplMimeType,
- kFlashPluginSplExtension,
- kFlashPluginName);
+ content::WebPluginMimeType spl_mime_type(content::kFlashPluginSplMimeType,
+ content::kFlashPluginSplExtension,
+ content::kFlashPluginName);
plugin_info->mime_types.push_back(spl_mime_type);
return true;
}
diff --git a/webkit/common/plugins/ppapi/ppapi_utils.cc b/chrome/browser/component_updater/ppapi_utils.cc
similarity index 97%
rename from webkit/common/plugins/ppapi/ppapi_utils.cc
rename to chrome/browser/component_updater/ppapi_utils.cc
index 619b03d..1de518c 100644
--- a/webkit/common/plugins/ppapi/ppapi_utils.cc
+++ b/chrome/browser/component_updater/ppapi_utils.cc
@@ -1,7 +1,7 @@
// 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 "webkit/common/plugins/ppapi/ppapi_utils.h"
+#include "chrome/browser/component_updater/ppapi_utils.h"
#include <cstring>
@@ -105,9 +105,6 @@
#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
#include "ppapi/thunk/thunk.h"
-namespace webkit {
-namespace ppapi {
-
bool IsSupportedPepperInterface(const char* name) {
// TODO(brettw) put these in a hash map for better performance.
#define UNPROXIED_IFACE(api_name, iface_str, iface_struct) \
@@ -134,6 +131,3 @@
#undef LEGACY_IFACE
return false;
}
-
-} // namespace ppapi
-} // namespace webkit
diff --git a/chrome/browser/component_updater/ppapi_utils.h b/chrome/browser/component_updater/ppapi_utils.h
new file mode 100644
index 0000000..41100eb
--- /dev/null
+++ b/chrome/browser/component_updater/ppapi_utils.h
@@ -0,0 +1,14 @@
+// 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 CHROME_BROWSER_COMPONENT_UPDATER_PPAPI_UTILS_H_
+#define CHROME_BROWSER_COMPONENT_UPDATER_PPAPI_UTILS_H_
+
+// Returns true if the interface name passed in is supported by the
+// browser.
+bool IsSupportedPepperInterface(const char* name);
+
+#endif // CHROME_BROWSER_COMPONENT_UPDATER_PPAPI_UTILS_H_
+
+
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 82165b6..0f1512f 100644
--- a/chrome/browser/component_updater/test/component_updater_service_unittest.cc
+++ b/chrome/browser/component_updater/test/component_updater_service_unittest.cc
@@ -10,11 +10,9 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
-#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/component_updater/component_updater_service.h"
#include "chrome/browser/component_updater/test/test_installer.h"
#include "chrome/common/chrome_paths.h"
-#include "content/public/browser/notification_service.h"
#include "content/test/net/url_request_prepackaged_interceptor.h"
#include "libxml/globals.h"
#include "net/base/upload_bytes_element_reader.h"
@@ -22,7 +20,6 @@
#include "url/gurl.h"
using content::BrowserThread;
-using content::TestNotificationTracker;
using ::testing::_;
using ::testing::InSequence;
@@ -145,18 +142,6 @@
PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
test_data_dir_ = test_data_dir_.AppendASCII("components");
- // Subscribe to all component updater notifications.
- const int notifications[] = {
- chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED,
- chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING,
- chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND,
- chrome::NOTIFICATION_COMPONENT_UPDATE_READY
- };
-
- for (int ix = 0; ix != arraysize(notifications); ++ix) {
- notification_tracker_.ListenFor(
- notifications[ix], content::NotificationService::AllSources());
- }
net::URLFetcher::SetEnableInterceptionForTests(true);
io_thread_.StartIOThread();
@@ -180,10 +165,6 @@
return test_data_dir_.AppendASCII(file);
}
-TestNotificationTracker& ComponentUpdaterTest::notification_tracker() {
- return notification_tracker_;
-}
-
TestConfigurator* ComponentUpdaterTest::test_configurator() {
return test_config_;
}
@@ -254,18 +235,14 @@
// be created and destroyed with no side effects.
TEST_F(ComponentUpdaterTest, VerifyFixture) {
EXPECT_TRUE(component_updater() != NULL);
- EXPECT_EQ(0ul, notification_tracker().size());
}
// Verify that the component updater can be caught in a quick
-// start-shutdown situation. Failure of this test will be a crash. Also
-// if there is no work to do, there are no notifications generated.
+// start-shutdown situation. Failure of this test will be a crash.
TEST_F(ComponentUpdaterTest, StartStop) {
component_updater()->Start();
message_loop_.RunUntilIdle();
component_updater()->Stop();
-
- EXPECT_EQ(0ul, notification_tracker().size());
}
// Verify that when the server has no updates, we go back to sleep and
@@ -300,20 +277,11 @@
.Times(1);
component_updater()->Start();
- ASSERT_EQ(1ul, notification_tracker().size());
- TestNotificationTracker::Event ev1 = notification_tracker().at(0);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev1.type);
-
EXPECT_CALL(observer,
OnEvent(ComponentObserver::COMPONENT_UPDATER_SLEEPING, 0))
.Times(2);
message_loop_.Run();
- ASSERT_EQ(3ul, notification_tracker().size());
- TestNotificationTracker::Event ev2 = notification_tracker().at(1);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
- TestNotificationTracker::Event ev3 = notification_tracker().at(2);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
EXPECT_EQ(2, interceptor.GetHitCount());
EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
@@ -327,7 +295,6 @@
interceptor.SetResponse(expected_update_url,
test_file("updatecheck_reply_empty"));
- notification_tracker().Reset();
test_configurator()->SetLoopCount(2);
EXPECT_CALL(observer,
@@ -340,13 +307,6 @@
.Times(2);
message_loop_.Run();
- ASSERT_EQ(3ul, notification_tracker().size());
- ev1 = notification_tracker().at(0);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev1.type);
- ev2 = notification_tracker().at(1);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
- ev3 = notification_tracker().at(2);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev2.type);
EXPECT_EQ(4, interceptor.GetHitCount());
EXPECT_EQ(0, static_cast<TestInstaller*>(com.installer)->error());
@@ -356,9 +316,9 @@
}
// Verify that we can check for updates and install one component. Besides
-// the notifications above NOTIFICATION_COMPONENT_UPDATE_FOUND and
-// NOTIFICATION_COMPONENT_UPDATE_READY should have been fired. We do two loops
-// so the second time around there should be nothing left to do.
+// the notifications above COMPONENT_UPDATE_FOUND and COMPONENT_UPDATE_READY
+// should have been fired. We do two loops so the second time around there
+// should be nothing left to do.
// We also check that only 3 non-ping network requests are issued:
// 1- manifest check
// 2- download crx
@@ -442,23 +402,6 @@
EXPECT_EQ(1, ping_checker.NumHits());
EXPECT_EQ(0, ping_checker.NumMisses());
- ASSERT_EQ(5ul, notification_tracker().size());
-
- TestNotificationTracker::Event ev0 = notification_tracker().at(0);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
-
- TestNotificationTracker::Event ev1 = notification_tracker().at(1);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type);
-
- TestNotificationTracker::Event ev2 = notification_tracker().at(2);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type);
-
- TestNotificationTracker::Event ev3 = notification_tracker().at(3);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type);
-
- TestNotificationTracker::Event ev4 = notification_tracker().at(4);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type);
-
component_updater()->Stop();
}
@@ -587,23 +530,6 @@
EXPECT_EQ(3, interceptor.GetHitCount());
- ASSERT_EQ(5ul, notification_tracker().size());
-
- TestNotificationTracker::Event ev0= notification_tracker().at(0);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
-
- TestNotificationTracker::Event ev1 = notification_tracker().at(1);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type);
-
- TestNotificationTracker::Event ev2 = notification_tracker().at(2);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev2.type);
-
- TestNotificationTracker::Event ev3 = notification_tracker().at(3);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev3.type);
-
- TestNotificationTracker::Event ev4 = notification_tracker().at(4);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type);
-
// Also check what happens if previous check too soon.
test_configurator()->SetOnDemandTime(60 * 60);
EXPECT_EQ(ComponentUpdateService::kError,
@@ -643,7 +569,6 @@
// No update: error from no server response
interceptor.SetResponse(expected_update_url_3,
test_file("updatecheck_reply_empty"));
- notification_tracker().Reset();
test_configurator()->SetLoopCount(1);
component_updater()->Start();
EXPECT_EQ(ComponentUpdateService::kOk,
@@ -651,11 +576,6 @@
message_loop_.Run();
- ASSERT_EQ(2ul, notification_tracker().size());
- ev0 = notification_tracker().at(0);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
- ev1 = notification_tracker().at(1);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type);
component_updater()->Stop();
// No update: already updated to 1.0 so nothing new
@@ -682,7 +602,6 @@
interceptor.SetResponse(expected_update_url_3,
test_file("updatecheck_reply_1.xml"));
- notification_tracker().Reset();
test_configurator()->SetLoopCount(1);
component_updater()->Start();
EXPECT_EQ(ComponentUpdateService::kOk,
@@ -692,11 +611,7 @@
EXPECT_EQ(1, ping_checker.NumHits());
EXPECT_EQ(0, ping_checker.NumMisses());
- ASSERT_EQ(2ul, notification_tracker().size());
- ev0 = notification_tracker().at(0);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
- ev1 = notification_tracker().at(1);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type);
+
component_updater()->Stop();
}
@@ -790,23 +705,6 @@
EXPECT_EQ(0, ping_checker.NumMisses());
EXPECT_EQ(3, interceptor.GetHitCount());
- ASSERT_EQ(5ul, notification_tracker().size());
-
- TestNotificationTracker::Event ev0 = notification_tracker().at(0);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
-
- TestNotificationTracker::Event ev1 = notification_tracker().at(1);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type);
-
- TestNotificationTracker::Event ev2 = notification_tracker().at(2);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type);
-
- TestNotificationTracker::Event ev3 = notification_tracker().at(3);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type);
-
- TestNotificationTracker::Event ev4 = notification_tracker().at(4);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type);
-
component_updater()->Stop();
// Now re-register, pretending to be an even newer version (2.2)
@@ -849,21 +747,11 @@
interceptor.SetResponse(expected_update_url_3,
test_file("updatecheck_reply_1.xml"));
- notification_tracker().Reset();
-
// Loop once just to notice the check happening with the re-register version.
test_configurator()->SetLoopCount(1);
component_updater()->Start();
message_loop_.Run();
- ASSERT_EQ(2ul, notification_tracker().size());
-
- ev0 = notification_tracker().at(0);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
-
- ev1 = notification_tracker().at(1);
- EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type);
-
EXPECT_EQ(4, interceptor.GetHitCount());
// We created a new installer, so the counts go back to 0.
@@ -954,7 +842,6 @@
// There should be one ping for the first attempted update.
TEST_F(ComponentUpdaterTest, DifferentialUpdateFails) {
-
std::map<std::string, std::string> map;
map.insert(std::pair<std::string, std::string>("eventtype", "\"3\""));
map.insert(std::pair<std::string, std::string>("eventresult", "\"1\""));
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 4169c0a..752b17b 100644
--- a/chrome/browser/component_updater/test/component_updater_service_unittest.h
+++ b/chrome/browser/component_updater/test/component_updater_service_unittest.h
@@ -19,7 +19,6 @@
#include "chrome/browser/component_updater/test/component_patcher_mock.h"
#include "chrome/browser/component_updater/test/url_request_post_interceptor.h"
#include "content/public/test/test_browser_thread.h"
-#include "content/public/test/test_notification_tracker.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -119,8 +118,6 @@
// Makes the full path to a component updater test file.
const base::FilePath test_file(const char* file);
- content::TestNotificationTracker& notification_tracker();
-
TestConfigurator* test_configurator();
ComponentUpdateService::Status RegisterComponent(CrxComponent* com,
@@ -133,7 +130,6 @@
private:
TestConfigurator* test_config_;
base::FilePath test_data_dir_;
- content::TestNotificationTracker notification_tracker_;
content::TestBrowserThread ui_thread_;
content::TestBrowserThread file_thread_;
content::TestBrowserThread io_thread_;
diff --git a/chrome/browser/content_settings/tab_specific_content_settings.cc b/chrome/browser/content_settings/tab_specific_content_settings.cc
index f16589e..d8e4278 100644
--- a/chrome/browser/content_settings/tab_specific_content_settings.cc
+++ b/chrome/browser/content_settings/tab_specific_content_settings.cc
@@ -502,17 +502,13 @@
void TabSpecificContentSettings::OnMIDISysExAccessed(
const GURL& requesting_origin) {
midi_usages_state_.OnPermissionSet(requesting_origin, true);
- // TODO(toyoshim): Bubble icon for MIDI is disabled for now.
- // http://crbug.com/257618
- // OnContentAllowed(CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
+ OnContentAllowed(CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
}
void TabSpecificContentSettings::OnMIDISysExAccessBlocked(
const GURL& requesting_origin) {
midi_usages_state_.OnPermissionSet(requesting_origin, false);
- // TODO(toyoshim): Bubble icon for MIDI is disabled for now.
- // http://crbug.com/257618
- // OnContentBlocked(CONTENT_SETTINGS_TYPE_MIDI_SYSEX, std::string());
+ OnContentBlocked(CONTENT_SETTINGS_TYPE_MIDI_SYSEX, std::string());
}
void TabSpecificContentSettings::ClearBlockedContentSettingsExceptForCookies() {
diff --git a/chrome/browser/devtools/adb/android_usb_device.cc b/chrome/browser/devtools/adb/android_usb_device.cc
index ce58cd9..82af86a 100644
--- a/chrome/browser/devtools/adb/android_usb_device.cc
+++ b/chrome/browser/devtools/adb/android_usb_device.cc
@@ -9,10 +9,12 @@
#include "base/base64.h"
#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
+#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/devtools/adb/android_rsa.h"
#include "chrome/browser/devtools/adb/android_usb_socket.h"
+#include "chrome/browser/usb/usb_device.h"
#include "chrome/browser/usb/usb_interface.h"
#include "chrome/browser/usb/usb_service.h"
#include "content/public/browser/browser_thread.h"
@@ -38,7 +40,7 @@
using content::BrowserThread;
-typedef std::vector<scoped_refptr<UsbDeviceHandle> > UsbDevices;
+typedef std::vector<scoped_refptr<UsbDevice> > UsbDevices;
base::LazyInstance<AndroidUsbDevices>::Leaky g_devices =
LAZY_INSTANCE_INITIALIZER;
@@ -151,20 +153,20 @@
AndroidUsbDevices& devices = g_devices.Get();
UsbDevices usb_devices;
- service->EnumerateDevices(&usb_devices);
+ service->GetDevices(&usb_devices);
// GC Android devices with no actual usb device.
AndroidUsbDevices::iterator it = devices.begin();
- std::set<UsbDeviceHandle*> claimed_devices;
+ std::set<UsbDevice*> claimed_devices;
while (it != devices.end()) {
bool found_device = false;
for (UsbDevices::iterator it2 = usb_devices.begin();
it2 != usb_devices.end() && !found_device; ++it2) {
- UsbDeviceHandle* usb_device = it2->get();
+ UsbDevice* usb_device = it2->get();
AndroidUsbDevice* device = it->get();
- if (usb_device == device->usb_device()) {
+ if (usb_device == device->usb_device()->device()) {
found_device = true;
- claimed_devices.insert(*it2);
+ claimed_devices.insert(usb_device);
}
}
@@ -177,13 +179,18 @@
// Add new devices.
for (UsbDevices::iterator it = usb_devices.begin(); it != usb_devices.end();
++it) {
- scoped_refptr<UsbDeviceHandle> usb_device = *it;
- if (claimed_devices.find(usb_device.get()) != claimed_devices.end())
+ if (ContainsKey(claimed_devices, it->get()))
continue;
+
scoped_refptr<UsbConfigDescriptor> config = new UsbConfigDescriptor();
- bool success = usb_device->ListInterfaces(config.get());
+ bool success = (*it)->ListInterfaces(config.get());
if (!success)
continue;
+
+ scoped_refptr<UsbDeviceHandle> usb_device = (*it)->Open();
+ if (!usb_device)
+ continue;
+
for (size_t j = 0; j < config->GetNumInterfaces(); ++j) {
scoped_refptr<AndroidUsbDevice> device =
ClaimInterface(rsa_key, usb_device, config->GetInterface(j));
diff --git a/chrome/browser/devtools/devtools_adb_bridge.cc b/chrome/browser/devtools/devtools_adb_bridge.cc
index 2973fa2..da72384 100644
--- a/chrome/browser/devtools/devtools_adb_bridge.cc
+++ b/chrome/browser/devtools/devtools_adb_bridge.cc
@@ -581,9 +581,6 @@
virtual void OnSocketOpened() OVERRIDE {
proxy_.reset(content::DevToolsExternalAgentProxy::Create(this));
- tethering_adb_filter_.reset(new TetheringAdbFilter(
- kAdbPort, serial_, adb_message_loop_, profile_->GetPrefs(),
- web_socket_));
OpenFrontend();
}
@@ -598,7 +595,7 @@
}
virtual bool ProcessIncomingMessage(const std::string& message) OVERRIDE {
- return tethering_adb_filter_->ProcessIncomingMessage(message);
+ return false;
}
const std::string id_;
@@ -608,7 +605,6 @@
Profile* profile_;
scoped_ptr<content::DevToolsExternalAgentProxy> proxy_;
- scoped_ptr<TetheringAdbFilter> tethering_adb_filter_;
scoped_refptr<AdbWebSocket> web_socket_;
DISALLOW_COPY_AND_ASSIGN(AgentHostDelegate);
};
diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc
index ab503e5..3cc06c8 100644
--- a/chrome/browser/devtools/devtools_window.cc
+++ b/chrome/browser/devtools/devtools_window.cc
@@ -63,7 +63,6 @@
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
-using content::BrowserThread;
using content::DevToolsAgentHost;
@@ -249,9 +248,10 @@
DCHECK(it != instances->end());
instances->erase(it);
- IndexingJobsMap::const_iterator jobs_it = indexing_jobs_.begin();
- for (; jobs_it != indexing_jobs_.end(); ++jobs_it)
+ for (IndexingJobsMap::const_iterator jobs_it(indexing_jobs_.begin());
+ jobs_it != indexing_jobs_.end(); ++jobs_it) {
jobs_it->second->Stop();
+ }
indexing_jobs_.clear();
}
@@ -970,32 +970,32 @@
void DevToolsWindow::IndexPath(int request_id,
const std::string& file_system_path) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
CHECK(web_contents_->GetURL().SchemeIs(chrome::kChromeDevToolsScheme));
if (!file_helper_->IsFileSystemAdded(file_system_path)) {
IndexingDone(request_id, file_system_path);
return;
}
- scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob> indexing_job =
- file_system_indexer_->IndexPath(
- file_system_path,
- Bind(&DevToolsWindow::IndexingTotalWorkCalculated,
- weak_factory_.GetWeakPtr(),
- request_id,
- file_system_path),
- Bind(&DevToolsWindow::IndexingWorked,
- weak_factory_.GetWeakPtr(),
- request_id,
- file_system_path),
- Bind(&DevToolsWindow::IndexingDone,
- weak_factory_.GetWeakPtr(),
- request_id,
- file_system_path));
- indexing_jobs_[request_id] = indexing_job;
+ indexing_jobs_[request_id] =
+ scoped_refptr<DevToolsFileSystemIndexer::FileSystemIndexingJob>(
+ file_system_indexer_->IndexPath(
+ file_system_path,
+ Bind(&DevToolsWindow::IndexingTotalWorkCalculated,
+ weak_factory_.GetWeakPtr(),
+ request_id,
+ file_system_path),
+ Bind(&DevToolsWindow::IndexingWorked,
+ weak_factory_.GetWeakPtr(),
+ request_id,
+ file_system_path),
+ Bind(&DevToolsWindow::IndexingDone,
+ weak_factory_.GetWeakPtr(),
+ request_id,
+ file_system_path)));
}
void DevToolsWindow::StopIndexing(int request_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
IndexingJobsMap::iterator it = indexing_jobs_.find(request_id);
if (it == indexing_jobs_.end())
return;
@@ -1006,7 +1006,7 @@
void DevToolsWindow::SearchInPath(int request_id,
const std::string& file_system_path,
const std::string& query) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
CHECK(web_contents_->GetURL().SchemeIs(chrome::kChromeDevToolsScheme));
if (!file_helper_->IsFileSystemAdded(file_system_path)) {
SearchCompleted(request_id, file_system_path, std::vector<std::string>());
@@ -1056,7 +1056,7 @@
int request_id,
const std::string& file_system_path,
int total_work) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
base::FundamentalValue request_id_value(request_id);
StringValue file_system_path_value(file_system_path);
base::FundamentalValue total_work_value(total_work);
@@ -1068,7 +1068,7 @@
void DevToolsWindow::IndexingWorked(int request_id,
const std::string& file_system_path,
int worked) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
base::FundamentalValue request_id_value(request_id);
StringValue file_system_path_value(file_system_path);
base::FundamentalValue worked_value(worked);
@@ -1079,7 +1079,7 @@
void DevToolsWindow::IndexingDone(int request_id,
const std::string& file_system_path) {
indexing_jobs_.erase(request_id);
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
base::FundamentalValue request_id_value(request_id);
StringValue file_system_path_value(file_system_path);
CallClientFunction("InspectorFrontendAPI.indexingDone", &request_id_value,
@@ -1090,10 +1090,10 @@
int request_id,
const std::string& file_system_path,
const std::vector<std::string>& file_paths) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
ListValue file_paths_value;
- std::vector<std::string>::const_iterator it = file_paths.begin();
- for (; it != file_paths.end(); ++it) {
+ for (std::vector<std::string>::const_iterator it(file_paths.begin());
+ it != file_paths.end(); ++it) {
file_paths_value.AppendString(*it);
}
base::FundamentalValue request_id_value(request_id);
diff --git a/chrome/browser/devtools/tethering_adb_filter.cc b/chrome/browser/devtools/tethering_adb_filter.cc
index 887ba94..ce36334 100644
--- a/chrome/browser/devtools/tethering_adb_filter.cc
+++ b/chrome/browser/devtools/tethering_adb_filter.cc
@@ -28,7 +28,6 @@
namespace {
-const int kAdbPort = 5037;
const int kBufferSize = 16 * 1024;
static const char kPortAttribute[] = "port";
@@ -36,7 +35,6 @@
static const char kTetheringAccepted[] = "Tethering.accepted";
static const char kTetheringBind[] = "Tethering.bind";
static const char kTetheringUnbind[] = "Tethering.unbind";
-static const char kLocalAbstractCommand[] = "localabstract:%s";
static const char kDevToolsRemoteSocketName[] = "chrome_devtools_remote";
static const char kDevToolsRemoteBrowserTarget[] = "/devtools/browser";
@@ -194,13 +192,12 @@
} // namespace
-TetheringAdbFilter::TetheringAdbFilter(int adb_port,
- const std::string& serial,
- base::MessageLoop* adb_message_loop,
- PrefService* pref_service,
- scoped_refptr<AdbWebSocket> web_socket)
- : adb_port_(adb_port),
- serial_(serial),
+TetheringAdbFilter::TetheringAdbFilter(
+ scoped_refptr<DevToolsAdbBridge::AndroidDevice> device,
+ base::MessageLoop* adb_message_loop,
+ PrefService* pref_service,
+ scoped_refptr<AdbWebSocket> web_socket)
+ : device_(device),
adb_message_loop_(adb_message_loop),
web_socket_(web_socket),
command_id_(0),
@@ -311,10 +308,7 @@
std::string location = it->second;
SocketTunnel* tunnel = new SocketTunnel(location);
- std::string command = base::StringPrintf(kLocalAbstractCommand,
- connection_id.c_str());
- AdbClientSocket::TransportQuery(
- adb_port_, serial_, command,
+ device_->OpenSocket(connection_id.c_str(),
base::Bind(&SocketTunnel::Start, base::Unretained(tunnel)));
return true;
}
@@ -338,7 +332,7 @@
virtual bool ProcessIncomingMessage(const std::string& message) OVERRIDE;
Registry* registry_;
- const std::string serial_;
+ scoped_refptr<DevToolsAdbBridge::AndroidDevice> device_;
base::MessageLoop* adb_message_loop_;
PrefService* pref_service_;
@@ -352,10 +346,10 @@
base::MessageLoop* adb_message_loop,
PrefService* pref_service)
: registry_(registry),
- serial_(device->serial()),
+ device_(device),
adb_message_loop_(adb_message_loop),
pref_service_(pref_service) {
- (*registry_)[serial_] = this;
+ (*registry_)[device_->serial()] = this;
web_socket_ = new AdbWebSocket(
device, kDevToolsRemoteSocketName, kDevToolsRemoteBrowserTarget,
adb_message_loop_, this);
@@ -370,8 +364,8 @@
PortForwardingController::Connection::~Connection() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (registry_) {
- DCHECK(registry_->find(serial_) != registry_->end());
- registry_->erase(serial_);
+ DCHECK(registry_->find(device_->serial()) != registry_->end());
+ registry_->erase(device_->serial());
}
}
@@ -383,7 +377,7 @@
}
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
tethering_adb_filter_.reset(new TetheringAdbFilter(
- kAdbPort, serial_, adb_message_loop_, pref_service_, web_socket_));
+ device_, adb_message_loop_, pref_service_, web_socket_));
}
void PortForwardingController::Connection::OnFrameRead(
diff --git a/chrome/browser/devtools/tethering_adb_filter.h b/chrome/browser/devtools/tethering_adb_filter.h
index 4267047..11c08b2 100644
--- a/chrome/browser/devtools/tethering_adb_filter.h
+++ b/chrome/browser/devtools/tethering_adb_filter.h
@@ -22,8 +22,7 @@
class TetheringAdbFilter {
public:
- TetheringAdbFilter(int adb_port,
- const std::string& serial,
+ TetheringAdbFilter(scoped_refptr<DevToolsAdbBridge::AndroidDevice> device,
base::MessageLoop* adb_message_loop,
PrefService* pref_service,
scoped_refptr<AdbWebSocket> web_socket);
@@ -44,8 +43,7 @@
void SendCommand(const std::string& method, int port);
- int adb_port_;
- std::string serial_;
+ scoped_refptr<DevToolsAdbBridge::AndroidDevice> device_;
base::MessageLoop* adb_message_loop_;
PrefChangeRegistrar pref_change_registrar_;
scoped_refptr<AdbWebSocket> web_socket_;
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index a810537..aec10bb 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -34,6 +34,7 @@
#include "chrome/browser/platform_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
+#include "chrome/common/chrome_constants.h"
#include "chrome/common/pref_names.h"
#include "components/user_prefs/pref_registry_syncable.h"
#include "content/public/browser/download_item.h"
@@ -402,6 +403,11 @@
callback);
}
+std::string
+ChromeDownloadManagerDelegate::ApplicationClientIdForFileScanning() const {
+ return std::string(chrome::kApplicationClientIDStringForAVScanning);
+}
+
DownloadProtectionService*
ChromeDownloadManagerDelegate::GetDownloadProtectionService() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
diff --git a/chrome/browser/download/chrome_download_manager_delegate.h b/chrome/browser/download/chrome_download_manager_delegate.h
index e2c13ad..d23337d 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.h
+++ b/chrome/browser/download/chrome_download_manager_delegate.h
@@ -93,6 +93,7 @@
virtual void CheckForFileExistence(
content::DownloadItem* download,
const content::CheckForFileExistenceCallback& callback) OVERRIDE;
+ virtual std::string ApplicationClientIdForFileScanning() const OVERRIDE;
DownloadPrefs* download_prefs() { return download_prefs_.get(); }
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc
index c065b85..1bacb68 100644
--- a/chrome/browser/download/download_browsertest.cc
+++ b/chrome/browser/download/download_browsertest.cc
@@ -15,6 +15,7 @@
#include "base/prefs/pref_service.h"
#include "base/stl_util.h"
#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
@@ -1066,8 +1067,9 @@
// A mock install prompt that simulates the user allowing an install request.
void SetAllowMockInstallPrompt() {
download_crx_util::SetMockInstallPromptForTesting(
- new MockAutoConfirmExtensionInstallPrompt(
- browser()->tab_strip_model()->GetActiveWebContents()));
+ scoped_ptr<ExtensionInstallPrompt>(
+ new MockAutoConfirmExtensionInstallPrompt(
+ browser()->tab_strip_model()->GetActiveWebContents())));
}
// This method:
@@ -1924,7 +1926,7 @@
HistoryServiceFactory::GetForProfile(
browser()->profile(), Profile::IMPLICIT_ACCESS)->FlushForTest(
base::Bind(&base::MessageLoop::Quit,
- base::Unretained(base::MessageLoop::current()->current())));
+ base::Unretained(base::MessageLoop::current()->current())));
content::RunMessageLoop();
}
@@ -1948,9 +1950,17 @@
manager->GetAllDownloads(&downloads);
ASSERT_EQ(1UL, downloads.size());
DownloadItem* item = downloads[0];
- ASSERT_EQ(file.value(), item->GetFullPath().BaseName().value());
- ASSERT_EQ(file.value(), item->GetTargetFilePath().BaseName().value());
- ASSERT_EQ(download_url, item->GetURL());
+ EXPECT_EQ(file.value(), item->GetFullPath().BaseName().value());
+ EXPECT_EQ(file.value(), item->GetTargetFilePath().BaseName().value());
+ EXPECT_EQ(download_url, item->GetURL());
+ // The following are set by download-test1.lib.mock-http-headers.
+ std::string etag = item->GetETag();
+ TrimWhitespaceASCII(etag, TRIM_ALL, &etag);
+ EXPECT_EQ("abracadabra", etag);
+
+ std::string last_modified = item->GetLastModifiedTime();
+ TrimWhitespaceASCII(last_modified, TRIM_ALL, &last_modified);
+ EXPECT_EQ("Mon, 13 Nov 2006 20:31:09 GMT", last_modified);
}
// Test for crbug.com/14505. This tests that chrome:// urls are still functional
@@ -2090,7 +2100,8 @@
// Install a mock install UI that simulates a user denying permission to
// finish the install.
download_crx_util::SetMockInstallPromptForTesting(
- new MockAbortExtensionInstallPrompt());
+ scoped_ptr<ExtensionInstallPrompt>(
+ new MockAbortExtensionInstallPrompt()));
scoped_ptr<content::DownloadTestObserver> observer(
DangerousDownloadWaiter(
diff --git a/chrome/browser/download/download_crx_util.cc b/chrome/browser/download/download_crx_util.cc
index 06e8b18..f6edf37 100644
--- a/chrome/browser/download/download_crx_util.cc
+++ b/chrome/browser/download/download_crx_util.cc
@@ -33,9 +33,9 @@
ExtensionInstallPrompt* mock_install_prompt_for_testing = NULL;
// Called to get an extension install UI object. In tests, will return
-// a mock if the test calls download_util::SetMockInstallUIForTesting()
+// a mock if the test calls download_util::SetMockInstallPromptForTesting()
// to set one.
-ExtensionInstallPrompt* CreateExtensionInstallPrompt(
+scoped_ptr<ExtensionInstallPrompt> CreateExtensionInstallPrompt(
Profile* profile,
const DownloadItem& download_item) {
// Use a mock if one is present. Otherwise, create a real extensions
@@ -43,7 +43,7 @@
if (mock_install_prompt_for_testing) {
ExtensionInstallPrompt* result = mock_install_prompt_for_testing;
mock_install_prompt_for_testing = NULL;
- return result;
+ return scoped_ptr<ExtensionInstallPrompt>(result);
} else {
content::WebContents* web_contents = download_item.GetWebContents();
if (!web_contents) {
@@ -55,7 +55,8 @@
profile, active_desktop));
web_contents = browser->tab_strip_model()->GetActiveWebContents();
}
- return new ExtensionInstallPrompt(web_contents);
+ return scoped_ptr<ExtensionInstallPrompt>(
+ new ExtensionInstallPrompt(web_contents));
}
}
@@ -63,8 +64,9 @@
// Tests can call this method to inject a mock ExtensionInstallPrompt
// to be used to confirm permissions on a downloaded CRX.
-void SetMockInstallPromptForTesting(ExtensionInstallPrompt* mock_prompt) {
- mock_install_prompt_for_testing = mock_prompt;
+void SetMockInstallPromptForTesting(
+ scoped_ptr<ExtensionInstallPrompt> mock_prompt) {
+ mock_install_prompt_for_testing = mock_prompt.release();
}
scoped_refptr<extensions::CrxInstaller> OpenChromeExtension(
diff --git a/chrome/browser/download/download_crx_util.h b/chrome/browser/download/download_crx_util.h
index ac9b36c..1807a59 100644
--- a/chrome/browser/download/download_crx_util.h
+++ b/chrome/browser/download/download_crx_util.h
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
class ExtensionInstallPrompt;
class Profile;
@@ -25,11 +26,9 @@
namespace download_crx_util {
// Allow tests to install a mock ExtensionInstallPrompt object, to fake
-// user clicks on the permissions dialog. Each installed mock object
-// is only used once. If you want to return a mock for two different
-// installs, you need to call this function once before the first
-// install, and again after the first install and before the second.
-void SetMockInstallPromptForTesting(ExtensionInstallPrompt* mock_prompt);
+// user clicks on the permissions dialog.
+void SetMockInstallPromptForTesting(
+ scoped_ptr<ExtensionInstallPrompt> mock_prompt);
// Start installing a downloaded item item as a CRX (extension, theme, app,
// ...). The installer does work on the file thread, so the installation
diff --git a/chrome/browser/download/download_crx_util_android.cc b/chrome/browser/download/download_crx_util_android.cc
index 6bdba5b..4b068a8 100644
--- a/chrome/browser/download/download_crx_util_android.cc
+++ b/chrome/browser/download/download_crx_util_android.cc
@@ -23,7 +23,7 @@
const DownloadItem& download_item) {
NOTIMPLEMENTED() << "CrxInstaller not implemented on Android";
scoped_refptr<extensions::CrxInstaller> installer(
- extensions::CrxInstaller::Create(NULL, NULL));
+ extensions::CrxInstaller::CreateSilent(NULL));
return installer;
}
diff --git a/chrome/browser/download/download_danger_prompt.cc b/chrome/browser/download/download_danger_prompt.cc
index fc0948d..d795b71 100644
--- a/chrome/browser/download/download_danger_prompt.cc
+++ b/chrome/browser/download/download_danger_prompt.cc
@@ -5,8 +5,10 @@
#include "chrome/browser/download/download_danger_prompt.h"
#include "base/bind.h"
+#include "base/metrics/field_trial.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/download/chrome_download_manager_delegate.h"
+#include "chrome/browser/download/download_util.h"
#include "chrome/browser/ui/tab_modal_confirm_dialog.h"
#include "chrome/browser/ui/tab_modal_confirm_dialog_delegate.h"
#include "content/public/browser/download_danger_type.h"
@@ -103,29 +105,41 @@
return l10n_util::GetStringUTF16(
IDS_PROMPT_CONFIRM_KEEP_DANGEROUS_DOWNLOAD);
switch (download_->GetDangerType()) {
- case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
+ case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: {
return l10n_util::GetStringFUTF16(
IDS_PROMPT_DANGEROUS_DOWNLOAD,
download_->GetFileNameToReportUser().LossyDisplayName());
+ }
case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: // Fall through
case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
- case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
- return l10n_util::GetStringFUTF16(
- IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
+ case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
+ std::string trial_condition =
+ base::FieldTrialList::FindFullName(download_util::kFinchTrialName);
+ if (trial_condition.empty()) {
+ return l10n_util::GetStringFUTF16(
+ IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
+ download_->GetFileNameToReportUser().LossyDisplayName());
+ }
+ return download_util::AssembleMalwareFinchString(
+ trial_condition,
download_->GetFileNameToReportUser().LossyDisplayName());
- case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
+ }
+ case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: {
return l10n_util::GetStringFUTF16(
IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
download_->GetFileNameToReportUser().LossyDisplayName());
- case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
+ }
+ case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
return l10n_util::GetStringFUTF16(
IDS_PROMPT_DOWNLOAD_CHANGES_SEARCH_SETTINGS,
download_->GetFileNameToReportUser().LossyDisplayName());
+ }
case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
- case content::DOWNLOAD_DANGER_TYPE_MAX:
+ case content::DOWNLOAD_DANGER_TYPE_MAX: {
break;
+ }
}
NOTREACHED();
return string16();
diff --git a/chrome/browser/download/download_extensions.cc b/chrome/browser/download/download_extensions.cc
index b8041b5..630d296 100644
--- a/chrome/browser/download/download_extensions.cc
+++ b/chrome/browser/download/download_extensions.cc
@@ -66,6 +66,8 @@
{ "class", DANGEROUS },
{ "jar", DANGEROUS },
{ "jnlp", DANGEROUS },
+#endif
+#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
// Relating to PDF.
{ "pdf", ALLOW_ON_USER_GESTURE },
{ "pdfxml", ALLOW_ON_USER_GESTURE },
@@ -77,6 +79,7 @@
// Relating to scripting languages.
{ "pl", ALLOW_ON_USER_GESTURE },
{ "py", ALLOW_ON_USER_GESTURE },
+ { "pyc", ALLOW_ON_USER_GESTURE },
{ "pyw", ALLOW_ON_USER_GESTURE },
{ "rb", ALLOW_ON_USER_GESTURE },
#endif
diff --git a/chrome/browser/download/download_history.cc b/chrome/browser/download/download_history.cc
index acda0ed..ea2f2e1 100644
--- a/chrome/browser/download/download_history.cc
+++ b/chrome/browser/download/download_history.cc
@@ -116,6 +116,8 @@
item->GetReferrerUrl(),
item->GetStartTime(),
item->GetEndTime(),
+ item->GetETag(),
+ item->GetLastModifiedTime(),
item->GetReceivedBytes(),
item->GetTotalBytes(),
item->GetState(),
@@ -136,6 +138,8 @@
(previous->end_time != current.end_time) ||
(previous->received_bytes != current.received_bytes) ||
(previous->total_bytes != current.total_bytes) ||
+ (previous->etag != current.etag) ||
+ (previous->last_modified != current.last_modified) ||
(previous->state != current.state) ||
(previous->danger_type != current.danger_type) ||
(previous->interrupt_reason != current.interrupt_reason) ||
@@ -233,6 +237,8 @@
it->referrer_url,
it->start_time,
it->end_time,
+ it->etag,
+ it->last_modified,
it->received_bytes,
it->total_bytes,
it->state,
diff --git a/chrome/browser/download/download_history_unittest.cc b/chrome/browser/download/download_history_unittest.cc
index 8ec764b..93fdb73 100644
--- a/chrome/browser/download/download_history_unittest.cc
+++ b/chrome/browser/download/download_history_unittest.cc
@@ -17,10 +17,14 @@
#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if !defined(OS_ANDROID)
+#include "chrome/browser/extensions/api/downloads/downloads_api.h"
+#endif
+
using testing::DoAll;
using testing::Invoke;
using testing::Return;
-using testing::ReturnRef;
+using testing::ReturnRefOfCopy;
using testing::SetArgPointee;
using testing::WithArg;
using testing::_;
@@ -40,17 +44,21 @@
EXPECT_EQ(left.referrer_url.spec(), right.referrer_url.spec());
EXPECT_EQ(left.start_time.ToTimeT(), right.start_time.ToTimeT());
EXPECT_EQ(left.end_time.ToTimeT(), right.end_time.ToTimeT());
+ EXPECT_EQ(left.etag, right.etag);
+ EXPECT_EQ(left.last_modified, right.last_modified);
EXPECT_EQ(left.received_bytes, right.received_bytes);
EXPECT_EQ(left.total_bytes, right.total_bytes);
EXPECT_EQ(left.state, right.state);
EXPECT_EQ(left.danger_type, right.danger_type);
EXPECT_EQ(left.id, right.id);
EXPECT_EQ(left.opened, right.opened);
+ EXPECT_EQ(left.by_ext_id, right.by_ext_id);
+ EXPECT_EQ(left.by_ext_name, right.by_ext_name);
}
typedef DownloadHistory::IdSet IdSet;
typedef std::vector<history::DownloadRow> InfoVector;
-typedef testing::NiceMock<content::MockDownloadItem> NiceMockDownloadItem;
+typedef testing::StrictMock<content::MockDownloadItem> StrictMockDownloadItem;
class FakeHistoryAdapter : public DownloadHistory::HistoryAdapter {
public:
@@ -243,6 +251,8 @@
infos->at(index).referrer_url,
infos->at(index).start_time,
infos->at(index).end_time,
+ infos->at(index).etag,
+ infos->at(index).last_modified,
infos->at(index).received_bytes,
infos->at(index).total_bytes,
infos->at(index).state,
@@ -323,9 +333,34 @@
history_->ExpectDownloadsRemoved(ids);
}
- // Caller is responsibile for making sure reference arguments lifetime is
- // greater than the lifetime of the NiceMockDownloadItem() created by this
- // routine.
+ void InitBasicItem(const base::FilePath::CharType* path,
+ const char* url_string,
+ const char* referrer_string,
+ history::DownloadRow* info) {
+ GURL url(url_string);
+ GURL referrer(referrer_string);
+ std::vector<GURL> url_chain;
+ url_chain.push_back(url);
+ InitItem(static_cast<uint32>(items_.size() + 1),
+ base::FilePath(path),
+ base::FilePath(path),
+ url_chain,
+ referrer,
+ (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
+ (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
+ "Etag",
+ "abc",
+ 100,
+ 100,
+ content::DownloadItem::COMPLETE,
+ content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ content::DOWNLOAD_INTERRUPT_REASON_NONE,
+ false,
+ std::string(),
+ std::string(),
+ info);
+ }
+
void InitItem(
uint32 id,
const base::FilePath& current_path,
@@ -334,16 +369,21 @@
const GURL& referrer,
const base::Time& start_time,
const base::Time& end_time,
+ const std::string& etag,
+ const std::string& last_modified,
int64 received_bytes,
int64 total_bytes,
content::DownloadItem::DownloadState state,
content::DownloadDangerType danger_type,
content::DownloadInterruptReason interrupt_reason,
bool opened,
+ const std::string& by_extension_id,
+ const std::string& by_extension_name,
history::DownloadRow* info) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
size_t index = items_.size();
- NiceMockDownloadItem* mock_item = new NiceMockDownloadItem();
+ StrictMockDownloadItem* mock_item = new StrictMockDownloadItem();
items_.push_back(mock_item);
info->current_path = current_path;
@@ -352,6 +392,8 @@
info->referrer_url = referrer;
info->start_time = start_time;
info->end_time = end_time;
+ info->etag = etag;
+ info->last_modified = last_modified;
info->received_bytes = received_bytes;
info->total_bytes = total_bytes;
info->state = state;
@@ -359,52 +401,64 @@
info->interrupt_reason = interrupt_reason;
info->id = id;
info->opened = opened;
+ info->by_ext_id = by_extension_id;
+ info->by_ext_name = by_extension_name;
EXPECT_CALL(item(index), GetId()).WillRepeatedly(Return(id));
- EXPECT_CALL(item(index),
- GetFullPath()).WillRepeatedly(ReturnRef(current_path));
- EXPECT_CALL(item(index),
- GetTargetFilePath()).WillRepeatedly(ReturnRef(target_path));
+ EXPECT_CALL(item(index), GetFullPath())
+ .WillRepeatedly(ReturnRefOfCopy(current_path));
+ EXPECT_CALL(item(index), GetTargetFilePath())
+ .WillRepeatedly(ReturnRefOfCopy(target_path));
DCHECK_LE(1u, url_chain.size());
- EXPECT_CALL(item(index), GetURL()).WillRepeatedly(ReturnRef(url_chain[0]));
- EXPECT_CALL(item(index),
- GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
- EXPECT_CALL(item(index), GetMimeType()).WillRepeatedly(Return(
- "application/octet-stream"));
- EXPECT_CALL(item(index), GetReferrerUrl()).WillRepeatedly(ReturnRef(
- referrer));
+ EXPECT_CALL(item(index), GetURL())
+ .WillRepeatedly(ReturnRefOfCopy(url_chain[0]));
+ EXPECT_CALL(item(index), GetUrlChain())
+ .WillRepeatedly(ReturnRefOfCopy(url_chain));
+ EXPECT_CALL(item(index), GetMimeType())
+ .WillRepeatedly(Return("application/octet-stream"));
+ EXPECT_CALL(item(index), GetReferrerUrl())
+ .WillRepeatedly(ReturnRefOfCopy(referrer));
EXPECT_CALL(item(index), GetStartTime()).WillRepeatedly(Return(start_time));
EXPECT_CALL(item(index), GetEndTime()).WillRepeatedly(Return(end_time));
+ EXPECT_CALL(item(index), GetETag()).WillRepeatedly(ReturnRefOfCopy(etag));
+ EXPECT_CALL(item(index), GetLastModifiedTime())
+ .WillRepeatedly(ReturnRefOfCopy(last_modified));
EXPECT_CALL(item(index), GetReceivedBytes())
.WillRepeatedly(Return(received_bytes));
- EXPECT_CALL(item(index), GetTotalBytes()).WillRepeatedly(Return(
- total_bytes));
+ EXPECT_CALL(item(index), GetTotalBytes())
+ .WillRepeatedly(Return(total_bytes));
EXPECT_CALL(item(index), GetState()).WillRepeatedly(Return(state));
EXPECT_CALL(item(index), GetDangerType())
.WillRepeatedly(Return(danger_type));
- EXPECT_CALL(item(index), GetLastReason()).WillRepeatedly(
- Return(interrupt_reason));
+ EXPECT_CALL(item(index), GetLastReason())
+ .WillRepeatedly(Return(interrupt_reason));
EXPECT_CALL(item(index), GetOpened()).WillRepeatedly(Return(opened));
- EXPECT_CALL(item(index), GetTargetDisposition()).WillRepeatedly(Return(
- content::DownloadItem::TARGET_DISPOSITION_OVERWRITE));
+ EXPECT_CALL(item(index), GetTargetDisposition())
+ .WillRepeatedly(
+ Return(content::DownloadItem::TARGET_DISPOSITION_OVERWRITE));
EXPECT_CALL(manager(), GetDownload(id))
.WillRepeatedly(Return(&item(index)));
- EXPECT_CALL(item(index), AddObserver(_)).WillOnce(WithArg<0>(Invoke(
- this, &DownloadHistoryTest::SetItemObserver)));
+ EXPECT_CALL(item(index), AddObserver(_))
+ .WillOnce(WithArg<0>(
+ Invoke(this, &DownloadHistoryTest::SetItemObserver)));
EXPECT_CALL(item(index), RemoveObserver(_));
+ EXPECT_CALL(item(index), IsTemporary()).WillRepeatedly(Return(false));
+#if !defined(OS_ANDROID)
+ new DownloadedByExtension(&item(index), by_extension_id, by_extension_name);
+#endif
std::vector<content::DownloadItem*> items;
for (size_t i = 0; i < items_.size(); ++i) {
items.push_back(&item(i));
}
EXPECT_CALL(*manager_.get(), GetAllDownloads(_))
- .WillRepeatedly(SetArgPointee<0>(items));
+ .WillRepeatedly(SetArgPointee<0>(items));
}
private:
base::MessageLoopForUI loop_;
content::TestBrowserThread ui_thread_;
- std::vector<NiceMockDownloadItem*> items_;
+ std::vector<StrictMockDownloadItem*> items_;
scoped_ptr<content::MockDownloadManager> manager_;
FakeHistoryAdapter* history_;
scoped_ptr<DownloadHistory> download_history_;
@@ -423,25 +477,10 @@
// Load a download from history, create the item, OnDownloadCreated,
// OnDownloadUpdated, OnDownloadRemoved.
history::DownloadRow info;
- base::FilePath path(FILE_PATH_LITERAL("/foo/bar.pdf"));
- GURL url("http://example.com/bar.pdf");
- GURL referrer("http://example.com/referrer.html");
- std::vector<GURL> url_chain;
- url_chain.push_back(url);
- InitItem(base::RandInt(0, 1 << 20),
- path,
- path,
- url_chain,
- referrer,
- (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
- (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
- 100,
- 100,
- content::DownloadItem::COMPLETE,
- content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
- content::DOWNLOAD_INTERRUPT_REASON_NONE,
- false,
- &info);
+ InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+ "http://example.com/bar.pdf",
+ "http://example.com/referrer.html",
+ &info);
{
scoped_ptr<InfoVector> infos(new InfoVector());
infos->push_back(info);
@@ -471,25 +510,10 @@
ExpectWillQueryDownloads(scoped_ptr<InfoVector>(new InfoVector()));
history::DownloadRow info;
- base::FilePath path(FILE_PATH_LITERAL("/foo/bar.pdf"));
- GURL url("http://example.com/bar.pdf");
- GURL referrer("http://example.com/referrer.html");
- std::vector<GURL> url_chain;
- url_chain.push_back(url);
- InitItem(base::RandInt(0, 1 << 20),
- path,
- path,
- url_chain,
- referrer,
- (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
- (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
- 100,
- 100,
- content::DownloadItem::COMPLETE,
- content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
- content::DOWNLOAD_INTERRUPT_REASON_NONE,
- false,
- &info);
+ InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+ "http://example.com/bar.pdf",
+ "http://example.com/referrer.html",
+ &info);
// Pretend the manager just created |item|.
CallOnDownloadCreated(0);
@@ -509,6 +533,97 @@
ExpectDownloadsRemoved(ids);
}
+// Test that changes to persisted fields in a DownloadItem triggers database
+// updates.
+TEST_F(DownloadHistoryTest, DownloadHistoryTest_Update) {
+ ExpectWillQueryDownloads(scoped_ptr<InfoVector>(new InfoVector()));
+
+ history::DownloadRow info;
+ InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+ "http://example.com/bar.pdf",
+ "http://example.com/referrer.html",
+ &info);
+ CallOnDownloadCreated(0);
+ ExpectDownloadCreated(info);
+ EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
+
+ base::FilePath new_path(FILE_PATH_LITERAL("/foo/baz.txt"));
+ base::Time new_time(base::Time::Now());
+ std::string new_etag("new etag");
+ std::string new_last_modifed("new last modified");
+
+ // current_path
+ EXPECT_CALL(item(0), GetFullPath()).WillRepeatedly(ReturnRefOfCopy(new_path));
+ info.current_path = new_path;
+ item_observer()->OnDownloadUpdated(&item(0));
+ ExpectDownloadUpdated(info);
+
+ // target_path
+ EXPECT_CALL(item(0), GetTargetFilePath())
+ .WillRepeatedly(ReturnRefOfCopy(new_path));
+ info.target_path = new_path;
+ item_observer()->OnDownloadUpdated(&item(0));
+ ExpectDownloadUpdated(info);
+
+ // end_time
+ EXPECT_CALL(item(0), GetEndTime()).WillRepeatedly(Return(new_time));
+ info.end_time = new_time;
+ item_observer()->OnDownloadUpdated(&item(0));
+ ExpectDownloadUpdated(info);
+
+ // received_bytes
+ EXPECT_CALL(item(0), GetReceivedBytes()).WillRepeatedly(Return(101));
+ info.received_bytes = 101;
+ item_observer()->OnDownloadUpdated(&item(0));
+ ExpectDownloadUpdated(info);
+
+ // total_bytes
+ EXPECT_CALL(item(0), GetTotalBytes()).WillRepeatedly(Return(102));
+ info.total_bytes = 102;
+ item_observer()->OnDownloadUpdated(&item(0));
+ ExpectDownloadUpdated(info);
+
+ // etag
+ EXPECT_CALL(item(0), GetETag()).WillRepeatedly(ReturnRefOfCopy(new_etag));
+ info.etag = new_etag;
+ item_observer()->OnDownloadUpdated(&item(0));
+ ExpectDownloadUpdated(info);
+
+ // last_modified
+ EXPECT_CALL(item(0), GetLastModifiedTime())
+ .WillRepeatedly(ReturnRefOfCopy(new_last_modifed));
+ info.last_modified = new_last_modifed;
+ item_observer()->OnDownloadUpdated(&item(0));
+ ExpectDownloadUpdated(info);
+
+ // state
+ EXPECT_CALL(item(0), GetState())
+ .WillRepeatedly(Return(content::DownloadItem::INTERRUPTED));
+ info.state = content::DownloadItem::INTERRUPTED;
+ item_observer()->OnDownloadUpdated(&item(0));
+ ExpectDownloadUpdated(info);
+
+ // danger_type
+ EXPECT_CALL(item(0), GetDangerType())
+ .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT));
+ info.danger_type = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT;
+ item_observer()->OnDownloadUpdated(&item(0));
+ ExpectDownloadUpdated(info);
+
+ // interrupt_reason
+ EXPECT_CALL(item(0), GetLastReason())
+ .WillRepeatedly(Return(content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED));
+ info.interrupt_reason = content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED;
+ item_observer()->OnDownloadUpdated(&item(0));
+ ExpectDownloadUpdated(info);
+
+ // opened
+ EXPECT_CALL(item(0), GetOpened()).WillRepeatedly(Return(true));
+ info.opened = true;
+ item_observer()->OnDownloadUpdated(&item(0));
+ ExpectDownloadUpdated(info);
+}
+
// Test creating a new item, saving it, removing it by setting it Temporary,
// changing it without saving it back because it's Temporary, clearing
// IsTemporary, saving it back, changing it, saving it back because it isn't
@@ -519,25 +634,10 @@
ExpectWillQueryDownloads(scoped_ptr<InfoVector>(new InfoVector()));
history::DownloadRow info;
- base::FilePath path(FILE_PATH_LITERAL("/foo/bar.pdf"));
- GURL url("http://example.com/bar.pdf");
- GURL referrer("http://example.com/referrer.html");
- std::vector<GURL> url_chain;
- url_chain.push_back(url);
- InitItem(base::RandInt(0, 1 << 20),
- path,
- path,
- url_chain,
- referrer,
- (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
- (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
- 100,
- 100,
- content::DownloadItem::COMPLETE,
- content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
- content::DOWNLOAD_INTERRUPT_REASON_NONE,
- false,
- &info);
+ InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+ "http://example.com/bar.pdf",
+ "http://example.com/referrer.html",
+ &info);
// Pretend the manager just created |item|.
CallOnDownloadCreated(0);
@@ -573,30 +673,14 @@
}
// Test removing downloads while they're still being added.
-TEST_F(DownloadHistoryTest,
- DownloadHistoryTest_RemoveWhileAdding) {
+TEST_F(DownloadHistoryTest, DownloadHistoryTest_RemoveWhileAdding) {
ExpectWillQueryDownloads(scoped_ptr<InfoVector>(new InfoVector()));
history::DownloadRow info;
- base::FilePath path(FILE_PATH_LITERAL("/foo/bar.pdf"));
- GURL url("http://example.com/bar.pdf");
- GURL referrer("http://example.com/referrer.html");
- std::vector<GURL> url_chain;
- url_chain.push_back(url);
- InitItem(base::RandInt(0, 1 << 20),
- path,
- path,
- url_chain,
- referrer,
- (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
- (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
- 100,
- 100,
- content::DownloadItem::COMPLETE,
- content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
- content::DOWNLOAD_INTERRUPT_REASON_NONE,
- false,
- &info);
+ InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+ "http://example.com/bar.pdf",
+ "http://example.com/referrer.html",
+ &info);
// Instruct CreateDownload() to not callback to DownloadHistory immediately,
// but to wait for FinishCreateDownload().
@@ -631,44 +715,14 @@
// Load a download from history, create the item, OnDownloadCreated,
// OnDownloadUpdated, OnDownloadRemoved.
history::DownloadRow info0, info1;
- base::FilePath path0(FILE_PATH_LITERAL("/foo/bar.pdf"));
- GURL url0("http://example.com/bar.pdf");
- GURL referrer0("http://example.com/referrer.html");
- std::vector<GURL> url0_chain;
- url0_chain.push_back(url0);
- InitItem(base::RandInt(0, 1 << 10),
- path0,
- path0,
- url0_chain,
- referrer0,
- (base::Time::Now() - base::TimeDelta::FromMinutes(11)),
- (base::Time::Now() - base::TimeDelta::FromMinutes(2)),
- 100,
- 100,
- content::DownloadItem::COMPLETE,
- content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
- content::DOWNLOAD_INTERRUPT_REASON_NONE,
- false,
- &info0);
- base::FilePath path1(FILE_PATH_LITERAL("/foo/qux.pdf"));
- GURL url1("http://example.com/qux.pdf");
- GURL referrer1("http://example.com/referrer.html");
- std::vector<GURL> url1_chain;
- url1_chain.push_back(url0);
- InitItem(item(0).GetId() + base::RandInt(1, 1 << 10),
- path1,
- path1,
- url1_chain,
- referrer1,
- (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
- (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
- 200,
- 200,
- content::DownloadItem::COMPLETE,
- content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
- content::DOWNLOAD_INTERRUPT_REASON_NONE,
- false,
- &info1);
+ InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+ "http://example.com/bar.pdf",
+ "http://example.com/referrer.html",
+ &info0);
+ InitBasicItem(FILE_PATH_LITERAL("/foo/qux.pdf"),
+ "http://example.com/qux.pdf",
+ "http://example.com/referrer1.html",
+ &info1);
{
scoped_ptr<InfoVector> infos(new InfoVector());
infos->push_back(info0);
@@ -696,25 +750,10 @@
ExpectWillQueryDownloads(scoped_ptr<InfoVector>(new InfoVector()));
history::DownloadRow info;
- base::FilePath path(FILE_PATH_LITERAL("/foo/bar.pdf"));
- GURL url("http://example.com/bar.pdf");
- GURL referrer("http://example.com/referrer.html");
- std::vector<GURL> url_chain;
- url_chain.push_back(url);
- InitItem(base::RandInt(0, 1 << 20),
- path,
- path,
- url_chain,
- referrer,
- (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
- (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
- 100,
- 100,
- content::DownloadItem::COMPLETE,
- content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
- content::DOWNLOAD_INTERRUPT_REASON_NONE,
- false,
- &info);
+ InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+ "http://example.com/bar.pdf",
+ "http://example.com/referrer.html",
+ &info);
FailCreateDownload();
// Pretend the manager just created |item|.
@@ -729,32 +768,16 @@
EXPECT_TRUE(DownloadHistory::IsPersisted(&item(0)));
}
-TEST_F(DownloadHistoryTest,
- DownloadHistoryTest_UpdateWhileAdding) {
+TEST_F(DownloadHistoryTest, DownloadHistoryTest_UpdateWhileAdding) {
// Create a fresh item not from history, OnDownloadCreated, OnDownloadUpdated,
// OnDownloadRemoved.
ExpectWillQueryDownloads(scoped_ptr<InfoVector>(new InfoVector()));
history::DownloadRow info;
- base::FilePath path(FILE_PATH_LITERAL("/foo/bar.pdf"));
- GURL url("http://example.com/bar.pdf");
- GURL referrer("http://example.com/referrer.html");
- std::vector<GURL> url_chain;
- url_chain.push_back(url);
- InitItem(base::RandInt(0, 1 << 20),
- path,
- path,
- url_chain,
- referrer,
- (base::Time::Now() - base::TimeDelta::FromMinutes(10)),
- (base::Time::Now() - base::TimeDelta::FromMinutes(1)),
- 100,
- 100,
- content::DownloadItem::COMPLETE,
- content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
- content::DOWNLOAD_INTERRUPT_REASON_NONE,
- false,
- &info);
+ InitBasicItem(FILE_PATH_LITERAL("/foo/bar.pdf"),
+ "http://example.com/bar.pdf",
+ "http://example.com/referrer.html",
+ &info);
// Instruct CreateDownload() to not callback to DownloadHistory immediately,
// but to wait for FinishCreateDownload().
diff --git a/chrome/browser/download/download_item_model.cc b/chrome/browser/download/download_item_model.cc
index b1c89fc..83c62f9 100644
--- a/chrome/browser/download/download_item_model.cc
+++ b/chrome/browser/download/download_item_model.cc
@@ -6,12 +6,14 @@
#include "base/i18n/number_formatting.h"
#include "base/i18n/rtl.h"
+#include "base/metrics/field_trial.h"
#include "base/strings/string16.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/supports_user_data.h"
#include "base/time/time.h"
#include "chrome/browser/download/download_crx_util.h"
+#include "chrome/browser/download/download_util.h"
#include "chrome/browser/safe_browsing/download_feedback_service.h"
#include "content/public/browser/download_danger_type.h"
#include "content/public/browser/download_interrupt_reasons.h"
@@ -304,10 +306,15 @@
string16 elided_filename =
ui::ElideFilename(download_->GetFileNameToReportUser(), font, base_width);
switch (download_->GetDangerType()) {
- case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
- return l10n_util::GetStringUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_URL);
-
- case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
+ case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: {
+ std::string trial_condition =
+ base::FieldTrialList::FindFullName(download_util::kFinchTrialName);
+ if (trial_condition.empty())
+ return l10n_util::GetStringUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_URL);
+ return download_util::AssembleMalwareFinchString(trial_condition,
+ elided_filename);
+ }
+ case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: {
if (download_crx_util::IsExtensionDownload(*download_)) {
return l10n_util::GetStringUTF16(
IDS_PROMPT_DANGEROUS_DOWNLOAD_EXTENSION);
@@ -315,25 +322,32 @@
return l10n_util::GetStringFUTF16(IDS_PROMPT_DANGEROUS_DOWNLOAD,
elided_filename);
}
-
+ }
case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
- case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
- return l10n_util::GetStringFUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
- elided_filename);
-
- case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
+ case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: {
+ std::string trial_condition =
+ base::FieldTrialList::FindFullName(download_util::kFinchTrialName);
+ if (trial_condition.empty()) {
+ return l10n_util::GetStringFUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_CONTENT,
+ elided_filename);
+ }
+ return download_util::AssembleMalwareFinchString(trial_condition,
+ elided_filename);
+ }
+ case content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: {
return l10n_util::GetStringFUTF16(IDS_PROMPT_UNCOMMON_DOWNLOAD_CONTENT,
elided_filename);
-
- case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
+ }
+ case content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: {
return l10n_util::GetStringFUTF16(
IDS_PROMPT_DOWNLOAD_CHANGES_SEARCH_SETTINGS, elided_filename);
-
+ }
case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
- case content::DOWNLOAD_DANGER_TYPE_MAX:
+ case content::DOWNLOAD_DANGER_TYPE_MAX: {
break;
+ }
}
NOTREACHED();
return string16();
diff --git a/chrome/browser/download/download_resource_throttle.cc b/chrome/browser/download/download_resource_throttle.cc
index 7b7b162..1fae14d 100644
--- a/chrome/browser/download/download_resource_throttle.cc
+++ b/chrome/browser/download/download_resource_throttle.cc
@@ -5,7 +5,7 @@
#include "chrome/browser/download/download_resource_throttle.h"
#include "base/bind.h"
-#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/download_stats.h"
#include "content/public/browser/resource_controller.h"
DownloadResourceThrottle::DownloadResourceThrottle(
@@ -63,9 +63,9 @@
if (allow) {
// Presumes all downloads initiated by navigation use this throttle and
// nothing else does.
- download_util::RecordDownloadSource(download_util::INITIATED_BY_NAVIGATION);
+ RecordDownloadSource(DOWNLOAD_INITIATED_BY_NAVIGATION);
} else {
- download_util::RecordDownloadCount(download_util::BLOCKED_BY_THROTTLING);
+ RecordDownloadCount(CHROME_DOWNLOAD_COUNT_BLOCKED_BY_THROTTLING);
}
if (request_deferred_) {
diff --git a/chrome/browser/download/download_stats.cc b/chrome/browser/download/download_stats.cc
new file mode 100644
index 0000000..042ac60
--- /dev/null
+++ b/chrome/browser/download/download_stats.cc
@@ -0,0 +1,32 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/download/download_stats.h"
+
+#include "base/metrics/histogram.h"
+
+void RecordDownloadShelfClose(int size, int in_progress, bool autoclose) {
+ static const int kMaxShelfSize = 16;
+ if (autoclose) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Download.ShelfSizeOnAutoClose", size, kMaxShelfSize);
+ UMA_HISTOGRAM_ENUMERATION(
+ "Download.ShelfInProgressSizeOnAutoClose", in_progress, kMaxShelfSize);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Download.ShelfSizeOnUserClose", size, kMaxShelfSize);
+ UMA_HISTOGRAM_ENUMERATION(
+ "Download.ShelfInProgressSizeOnUserClose", in_progress, kMaxShelfSize);
+ }
+}
+
+void RecordDownloadCount(ChromeDownloadCountTypes type) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Download.CountsChrome", type, CHROME_DOWNLOAD_COUNT_TYPES_LAST_ENTRY);
+}
+
+void RecordDownloadSource(ChromeDownloadSource source) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Download.SourcesChrome", source, CHROME_DOWNLOAD_SOURCE_LAST_ENTRY);
+}
diff --git a/chrome/browser/download/download_stats.h b/chrome/browser/download/download_stats.h
new file mode 100644
index 0000000..50d2531
--- /dev/null
+++ b/chrome/browser/download/download_stats.h
@@ -0,0 +1,63 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_STATS_H_
+#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_STATS_H_
+
+// Record the total number of items and the number of in-progress items showing
+// in the shelf when it closes. Set |autoclose| to true when the shelf is
+// closing itself, false when the user explicitly closed it.
+void RecordDownloadShelfClose(int size, int in_progress, bool autoclose);
+
+// Used for counting UMA stats. Similar to content's
+// download_stats::DownloadCountTypes but from the chrome layer.
+enum ChromeDownloadCountTypes {
+ // Stale enum values left around os that values passed to UMA don't
+ // change.
+ CHROME_DOWNLOAD_COUNT_UNUSED_0 = 0,
+ CHROME_DOWNLOAD_COUNT_UNUSED_1,
+ CHROME_DOWNLOAD_COUNT_UNUSED_2,
+ CHROME_DOWNLOAD_COUNT_UNUSED_3,
+
+ // A download *would* have been initiated, but it was blocked
+ // by the DownloadThrottlingResourceHandler.
+ CHROME_DOWNLOAD_COUNT_BLOCKED_BY_THROTTLING,
+
+ CHROME_DOWNLOAD_COUNT_TYPES_LAST_ENTRY
+};
+
+// Used for counting UMA stats. Similar to content's
+// download_stats::DownloadInitiattionSources but from the chrome layer.
+enum ChromeDownloadSource {
+ // The download was initiated by navigating to a URL (e.g. by user click).
+ DOWNLOAD_INITIATED_BY_NAVIGATION = 0,
+
+ // The download was initiated by invoking a context menu within a page.
+ DOWNLOAD_INITIATED_BY_CONTEXT_MENU,
+
+ // The download was initiated by the WebStore installer.
+ DOWNLOAD_INITIATED_BY_WEBSTORE_INSTALLER,
+
+ // The download was initiated by the ImageBurner (cros).
+ DOWNLOAD_INITIATED_BY_IMAGE_BURNER,
+
+ // The download was initiated by the plugin installer.
+ DOWNLOAD_INITIATED_BY_PLUGIN_INSTALLER,
+
+ // The download was initiated by the PDF plugin..
+ DOWNLOAD_INITIATED_BY_PDF_SAVE,
+
+ // The download was initiated by chrome.downloads.download().
+ DOWNLOAD_INITIATED_BY_EXTENSION,
+
+ CHROME_DOWNLOAD_SOURCE_LAST_ENTRY,
+};
+
+// Increment one of the above counts.
+void RecordDownloadCount(ChromeDownloadCountTypes type);
+
+// Record initiation of a download from a specific source.
+void RecordDownloadSource(ChromeDownloadSource source);
+
+#endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_STATS_H_
diff --git a/chrome/browser/download/download_util.cc b/chrome/browser/download/download_util.cc
index 8010f97..5b85b2a 100644
--- a/chrome/browser/download/download_util.cc
+++ b/chrome/browser/download/download_util.cc
@@ -13,7 +13,6 @@
#include "base/i18n/rtl.h"
#include "base/i18n/time_formatting.h"
#include "base/lazy_instance.h"
-#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
@@ -240,33 +239,64 @@
speed_text, amount, time_remaining);
}
-void RecordShelfClose(int size, int in_progress, bool autoclose) {
- static const int kMaxShelfSize = 16;
- if (autoclose) {
- UMA_HISTOGRAM_ENUMERATION("Download.ShelfSizeOnAutoClose",
- size,
- kMaxShelfSize);
- UMA_HISTOGRAM_ENUMERATION("Download.ShelfInProgressSizeOnAutoClose",
- in_progress,
- kMaxShelfSize);
+// Finch trial -----------------------------------------------------------------
+
+const char kFinchTrialName[] = "MalwareDownloadWarning";
+const char kCondition1Control[] = "Condition1Control";
+const char kCondition2Control[] = "Condition2Control";
+const char kCondition3Malicious[] = "Condition3Malicious";
+const char kCondition4Unsafe[] = "Condition4Unsafe";
+const char kCondition5Dangerous[] = "Condition5Dangerous";
+const char kCondition6Harmful[] = "Condition6Harmful";
+const char kCondition7DiscardSecond[] = "Condition7DiscardSecond";
+const char kCondition8DiscardFirst[] = "Condition8DiscardFirst";
+const char kCondition9SafeDiscard[] = "Condition9SafeDiscard";
+const char kCondition10SafeDontRun[] = "Condition10SafeDontRun";
+
+base::string16 AssembleMalwareFinchString(
+ const std::string& trial_condition, const base::string16& elided_filename) {
+ // Sanity check to make sure we have a filename.
+ base::string16 filename;
+ if (elided_filename.empty()) {
+ filename = ASCIIToUTF16("This file");
} else {
- UMA_HISTOGRAM_ENUMERATION("Download.ShelfSizeOnUserClose",
- size,
- kMaxShelfSize);
- UMA_HISTOGRAM_ENUMERATION("Download.ShelfInProgressSizeOnUserClose",
- in_progress,
- kMaxShelfSize);
+ filename = ReplaceStringPlaceholders(ASCIIToUTF16("File '$1'"),
+ elided_filename,
+ NULL);
}
-}
-void RecordDownloadCount(ChromeDownloadCountTypes type) {
- UMA_HISTOGRAM_ENUMERATION(
- "Download.CountsChrome", type, CHROME_DOWNLOAD_COUNT_TYPES_LAST_ENTRY);
-}
+ // Set the message text according to the condition.
+ if (trial_condition == kCondition1Control) {
+ return ASCIIToUTF16("This file appears malicious.");
+ }
+ base::string16 message_text;
+ if (trial_condition == kCondition2Control) {
+ message_text = ASCIIToUTF16("$1 appears malicious.");
+ } else if (trial_condition == kCondition3Malicious) {
+ message_text = ASCIIToUTF16("$1 is malicious.");
+ } else if (trial_condition == kCondition4Unsafe) {
+ message_text = ASCIIToUTF16("$1 is unsafe.");
+ } else if (trial_condition == kCondition5Dangerous) {
+ message_text = ASCIIToUTF16("$1 is dangerous.");
+ } else if (trial_condition == kCondition6Harmful) {
+ message_text = ASCIIToUTF16("$1 is harmful.");
+ } else if (trial_condition == kCondition7DiscardSecond) {
+ message_text = ASCIIToUTF16(
+ "$1 is malicious. Discard this file to stay safe.");
+ } else if (trial_condition == kCondition8DiscardFirst) {
+ message_text = ASCIIToUTF16(
+ "Discard this file to stay safe. $1 is malicious.");
+ } else if (trial_condition == kCondition9SafeDiscard) {
+ message_text = ASCIIToUTF16("$1 is malicious. To stay safe, discard it.");
+ } else if (trial_condition == kCondition10SafeDontRun) {
+ message_text = ASCIIToUTF16("$1 is malicious. To stay safe, don't run it.");
+ } else {
+ // We use the second control as a default for other conditions that don't
+ // change the warning string.
+ message_text = ASCIIToUTF16("$1 appears malicious.");
+ }
-void RecordDownloadSource(ChromeDownloadSource source) {
- UMA_HISTOGRAM_ENUMERATION(
- "Download.SourcesChrome", source, CHROME_DOWNLOAD_SOURCE_LAST_ENTRY);
+ return ReplaceStringPlaceholders(message_text, filename, NULL);
}
} // namespace download_util
diff --git a/chrome/browser/download/download_util.h b/chrome/browser/download/download_util.h
index 60288a3..515bd82 100644
--- a/chrome/browser/download/download_util.h
+++ b/chrome/browser/download/download_util.h
@@ -13,6 +13,7 @@
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
#include "ui/gfx/native_widget_types.h"
#if defined(TOOLKIT_VIEWS)
@@ -60,60 +61,27 @@
// Get the localized status text for an in-progress download.
string16 GetProgressStatusText(content::DownloadItem* download);
-// Record the total number of items and the number of in-progress items showing
-// in the shelf when it closes. Set |autoclose| to true when the shelf is
-// closing itself, false when the user explicitly closed it.
-void RecordShelfClose(int size, int in_progress, bool autoclose);
+// Summer/Fall 2013 Finch experiment strings -----------------------------------
+// Only deployed to English speakers, don't need translation.
-// Used for counting UMA stats. Similar to content's
-// download_stats::DownloadCountTypes but from the chrome layer.
-enum ChromeDownloadCountTypes {
- // Stale enum values left around os that values passed to UMA don't
- // change.
- CHROME_DOWNLOAD_COUNT_UNUSED_0 = 0,
- CHROME_DOWNLOAD_COUNT_UNUSED_1,
- CHROME_DOWNLOAD_COUNT_UNUSED_2,
- CHROME_DOWNLOAD_COUNT_UNUSED_3,
+// Study and condition names.
+extern const char kFinchTrialName[];
+extern const char kCondition1Control[];
+extern const char kCondition2Control[];
+extern const char kCondition3Malicious[];
+extern const char kCondition4Unsafe[];
+extern const char kCondition5Dangerous[];
+extern const char kCondition6Harmful[];
+extern const char kCondition7DiscardSecond[];
+extern const char kCondition8DiscardFirst[];
+extern const char kCondition9SafeDiscard[];
+extern const char kCondition10SafeDontRun[];
- // A download *would* have been initiated, but it was blocked
- // by the DownloadThrottlingResourceHandler.
- BLOCKED_BY_THROTTLING,
-
- CHROME_DOWNLOAD_COUNT_TYPES_LAST_ENTRY
-};
-
-// Used for counting UMA stats. Similar to content's
-// download_stats::DownloadInitiattionSources but from the chrome layer.
-enum ChromeDownloadSource {
- // The download was initiated by navigating to a URL (e.g. by user click).
- INITIATED_BY_NAVIGATION = 0,
-
- // The download was initiated by invoking a context menu within a page.
- INITIATED_BY_CONTEXT_MENU,
-
- // The download was initiated by the WebStore installer.
- INITIATED_BY_WEBSTORE_INSTALLER,
-
- // The download was initiated by the ImageBurner (cros).
- INITIATED_BY_IMAGE_BURNER,
-
- // The download was initiated by the plugin installer.
- INITIATED_BY_PLUGIN_INSTALLER,
-
- // The download was initiated by the PDF plugin..
- INITIATED_BY_PDF_SAVE,
-
- // The download was initiated by chrome.downloads.download().
- INITIATED_BY_EXTENSION,
-
- CHROME_DOWNLOAD_SOURCE_LAST_ENTRY,
-};
-
-// Increment one of the above counts.
-void RecordDownloadCount(ChromeDownloadCountTypes type);
-
-// Record initiation of a download from a specific source.
-void RecordDownloadSource(ChromeDownloadSource source);
+// Helper for getting the appropriate message for a Finch trial.
+// You should only invoke this if you believe you're in the kFinchTrialName
+// finch trial; if you aren't, use the default string and don't invoke this.
+base::string16 AssembleMalwareFinchString(const std::string& trial_condition,
+ const string16& elided_filename);
} // namespace download_util
diff --git a/chrome/browser/download/download_util_unittest.cc b/chrome/browser/download/download_util_unittest.cc
new file mode 100644
index 0000000..841260b
--- /dev/null
+++ b/chrome/browser/download/download_util_unittest.cc
@@ -0,0 +1,20 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/download/download_util.h"
+
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(DownloadUtilTest, FinchStrings) {
+ EXPECT_EQ(
+ ASCIIToUTF16("This file is malicious."),
+ download_util::AssembleMalwareFinchString(
+ download_util::kCondition3Malicious, string16()));
+ EXPECT_EQ(
+ ASCIIToUTF16("File 'malware.exe' is malicious."),
+ download_util::AssembleMalwareFinchString(
+ download_util::kCondition3Malicious, ASCIIToUTF16("malware.exe")));
+}
diff --git a/chrome/browser/drive/fake_drive_service.cc b/chrome/browser/drive/fake_drive_service.cc
index 74b8f2b..5fc49e3 100644
--- a/chrome/browser/drive/fake_drive_service.cc
+++ b/chrome/browser/drive/fake_drive_service.cc
@@ -216,7 +216,12 @@
bool FakeDriveService::LoadAccountMetadataForWapi(
const std::string& relative_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- account_metadata_value_ = test_util::LoadJSONFile(relative_path);
+
+ // Load JSON data, which must be a dictionary.
+ scoped_ptr<base::Value> value = test_util::LoadJSONFile(relative_path);
+ CHECK_EQ(base::Value::TYPE_DICTIONARY, value->GetType());
+ account_metadata_value_.reset(
+ static_cast<base::DictionaryValue*>(value.release()));
// Update the largest_changestamp_.
scoped_ptr<AccountMetadata> account_metadata =
@@ -248,6 +253,16 @@
return app_info_value_;
}
+void FakeDriveService::SetQuotaValue(int64 used, int64 total) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(account_metadata_value_);
+
+ account_metadata_value_->SetString("entry.gd$quotaBytesUsed.$t",
+ base::Int64ToString16(used));
+ account_metadata_value_->SetString("entry.gd$quotaBytesTotal.$t",
+ base::Int64ToString16(total));
+}
+
GURL FakeDriveService::GetFakeLinkUrl(const std::string& resource_id) {
return GURL("https://fake_server/" + net::EscapePath(resource_id));
}
diff --git a/chrome/browser/drive/fake_drive_service.h b/chrome/browser/drive/fake_drive_service.h
index b2eb5fc..994bc53 100644
--- a/chrome/browser/drive/fake_drive_service.h
+++ b/chrome/browser/drive/fake_drive_service.h
@@ -52,6 +52,9 @@
share_url_base_ = share_url_base;
}
+ // Changes the quota fields returned from GetAboutResource().
+ void SetQuotaValue(int64 used, int64 total);
+
// Returns the largest changestamp, which starts from 0 by default. See
// also comments at LoadAccountMetadataForWapi().
int64 largest_changestamp() const { return largest_changestamp_; }
@@ -270,7 +273,7 @@
GURL GetNewUploadSessionUrl();
scoped_ptr<base::DictionaryValue> resource_list_value_;
- scoped_ptr<base::Value> account_metadata_value_;
+ scoped_ptr<base::DictionaryValue> account_metadata_value_;
scoped_ptr<base::Value> app_info_value_;
std::map<GURL, UploadSession> upload_sessions_;
int64 largest_changestamp_;
diff --git a/chrome/browser/extensions/DEPS b/chrome/browser/extensions/DEPS
index 290e2e5..d16e654 100644
--- a/chrome/browser/extensions/DEPS
+++ b/chrome/browser/extensions/DEPS
@@ -8,6 +8,7 @@
"+apps/launcher.h",
"+apps/native_app_window.h",
"+apps/shell_window.h",
+ "+apps/shell_window_registry.h",
# TODO(tfarina): Remove all these. crbug.com/125846.
# DO NOT ADD ANY MORE ITEMS TO THE LIST BELOW!
diff --git a/chrome/browser/extensions/activity_log/activity_actions.cc b/chrome/browser/extensions/activity_log/activity_actions.cc
index 1d79225..4baca4c 100644
--- a/chrome/browser/extensions/activity_log/activity_actions.cc
+++ b/chrome/browser/extensions/activity_log/activity_actions.cc
@@ -11,9 +11,9 @@
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
-#include "chrome/browser/extensions/activity_log/api_name_constants.h"
#include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
@@ -36,63 +36,6 @@
return value_as_text;
}
-// Sets up the hashmap for mapping extension strings to "ints". The hashmap is
-// only set up once because it's quite long; the value is then cached.
-class APINameMap {
- public:
- APINameMap() {
- SetupMap();
- }
-
- // activity_log_api_name_constants.h lists all known API calls as of 5/17.
- // This code maps each of those API calls (and events) to short strings
- // (integers converted to strings). They're all strings because (1) sqlite
- // databases are all strings underneath anyway and (2) the Lookup function
- // will simply return the original api_call string if we don't have it in our
- // lookup table.
- void SetupMap() {
- for (size_t i = 0;
- i < arraysize(activity_log_api_name_constants::kNames);
- ++i) {
- std::string name =
- std::string(activity_log_api_name_constants::kNames[i]);
- std::string num = base::IntToString(i);
- names_to_nums_[name] = num;
- nums_to_names_[num] = name;
- }
- }
-
- static APINameMap* GetInstance() {
- return Singleton<APINameMap>::get();
- }
-
- // This matches an api call to a number, if it's in the lookup table. If not,
- // it returns the original api call.
- const std::string& ApiToShortname(const std::string& api_call) {
- std::map<std::string, std::string>::iterator it =
- names_to_nums_.find(api_call);
- if (it == names_to_nums_.end())
- return api_call;
- else
- return it->second;
- }
-
- // This matches a number to an API call -- it's the opposite of
- // ApiToShortname.
- const std::string& ShortnameToApi(const std::string& shortname) {
- std::map<std::string, std::string>::iterator it =
- nums_to_names_.find(shortname);
- if (it == nums_to_names_.end())
- return shortname;
- else
- return it->second;
- }
-
- private:
- std::map<std::string, std::string> names_to_nums_; // <name, number label>
- std::map<std::string, std::string> nums_to_names_; // <number label, name>
-};
-
} // namespace
namespace extensions {
@@ -163,6 +106,30 @@
return other_.get();
}
+std::string Action::SerializePageUrl() const {
+ return (page_incognito() ? constants::kIncognitoUrl : "") + page_url().spec();
+}
+
+void Action::ParsePageUrl(const std::string& url) {
+ set_page_incognito(StartsWithASCII(url, constants::kIncognitoUrl, true));
+ if (page_incognito())
+ set_page_url(GURL(url.substr(strlen(constants::kIncognitoUrl))));
+ else
+ set_page_url(GURL(url));
+}
+
+std::string Action::SerializeArgUrl() const {
+ return (arg_incognito() ? constants::kIncognitoUrl : "") + arg_url().spec();
+}
+
+void Action::ParseArgUrl(const std::string& url) {
+ set_arg_incognito(StartsWithASCII(url, constants::kIncognitoUrl, true));
+ if (arg_incognito())
+ set_arg_url(GURL(url.substr(strlen(constants::kIncognitoUrl))));
+ else
+ set_arg_url(GURL(url));
+}
+
scoped_ptr<ExtensionActivity> Action::ConvertToExtensionActivity() {
scoped_ptr<ExtensionActivity> result(new ExtensionActivity);
@@ -246,7 +213,7 @@
return result.Pass();
}
-std::string Action::PrintForDebug() {
+std::string Action::PrintForDebug() const {
std::string result = "ID=" + extension_id() + " CATEGORY=";
switch (action_type_) {
case ACTION_API_CALL:
diff --git a/chrome/browser/extensions/activity_log/activity_actions.h b/chrome/browser/extensions/activity_log/activity_actions.h
index 6782b83..8e3e31c 100644
--- a/chrome/browser/extensions/activity_log/activity_actions.h
+++ b/chrome/browser/extensions/activity_log/activity_actions.h
@@ -98,12 +98,20 @@
void set_other(scoped_ptr<DictionaryValue> other);
DictionaryValue* mutable_other();
+ // Helper methods for serializing and deserializing URLs into strings. If
+ // the URL is marked as incognito, then the string is prefixed with
+ // kIncognitoUrl ("<incognito>").
+ std::string SerializePageUrl() const;
+ void ParsePageUrl(const std::string& url);
+ std::string SerializeArgUrl() const;
+ void ParseArgUrl(const std::string& url);
+
// Flatten the activity's type-specific fields into an ExtensionActivity.
scoped_ptr<api::activity_log_private::ExtensionActivity>
ConvertToExtensionActivity();
// Print an action as a regular string for debugging purposes.
- std::string PrintForDebug();
+ virtual std::string PrintForDebug() const;
protected:
virtual ~Action();
diff --git a/chrome/browser/extensions/activity_log/activity_database.cc b/chrome/browser/extensions/activity_log/activity_database.cc
index 810c758..7679d15 100644
--- a/chrome/browser/extensions/activity_log/activity_database.cc
+++ b/chrome/browser/extensions/activity_log/activity_database.cc
@@ -91,8 +91,10 @@
SoftFailureClose();
}
-void ActivityDatabase::NotifyAction() {
- if (valid_db_ && !batch_mode_) {
+void ActivityDatabase::AdviseFlush(int size) {
+ if (!valid_db_)
+ return;
+ if (!batch_mode_ || size == kFlushImmediately) {
if (!delegate_->FlushDatabase(&db_))
SoftFailureClose();
}
diff --git a/chrome/browser/extensions/activity_log/activity_database.h b/chrome/browser/extensions/activity_log/activity_database.h
index ea2cff9..30b32f7 100644
--- a/chrome/browser/extensions/activity_log/activity_database.h
+++ b/chrome/browser/extensions/activity_log/activity_database.h
@@ -75,10 +75,13 @@
// Initializes the database schema; this gives a policy a chance to create
// or update database tables as needed. Should return true on success.
+ // Will be called from within a database transaction.
virtual bool InitDatabase(sql::Connection* db) = 0;
// Requests that the policy flush any pending actions to the database.
- // Should return true on success or false on a database error.
+ // Should return true on success or false on a database error. Will not be
+ // called from a transaction (the implementation may wish to use a
+ // transaction for the flush).
virtual bool FlushDatabase(sql::Connection* db) = 0;
// Called if the database encounters a permanent error; the policy should
@@ -93,6 +96,9 @@
virtual void OnDatabaseClose() = 0;
};
+ // Value to be passed to AdviseFlush below to force a database flush.
+ static const int kFlushImmediately = -1;
+
// Need to call Init to actually use the ActivityDatabase. The Delegate
// provides hooks for an ActivityLogPolicy to control the database schema and
// reads/writes.
@@ -106,11 +112,13 @@
void Close();
// Inform the database that there may be additional data which could be
- // written out.
- // TODO(mvrable): Add a method to force a database flush, or perhaps pass
- // hints to the database about how much data is queued up so the database can
- // flush before the timeout if there is a large amount of data?
- void NotifyAction();
+ // written out. The size parameter should indicate (approximately) how many
+ // records are queued to be written; the database may use this information to
+ // schedule a flush early if too much data is queueing up. A value of
+ // kFlushImmediately will force an immediate call into
+ // Delegate::FlushDatabase(); otherwise, it is up to the database to
+ // determine when to flush.
+ void AdviseFlush(int size);
// Turns off batch I/O writing mode. This should only be used in unit tests,
// browser tests, or in our special --enable-extension-activity-log-testing
@@ -188,6 +196,7 @@
friend class ActivityLogDatabasePolicy;
FRIEND_TEST_ALL_PREFIXES(ActivityDatabaseTest, BatchModeOff);
FRIEND_TEST_ALL_PREFIXES(ActivityDatabaseTest, BatchModeOn);
+ FRIEND_TEST_ALL_PREFIXES(ActivityDatabaseTest, BatchModeFlush);
DISALLOW_COPY_AND_ASSIGN(ActivityDatabase);
};
diff --git a/chrome/browser/extensions/activity_log/activity_database_unittest.cc b/chrome/browser/extensions/activity_log/activity_database_unittest.cc
index b8f9d91..5894999 100644
--- a/chrome/browser/extensions/activity_log/activity_database_unittest.cc
+++ b/chrome/browser/extensions/activity_log/activity_database_unittest.cc
@@ -103,7 +103,7 @@
void ActivityDatabaseTestPolicy::Record(ActivityDatabase* db,
scoped_refptr<Action> action) {
queue_.push_back(action);
- db->NotifyAction();
+ db->AdviseFlush(queue_.size());
}
class ActivityDatabaseTest : public ChromeRenderViewHostTestHarness {
@@ -151,7 +151,8 @@
std::string sql_str = "SELECT COUNT(*) FROM " +
std::string(ActivityDatabaseTestPolicy::kTableName) +
" WHERE api_name LIKE ?";
- sql::Statement statement(db->GetUniqueStatement(sql_str.c_str()));
+ sql::Statement statement(db->GetCachedStatement(
+ sql::StatementID(SQL_FROM_HERE), sql_str.c_str()));
statement.BindString(0, api_name_pattern);
if (!statement.Step())
return -1;
@@ -246,6 +247,27 @@
activity_db->Close();
}
+TEST_F(ActivityDatabaseTest, BatchModeFlush) {
+ base::ScopedTempDir temp_dir;
+ base::FilePath db_file;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ db_file = temp_dir.path().AppendASCII("ActivityFlush.db");
+ base::DeleteFile(db_file, false);
+
+ // Record some actions
+ ActivityDatabase* activity_db = OpenDatabase(db_file);
+ activity_db->SetBatchModeForTesting(true);
+ scoped_refptr<Action> action = CreateAction(base::Time::Now(), "brewster");
+ Record(activity_db, action);
+ ASSERT_EQ(0, CountActions(&activity_db->db_, "brewster"));
+
+ // Request an immediate database flush.
+ activity_db->AdviseFlush(ActivityDatabase::kFlushImmediately);
+ ASSERT_EQ(1, CountActions(&activity_db->db_, "brewster"));
+
+ activity_db->Close();
+}
+
// Check that nothing explodes if the DB isn't initialized.
TEST_F(ActivityDatabaseTest, InitFailure) {
base::ScopedTempDir temp_dir;
diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc
index 2b81ed5..bc973e7 100644
--- a/chrome/browser/extensions/activity_log/activity_log.cc
+++ b/chrome/browser/extensions/activity_log/activity_log.cc
@@ -14,7 +14,8 @@
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_checker.h"
#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
-#include "chrome/browser/extensions/activity_log/stream_noargs_ui_policy.h"
+#include "chrome/browser/extensions/activity_log/counting_policy.h"
+#include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h"
#include "chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
@@ -240,8 +241,8 @@
case ActivityLogPolicy::POLICY_FULLSTREAM:
policy_ = new FullStreamUIPolicy(profile_);
break;
- case ActivityLogPolicy::POLICY_NOARGS:
- policy_ = new StreamWithoutArgsUIPolicy(profile_);
+ case ActivityLogPolicy::POLICY_COUNTS:
+ policy_ = new CountingPolicy(profile_);
break;
default:
NOTREACHED();
@@ -302,7 +303,7 @@
if (testing_mode_)
SetDefaultPolicy(ActivityLogPolicy::POLICY_FULLSTREAM);
else
- SetDefaultPolicy(ActivityLogPolicy::POLICY_NOARGS);
+ SetDefaultPolicy(ActivityLogPolicy::POLICY_COUNTS);
}
void ActivityLog::Shutdown() {
diff --git a/chrome/browser/extensions/activity_log/activity_log_policy.cc b/chrome/browser/extensions/activity_log/activity_log_policy.cc
index 3e8b889..c02da5e 100644
--- a/chrome/browser/extensions/activity_log/activity_log_policy.cc
+++ b/chrome/browser/extensions/activity_log/activity_log_policy.cc
@@ -7,9 +7,12 @@
#include <stdint.h>
#include "base/files/file_path.h"
+#include "base/json/json_string_value_serializer.h"
#include "base/logging.h"
+#include "base/strings/stringprintf.h"
#include "base/time/clock.h"
#include "base/time/time.h"
+#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/extension.h"
#include "content/public/browser/browser_thread.h"
@@ -17,12 +20,25 @@
using content::BrowserThread;
+namespace constants = activity_log_constants;
+
+namespace {
+// Obsolete database tables: these should be dropped from the database if
+// found.
+const char* kObsoleteTables[] = {"activitylog_apis", "activitylog_blocked",
+ "activitylog_urls"};
+} // namespace
+
namespace extensions {
-ActivityLogPolicy::ActivityLogPolicy(Profile* profile) : testing_clock_(NULL) {}
+ActivityLogPolicy::ActivityLogPolicy(Profile* profile) {}
ActivityLogPolicy::~ActivityLogPolicy() {}
+void ActivityLogPolicy::SetClockForTesting(scoped_ptr<base::Clock> clock) {
+ testing_clock_.reset(clock.release());
+}
+
base::Time ActivityLogPolicy::Now() const {
if (testing_clock_)
return testing_clock_->Now();
@@ -30,10 +46,6 @@
return base::Time::Now();
}
-std::string ActivityLogPolicy::GetKey(KeyType) const {
- return std::string();
-}
-
ActivityLogDatabasePolicy::ActivityLogDatabasePolicy(
Profile* profile,
const base::FilePath& database_name)
@@ -49,4 +61,111 @@
return db_->GetSqlConnection();
}
+// static
+std::string ActivityLogPolicy::Util::Serialize(const base::Value* value) {
+ std::string value_as_text;
+ if (!value) {
+ value_as_text = "";
+ } else {
+ JSONStringValueSerializer serializer(&value_as_text);
+ serializer.SerializeAndOmitBinaryValues(*value);
+ }
+ return value_as_text;
+}
+
+// static
+void ActivityLogPolicy::Util::StripPrivacySensitiveFields(
+ scoped_refptr<Action> action) {
+ // Clear incognito URLs/titles.
+ if (action->page_incognito()) {
+ action->set_page_url(GURL());
+ action->set_page_title("");
+ }
+ if (action->arg_incognito()) {
+ action->set_arg_url(GURL());
+ }
+
+ // Strip query parameters, username/password, etc., from URLs.
+ if (action->page_url().is_valid() || action->arg_url().is_valid()) {
+ url_canon::Replacements<char> url_sanitizer;
+ url_sanitizer.ClearUsername();
+ url_sanitizer.ClearPassword();
+ url_sanitizer.ClearQuery();
+ url_sanitizer.ClearRef();
+
+ if (action->page_url().is_valid())
+ action->set_page_url(action->page_url().ReplaceComponents(url_sanitizer));
+ if (action->arg_url().is_valid())
+ action->set_arg_url(action->arg_url().ReplaceComponents(url_sanitizer));
+ }
+
+ // Clear WebRequest details; only keep a record of which types of
+ // modifications were performed.
+ if (action->action_type() == Action::ACTION_WEB_REQUEST) {
+ DictionaryValue* details = NULL;
+ if (action->mutable_other()->GetDictionary(constants::kActionWebRequest,
+ &details)) {
+ DictionaryValue::Iterator details_iterator(*details);
+ while (!details_iterator.IsAtEnd()) {
+ details->SetBoolean(details_iterator.key(), true);
+ details_iterator.Advance();
+ }
+ }
+ }
+}
+
+// static
+void ActivityLogPolicy::Util::StripArguments(
+ const std::set<std::string>& api_whitelist,
+ scoped_refptr<Action> action) {
+ if (action->action_type() != Action::ACTION_API_CALL &&
+ action->action_type() != Action::ACTION_API_EVENT &&
+ action->action_type() != Action::ACTION_API_BLOCKED)
+ return;
+
+ if (api_whitelist.find(action->api_name()) == api_whitelist.end())
+ action->set_args(scoped_ptr<ListValue>());
+}
+
+// static
+base::Time ActivityLogPolicy::Util::AddDays(const base::Time& base_date,
+ int days) {
+ // To allow for time zone changes, add an additional partial day then round
+ // down to midnight.
+ return (base_date + base::TimeDelta::FromDays(days) +
+ base::TimeDelta::FromHours(4)).LocalMidnight();
+}
+
+// static
+void ActivityLogPolicy::Util::ComputeDatabaseTimeBounds(const base::Time& now,
+ int days_ago,
+ int64* early_bound,
+ int64* late_bound) {
+ base::Time morning_midnight = now.LocalMidnight();
+ if (days_ago == 0) {
+ *early_bound = morning_midnight.ToInternalValue();
+ *late_bound = base::Time::Max().ToInternalValue();
+ } else {
+ base::Time early_time = Util::AddDays(morning_midnight, -days_ago);
+ base::Time late_time = Util::AddDays(early_time, 1);
+ *early_bound = early_time.ToInternalValue();
+ *late_bound = late_time.ToInternalValue();
+ }
+}
+
+// static
+bool ActivityLogPolicy::Util::DropObsoleteTables(sql::Connection* db) {
+ for (size_t i = 0; i < arraysize(kObsoleteTables); i++) {
+ const char* table_name = kObsoleteTables[i];
+ if (db->DoesTableExist(table_name)) {
+ std::string drop_statement =
+ base::StringPrintf("DROP TABLE %s", table_name);
+ if (!db->Execute(drop_statement.c_str())) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
} // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/activity_log_policy.h b/chrome/browser/extensions/activity_log/activity_log_policy.h
index e8421dc..ebfdf4e 100644
--- a/chrome/browser/extensions/activity_log/activity_log_policy.h
+++ b/chrome/browser/extensions/activity_log/activity_log_policy.h
@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_POLICY_H_
#define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_POLICY_H_
+#include <set>
#include <string>
#include "base/bind.h"
@@ -51,23 +52,10 @@
public:
enum PolicyType {
POLICY_FULLSTREAM,
- POLICY_NOARGS,
+ POLICY_COUNTS,
POLICY_INVALID,
};
- // For all subclasses, add all the key types they might support here.
- // The actual key is returned by calling GetKey(KeyType). The subclasses
- // are free to return an empty string for keys they don't support.
- // For every key added here, you should update the GetKey member function
- // for at least one policy.
- enum KeyType {
- PARAM_KEY_REASON, // Why an action was blocked
- PARAM_KEY_DOM_ACTION, // Getter, Setter, Method,...
- PARAM_KEY_URL_TITLE,
- PARAM_KEY_DETAILS_STRING,
- PARAM_KEY_EXTRA,
- };
-
// Parameters are the profile and the thread that will be used to execute
// the callback when ReadData is called.
// TODO(felt,dbabic) Since only ReadData uses thread_id, it would be
@@ -99,10 +87,52 @@
const base::Callback
<void(scoped_ptr<Action::ActionVector>)>& callback) = 0;
- virtual std::string GetKey(KeyType key_id) const;
-
// For unit testing only.
- void SetClockForTesting(base::Clock* clock) { testing_clock_ = clock; }
+ void SetClockForTesting(scoped_ptr<base::Clock> clock);
+
+ // A collection of methods that are useful for implementing policies. These
+ // are all static methods; the ActivityLogPolicy::Util class cannot be
+ // instantiated. This is nested within ActivityLogPolicy to make calling
+ // these methods more convenient from within a policy, but they are public.
+ class Util {
+ public:
+ // Serialize a Value as a JSON string. Returns an empty string if value is
+ // null.
+ static std::string Serialize(const base::Value* value);
+
+ // Removes potentially privacy-sensitive data that should not be logged.
+ // This should generally be called on an Action before logging, unless
+ // debugging flags are enabled. Modifies the Action object in place; if
+ // the action might be shared with other users, it is up to the caller to
+ // call ->Clone() first.
+ static void StripPrivacySensitiveFields(scoped_refptr<Action> action);
+
+ // Strip arguments from most API actions, preserving actions only for a
+ // whitelisted set. Modifies the Action object in-place.
+ static void StripArguments(const std::set<std::string>& api_whitelist,
+ scoped_refptr<Action> action);
+
+ // Given a base day (timestamp at local midnight), computes the timestamp
+ // at midnight the given number of days before or after.
+ static base::Time AddDays(const base::Time& base_date, int days);
+
+ // Compute the time bounds that should be used for a database query to
+ // cover a time range days_ago days in the past, relative to the specified
+ // time.
+ static void ComputeDatabaseTimeBounds(const base::Time& now,
+ int days_ago,
+ int64* early_bound,
+ int64* late_bound);
+
+ // Deletes obsolete database tables from an activity log database. This
+ // can be used in InitDatabase() methods of ActivityLogDatabasePolicy
+ // subclasses to clean up data from old versions of the activity logging
+ // code. Returns true on success, false on database error.
+ static bool DropObsoleteTables(sql::Connection* db);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Util);
+ };
protected:
// An ActivityLogPolicy is not directly destroyed. Instead, call Close()
@@ -118,7 +148,7 @@
// Support for a mock clock for testing purposes. This is used by ReadData
// to determine the date for "today" when when interpreting date ranges to
// fetch. This has no effect on batching of writes to the database.
- base::Clock* testing_clock_;
+ scoped_ptr<base::Clock> testing_clock_;
DISALLOW_COPY_AND_ASSIGN(ActivityLogPolicy);
};
diff --git a/chrome/browser/extensions/activity_log/activity_log_policy_unittest.cc b/chrome/browser/extensions/activity_log/activity_log_policy_unittest.cc
new file mode 100644
index 0000000..7b0e078
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/activity_log_policy_unittest.cc
@@ -0,0 +1,102 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/values.h"
+#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
+#include "chrome/browser/extensions/activity_log/activity_actions.h"
+#include "chrome/browser/extensions/activity_log/activity_log_policy.h"
+#include "chrome/browser/extensions/activity_log/web_request_constants.h"
+#include "chrome/common/extensions/value_builder.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+class ActivityLogPolicyUtilTest : public testing::Test {};
+
+// Test that incognito values are stripped, and non-incognito ones aren't.
+TEST_F(ActivityLogPolicyUtilTest, StripPrivacySensitive) {
+ scoped_refptr<Action> action =
+ new Action("punky",
+ base::Time::Now(),
+ Action::ACTION_API_CALL,
+ "tabs.executeScript");
+ action->mutable_args()->AppendString("woof");
+ action->set_page_url(GURL("http://www.google.com/"));
+ action->set_page_incognito(true);
+ action->set_page_title("private");
+ action->set_arg_url(GURL("http://www.youtube.com/?privatekey"));
+
+ ASSERT_EQ("<incognito>http://www.google.com/", action->SerializePageUrl());
+
+ ActivityLogPolicy::Util::StripPrivacySensitiveFields(action);
+
+ ASSERT_FALSE(action->page_url().is_valid());
+ ASSERT_EQ("<incognito>", action->SerializePageUrl());
+ ASSERT_EQ("", action->page_title());
+ ASSERT_EQ("http://www.youtube.com/", action->arg_url().spec());
+}
+
+// Test that WebRequest details are stripped for privacy.
+TEST_F(ActivityLogPolicyUtilTest, StripPrivacySensitiveWebRequest) {
+ scoped_refptr<Action> action = new Action(
+ "punky", base::Time::Now(), Action::ACTION_WEB_REQUEST, "webRequest");
+ action->mutable_other()->Set(
+ activity_log_constants::kActionWebRequest,
+ DictionaryBuilder()
+ .Set(activity_log_web_request_constants::kNewUrlKey,
+ "http://www.youtube.com/")
+ .Set(activity_log_web_request_constants::kAddedRequestHeadersKey,
+ ListBuilder().Append("arg"))
+ .Build().release());
+
+ ActivityLogPolicy::Util::StripPrivacySensitiveFields(action);
+
+ ASSERT_EQ(
+ "{\"web_request\":{\"added_request_headers\":true,\"new_url\":true}}",
+ ActivityLogPolicy::Util::Serialize(action->other()));
+}
+
+// Test that argument values are stripped as appropriate.
+TEST_F(ActivityLogPolicyUtilTest, StripArguments) {
+ std::set<std::string> whitelist;
+ whitelist.insert("tabs.executeScript");
+
+ // API is in whitelist; not stripped.
+ scoped_refptr<Action> action =
+ new Action("punky",
+ base::Time::Now(),
+ Action::ACTION_API_CALL,
+ "tabs.executeScript");
+ action->mutable_args()->AppendString("woof");
+ ActivityLogPolicy::Util::StripArguments(whitelist, action);
+ ASSERT_EQ("[\"woof\"]", ActivityLogPolicy::Util::Serialize(action->args()));
+
+ // Not in whitelist: stripped.
+ action = new Action(
+ "punky", base::Time::Now(), Action::ACTION_API_CALL, "tabs.create");
+ action->mutable_args()->AppendString("woof");
+ ActivityLogPolicy::Util::StripArguments(whitelist, action);
+ ASSERT_EQ("", ActivityLogPolicy::Util::Serialize(action->args()));
+
+ // Not an API type: not stripped.
+ action = new Action(
+ "punky", base::Time::Now(), Action::ACTION_DOM_ACCESS, "tabs.create");
+ action->mutable_args()->AppendString("woof");
+ ActivityLogPolicy::Util::StripArguments(whitelist, action);
+ ASSERT_EQ("[\"woof\"]", ActivityLogPolicy::Util::Serialize(action->args()));
+}
+
+// Test parsing of URLs serialized to strings.
+TEST_F(ActivityLogPolicyUtilTest, ParseUrls) {
+ scoped_refptr<Action> action =
+ new Action("punky",
+ base::Time::Now(),
+ Action::ACTION_API_CALL,
+ "tabs.executeScript");
+ action->ParsePageUrl("<incognito>http://www.google.com/");
+ EXPECT_EQ("http://www.google.com/", action->page_url().spec());
+ EXPECT_TRUE(action->page_incognito());
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/activity_log_unittest.cc b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
index 118cb4d..25c9cea 100644
--- a/chrome/browser/extensions/activity_log/activity_log_unittest.cc
+++ b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
@@ -81,7 +81,7 @@
if (log_arguments)
activity_log->SetDefaultPolicy(ActivityLogPolicy::POLICY_FULLSTREAM);
else
- activity_log->SetDefaultPolicy(ActivityLogPolicy::POLICY_NOARGS);
+ activity_log->SetDefaultPolicy(ActivityLogPolicy::POLICY_COUNTS);
}
static void Arguments_Prerender(
diff --git a/chrome/browser/extensions/activity_log/api_name_constants.h b/chrome/browser/extensions/activity_log/api_name_constants.h
deleted file mode 100644
index d745b66..0000000
--- a/chrome/browser/extensions/activity_log/api_name_constants.h
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Constants used in api_actions.cc.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_API_NAME_CONSTANTS_H_
-#define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_API_NAME_CONSTANTS_H_
-
-namespace activity_log_api_name_constants {
-
-// All of the chrome.* API names and events. ADD TO THE END. Do not remove any!
-const char* const kNames[] = {
- "alarms.clear", "alarms.clearAll", "alarms.create", "alarms.get",
- "alarms.getAll", "alarms.onAlarm", "app.runtime.onLaunched",
- "app.runtime.onRestarted", "app.window.create", "app.window.current",
- "app.window.onBoundsChanged", "app.window.onClosed",
- "app.window.onFullscreened", "app.window.onMaximized",
- "app.window.onMinimized", "app.window.onRestored", "bluetooth.connect",
- "bluetooth.disconnect", "bluetooth.getAdapterState",
- "bluetooth.getDevices", "bluetooth.getLocalOutOfBandPairingData",
- "bluetooth.getServices", "bluetooth.onAdapterStateChanged",
- "bluetooth.read", "bluetooth.setOutOfBandPairingData",
- "bluetooth.startDiscovery", "bluetooth.stopDiscovery", "bluetooth.write",
- "bookmarks.create", "bookmarks.get", "bookmarks.getChildren",
- "bookmarks.getRecent", "bookmarks.getSubTree", "bookmarks.getTree",
- "bookmarks.move", "bookmarks.onChanged", "bookmarks.onChildrenReordered",
- "bookmarks.onCreated", "bookmarks.onImportBegan",
- "bookmarks.onImportEnded", "bookmarks.onMoved", "bookmarks.onRemoved",
- "bookmarks.remove", "bookmarks.removeTree", "bookmarks.search",
- "bookmarks.update", "browserAction.disable", "browserAction.enable",
- "browserAction.getBadgeBackgroundColor", "browserAction.getBadgeText",
- "browserAction.getPopup", "browserAction.getTitle",
- "browserAction.onClicked", "browserAction.setBadgeBackgroundColor",
- "browserAction.setBadgeText", "browserAction.setIcon",
- "browserAction.setPopup", "browserAction.setTitle", "browsingData.remove",
- "browsingData.removeAppcache", "browsingData.removeCache",
- "browsingData.removeCookies", "browsingData.removeDownloads",
- "browsingData.removeFileSystems", "browsingData.removeFormData",
- "browsingData.removeHistory", "browsingData.removeIndexedDB",
- "browsingData.removeLocalStorage", "browsingData.removePasswords",
- "browsingData.removePluginData", "browsingData.removeWebSQL",
- "browsingData.settings", "commands.getAll", "commands.onCommand",
- "contextMenus.create", "contextMenus.onClicked", "contextMenus.remove",
- "contextMenus.removeAll", "contextMenus.update", "cookies.get",
- "cookies.getAll", "cookies.getAllCookieStores", "cookies.onChanged",
- "cookies.remove", "cookies.set", "debugger.attach", "debugger.detach",
- "debugger.getTargets", "debugger.onDetach", "debugger.onEvent",
- "debugger.sendCommand", "declarativeContent.onPageChanged",
- "declarativeWebRequest.onMessage", "declarativeWebRequest.onRequest",
- "devtools.inspectedWindow.eval", "devtools.inspectedWindow.getResources",
- "devtools.inspectedWindow.onResourceAdded",
- "devtools.inspectedWindow.onResourceContentCommitted",
- "devtools.inspectedWindow.reload", "devtools.network.getHAR",
- "devtools.network.onNavigated", "devtools.network.onRequestFinished",
- "devtools.panels.create", "devtools.panels.setOpenResourceHandler",
- "downloads.acceptDanger", "downloads.cancel", "downloads.download",
- "downloads.drag", "downloads.erase", "downloads.getFileIcon",
- "downloads.onChanged", "downloads.onCreated",
- "downloads.onDeterminingFilename", "downloads.onErased", "downloads.open",
- "downloads.pause", "downloads.resume", "downloads.search",
- "downloads.show", "experimental.devtools.audits.addCategory",
- "experimental.devtools.console.addMessage",
- "experimental.devtools.console.getMessages",
- "experimental.devtools.console.onMessageAdded",
- "experimental.discovery.clearAllSuggestions",
- "experimental.discovery.removeSuggestion",
- "experimental.discovery.suggest", "experimental.history.getMostVisited",
- "experimental.identity.getAuthToken",
- "experimental.identity.launchWebAuthFlow", "infobars.show",
- "removed.experimental.mediaGalleries.assembleMediaFile",
- "removed.experimental.mediaGalleries.extractEmbeddedThumbnails",
- "experimental.processes.getProcessIdForTab",
- "experimental.processes.getProcessInfo",
- "experimental.processes.onCreated", "experimental.processes.onExited",
- "experimental.processes.onUnresponsive",
- "experimental.processes.onUpdated",
- "experimental.processes.onUpdatedWithMemory",
- "experimental.processes.terminate",
- "experimental.record.captureURLs", "experimental.record.replayURLs",
- "experimental.speechInput.isRecording", "experimental.speechInput.onError",
- "experimental.speechInput.onResult", "experimental.speechInput.onSoundEnd",
- "experimental.speechInput.onSoundStart", "experimental.speechInput.start",
- "experimental.speechInput.stop", "experimental.systemInfo.cpu.get" ,
- "experimental.systemInfo.cpu.onUpdated",
- "experimental.systemInfo.display.get",
- "experimental.systemInfo.memory.get", "experimental.systemInfo.storage.get",
- "experimental.systemInfo.storage.onAttached",
- "experimental.systemInfo.storage.onAvailableCapacityChanged",
- "experimental.systemInfo.storage.onDetached",
- "extension.getBackgroundPage", "extension.getURL", "extension.getViews",
- "extension.isAllowedFileSchemeAccess",
- "extension.isAllowedIncognitoAccess", "extension.setUpdateUrlData",
- "fileBrowserHandler.onExecute", "fileBrowserHandler.selectFile",
- "fileSystem.chooseEntry", "fileSystem.getDisplayPath",
- "fileSystem.getEntryById", "fileSystem.getEntryId",
- "fileSystem.getWritableEntry", "fileSystem.isWritableEntry",
- "fontSettings.clearDefaultFixedFontSize",
- "fontSettings.clearDefaultFontSize", "fontSettings.clearFont",
- "fontSettings.clearMinimumFontSize",
- "fontSettings.getDefaultFixedFontSize", "fontSettings.getDefaultFontSize",
- "fontSettings.getFont", "fontSettings.getFontList",
- "fontSettings.getMinimumFontSize",
- "fontSettings.onDefaultFixedFontSizeChanged",
- "fontSettings.onDefaultFontSizeChanged", "fontSettings.onFontChanged",
- "fontSettings.onMinimumFontSizeChanged",
- "fontSettings.setDefaultFixedFontSize", "fontSettings.setDefaultFontSize",
- "fontSettings.setFont", "fontSettings.setMinimumFontSize",
- "history.addUrl", "history.deleteAll", "history.deleteRange",
- "history.deleteUrl", "history.getVisits", "history.onVisitRemoved",
- "history.onVisited", "history.search", "i18n.getAcceptLanguages",
- "i18n.getMessage", "idle.onStateChanged", "idle.queryState",
- "idle.setDetectionInterval", "input.ime.clearComposition",
- "input.ime.commitText", "input.ime.deleteSurroundingText",
- "input.ime.keyEventHandled", "input.ime.onActivate", "input.ime.onBlur",
- "input.ime.onCandidateClicked", "input.ime.onDeactivated",
- "input.ime.onFocus", "input.ime.onInputContextUpdate",
- "input.ime.onKeyEvent", "input.ime.onMenuItemActivated",
- "input.ime.onSurroundingTextChanged",
- "input.ime.setCandidateWindowProperties", "input.ime.setCandidates",
- "input.ime.setComposition", "input.ime.setCursorPosition",
- "input.ime.setMenuItems", "input.ime.updateMenuItems", "management.get",
- "management.getAll", "management.getPermissionWarningsById",
- "management.getPermissionWarningsByManifest", "management.launchApp",
- "management.onDisabled", "management.onEnabled", "management.onInstalled",
- "management.onUninstalled", "management.setEnabled",
- "management.uninstall", "management.uninstallSelf",
- "mediaGalleries.getMediaFileSystemMetadata",
- "mediaGalleries.getMediaFileSystems", "notifications.clear",
- "notifications.create", "notifications.onButtonClicked",
- "notifications.onClicked", "notifications.onClosed",
- "notifications.onDisplayed", "notifications.update",
- "omnibox.onInputCancelled", "omnibox.onInputChanged",
- "omnibox.onInputEntered", "omnibox.onInputStarted",
- "omnibox.setDefaultSuggestion", "pageAction.getPopup",
- "pageAction.getTitle", "pageAction.hide", "pageAction.onClicked",
- "pageAction.setIcon", "pageAction.setPopup", "pageAction.setTitle",
- "pageAction.show", "pageCapture.saveAsMHTML", "permissions.contains",
- "permissions.getAll", "permissions.onAdded", "permissions.onRemoved",
- "permissions.remove", "permissions.request", "power.releaseKeepAwake",
- "power.requestKeepAwake", "proxy.onProxyError",
- "pushMessaging.getChannelId", "pushMessaging.onMessage", "runtime.connect",
- "runtime.getBackgroundPage", "runtime.getManifest", "runtime.getURL",
- "runtime.onBrowserUpdateAvailable", "runtime.onConnect",
- "runtime.onConnectExternal", "runtime.onInstalled", "runtime.onMessage",
- "runtime.onMessageExternal", "runtime.onStartup", "runtime.onSuspend",
- "runtime.onSuspendCanceled", "runtime.onUpdateAvailable", "runtime.reload",
- "runtime.requestUpdateCheck", "runtime.sendMessage",
- "scriptBadge.getAttention", "scriptBadge.getPopup",
- "scriptBadge.onClicked", "scriptBadge.setPopup", "serial.close",
- "serial.flush", "serial.getControlSignals", "serial.getPorts",
- "serial.open", "serial.read", "serial.setControlSignals", "serial.write",
- "sessionRestore.getRecentlyClosed", "sessionRestore.restore",
- "socket.accept", "socket.bind", "socket.connect", "socket.create",
- "socket.destroy", "socket.disconnect", "socket.getInfo",
- "socket.getNetworkList", "socket.listen", "socket.read", "socket.recvFrom",
- "socket.sendTo", "socket.setKeepAlive", "socket.setNoDelay",
- "socket.write", "storage.onChanged",
- "syncFileSystem.getConflictResolutionPolicy",
- "syncFileSystem.getFileStatus", "syncFileSystem.getFileStatuses",
- "syncFileSystem.getUsageAndQuota", "syncFileSystem.onFileStatusChanged",
- "syncFileSystem.onServiceStatusChanged",
- "syncFileSystem.requestFileSystem",
- "syncFileSystem.setConflictResolutionPolicy", "tabCapture.capture",
- "tabCapture.getCapturedTabs", "tabCapture.onStatusChanged",
- "tabs.captureVisibleTab", "tabs.connect", "tabs.create",
- "tabs.detectLanguage", "tabs.duplicate", "tabs.executeScript", "tabs.get",
- "tabs.getCurrent", "tabs.highlight", "tabs.insertCSS", "tabs.move",
- "tabs.onActivated", "tabs.onAttached", "tabs.onCreated", "tabs.onDetached",
- "tabs.onHighlighted", "tabs.onMoved", "tabs.onRemoved", "tabs.onReplaced",
- "tabs.onUpdated", "tabs.query", "tabs.reload", "tabs.remove",
- "tabs.sendMessage", "tabs.update", "topSites.get", "tts.getVoices",
- "tts.isSpeaking", "tts.speak", "tts.stop", "ttsEngine.onSpeak",
- "ttsEngine.onStop", "usb.bulkTransfer", "usb.claimInterface",
- "usb.closeDevice", "usb.controlTransfer", "usb.findDevices",
- "usb.interruptTransfer", "usb.isochronousTransfer", "usb.releaseInterface",
- "usb.setInterfaceAlternateSetting", "webNavigation.getAllFrames",
- "webNavigation.getFrame", "webNavigation.onBeforeNavigate",
- "webNavigation.onCommitted", "webNavigation.onCompleted",
- "webNavigation.onCreatedNavigationTarget",
- "webNavigation.onDOMContentLoaded", "webNavigation.onErrorOccurred",
- "webNavigation.onHistoryStateUpdated",
- "webNavigation.onReferenceFragmentUpdated", "webNavigation.onTabReplaced",
- "webRequest.handlerBehaviorChanged", "webRequest.onAuthRequired",
- "webRequest.onBeforeRedirect", "webRequest.onBeforeRequest",
- "webRequest.onBeforeSendHeaders", "webRequest.onCompleted",
- "webRequest.onErrorOccurred", "webRequest.onHeadersReceived",
- "webRequest.onResponseStarted", "webRequest.onSendHeaders",
- "webstore.install", "windows.create", "windows.get", "windows.getAll",
- "windows.getCurrent", "windows.getLastFocused", "windows.onCreated",
- "windows.onFocusChanged", "windows.onRemoved", "windows.remove",
- "windows.update",
- "tabs.getSelected", "tabs.sendRequest",
- "systemInfo.cpu.get", "systemInfo.memory.get",
- "runtime.onRestartRequired",
- "system.cpu.getInfo",
- "system.display.getInfo",
- "system.display.onDisplayChanged",
- "system.display.setDisplayProperties",
- "system.memory.getInfo",
- "system.storage.getInfo",
- "system.storage.onAttached",
- "system.storage.onDetached",
- "system.storage.ejectDevice",
- "system.storage.addAvailableCapacityWatch",
- "system.storage.removeAvailableCapacityWatch",
- "system.storage.getAllAvailableCapacityWatches",
- "system.storage.removeAllAvailableCapacityWatches",
- "system.storage.onAvailableCapacityChanged"
-};
-
-} // namespace activity_log_api_name_constants
-
-#endif // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_API_NAME_CONSTANTS_H_
diff --git a/chrome/browser/extensions/activity_log/counting_policy.cc b/chrome/browser/extensions/activity_log/counting_policy.cc
new file mode 100644
index 0000000..e99fade
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/counting_policy.cc
@@ -0,0 +1,505 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// A policy for storing activity log data to a database that performs
+// aggregation to reduce the size of the database. The database layout is
+// nearly the same as FullStreamUIPolicy, which stores a complete log, with a
+// few changes:
+// - a "count" column is added to track how many log records were merged
+// together into this row
+// - the "time" column measures the most recent time that the current row was
+// updated
+// When writing a record, if a row already exists where all other columns
+// (extension_id, action_type, api_name, args, urls, etc.) all match, and the
+// previous time falls within today (the current time), then the count field on
+// the old row is incremented. Otherwise, a new row is written.
+//
+// For many text columns, repeated strings are compressed by moving string
+// storage to a separate table ("string_ids") and storing only an identifier in
+// the logging table. For example, if the api_name_x column contained the
+// value 4 and the string_ids table contained a row with primary key 4 and
+// value 'tabs.query', then the api_name field should be taken to have the
+// value 'tabs.query'. Each column ending with "_x" is compressed in this way.
+// All lookups are to the string_ids table, except for the page_url_x and
+// arg_url_x columns, which are converted via the url_ids table (this
+// separation of URL values is to help simplify history clearing).
+//
+// The activitylog_uncompressed view allows for simpler reading of the activity
+// log contents with identifiers already translated to string values.
+
+#include "chrome/browser/extensions/activity_log/counting_policy.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_string_value_serializer.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/common/chrome_constants.h"
+
+using content::BrowserThread;
+
+namespace {
+
+// Delay between cleaning passes (to delete old action records) through the
+// database.
+const int kCleaningDelayInHours = 12;
+
+// We should log the arguments to these API calls. Be careful when
+// constructing this whitelist to not keep arguments that might compromise
+// privacy by logging too much data to the activity log.
+//
+// TODO(mvrable): The contents of this whitelist should be reviewed and
+// expanded as needed.
+const char* kAlwaysLog[] = {"extension.connect", "extension.sendMessage",
+ "tabs.executeScript", "tabs.insertCSS"};
+
+// Columns in the main database table. See the file-level comment for a
+// discussion of how data is stored and the meanings of the _x columns.
+const char* kTableContentFields[] = {
+ "count", "extension_id_x", "time", "action_type", "api_name_x", "args_x",
+ "page_url_x", "page_title_x", "arg_url_x", "other_x"};
+const char* kTableFieldTypes[] = {
+ "INTEGER NOT NULL DEFAULT 1", "INTEGER NOT NULL", "INTEGER", "INTEGER",
+ "INTEGER", "INTEGER", "INTEGER", "INTEGER", "INTEGER",
+ "INTEGER"};
+
+// Miscellaneous SQL commands for initializing the database; these should be
+// idempotent.
+static const char kPolicyMiscSetup[] =
+ // The activitylog_uncompressed view performs string lookups for simpler
+ // access to the log data.
+ "DROP VIEW IF EXISTS activitylog_uncompressed;\n"
+ "CREATE VIEW activitylog_uncompressed AS\n"
+ "SELECT count,\n"
+ " x1.value AS extension_id,\n"
+ " time,\n"
+ " action_type,\n"
+ " x2.value AS api_name,\n"
+ " x3.value AS args,\n"
+ " x4.value AS page_url,\n"
+ " x5.value AS page_title,\n"
+ " x6.value AS arg_url,\n"
+ " x7.value AS other\n"
+ "FROM activitylog_compressed\n"
+ " LEFT JOIN string_ids AS x1 ON (x1.id = extension_id_x)\n"
+ " LEFT JOIN string_ids AS x2 ON (x2.id = api_name_x)\n"
+ " LEFT JOIN string_ids AS x3 ON (x3.id = args_x)\n"
+ " LEFT JOIN url_ids AS x4 ON (x4.id = page_url_x)\n"
+ " LEFT JOIN string_ids AS x5 ON (x5.id = page_title_x)\n"
+ " LEFT JOIN url_ids AS x6 ON (x6.id = arg_url_x)\n"
+ " LEFT JOIN string_ids AS x7 ON (x7.id = other_x);\n"
+ // An index on all fields except count and time: all the fields that aren't
+ // changed when incrementing a count. This should accelerate finding the
+ // rows to update (at worst several rows will need to be checked to find
+ // the one in the right time range).
+ "CREATE INDEX IF NOT EXISTS activitylog_compressed_index\n"
+ "ON activitylog_compressed(extension_id_x, action_type, api_name_x,\n"
+ " args_x, page_url_x, page_title_x, arg_url_x, other_x)";
+
+// SQL statements to clean old, unused entries out of the string and URL id
+// tables.
+static const char kStringTableCleanup[] =
+ "DELETE FROM string_ids WHERE id NOT IN\n"
+ "(SELECT extension_id_x FROM activitylog_compressed\n"
+ " UNION SELECT api_name_x FROM activitylog_compressed\n"
+ " UNION SELECT args_x FROM activitylog_compressed\n"
+ " UNION SELECT page_title_x FROM activitylog_compressed\n"
+ " UNION SELECT other_x FROM activitylog_compressed)";
+static const char kUrlTableCleanup[] =
+ "DELETE FROM url_ids WHERE id NOT IN\n"
+ "(SELECT page_url_x FROM activitylog_compressed\n"
+ " UNION SELECT arg_url_x FROM activitylog_compressed)";
+
+} // namespace
+
+namespace extensions {
+
+// A specialized Action subclass which is used to represent an action read from
+// the database with a corresponding count.
+class CountedAction : public Action {
+ public:
+ CountedAction(const std::string& extension_id,
+ const base::Time& time,
+ const ActionType action_type,
+ const std::string& api_name)
+ : Action(extension_id, time, action_type, api_name) {}
+
+ // Number of merged records for this action.
+ int count() const { return count_; }
+ void set_count(int count) { count_ = count; }
+
+ virtual std::string PrintForDebug() const OVERRIDE;
+
+ protected:
+ virtual ~CountedAction() {}
+
+ private:
+ int count_;
+};
+
+std::string CountedAction::PrintForDebug() const {
+ return base::StringPrintf(
+ "%s COUNT=%d", Action::PrintForDebug().c_str(), count());
+}
+
+const char* CountingPolicy::kTableName = "activitylog_compressed";
+const char* CountingPolicy::kReadViewName = "activitylog_uncompressed";
+
+CountingPolicy::CountingPolicy(Profile* profile)
+ : ActivityLogDatabasePolicy(
+ profile,
+ base::FilePath(chrome::kExtensionActivityLogFilename)),
+ string_table_("string_ids"),
+ url_table_("url_ids"),
+ retention_time_(base::TimeDelta::FromHours(60)) {
+ for (size_t i = 0; i < arraysize(kAlwaysLog); i++) {
+ api_arg_whitelist_.insert(kAlwaysLog[i]);
+ }
+}
+
+CountingPolicy::~CountingPolicy() {}
+
+bool CountingPolicy::InitDatabase(sql::Connection* db) {
+ if (!Util::DropObsoleteTables(db))
+ return false;
+
+ if (!string_table_.Initialize(db))
+ return false;
+ if (!url_table_.Initialize(db))
+ return false;
+
+ // Create the unified activity log entry table.
+ if (!ActivityDatabase::InitializeTable(db,
+ kTableName,
+ kTableContentFields,
+ kTableFieldTypes,
+ arraysize(kTableContentFields)))
+ return false;
+
+ // Create a view for easily accessing the uncompressed form of the data, and
+ // any necessary indexes if needed.
+ return db->Execute(kPolicyMiscSetup);
+}
+
+void CountingPolicy::ProcessAction(scoped_refptr<Action> action) {
+ ScheduleAndForget(this, &CountingPolicy::QueueAction, action);
+}
+
+void CountingPolicy::QueueAction(scoped_refptr<Action> action) {
+ if (activity_database()->is_db_valid()) {
+ action = action->Clone();
+ Util::StripPrivacySensitiveFields(action);
+ Util::StripArguments(api_arg_whitelist_, action);
+ queued_actions_.push_back(action);
+ activity_database()->AdviseFlush(queued_actions_.size());
+ }
+}
+
+bool CountingPolicy::FlushDatabase(sql::Connection* db) {
+ // Columns that must match exactly for database rows to be coalesced.
+ static const char* matched_columns[] = {
+ "extension_id_x", "action_type", "api_name_x", "args_x", "page_url_x",
+ "page_title_x", "arg_url_x", "other_x"};
+ Action::ActionVector queue;
+ queue.swap(queued_actions_);
+
+ // Whether to clean old records out of the activity log database. Do this
+ // much less frequently than database flushes since it is expensive, but
+ // always check on the first database flush (since there might be a large
+ // amount of data to clear).
+ bool clean_database = (last_database_cleaning_time_.is_null() ||
+ Now() - last_database_cleaning_time_ >
+ base::TimeDelta::FromHours(kCleaningDelayInHours));
+
+ if (queue.empty() && !clean_database)
+ return true;
+
+ sql::Transaction transaction(db);
+ if (!transaction.Begin())
+ return false;
+
+ std::string insert_str =
+ "INSERT INTO " + std::string(kTableName) + "(count, time";
+ std::string update_str =
+ "UPDATE " + std::string(kTableName) +
+ " SET count = count + 1, time = max(?, time)"
+ " WHERE time >= ? AND time < ?";
+
+ for (size_t i = 0; i < arraysize(matched_columns); i++) {
+ insert_str =
+ base::StringPrintf("%s, %s", insert_str.c_str(), matched_columns[i]);
+ update_str = base::StringPrintf(
+ "%s AND %s IS ?", update_str.c_str(), matched_columns[i]);
+ }
+ insert_str += ") VALUES (1, ?";
+ for (size_t i = 0; i < arraysize(matched_columns); i++) {
+ insert_str += ", ?";
+ }
+ insert_str += ")";
+
+ Action::ActionVector::size_type i;
+ for (i = 0; i != queue.size(); ++i) {
+ const Action& action = *queue[i];
+
+ base::Time day_start = action.time().LocalMidnight();
+ base::Time next_day = Util::AddDays(day_start, 1);
+
+ // The contents in values must match up with fields in matched_columns. A
+ // value of -1 is used to encode a null database value.
+ int64 id;
+ std::vector<int64> matched_values;
+
+ if (!string_table_.StringToInt(db, action.extension_id(), &id))
+ return false;
+ matched_values.push_back(id);
+
+ matched_values.push_back(static_cast<int>(action.action_type()));
+
+ if (!string_table_.StringToInt(db, action.api_name(), &id))
+ return false;
+ matched_values.push_back(id);
+
+ if (action.args()) {
+ std::string args = Util::Serialize(action.args());
+ // TODO(mvrable): For now, truncate long argument lists. This is a
+ // workaround for excessively-long values coming from DOM logging. When
+ // the V8ValueConverter is fixed to return more reasonable values, we can
+ // drop the truncation.
+ if (args.length() > 10000) {
+ args = "[\"<too_large>\"]";
+ }
+ if (!string_table_.StringToInt(db, args, &id))
+ return false;
+ matched_values.push_back(id);
+ } else {
+ matched_values.push_back(-1);
+ }
+
+ std::string page_url_string = action.SerializePageUrl();
+ if (!page_url_string.empty()) {
+ if (!url_table_.StringToInt(db, page_url_string, &id))
+ return false;
+ matched_values.push_back(id);
+ } else {
+ matched_values.push_back(-1);
+ }
+
+ // TODO(mvrable): Create a title_table_?
+ if (!action.page_title().empty()) {
+ if (!string_table_.StringToInt(db, action.page_title(), &id))
+ return false;
+ matched_values.push_back(id);
+ } else {
+ matched_values.push_back(-1);
+ }
+
+ std::string arg_url_string = action.SerializeArgUrl();
+ if (!arg_url_string.empty()) {
+ if (!url_table_.StringToInt(db, arg_url_string, &id))
+ return false;
+ matched_values.push_back(id);
+ } else {
+ matched_values.push_back(-1);
+ }
+
+ if (action.other()) {
+ if (!string_table_.StringToInt(db, Util::Serialize(action.other()), &id))
+ return false;
+ matched_values.push_back(id);
+ } else {
+ matched_values.push_back(-1);
+ }
+
+ // Assume there is an existing row for this action, and try to update the
+ // count.
+ sql::Statement update_statement(db->GetCachedStatement(
+ sql::StatementID(SQL_FROM_HERE), update_str.c_str()));
+ update_statement.BindInt64(0, action.time().ToInternalValue());
+ update_statement.BindInt64(1, day_start.ToInternalValue());
+ update_statement.BindInt64(2, next_day.ToInternalValue());
+ for (size_t j = 0; j < matched_values.size(); j++) {
+ if (matched_values[j] == -1)
+ update_statement.BindNull(j + 3);
+ else
+ update_statement.BindInt64(j + 3, matched_values[j]);
+ }
+ if (!update_statement.Run())
+ return false;
+
+ // Check if the update succeeded (was the count of updated rows non-zero)?
+ // If it failed because no matching row existed, fall back to inserting a
+ // new record.
+ if (db->GetLastChangeCount() > 0) {
+ if (db->GetLastChangeCount() > 1) {
+ LOG(WARNING) << "Found and updated multiple rows in the activity log "
+ << "database; counts may be off!";
+ }
+ continue;
+ }
+ sql::Statement insert_statement(db->GetCachedStatement(
+ sql::StatementID(SQL_FROM_HERE), insert_str.c_str()));
+ insert_statement.BindInt64(0, action.time().ToInternalValue());
+ for (size_t j = 0; j < matched_values.size(); j++) {
+ if (matched_values[j] == -1)
+ update_statement.BindNull(j + 1);
+ else
+ insert_statement.BindInt64(j + 1, matched_values[j]);
+ }
+ if (!insert_statement.Run())
+ return false;
+ }
+
+ if (clean_database) {
+ base::Time cutoff = (Now() - retention_time()).LocalMidnight();
+ if (!CleanOlderThan(db, cutoff))
+ return false;
+ last_database_cleaning_time_ = Now();
+ }
+
+ if (!transaction.Commit())
+ return false;
+
+ return true;
+}
+
+scoped_ptr<Action::ActionVector> CountingPolicy::DoReadData(
+ const std::string& extension_id,
+ const int days_ago) {
+ // Ensure data is flushed to the database first so that we query over all
+ // data.
+ activity_database()->AdviseFlush(ActivityDatabase::kFlushImmediately);
+
+ DCHECK_GE(days_ago, 0);
+ scoped_ptr<Action::ActionVector> actions(new Action::ActionVector());
+
+ sql::Connection* db = GetDatabaseConnection();
+ if (!db) {
+ return actions.Pass();
+ }
+
+ int64 early_bound;
+ int64 late_bound;
+ Util::ComputeDatabaseTimeBounds(Now(), days_ago, &early_bound, &late_bound);
+ std::string query_str = base::StringPrintf(
+ "SELECT time, action_type, api_name, args, page_url, page_title, "
+ "arg_url, other, count "
+ "FROM %s WHERE extension_id=? AND time>? AND time<=? "
+ "ORDER BY time DESC",
+ kReadViewName);
+ sql::Statement query(db->GetCachedStatement(SQL_FROM_HERE,
+ query_str.c_str()));
+ query.BindString(0, extension_id);
+ query.BindInt64(1, early_bound);
+ query.BindInt64(2, late_bound);
+
+ while (query.is_valid() && query.Step()) {
+ scoped_refptr<CountedAction> action =
+ new CountedAction(extension_id,
+ base::Time::FromInternalValue(query.ColumnInt64(0)),
+ static_cast<Action::ActionType>(query.ColumnInt(1)),
+ query.ColumnString(2));
+
+ if (query.ColumnType(3) != sql::COLUMN_TYPE_NULL) {
+ scoped_ptr<Value> parsed_value(
+ base::JSONReader::Read(query.ColumnString(3)));
+ if (parsed_value && parsed_value->IsType(Value::TYPE_LIST)) {
+ action->set_args(
+ make_scoped_ptr(static_cast<ListValue*>(parsed_value.release())));
+ } else {
+ LOG(WARNING) << "Unable to parse args: '" << query.ColumnString(3)
+ << "'";
+ }
+ }
+
+ action->ParsePageUrl(query.ColumnString(4));
+ action->set_page_title(query.ColumnString(5));
+ action->ParseArgUrl(query.ColumnString(6));
+
+ if (query.ColumnType(7) != sql::COLUMN_TYPE_NULL) {
+ scoped_ptr<Value> parsed_value(
+ base::JSONReader::Read(query.ColumnString(7)));
+ if (parsed_value && parsed_value->IsType(Value::TYPE_DICTIONARY)) {
+ action->set_other(make_scoped_ptr(
+ static_cast<DictionaryValue*>(parsed_value.release())));
+ } else {
+ LOG(WARNING) << "Unable to parse other: '" << query.ColumnString(7)
+ << "'";
+ }
+ }
+
+ action->set_count(query.ColumnInt(8));
+
+ actions->push_back(action);
+ }
+
+ return actions.Pass();
+}
+
+void CountingPolicy::ReadData(
+ const std::string& extension_id,
+ const int day,
+ const base::Callback<void(scoped_ptr<Action::ActionVector>)>& callback) {
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::DB,
+ FROM_HERE,
+ base::Bind(&CountingPolicy::DoReadData,
+ base::Unretained(this),
+ extension_id,
+ day),
+ callback);
+}
+
+void CountingPolicy::OnDatabaseFailure() {
+ queued_actions_.clear();
+}
+
+void CountingPolicy::OnDatabaseClose() {
+ delete this;
+}
+
+// Cleans old records from the activity log database.
+bool CountingPolicy::CleanOlderThan(sql::Connection* db,
+ const base::Time& cutoff) {
+ std::string clean_statement =
+ "DELETE FROM " + std::string(kTableName) + " WHERE time < ?";
+ sql::Statement cleaner(db->GetCachedStatement(sql::StatementID(SQL_FROM_HERE),
+ clean_statement.c_str()));
+ cleaner.BindInt64(0, cutoff.ToInternalValue());
+ if (!cleaner.Run())
+ return false;
+ return CleanStringTables(db);
+}
+
+// Cleans unused interned strings from the database. This should be run after
+// deleting rows from the main log table to clean out stale values.
+bool CountingPolicy::CleanStringTables(sql::Connection* db) {
+ sql::Statement cleaner1(db->GetCachedStatement(
+ sql::StatementID(SQL_FROM_HERE), kStringTableCleanup));
+ if (!cleaner1.Run())
+ return false;
+ if (db->GetLastChangeCount() > 0)
+ string_table_.ClearCache();
+
+ sql::Statement cleaner2(db->GetCachedStatement(
+ sql::StatementID(SQL_FROM_HERE), kUrlTableCleanup));
+ if (!cleaner2.Run())
+ return false;
+ if (db->GetLastChangeCount() > 0)
+ url_table_.ClearCache();
+
+ return true;
+}
+
+void CountingPolicy::Close() {
+ // The policy object should have never been created if there's no DB thread.
+ DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::DB));
+ ScheduleAndForget(activity_database(), &ActivityDatabase::Close);
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/counting_policy.h b/chrome/browser/extensions/activity_log/counting_policy.h
new file mode 100644
index 0000000..5981bca
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/counting_policy.h
@@ -0,0 +1,100 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_COUNTING_POLICY_H_
+#define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_COUNTING_POLICY_H_
+
+#include <string>
+
+#include "base/containers/hash_tables.h"
+#include "chrome/browser/extensions/activity_log/activity_database.h"
+#include "chrome/browser/extensions/activity_log/activity_log_policy.h"
+#include "chrome/browser/extensions/activity_log/database_string_table.h"
+
+namespace extensions {
+
+// A policy for logging the stream of actions, but without arguments.
+class CountingPolicy : public ActivityLogDatabasePolicy {
+ public:
+ explicit CountingPolicy(Profile* profile);
+ virtual ~CountingPolicy();
+
+ virtual void ProcessAction(scoped_refptr<Action> action) OVERRIDE;
+
+ virtual void ReadData(
+ const std::string& extension_id,
+ const int day,
+ const base::Callback
+ <void(scoped_ptr<Action::ActionVector>)>& callback) OVERRIDE;
+
+ virtual void Close() OVERRIDE;
+
+ // Gets or sets the amount of time that old records are kept in the database.
+ const base::TimeDelta& retention_time() const { return retention_time_; }
+ void set_retention_time(const base::TimeDelta& delta) {
+ retention_time_ = delta;
+ }
+
+ // The main database table, and the name for a read-only view that
+ // decompresses string values for easier parsing.
+ static const char* kTableName;
+ static const char* kReadViewName;
+
+ protected:
+ // The ActivityDatabase::Delegate interface. These are always called from
+ // the database thread.
+ virtual bool InitDatabase(sql::Connection* db) OVERRIDE;
+ virtual bool FlushDatabase(sql::Connection* db) OVERRIDE;
+ virtual void OnDatabaseFailure() OVERRIDE;
+ virtual void OnDatabaseClose() OVERRIDE;
+
+ private:
+ // Adds an Action to those to be written out; this is an internal method used
+ // by ProcessAction and is called on the database thread.
+ void QueueAction(scoped_refptr<Action> action);
+
+ // Internal method to read data from the database; called on the database
+ // thread.
+ scoped_ptr<Action::ActionVector> DoReadData(
+ const std::string& extension_id,
+ const int days_ago);
+
+ // Cleans old records from the activity log database.
+ bool CleanOlderThan(sql::Connection* db, const base::Time& cutoff);
+
+ // Cleans unused interned strings from the database. This should be run
+ // after deleting rows from the main log table to clean out stale values.
+ bool CleanStringTables(sql::Connection* db);
+
+ // API calls for which complete arguments should be logged.
+ std::set<std::string> api_arg_whitelist_;
+
+ // Tables for mapping strings to integers for shrinking database storage
+ // requirements. URLs are kept in a separate table from other strings to
+ // make history clearing simpler.
+ DatabaseStringTable string_table_;
+ DatabaseStringTable url_table_;
+
+ // Tracks any pending updates to be written to the database, if write
+ // batching is turned on. Should only be accessed from the database thread.
+ // TODO(mvrable): Do in-memory aggregation as well.
+ Action::ActionVector queued_actions_;
+
+ // The amount of time old activity log records should be kept in the
+ // database. This time is subtracted from the current time, rounded down to
+ // midnight, and rows older than this are deleted from the database when
+ // cleaning runs.
+ base::TimeDelta retention_time_;
+
+ // The time at which old activity log records were last cleaned out of the
+ // database (only tracked for this browser session). Old records are deleted
+ // on the first database flush, and then every 12 hours subsequently.
+ base::Time last_database_cleaning_time_;
+
+ FRIEND_TEST_ALL_PREFIXES(CountingPolicyTest, MergingAndExpiring);
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_COUNTING_POLICY_H_
diff --git a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
new file mode 100644
index 0000000..748b528
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
@@ -0,0 +1,407 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/cancelable_callback.h"
+#include "base/command_line.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/simple_test_clock.h"
+#include "chrome/browser/extensions/activity_log/activity_log.h"
+#include "chrome/browser/extensions/activity_log/counting_policy.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/test_extension_system.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension_builder.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "sql/statement.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
+#include "chrome/browser/chromeos/settings/device_settings_service.h"
+#endif
+
+namespace extensions {
+
+class CountingPolicyTest : public testing::Test {
+ public:
+ CountingPolicyTest()
+ : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+ saved_cmdline_(CommandLine::NO_PROGRAM) {
+#if defined OS_CHROMEOS
+ test_user_manager_.reset(new chromeos::ScopedTestUserManager());
+#endif
+ CommandLine command_line(CommandLine::NO_PROGRAM);
+ saved_cmdline_ = *CommandLine::ForCurrentProcess();
+ profile_.reset(new TestingProfile());
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExtensionActivityLogging);
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExtensionActivityLogTesting);
+ extension_service_ = static_cast<TestExtensionSystem*>(
+ ExtensionSystem::Get(profile_.get()))->CreateExtensionService
+ (&command_line, base::FilePath(), false);
+ }
+
+ virtual ~CountingPolicyTest() {
+#if defined OS_CHROMEOS
+ test_user_manager_.reset();
+#endif
+ base::RunLoop().RunUntilIdle();
+ profile_.reset(NULL);
+ base::RunLoop().RunUntilIdle();
+ // Restore the original command line and undo the affects of SetUp().
+ *CommandLine::ForCurrentProcess() = saved_cmdline_;
+ }
+
+ // A helper function to call ReadData on a policy object and wait for the
+ // results to be processed.
+ void CheckReadData(
+ ActivityLogPolicy* policy,
+ const std::string& extension_id,
+ const int day,
+ const base::Callback<void(scoped_ptr<Action::ActionVector>)>& checker) {
+ // Submit a request to the policy to read back some data, and call the
+ // checker function when results are available. This will happen on the
+ // database thread.
+ policy->ReadData(
+ extension_id,
+ day,
+ base::Bind(&CountingPolicyTest::CheckWrapper,
+ checker,
+ base::MessageLoop::current()->QuitClosure()));
+
+ // Set up a timeout that will trigger after 5 seconds; if we haven't
+ // received any results by then assume that the test is broken.
+ base::CancelableClosure timeout(
+ base::Bind(&CountingPolicyTest::TimeoutCallback));
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE, timeout.callback(), base::TimeDelta::FromSeconds(5));
+
+ // Wait for results; either the checker or the timeout callbacks should
+ // cause the main loop to exit.
+ base::MessageLoop::current()->Run();
+
+ timeout.Cancel();
+ }
+
+ static void CheckWrapper(
+ const base::Callback<void(scoped_ptr<Action::ActionVector>)>& checker,
+ const base::Closure& done,
+ scoped_ptr<Action::ActionVector> results) {
+ checker.Run(results.Pass());
+ done.Run();
+ }
+
+ static void TimeoutCallback() {
+ base::MessageLoop::current()->QuitWhenIdle();
+ FAIL() << "Policy test timed out waiting for results";
+ }
+
+ static void Arguments_Stripped(scoped_ptr<Action::ActionVector> i) {
+ scoped_refptr<Action> last = i->front();
+ std::string args =
+ "ID=odlameecjipmbmbejkplpemijjgpljce CATEGORY=api_call "
+ "API=extension.connect ARGS=[\"hello\",\"world\"] COUNT=1";
+ ASSERT_EQ(args, last->PrintForDebug());
+ }
+
+ static void Arguments_GetTodaysActions(
+ scoped_ptr<Action::ActionVector> actions) {
+ std::string api_stripped_print =
+ "ID=punky CATEGORY=api_call API=brewster COUNT=2";
+ std::string api_print =
+ "ID=punky CATEGORY=api_call API=extension.sendMessage "
+ "ARGS=[\"not\",\"stripped\"] COUNT=1";
+ std::string dom_print =
+ "ID=punky CATEGORY=dom_access API=lets ARGS=[\"vamoose\"] "
+ "PAGE_URL=http://www.google.com/ COUNT=1";
+ ASSERT_EQ(3, static_cast<int>(actions->size()));
+ ASSERT_EQ(dom_print, actions->at(0)->PrintForDebug());
+ ASSERT_EQ(api_print, actions->at(1)->PrintForDebug());
+ ASSERT_EQ(api_stripped_print, actions->at(2)->PrintForDebug());
+ }
+
+ static void Arguments_GetOlderActions(
+ scoped_ptr<Action::ActionVector> actions) {
+ std::string api_print =
+ "ID=punky CATEGORY=api_call API=brewster COUNT=1";
+ std::string dom_print =
+ "ID=punky CATEGORY=dom_access API=lets ARGS=[\"vamoose\"] "
+ "PAGE_URL=http://www.google.com/ COUNT=1";
+ ASSERT_EQ(2, static_cast<int>(actions->size()));
+ ASSERT_EQ(dom_print, actions->at(0)->PrintForDebug());
+ ASSERT_EQ(api_print, actions->at(1)->PrintForDebug());
+ }
+
+ static void Arguments_CheckMergeCount(
+ int count,
+ scoped_ptr<Action::ActionVector> actions) {
+ std::string api_print = base::StringPrintf(
+ "ID=punky CATEGORY=api_call API=brewster COUNT=%d", count);
+ if (count > 0) {
+ ASSERT_EQ(1u, actions->size());
+ ASSERT_EQ(api_print, actions->at(0)->PrintForDebug());
+ } else {
+ ASSERT_EQ(0u, actions->size());
+ }
+ }
+
+ protected:
+ ExtensionService* extension_service_;
+ scoped_ptr<TestingProfile> profile_;
+ content::TestBrowserThreadBundle thread_bundle_;
+ // Used to preserve a copy of the original command line.
+ // The test framework will do this itself as well. However, by then,
+ // it is too late to call ActivityLog::RecomputeLoggingIsEnabled() in
+ // TearDown().
+ CommandLine saved_cmdline_;
+
+#if defined OS_CHROMEOS
+ chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
+ chromeos::ScopedTestCrosSettings test_cros_settings_;
+ scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
+#endif
+};
+
+TEST_F(CountingPolicyTest, Construct) {
+ ActivityLogPolicy* policy = new CountingPolicy(profile_.get());
+ scoped_refptr<const Extension> extension =
+ ExtensionBuilder()
+ .SetManifest(DictionaryBuilder()
+ .Set("name", "Test extension")
+ .Set("version", "1.0.0")
+ .Set("manifest_version", 2))
+ .Build();
+ extension_service_->AddExtension(extension.get());
+ scoped_ptr<base::ListValue> args(new base::ListValue());
+ scoped_refptr<Action> action = new Action(extension->id(),
+ base::Time::Now(),
+ Action::ACTION_API_CALL,
+ "tabs.testMethod");
+ action->set_args(args.Pass());
+ policy->ProcessAction(action);
+ policy->Close();
+}
+
+TEST_F(CountingPolicyTest, LogWithStrippedArguments) {
+ ActivityLogPolicy* policy = new CountingPolicy(profile_.get());
+ scoped_refptr<const Extension> extension =
+ ExtensionBuilder()
+ .SetManifest(DictionaryBuilder()
+ .Set("name", "Test extension")
+ .Set("version", "1.0.0")
+ .Set("manifest_version", 2))
+ .Build();
+ extension_service_->AddExtension(extension.get());
+
+ scoped_ptr<base::ListValue> args(new base::ListValue());
+ args->Set(0, new base::StringValue("hello"));
+ args->Set(1, new base::StringValue("world"));
+ scoped_refptr<Action> action = new Action(extension->id(),
+ base::Time::Now(),
+ Action::ACTION_API_CALL,
+ "extension.connect");
+ action->set_args(args.Pass());
+
+ policy->ProcessAction(action);
+ CheckReadData(policy,
+ extension->id(),
+ 0,
+ base::Bind(&CountingPolicyTest::Arguments_Stripped));
+ policy->Close();
+}
+
+TEST_F(CountingPolicyTest, GetTodaysActions) {
+ CountingPolicy* policy = new CountingPolicy(profile_.get());
+ // Disable row expiration for this test by setting a time before any actions
+ // we generate.
+ policy->set_retention_time(base::TimeDelta::FromDays(14));
+
+ // Use a mock clock to ensure that events are not recorded on the wrong day
+ // when the test is run close to local midnight. Note: Ownership is passed
+ // to the policy, but we still keep a pointer locally. The policy will take
+ // care of destruction; this is safe since the policy outlives all our
+ // accesses to the mock clock.
+ base::SimpleTestClock* mock_clock = new base::SimpleTestClock();
+ mock_clock->SetNow(base::Time::Now().LocalMidnight() +
+ base::TimeDelta::FromHours(12));
+ policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock));
+
+ // Record some actions
+ scoped_refptr<Action> action =
+ new Action("punky",
+ mock_clock->Now() - base::TimeDelta::FromMinutes(40),
+ Action::ACTION_API_CALL,
+ "brewster");
+ action->mutable_args()->AppendString("woof");
+ policy->ProcessAction(action);
+
+ action = new Action("punky",
+ mock_clock->Now() - base::TimeDelta::FromMinutes(30),
+ Action::ACTION_API_CALL,
+ "brewster");
+ action->mutable_args()->AppendString("meow");
+ policy->ProcessAction(action);
+
+ action = new Action("punky",
+ mock_clock->Now() - base::TimeDelta::FromMinutes(20),
+ Action::ACTION_API_CALL,
+ "extension.sendMessage");
+ action->mutable_args()->AppendString("not");
+ action->mutable_args()->AppendString("stripped");
+ policy->ProcessAction(action);
+
+ action =
+ new Action("punky", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets");
+ action->mutable_args()->AppendString("vamoose");
+ action->set_page_url(GURL("http://www.google.com"));
+ policy->ProcessAction(action);
+
+ action = new Action(
+ "scoobydoo", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets");
+ action->mutable_args()->AppendString("vamoose");
+ action->set_page_url(GURL("http://www.google.com"));
+ policy->ProcessAction(action);
+
+ CheckReadData(
+ policy,
+ "punky",
+ 0,
+ base::Bind(&CountingPolicyTest::Arguments_GetTodaysActions));
+ policy->Close();
+}
+
+// Check that we can read back less recent actions in the db.
+TEST_F(CountingPolicyTest, GetOlderActions) {
+ CountingPolicy* policy = new CountingPolicy(profile_.get());
+ policy->set_retention_time(base::TimeDelta::FromDays(14));
+
+ // Use a mock clock to ensure that events are not recorded on the wrong day
+ // when the test is run close to local midnight.
+ base::SimpleTestClock* mock_clock = new base::SimpleTestClock();
+ mock_clock->SetNow(base::Time::Now().LocalMidnight() +
+ base::TimeDelta::FromHours(12));
+ policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock));
+
+ // Record some actions
+ scoped_refptr<Action> action =
+ new Action("punky",
+ mock_clock->Now() - base::TimeDelta::FromDays(3) -
+ base::TimeDelta::FromMinutes(40),
+ Action::ACTION_API_CALL,
+ "brewster");
+ action->mutable_args()->AppendString("woof");
+ policy->ProcessAction(action);
+
+ action = new Action("punky",
+ mock_clock->Now() - base::TimeDelta::FromDays(3),
+ Action::ACTION_DOM_ACCESS,
+ "lets");
+ action->mutable_args()->AppendString("vamoose");
+ action->set_page_url(GURL("http://www.google.com"));
+ policy->ProcessAction(action);
+
+ action = new Action("punky",
+ mock_clock->Now(),
+ Action::ACTION_DOM_ACCESS,
+ "lets");
+ action->mutable_args()->AppendString("too new");
+ action->set_page_url(GURL("http://www.google.com"));
+ policy->ProcessAction(action);
+
+ action = new Action("punky",
+ mock_clock->Now() - base::TimeDelta::FromDays(7),
+ Action::ACTION_DOM_ACCESS,
+ "lets");
+ action->mutable_args()->AppendString("too old");
+ action->set_page_url(GURL("http://www.google.com"));
+ policy->ProcessAction(action);
+
+ CheckReadData(
+ policy,
+ "punky",
+ 3,
+ base::Bind(&CountingPolicyTest::Arguments_GetOlderActions));
+
+ policy->Close();
+}
+
+// Check that merging of actions only occurs within the same day, not across
+// days, and that old data can be expired from the database.
+TEST_F(CountingPolicyTest, MergingAndExpiring) {
+ CountingPolicy* policy = new CountingPolicy(profile_.get());
+ // Initially disable expiration by setting a retention time before any
+ // actions we generate.
+ policy->set_retention_time(base::TimeDelta::FromDays(14));
+
+ // Use a mock clock to ensure that events are not recorded on the wrong day
+ // when the test is run close to local midnight.
+ base::SimpleTestClock* mock_clock = new base::SimpleTestClock();
+ mock_clock->SetNow(base::Time::Now().LocalMidnight() +
+ base::TimeDelta::FromHours(12));
+ policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock));
+
+ // The first two actions should be merged; the last one is on a separate day
+ // and should not be.
+ scoped_refptr<Action> action =
+ new Action("punky",
+ mock_clock->Now() - base::TimeDelta::FromDays(3) -
+ base::TimeDelta::FromMinutes(40),
+ Action::ACTION_API_CALL,
+ "brewster");
+ policy->ProcessAction(action);
+
+ action = new Action("punky",
+ mock_clock->Now() - base::TimeDelta::FromDays(3) -
+ base::TimeDelta::FromMinutes(20),
+ Action::ACTION_API_CALL,
+ "brewster");
+ policy->ProcessAction(action);
+
+ action = new Action("punky",
+ mock_clock->Now() - base::TimeDelta::FromDays(2) -
+ base::TimeDelta::FromMinutes(20),
+ Action::ACTION_API_CALL,
+ "brewster");
+ policy->ProcessAction(action);
+
+ CheckReadData(policy,
+ "punky",
+ 3,
+ base::Bind(&CountingPolicyTest::Arguments_CheckMergeCount, 2));
+ CheckReadData(policy,
+ "punky",
+ 2,
+ base::Bind(&CountingPolicyTest::Arguments_CheckMergeCount, 1));
+
+ // Clean actions before midnight two days ago. Force expiration to run by
+ // clearing last_database_cleaning_time_ and submitting a new action.
+ policy->set_retention_time(base::TimeDelta::FromDays(2));
+ policy->last_database_cleaning_time_ = base::Time();
+ action = new Action("punky",
+ mock_clock->Now(),
+ Action::ACTION_API_CALL,
+ "brewster");
+ policy->ProcessAction(action);
+
+ CheckReadData(policy,
+ "punky",
+ 3,
+ base::Bind(&CountingPolicyTest::Arguments_CheckMergeCount, 0));
+ CheckReadData(policy,
+ "punky",
+ 2,
+ base::Bind(&CountingPolicyTest::Arguments_CheckMergeCount, 1));
+
+ policy->Close();
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/database_string_table.cc b/chrome/browser/extensions/activity_log/database_string_table.cc
new file mode 100644
index 0000000..c9e832e
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/database_string_table.cc
@@ -0,0 +1,103 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/activity_log/database_string_table.h"
+
+#include "base/strings/stringprintf.h"
+#include "sql/connection.h"
+#include "sql/statement.h"
+
+using base::StringPrintf;
+
+namespace extensions {
+
+DatabaseStringTable::DatabaseStringTable(const std::string& table)
+ : table_(table) {}
+
+DatabaseStringTable::~DatabaseStringTable() {}
+
+bool DatabaseStringTable::Initialize(sql::Connection* connection) {
+ if (!connection->DoesTableExist(table_.c_str())) {
+ return connection->Execute(StringPrintf(
+ "CREATE TABLE %s (id INTEGER PRIMARY KEY, value TEXT NOT NULL); "
+ "CREATE UNIQUE INDEX %s_index ON %s(value)",
+ table_.c_str(),
+ table_.c_str(),
+ table_.c_str()).c_str());
+ } else {
+ return true;
+ }
+}
+
+bool DatabaseStringTable::StringToInt(sql::Connection* connection,
+ const std::string& value,
+ int64* id) {
+ std::map<std::string, int64>::const_iterator lookup =
+ value_to_id_.find(value);
+ if (lookup != value_to_id_.end()) {
+ *id = lookup->second;
+ return true;
+ }
+
+ // Operate on the assumption that the cache does a good job on
+ // frequently-used strings--if there is a cache miss, first act on the
+ // assumption that the string is not in the database either.
+ sql::Statement update(connection->GetUniqueStatement(
+ StringPrintf("INSERT OR IGNORE INTO %s(value) VALUES (?)", table_.c_str())
+ .c_str()));
+ update.BindString(0, value);
+ if (!update.Run())
+ return false;
+
+ if (connection->GetLastChangeCount() == 1) {
+ *id = connection->GetLastInsertRowId();
+ id_to_value_[*id] = value;
+ value_to_id_[value] = *id;
+ return true;
+ }
+
+ // The specified string may have already existed in the database, in which
+ // case the insert above will have been ignored. If this happens, do a
+ // lookup to find the old value.
+ sql::Statement query(connection->GetUniqueStatement(
+ StringPrintf("SELECT id FROM %s WHERE value = ?", table_.c_str())
+ .c_str()));
+ query.BindString(0, value);
+ if (!query.Step())
+ return false;
+ *id = query.ColumnInt64(0);
+ id_to_value_[*id] = value;
+ value_to_id_[value] = *id;
+ return true;
+}
+
+bool DatabaseStringTable::IntToString(sql::Connection* connection,
+ int64 id,
+ std::string* value) {
+ std::map<int64, std::string>::const_iterator lookup =
+ id_to_value_.find(id);
+ if (lookup != id_to_value_.end()) {
+ *value = lookup->second;
+ return true;
+ }
+
+ sql::Statement query(connection->GetUniqueStatement(
+ StringPrintf("SELECT value FROM %s WHERE id = ?", table_.c_str())
+ .c_str()));
+ query.BindInt64(0, id);
+ if (!query.Step())
+ return false;
+
+ *value = query.ColumnString(0);
+ id_to_value_[id] = *value;
+ value_to_id_[*value] = id;
+ return true;
+}
+
+void DatabaseStringTable::ClearCache() {
+ id_to_value_.clear();
+ value_to_id_.clear();
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/database_string_table.h b/chrome/browser/extensions/activity_log/database_string_table.h
new file mode 100644
index 0000000..9677fae
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/database_string_table.h
@@ -0,0 +1,71 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_DATABASE_STRING_TABLE_H_
+#define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_DATABASE_STRING_TABLE_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+
+namespace sql {
+class Connection;
+} // namespace sql
+
+namespace extensions {
+
+// A class for maintaining a persistent mapping between strings and integers.
+// This is used to help compress the contents of the activity log database on
+// disk by replacing repeated strings by smaller integers.
+//
+// The mapping from integers to strings is maintained in a database table, but
+// the mapping is also cached in memory.
+//
+// The database table used to store the strings is configurable, but its layout
+// is fixed: it always consists of just two columns, "id" and "value".
+//
+// All calls to DatabaseStringTable must occur on the database thread.
+class DatabaseStringTable {
+ public:
+ explicit DatabaseStringTable(const std::string& table);
+
+ ~DatabaseStringTable();
+
+ // Initialize the database table. This will create the table if it does not
+ // exist. Returns true on success; false on error.
+ bool Initialize(sql::Connection* connection);
+
+ // Interns a string in the database table and sets *id to the corresponding
+ // integer. If the string already exists, the existing number is returned;
+ // otherwise, new database row is inserted with the new string. Returns true
+ // on success and false on database error.
+ bool StringToInt(sql::Connection* connection,
+ const std::string& value,
+ int64* id);
+
+ // Looks up an integer value and converts it to a string (which is stored in
+ // *value). Returns true on success. A false return does not necessarily
+ // indicate a database error; it might simply be that the value cannot be
+ // found.
+ bool IntToString(sql::Connection* connection, int64 id, std::string* value);
+
+ // Clear the in-memory cache; this should be called if the underlying
+ // database table has been manipulated and the cache may be stale.
+ void ClearCache();
+
+ private:
+ // In-memory caches of recently accessed values.
+ std::map<int64, std::string> id_to_value_;
+ std::map<std::string, int64> value_to_id_;
+
+ // The name of the database table where the mapping is stored.
+ std::string table_;
+
+ DISALLOW_COPY_AND_ASSIGN(DatabaseStringTable);
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_DATABASE_STRING_TABLE_H_
diff --git a/chrome/browser/extensions/activity_log/database_string_table_unittest.cc b/chrome/browser/extensions/activity_log/database_string_table_unittest.cc
new file mode 100644
index 0000000..2024827
--- /dev/null
+++ b/chrome/browser/extensions/activity_log/database_string_table_unittest.cc
@@ -0,0 +1,133 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/files/scoped_temp_dir.h"
+#include "chrome/browser/extensions/activity_log/database_string_table.h"
+#include "sql/connection.h"
+#include "sql/statement.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+class DatabaseStringTableTest : public testing::Test {
+ protected:
+ virtual void SetUp() OVERRIDE {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ base::FilePath db_file = temp_dir_.path().AppendASCII("StringTable.db");
+
+ ASSERT_TRUE(db_.Open(db_file));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ db_.Close();
+ }
+
+ base::ScopedTempDir temp_dir_;
+ sql::Connection db_;
+};
+
+// Check that initializing the database works.
+TEST_F(DatabaseStringTableTest, Init) {
+ DatabaseStringTable table("test");
+ table.Initialize(&db_);
+ ASSERT_TRUE(db_.DoesTableExist("test"));
+ ASSERT_TRUE(db_.DoesIndexExist("test_index"));
+}
+
+// Insert a new mapping into the table, then verify the table contents.
+TEST_F(DatabaseStringTableTest, Insert) {
+ DatabaseStringTable table("test");
+ table.Initialize(&db_);
+ int64 id;
+ ASSERT_TRUE(table.StringToInt(&db_, "abc", &id));
+
+ sql::Statement query(
+ db_.GetUniqueStatement("SELECT id FROM test WHERE value = 'abc'"));
+ ASSERT_TRUE(query.Step());
+ int64 raw_id = query.ColumnInt64(0);
+ ASSERT_EQ(id, raw_id);
+}
+
+// Check that different strings are mapped to different values, and the same
+// string is mapped to the same value repeatably.
+TEST_F(DatabaseStringTableTest, InsertMultiple) {
+ DatabaseStringTable table("test");
+ table.Initialize(&db_);
+
+ int64 id1;
+ int64 id2;
+ ASSERT_TRUE(table.StringToInt(&db_, "string1", &id1));
+ ASSERT_TRUE(table.StringToInt(&db_, "string2", &id2));
+ ASSERT_NE(id1, id2);
+
+ int64 id1a;
+ ASSERT_TRUE(table.StringToInt(&db_, "string1", &id1a));
+ ASSERT_EQ(id1, id1a);
+}
+
+// Check that values can be read back from the database even after the
+// in-memory cache is cleared.
+TEST_F(DatabaseStringTableTest, CacheCleared) {
+ DatabaseStringTable table("test");
+ table.Initialize(&db_);
+
+ int64 id1;
+ ASSERT_TRUE(table.StringToInt(&db_, "string1", &id1));
+
+ table.ClearCache();
+
+ int64 id2;
+ ASSERT_TRUE(table.StringToInt(&db_, "string1", &id2));
+ ASSERT_EQ(id1, id2);
+}
+
+// Check that direct database modifications are picked up after the cache is
+// cleared.
+TEST_F(DatabaseStringTableTest, DatabaseModified) {
+ DatabaseStringTable table("test");
+ table.Initialize(&db_);
+
+ int64 id1;
+ ASSERT_TRUE(table.StringToInt(&db_, "modified", &id1));
+
+ ASSERT_TRUE(
+ db_.Execute("UPDATE test SET id = id + 1 WHERE value = 'modified'"));
+
+ int64 id2;
+ ASSERT_TRUE(table.StringToInt(&db_, "modified", &id2));
+ ASSERT_EQ(id1, id2);
+
+ table.ClearCache();
+
+ int64 id3;
+ ASSERT_TRUE(table.StringToInt(&db_, "modified", &id3));
+ ASSERT_EQ(id1 + 1, id3);
+}
+
+// Check that looking up an unknown id returns an error.
+TEST_F(DatabaseStringTableTest, BadLookup) {
+ DatabaseStringTable table("test");
+ table.Initialize(&db_);
+ std::string value;
+ ASSERT_FALSE(table.IntToString(&db_, 1, &value));
+}
+
+// Check looking up an inserted value, both cached and not cached.
+TEST_F(DatabaseStringTableTest, Lookup) {
+ DatabaseStringTable table("test");
+ table.Initialize(&db_);
+ int64 id;
+ ASSERT_TRUE(table.StringToInt(&db_, "abc", &id));
+
+ std::string value;
+ ASSERT_TRUE(table.IntToString(&db_, id, &value));
+ ASSERT_EQ("abc", value);
+
+ table.ClearCache();
+ value = "";
+ ASSERT_TRUE(table.IntToString(&db_, id, &value));
+ ASSERT_EQ("abc", value);
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc b/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc
index 24f5494..94f6371 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy.cc
@@ -31,32 +31,6 @@
namespace constants = activity_log_constants;
-namespace {
-
-// Key strings for passing parameters to the ProcessAction member function.
-const char kKeyReason[] = "fsuip.reason";
-const char kKeyDomainAction[] = "fsuip.domact";
-const char kKeyURLTitle[] = "fsuip.urltitle";
-const char kKeyDetailsString[] = "fsuip.details";
-
-// Obsolete database tables: these should be dropped from the database if
-// found.
-const char* kObsoleteTables[] = {"activitylog_apis", "activitylog_blocked",
- "activitylog_urls"};
-
-std::string Serialize(const base::Value* value) {
- std::string value_as_text;
- if (!value) {
- value_as_text = "null";
- } else {
- JSONStringValueSerializer serializer(&value_as_text);
- serializer.SerializeAndOmitBinaryValues(*value);
- }
- return value_as_text;
-}
-
-} // namespace
-
namespace extensions {
const char* FullStreamUIPolicy::kTableName = "activitylog_full";
@@ -68,7 +42,8 @@
"LONGVARCHAR NOT NULL", "INTEGER", "INTEGER", "LONGVARCHAR", "LONGVARCHAR",
"LONGVARCHAR", "LONGVARCHAR", "LONGVARCHAR", "LONGVARCHAR"
};
-const int FullStreamUIPolicy::kTableFieldCount = arraysize(kTableContentFields);
+const int FullStreamUIPolicy::kTableFieldCount =
+ arraysize(FullStreamUIPolicy::kTableContentFields);
FullStreamUIPolicy::FullStreamUIPolicy(Profile* profile)
: ActivityLogDatabasePolicy(
@@ -78,17 +53,8 @@
FullStreamUIPolicy::~FullStreamUIPolicy() {}
bool FullStreamUIPolicy::InitDatabase(sql::Connection* db) {
- // Drop old database tables.
- for (size_t i = 0; i < arraysize(kObsoleteTables); i++) {
- const char* table_name = kObsoleteTables[i];
- if (db->DoesTableExist(table_name)) {
- std::string drop_statement =
- base::StringPrintf("DROP TABLE %s", table_name);
- if (!db->Execute(drop_statement.c_str())) {
- return false;
- }
- }
- }
+ if (!Util::DropObsoleteTables(db))
+ return false;
// Create the unified activity log entry table.
return ActivityDatabase::InitializeTable(db,
@@ -113,13 +79,6 @@
sql::Statement statement(db->GetCachedStatement(
sql::StatementID(SQL_FROM_HERE), sql_str.c_str()));
- url_canon::Replacements<char> url_sanitizer;
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableExtensionActivityLogTesting)) {
- url_sanitizer.ClearQuery();
- url_sanitizer.ClearRef();
- }
-
Action::ActionVector::size_type i;
for (i = 0; i != queued_actions_.size(); ++i) {
const Action& action = *queued_actions_[i];
@@ -129,29 +88,21 @@
statement.BindInt(2, static_cast<int>(action.action_type()));
statement.BindString(3, action.api_name());
if (action.args()) {
- statement.BindString(4, Serialize(action.args()));
+ statement.BindString(4, Util::Serialize(action.args()));
}
- if (action.page_url().is_valid()) {
- if (action.page_incognito()) {
- statement.BindString(5, constants::kIncognitoUrl);
- } else {
- statement.BindString(
- 5, action.page_url().ReplaceComponents(url_sanitizer).spec());
- }
+ std::string page_url_string = action.SerializePageUrl();
+ if (!page_url_string.empty()) {
+ statement.BindString(5, page_url_string);
}
- if (!action.page_title().empty() && !action.page_incognito()) {
+ if (!action.page_title().empty()) {
statement.BindString(6, action.page_title());
}
- if (action.arg_url().is_valid()) {
- if (action.arg_incognito()) {
- statement.BindString(7, constants::kIncognitoUrl);
- } else {
- statement.BindString(
- 7, action.arg_url().ReplaceComponents(url_sanitizer).spec());
- }
+ std::string arg_url_string = action.SerializePageUrl();
+ if (!arg_url_string.empty()) {
+ statement.BindString(5, arg_url_string);
}
if (action.other()) {
- statement.BindString(8, Serialize(action.other()));
+ statement.BindString(8, Util::Serialize(action.other()));
}
if (!statement.Run()) {
@@ -170,6 +121,10 @@
scoped_ptr<Action::ActionVector> FullStreamUIPolicy::DoReadData(
const std::string& extension_id,
const int days_ago) {
+ // Ensure data is flushed to the database first so that we query over all
+ // data.
+ activity_database()->AdviseFlush(ActivityDatabase::kFlushImmediately);
+
DCHECK_GE(days_ago, 0);
scoped_ptr<Action::ActionVector> actions(new Action::ActionVector());
@@ -178,21 +133,9 @@
return actions.Pass();
}
- // Compute the time bounds for that day.
- base::Time morning_midnight = Now().LocalMidnight();
- int64 early_bound = 0;
- int64 late_bound = 0;
- if (days_ago == 0) {
- early_bound = morning_midnight.ToInternalValue();
- late_bound = base::Time::Max().ToInternalValue();
- } else {
- base::Time early_time = morning_midnight -
- base::TimeDelta::FromDays(days_ago);
- base::Time late_time = morning_midnight -
- base::TimeDelta::FromDays(days_ago-1);
- early_bound = early_time.ToInternalValue();
- late_bound = late_time.ToInternalValue();
- }
+ int64 early_bound;
+ int64 late_bound;
+ Util::ComputeDatabaseTimeBounds(Now(), days_ago, &early_bound, &late_bound);
std::string query_str = base::StringPrintf(
"SELECT time, action_type, api_name, args, page_url, page_title, "
"arg_url, other "
@@ -223,13 +166,9 @@
}
}
- GURL page_url(query.ColumnString(4));
- action->set_page_url(page_url);
-
+ action->ParsePageUrl(query.ColumnString(4));
action->set_page_title(query.ColumnString(5));
-
- GURL arg_url(query.ColumnString(6));
- action->set_arg_url(arg_url);
+ action->ParseArgUrl(query.ColumnString(6));
if (query.ColumnType(7) != sql::COLUMN_TYPE_NULL) {
scoped_ptr<Value> parsed_value(
@@ -277,22 +216,6 @@
callback);
}
-std::string FullStreamUIPolicy::GetKey(ActivityLogPolicy::KeyType key_ty) const
-{
- switch (key_ty) {
- case PARAM_KEY_REASON:
- return std::string(kKeyReason);
- case PARAM_KEY_DOM_ACTION:
- return std::string(kKeyDomainAction);
- case PARAM_KEY_URL_TITLE:
- return std::string(kKeyURLTitle);
- case PARAM_KEY_DETAILS_STRING:
- return std::string(kKeyDetailsString);
- default:
- return std::string();
- }
-}
-
scoped_refptr<Action> FullStreamUIPolicy::ProcessArguments(
scoped_refptr<Action> action) const {
return action;
@@ -310,7 +233,7 @@
void FullStreamUIPolicy::QueueAction(scoped_refptr<Action> action) {
if (activity_database()->is_db_valid()) {
queued_actions_.push_back(action);
- activity_database()->NotifyAction();
+ activity_database()->AdviseFlush(queued_actions_.size());
}
}
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy.h b/chrome/browser/extensions/activity_log/fullstream_ui_policy.h
index 49a8b70..4f50d54 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy.h
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy.h
@@ -16,6 +16,11 @@
// A policy for logging the full stream of actions, including all arguments.
// It's mostly intended to be used in testing and analysis.
+//
+// NOTE: The FullStreamUIPolicy deliberately keeps almost all information,
+// including some data that could be privacy sensitive (full URLs including
+// incognito URLs, full headers when WebRequest is used, etc.). It should not
+// be used during normal browsing if users care about privacy.
class FullStreamUIPolicy : public ActivityLogDatabasePolicy {
public:
// For more info about these member functions, see the super class.
@@ -34,9 +39,6 @@
const base::Callback
<void(scoped_ptr<Action::ActionVector>)>& callback) OVERRIDE;
- // Returns the actual key for a given key type
- virtual std::string GetKey(ActivityLogPolicy::KeyType key_id) const OVERRIDE;
-
virtual void Close() OVERRIDE;
// Database table schema.
@@ -50,8 +52,8 @@
// ActivityDatabase class for an overall discussion of how cleanup works.
virtual ~FullStreamUIPolicy();
- // The ActivityDatabase::PolicyDelegate interface. These are always called
- // from the database thread.
+ // The ActivityDatabase::Delegate interface. These are always called from
+ // the database thread.
virtual bool InitDatabase(sql::Connection* db) OVERRIDE;
virtual bool FlushDatabase(sql::Connection* db) OVERRIDE;
virtual void OnDatabaseFailure() OVERRIDE;
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
index 0421357..2c453a8 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
@@ -247,29 +247,32 @@
ActivityLogPolicy* policy = new FullStreamUIPolicy(profile_.get());
// Use a mock clock to ensure that events are not recorded on the wrong day
- // when the test is run close to local midnight.
- base::SimpleTestClock mock_clock;
- mock_clock.SetNow(base::Time::Now().LocalMidnight() +
- base::TimeDelta::FromHours(12));
- policy->SetClockForTesting(&mock_clock);
+ // when the test is run close to local midnight. Note: Ownership is passed
+ // to the policy, but we still keep a pointer locally. The policy will take
+ // care of destruction; this is safe since the policy outlives all our
+ // accesses to the mock clock.
+ base::SimpleTestClock* mock_clock = new base::SimpleTestClock();
+ mock_clock->SetNow(base::Time::Now().LocalMidnight() +
+ base::TimeDelta::FromHours(12));
+ policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock));
// Record some actions
scoped_refptr<Action> action =
new Action("punky",
- mock_clock.Now() - base::TimeDelta::FromMinutes(40),
+ mock_clock->Now() - base::TimeDelta::FromMinutes(40),
Action::ACTION_API_CALL,
"brewster");
action->mutable_args()->AppendString("woof");
policy->ProcessAction(action);
action =
- new Action("punky", mock_clock.Now(), Action::ACTION_DOM_ACCESS, "lets");
+ new Action("punky", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets");
action->mutable_args()->AppendString("vamoose");
action->set_page_url(GURL("http://www.google.com"));
policy->ProcessAction(action);
action = new Action(
- "scoobydoo", mock_clock.Now(), Action::ACTION_DOM_ACCESS, "lets");
+ "scoobydoo", mock_clock->Now(), Action::ACTION_DOM_ACCESS, "lets");
action->mutable_args()->AppendString("vamoose");
action->set_page_url(GURL("http://www.google.com"));
policy->ProcessAction(action);
@@ -288,15 +291,15 @@
// Use a mock clock to ensure that events are not recorded on the wrong day
// when the test is run close to local midnight.
- base::SimpleTestClock mock_clock;
- mock_clock.SetNow(base::Time::Now().LocalMidnight() +
- base::TimeDelta::FromHours(12));
- policy->SetClockForTesting(&mock_clock);
+ base::SimpleTestClock* mock_clock = new base::SimpleTestClock();
+ mock_clock->SetNow(base::Time::Now().LocalMidnight() +
+ base::TimeDelta::FromHours(12));
+ policy->SetClockForTesting(scoped_ptr<base::Clock>(mock_clock));
// Record some actions
scoped_refptr<Action> action =
new Action("punky",
- mock_clock.Now() - base::TimeDelta::FromDays(3) -
+ mock_clock->Now() - base::TimeDelta::FromDays(3) -
base::TimeDelta::FromMinutes(40),
Action::ACTION_API_CALL,
"brewster");
@@ -304,7 +307,7 @@
policy->ProcessAction(action);
action = new Action("punky",
- mock_clock.Now() - base::TimeDelta::FromDays(3),
+ mock_clock->Now() - base::TimeDelta::FromDays(3),
Action::ACTION_DOM_ACCESS,
"lets");
action->mutable_args()->AppendString("vamoose");
@@ -312,7 +315,7 @@
policy->ProcessAction(action);
action = new Action("punky",
- mock_clock.Now(),
+ mock_clock->Now(),
Action::ACTION_DOM_ACCESS,
"lets");
action->mutable_args()->AppendString("too new");
@@ -320,7 +323,7 @@
policy->ProcessAction(action);
action = new Action("punky",
- mock_clock.Now() - base::TimeDelta::FromDays(7),
+ mock_clock->Now() - base::TimeDelta::FromDays(7),
Action::ACTION_DOM_ACCESS,
"lets");
action->mutable_args()->AppendString("too old");
diff --git a/chrome/browser/extensions/activity_log/stream_noargs_ui_policy.cc b/chrome/browser/extensions/activity_log/stream_noargs_ui_policy.cc
deleted file mode 100644
index 6ec8916..0000000
--- a/chrome/browser/extensions/activity_log/stream_noargs_ui_policy.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/activity_log/stream_noargs_ui_policy.h"
-
-#include "base/json/json_string_value_serializer.h"
-#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
-
-namespace constants = activity_log_constants;
-
-namespace {
-
-// We should log the arguments to these API calls. Be careful when
-// constructing this whitelist to not keep arguments that might compromise
-// privacy by logging too much data to the activity log.
-//
-// TODO(mvrable): The contents of this whitelist should be reviewed and
-// expanded as needed.
-const char* kAlwaysLog[] = {"extension.connect", "extension.sendMessage",
- "tabs.executeScript", "tabs.insertCSS"};
-
-} // namespace
-
-namespace extensions {
-
-StreamWithoutArgsUIPolicy::StreamWithoutArgsUIPolicy(Profile* profile)
- : FullStreamUIPolicy(profile) {
- for (size_t i = 0; i < arraysize(kAlwaysLog); i++) {
- arg_whitelist_api_.insert(kAlwaysLog[i]);
- }
-}
-
-StreamWithoutArgsUIPolicy::~StreamWithoutArgsUIPolicy() {}
-
-scoped_refptr<Action> StreamWithoutArgsUIPolicy::ProcessArguments(
- scoped_refptr<Action> action) const {
- if (action->action_type() == Action::ACTION_DOM_ACCESS ||
- action->action_type() == Action::ACTION_DOM_EVENT ||
- arg_whitelist_api_.find(action->api_name()) != arg_whitelist_api_.end()) {
- // No stripping of arguments
- } else {
- // Do not modify the Action in-place, as there might be other users.
- action = action->Clone();
- action->set_args(scoped_ptr<ListValue>());
-
- // Strip details of the web request modifications (for privacy reasons).
- if (action->action_type() == Action::ACTION_WEB_REQUEST) {
- DictionaryValue* details = NULL;
- if (action->mutable_other()->GetDictionary(constants::kActionWebRequest,
- &details)) {
- DictionaryValue::Iterator details_iterator(*details);
- while (!details_iterator.IsAtEnd()) {
- details->SetBoolean(details_iterator.key(), true);
- details_iterator.Advance();
- }
- }
- }
- }
- return action;
-}
-
-} // namespace extensions
diff --git a/chrome/browser/extensions/activity_log/stream_noargs_ui_policy.h b/chrome/browser/extensions/activity_log/stream_noargs_ui_policy.h
deleted file mode 100644
index addbacd..0000000
--- a/chrome/browser/extensions/activity_log/stream_noargs_ui_policy.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_STREAM_NOARGS_UI_POLICY_H_
-#define CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_STREAM_NOARGS_UI_POLICY_H_
-
-#include <string>
-
-#include "base/containers/hash_tables.h"
-#include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h"
-
-namespace extensions {
-
-// A policy for logging the stream of actions, but without arguments.
-class StreamWithoutArgsUIPolicy : public FullStreamUIPolicy {
- public:
- explicit StreamWithoutArgsUIPolicy(Profile* profile);
- virtual ~StreamWithoutArgsUIPolicy();
-
- protected:
- // Clears the args field of the action (except for some DOM events and a
- // small whitelisted set of api_names). For WEB_REQUEST actions, keeps keys
- // but removes values from the "web_request" dictionary in other.
- virtual scoped_refptr<Action> ProcessArguments(
- scoped_refptr<Action> action) const OVERRIDE;
-
- private:
- base::hash_set<std::string> arg_whitelist_api_;
-};
-
-} // namespace extensions
-
-#endif // CHROME_BROWSER_EXTENSIONS_ACTIVITY_LOG_STREAM_NOARGS_UI_POLICY_H_
diff --git a/chrome/browser/extensions/activity_log/stream_noargs_ui_policy_unittest.cc b/chrome/browser/extensions/activity_log/stream_noargs_ui_policy_unittest.cc
deleted file mode 100644
index 5c5207a..0000000
--- a/chrome/browser/extensions/activity_log/stream_noargs_ui_policy_unittest.cc
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/command_line.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/run_loop.h"
-#include "base/synchronization/waitable_event.h"
-#include "chrome/browser/extensions/activity_log/activity_log.h"
-#include "chrome/browser/extensions/activity_log/stream_noargs_ui_policy.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/test_extension_system.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/extension_builder.h"
-#include "chrome/test/base/chrome_render_view_host_test_harness.h"
-#include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "sql/statement.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/login/user_manager.h"
-#include "chrome/browser/chromeos/settings/cros_settings.h"
-#include "chrome/browser/chromeos/settings/device_settings_service.h"
-#endif
-
-namespace extensions {
-
-class StreamWithoutArgsUIPolicyTest : public testing::Test {
- public:
- StreamWithoutArgsUIPolicyTest()
- : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
- saved_cmdline_(CommandLine::NO_PROGRAM) {
-#if defined OS_CHROMEOS
- test_user_manager_.reset(new chromeos::ScopedTestUserManager());
-#endif
- CommandLine command_line(CommandLine::NO_PROGRAM);
- saved_cmdline_ = *CommandLine::ForCurrentProcess();
- profile_.reset(new TestingProfile());
- CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableExtensionActivityLogging);
- CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableExtensionActivityLogTesting);
- extension_service_ = static_cast<TestExtensionSystem*>(
- ExtensionSystem::Get(profile_.get()))->CreateExtensionService
- (&command_line, base::FilePath(), false);
- }
-
- virtual ~StreamWithoutArgsUIPolicyTest() {
-#if defined OS_CHROMEOS
- test_user_manager_.reset();
-#endif
- base::RunLoop().RunUntilIdle();
- profile_.reset(NULL);
- base::RunLoop().RunUntilIdle();
- // Restore the original command line and undo the affects of SetUp().
- *CommandLine::ForCurrentProcess() = saved_cmdline_;
- }
-
- static void RetrieveActions_LogAndFetchActions(
- scoped_ptr<std::vector<scoped_refptr<Action> > > i) {
- ASSERT_EQ(2, static_cast<int>(i->size()));
- }
-
- static void Arguments_Missing(
- scoped_ptr<std::vector<scoped_refptr<Action> > > i) {
- scoped_refptr<Action> last = i->front();
- std::string noargs =
- "ID=odlameecjipmbmbejkplpemijjgpljce CATEGORY=api_call "
- "API=tabs.testMethod";
- ASSERT_EQ(noargs, last->PrintForDebug());
- }
-
- protected:
- ExtensionService* extension_service_;
- scoped_ptr<TestingProfile> profile_;
- content::TestBrowserThreadBundle thread_bundle_;
- // Used to preserve a copy of the original command line.
- // The test framework will do this itself as well. However, by then,
- // it is too late to call ActivityLog::RecomputeLoggingIsEnabled() in
- // TearDown().
- CommandLine saved_cmdline_;
-
-#if defined OS_CHROMEOS
- chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
- chromeos::ScopedTestCrosSettings test_cros_settings_;
- scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
-#endif
-};
-
-TEST_F(StreamWithoutArgsUIPolicyTest, Construct) {
- ActivityLogPolicy* policy = new StreamWithoutArgsUIPolicy(profile_.get());
- scoped_refptr<const Extension> extension =
- ExtensionBuilder()
- .SetManifest(DictionaryBuilder()
- .Set("name", "Test extension")
- .Set("version", "1.0.0")
- .Set("manifest_version", 2))
- .Build();
- extension_service_->AddExtension(extension.get());
- scoped_ptr<base::ListValue> args(new base::ListValue());
- scoped_refptr<Action> action = new Action(extension->id(),
- base::Time::Now(),
- Action::ACTION_API_CALL,
- "tabs.testMethod");
- action->set_args(args.Pass());
- policy->ProcessAction(action);
- policy->Close();
-}
-
-TEST_F(StreamWithoutArgsUIPolicyTest, LogAndFetchActions) {
- ActivityLogPolicy* policy = new StreamWithoutArgsUIPolicy(profile_.get());
- scoped_refptr<const Extension> extension =
- ExtensionBuilder()
- .SetManifest(DictionaryBuilder()
- .Set("name", "Test extension")
- .Set("version", "1.0.0")
- .Set("manifest_version", 2))
- .Build();
- extension_service_->AddExtension(extension.get());
- GURL gurl("http://www.google.com");
-
- // Write some API calls
- scoped_refptr<Action> action_api = new Action(extension->id(),
- base::Time::Now(),
- Action::ACTION_API_CALL,
- "tabs.testMethod");
- action_api->set_args(make_scoped_ptr(new base::ListValue()));
- policy->ProcessAction(action_api);
-
- scoped_refptr<Action> action_dom = new Action(extension->id(),
- base::Time::Now(),
- Action::ACTION_DOM_ACCESS,
- "document.write");
- action_dom->set_args(make_scoped_ptr(new base::ListValue()));
- action_dom->set_page_url(gurl);
- policy->ProcessAction(action_dom);
-
- policy->ReadData(extension->id(), 0,
- base::Bind(
- StreamWithoutArgsUIPolicyTest::RetrieveActions_LogAndFetchActions));
-
- policy->Close();
-}
-
-TEST_F(StreamWithoutArgsUIPolicyTest, LogWithoutArguments) {
- ActivityLogPolicy* policy = new StreamWithoutArgsUIPolicy(profile_.get());
- scoped_refptr<const Extension> extension =
- ExtensionBuilder()
- .SetManifest(DictionaryBuilder()
- .Set("name", "Test extension")
- .Set("version", "1.0.0")
- .Set("manifest_version", 2))
- .Build();
- extension_service_->AddExtension(extension.get());
-
- scoped_ptr<base::ListValue> args(new base::ListValue());
- args->Set(0, new base::StringValue("hello"));
- args->Set(1, new base::StringValue("world"));
- scoped_refptr<Action> action = new Action(extension->id(),
- base::Time::Now(),
- Action::ACTION_API_CALL,
- "tabs.testMethod");
- action->set_args(args.Pass());
-
- policy->ProcessAction(action);
- policy->ReadData(extension->id(), 0,
- base::Bind(StreamWithoutArgsUIPolicyTest::Arguments_Missing));
- policy->Close();
-}
-
-} // namespace extensions
diff --git a/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.cc b/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.cc
index eabfc1c..dcda353 100644
--- a/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.cc
+++ b/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.cc
@@ -6,11 +6,11 @@
#include "apps/native_app_window.h"
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "base/command_line.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/common/extensions/api/app_current_window_internal.h"
#include "chrome/common/extensions/api/app_window.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "extensions/common/switches.h"
using apps::ShellWindow;
@@ -32,7 +32,8 @@
} // namespace
bool AppCurrentWindowInternalExtensionFunction::RunImpl() {
- ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile());
+ apps::ShellWindowRegistry* registry =
+ apps::ShellWindowRegistry::Get(profile());
DCHECK(registry);
content::RenderViewHost* rvh = render_view_host();
if (!rvh)
@@ -123,7 +124,7 @@
bool AppCurrentWindowInternalSetIconFunction::RunWithWindow(
ShellWindow* window) {
- if (Feature::GetCurrentChannel() > chrome::VersionInfo::CHANNEL_DEV &&
+ if (GetCurrentChannel() > chrome::VersionInfo::CHANNEL_DEV &&
GetExtension()->location() != extensions::Manifest::COMPONENT) {
error_ = kDevChannelOnly;
return false;
diff --git a/chrome/browser/extensions/api/app_window/app_window_api.cc b/chrome/browser/extensions/api/app_window/app_window_api.cc
index a172a5a..7fa2492 100644
--- a/chrome/browser/extensions/api/app_window/app_window_api.cc
+++ b/chrome/browser/extensions/api/app_window/app_window_api.cc
@@ -7,17 +7,17 @@
#include "apps/app_window_contents.h"
#include "apps/native_app_window.h"
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "base/command_line.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/app_mode/app_mode_utils.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/devtools/devtools_window.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/extensions/window_controller.h"
#include "chrome/browser/ui/apps/chrome_shell_window_delegate.h"
#include "chrome/common/extensions/api/app_window.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host.h"
@@ -150,7 +150,7 @@
create_params.window_key = *options->id;
if (!options->singleton || *options->singleton) {
- ShellWindow* window = ShellWindowRegistry::Get(profile())->
+ ShellWindow* window = apps::ShellWindowRegistry::Get(profile())->
GetShellWindowForAppAndKey(extension_id(),
create_params.window_key);
if (window) {
@@ -207,7 +207,7 @@
create_params.bounds.set_y(*bounds->top.get());
}
- if (Feature::GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV ||
+ if (GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV ||
GetExtension()->location() == extensions::Manifest::COMPONENT) {
if (options->type == extensions::api::app_window::WINDOW_TYPE_PANEL) {
create_params.window_type = ShellWindow::WINDOW_TYPE_PANEL;
@@ -318,7 +318,8 @@
SetCreateResultFromShellWindow(shell_window, result);
SetResult(result);
- if (ShellWindowRegistry::Get(profile())->HadDevToolsAttached(created_view)) {
+ if (apps::ShellWindowRegistry::Get(profile())->
+ HadDevToolsAttached(created_view)) {
new DevToolsRestorer(this, created_view);
return true;
}
diff --git a/chrome/browser/extensions/api/app_window/app_window_apitest.cc b/chrome/browser/extensions/api/app_window/app_window_apitest.cc
index aee3c9c..a4f3909 100644
--- a/chrome/browser/extensions/api/app_window/app_window_apitest.cc
+++ b/chrome/browser/extensions/api/app_window/app_window_apitest.cc
@@ -4,11 +4,11 @@
#include "apps/native_app_window.h"
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/extensions/platform_app_browsertest_util.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/testing_profile.h"
#include "ui/base/base_window.h"
@@ -23,15 +23,15 @@
namespace {
class TestShellWindowRegistryObserver
- : public extensions::ShellWindowRegistry::Observer {
+ : public apps::ShellWindowRegistry::Observer {
public:
explicit TestShellWindowRegistryObserver(Profile* profile)
: profile_(profile),
icon_updates_(0) {
- extensions::ShellWindowRegistry::Get(profile_)->AddObserver(this);
+ apps::ShellWindowRegistry::Get(profile_)->AddObserver(this);
}
virtual ~TestShellWindowRegistryObserver() {
- extensions::ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
+ apps::ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
}
// Overridden from ShellWindowRegistry::Observer:
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_store.cc b/chrome/browser/extensions/api/content_settings/content_settings_store.cc
index ebae984..ff58296 100644
--- a/chrome/browser/extensions/api/content_settings/content_settings_store.cc
+++ b/chrome/browser/extensions/api/content_settings/content_settings_store.cc
@@ -349,7 +349,7 @@
bool ContentSettingsStore::OnCorrectThread() {
// If there is no UI thread, we're most likely in a unit test.
- return !BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+ return !BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
BrowserThread::CurrentlyOn(BrowserThread::UI);
}
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
index dc3bead..363d987 100644
--- a/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
+++ b/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
@@ -8,7 +8,7 @@
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "content/public/test/browser_test_utils.h"
namespace extensions {
@@ -23,7 +23,7 @@
}
virtual ~DeclarativeContentApiTest() {}
- extensions::Feature::ScopedCurrentChannel current_channel_;
+ extensions::ScopedCurrentChannel current_channel_;
};
IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, Overview) {
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 986598c..a7d8732 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -8,6 +8,7 @@
#include "apps/app_restore_service.h"
#include "apps/saved_files_service.h"
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "base/base64.h"
#include "base/command_line.h"
#include "base/file_util.h"
@@ -27,7 +28,6 @@
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/management_policy.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/extensions/unpacked_installer.h"
#include "chrome/browser/extensions/updater/extension_updater.h"
#include "chrome/browser/platform_util.h"
@@ -67,6 +67,7 @@
#include "webkit/common/blob/shareable_file_reference.h"
using apps::ShellWindow;
+using apps::ShellWindowRegistry;
using content::RenderViewHost;
namespace extensions {
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
index 1bfc27b..9f7dc63 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -36,6 +36,7 @@
#include "chrome/browser/download/download_service.h"
#include "chrome/browser/download/download_service_factory.h"
#include "chrome/browser/download/download_shelf.h"
+#include "chrome/browser/download/download_stats.h"
#include "chrome/browser/download/download_util.h"
#include "chrome/browser/extensions/event_names.h"
#include "chrome/browser/extensions/event_router.h"
@@ -44,6 +45,8 @@
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/extension_warning_service.h"
+#include "chrome/browser/extensions/extension_warning_set.h"
#include "chrome/browser/icon_loader.h"
#include "chrome/browser/icon_manager.h"
#include "chrome/browser/platform_util.h"
@@ -592,6 +595,7 @@
extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY),
determined_conflict_action_(
extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
download_item->SetUserData(kKey, this);
}
@@ -613,6 +617,7 @@
void set_filename_change_callbacks(
const base::Closure& no_change,
const ExtensionDownloadsEventRouter::FilenameChangedCallback& change) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
filename_no_change_ = no_change;
filename_change_ = change;
determined_filename_ = creator_suggested_filename_;
@@ -622,6 +627,7 @@
}
void ClearPendingDeterminers() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
determined_filename_.clear();
determined_conflict_action_ =
extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY;
@@ -633,6 +639,7 @@
}
void DeterminerRemoved(const std::string& extension_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
for (DeterminerInfoVector::iterator iter = determiners_.begin();
iter != determiners_.end();) {
if (iter->extension_id == extension_id) {
@@ -648,6 +655,7 @@
void AddPendingDeterminer(const std::string& extension_id,
const base::Time& installed) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
for (size_t index = 0; index < determiners_.size(); ++index) {
if (determiners_[index].extension_id == extension_id) {
DCHECK(false) << extension_id;
@@ -658,6 +666,7 @@
}
bool DeterminerAlreadyReported(const std::string& extension_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
for (size_t index = 0; index < determiners_.size(); ++index) {
if (determiners_[index].extension_id == extension_id) {
return determiners_[index].reported;
@@ -669,6 +678,7 @@
void CreatorSuggestedFilename(
const base::FilePath& filename,
extensions::api::downloads::FilenameConflictAction conflict_action) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
creator_suggested_filename_ = filename;
creator_conflict_action_ = conflict_action;
}
@@ -683,6 +693,7 @@
}
void ResetCreatorSuggestion() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
creator_suggested_filename_.clear();
creator_conflict_action_ =
extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY;
@@ -692,9 +703,11 @@
// |extension_id| has already reported. The caller is responsible for
// validating |filename|.
bool DeterminerCallback(
+ Profile* profile,
const std::string& extension_id,
const base::FilePath& filename,
extensions::api::downloads::FilenameConflictAction conflict_action) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
bool found_info = false;
for (size_t index = 0; index < determiners_.size(); ++index) {
if (determiners_[index].extension_id == extension_id) {
@@ -705,12 +718,25 @@
// Do not use filename if another determiner has already overridden the
// filename and they take precedence. Extensions that were installed
// later take precedence over previous extensions.
- if (!filename.empty() &&
- (determiner_.extension_id.empty() ||
- (determiners_[index].install_time > determiner_.install_time))) {
- determined_filename_ = filename;
- determined_conflict_action_ = conflict_action;
- determiner_ = determiners_[index];
+ if (!filename.empty()) {
+ extensions::ExtensionWarningSet warnings;
+ std::string winner_extension_id;
+ ExtensionDownloadsEventRouter::DetermineFilenameInternal(
+ filename,
+ conflict_action,
+ determiners_[index].extension_id,
+ determiners_[index].install_time,
+ determiner_.extension_id,
+ determiner_.install_time,
+ &winner_extension_id,
+ &determined_filename_,
+ &determined_conflict_action_,
+ &warnings);
+ if (!warnings.empty())
+ extensions::ExtensionWarningService::NotifyWarningsOnUI(
+ profile, warnings);
+ if (winner_extension_id == determiners_[index].extension_id)
+ determiner_ = determiners_[index];
}
break;
}
@@ -1003,7 +1029,7 @@
DownloadManager* manager = BrowserContext::GetDownloadManager(
current_profile);
manager->DownloadUrl(download_params.Pass());
- download_util::RecordDownloadSource(download_util::INITIATED_BY_EXTENSION);
+ RecordDownloadSource(DOWNLOAD_INITIATED_BY_EXTENSION);
RecordApiFunctions(DOWNLOADS_FUNCTION_DOWNLOAD);
return true;
}
@@ -1558,6 +1584,50 @@
}
}
+void ExtensionDownloadsEventRouter::DetermineFilenameInternal(
+ const base::FilePath& filename,
+ extensions::api::downloads::FilenameConflictAction conflict_action,
+ const std::string& suggesting_extension_id,
+ const base::Time& suggesting_install_time,
+ const std::string& incumbent_extension_id,
+ const base::Time& incumbent_install_time,
+ std::string* winner_extension_id,
+ base::FilePath* determined_filename,
+ extensions::api::downloads::FilenameConflictAction*
+ determined_conflict_action,
+ extensions::ExtensionWarningSet* warnings) {
+ DCHECK(!filename.empty());
+ DCHECK(!suggesting_extension_id.empty());
+
+ if (incumbent_extension_id.empty()) {
+ *winner_extension_id = suggesting_extension_id;
+ *determined_filename = filename;
+ *determined_conflict_action = conflict_action;
+ return;
+ }
+
+ if (suggesting_install_time < incumbent_install_time) {
+ *winner_extension_id = incumbent_extension_id;
+ warnings->insert(
+ extensions::ExtensionWarning::CreateDownloadFilenameConflictWarning(
+ suggesting_extension_id,
+ incumbent_extension_id,
+ filename,
+ *determined_filename));
+ return;
+ }
+
+ *winner_extension_id = suggesting_extension_id;
+ warnings->insert(
+ extensions::ExtensionWarning::CreateDownloadFilenameConflictWarning(
+ incumbent_extension_id,
+ suggesting_extension_id,
+ *determined_filename,
+ filename));
+ *determined_filename = filename;
+ *determined_conflict_action = conflict_action;
+}
+
bool ExtensionDownloadsEventRouter::DetermineFilename(
Profile* profile,
bool include_incognito,
@@ -1591,7 +1661,8 @@
base::FilePath());
// If the invalid filename check is moved to before DeterminerCallback(), then
// it will block forever waiting for this ext_id to report.
- if (Fault(!data->DeterminerCallback(ext_id, filename, conflict_action),
+ if (Fault(!data->DeterminerCallback(
+ profile, ext_id, filename, conflict_action),
errors::kUnexpectedDeterminer, error) ||
Fault((!const_filename.empty() && !valid_filename),
errors::kInvalidFilename, error))
@@ -1790,6 +1861,7 @@
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
switch (type) {
case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
extensions::UnloadedExtensionInfo* unloaded =
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.h b/chrome/browser/extensions/api/downloads/downloads_api.h
index a6fda46..e7db6d0 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.h
+++ b/chrome/browser/extensions/api/downloads/downloads_api.h
@@ -17,6 +17,7 @@
#include "chrome/browser/download/download_path_reservation_tracker.h"
#include "chrome/browser/extensions/event_router.h"
#include "chrome/browser/extensions/extension_function.h"
+#include "chrome/browser/extensions/extension_warning_set.h"
#include "chrome/common/extensions/api/downloads.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/download_manager.h"
@@ -298,6 +299,21 @@
DownloadPathReservationTracker::FilenameConflictAction)>
FilenameChangedCallback;
+ // The logic for how to handle conflicting filename suggestions from multiple
+ // extensions is split out here for testing.
+ static void DetermineFilenameInternal(
+ const base::FilePath& filename,
+ extensions::api::downloads::FilenameConflictAction conflict_action,
+ const std::string& suggesting_extension_id,
+ const base::Time& suggesting_install_time,
+ const std::string& incumbent_extension_id,
+ const base::Time& incumbent_install_time,
+ std::string* winner_extension_id,
+ base::FilePath* determined_filename,
+ extensions::api::downloads::FilenameConflictAction*
+ determined_conflict_action,
+ extensions::ExtensionWarningSet* warnings);
+
// A downloads.onDeterminingFilename listener has returned. If the extension
// wishes to override the download's filename, then |filename| will be
// non-empty. |filename| will be interpreted as a relative path, appended to
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
index 82a5f6f..e5962af 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -427,6 +427,7 @@
downloads_directory().Append(history_info[i].filename),
url_chain, GURL(), // URL Chain, referrer
current, current, // start_time, end_time
+ std::string(), std::string(), // etag, last_modified
1, 1, // received_bytes, total_bytes
history_info[i].state, // state
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
@@ -3496,3 +3497,73 @@
#include "content/public/browser/download_interrupt_reason_values.h"
#undef INTERRUPT_REASON
}
+
+TEST(ExtensionDetermineDownloadFilenameInternal,
+ ExtensionDetermineDownloadFilenameInternal) {
+
+ std::string winner_id;
+ base::FilePath filename;
+ extensions::api::downloads::FilenameConflictAction conflict_action =
+ api::FILENAME_CONFLICT_ACTION_UNIQUIFY;
+ extensions::ExtensionWarningSet warnings;
+
+ // Empty incumbent determiner
+ warnings.clear();
+ ExtensionDownloadsEventRouter::DetermineFilenameInternal(
+ base::FilePath(FILE_PATH_LITERAL("a")),
+ api::FILENAME_CONFLICT_ACTION_OVERWRITE,
+ "suggester",
+ base::Time::Now(),
+ "",
+ base::Time(),
+ &winner_id,
+ &filename,
+ &conflict_action,
+ &warnings);
+ EXPECT_EQ("suggester", winner_id);
+ EXPECT_EQ(FILE_PATH_LITERAL("a"), filename.value());
+ EXPECT_EQ(api::FILENAME_CONFLICT_ACTION_OVERWRITE, conflict_action);
+ EXPECT_TRUE(warnings.empty());
+
+ // Incumbent wins
+ warnings.clear();
+ ExtensionDownloadsEventRouter::DetermineFilenameInternal(
+ base::FilePath(FILE_PATH_LITERAL("b")),
+ api::FILENAME_CONFLICT_ACTION_PROMPT,
+ "suggester",
+ base::Time::Now() - base::TimeDelta::FromDays(1),
+ "incumbent",
+ base::Time::Now(),
+ &winner_id,
+ &filename,
+ &conflict_action,
+ &warnings);
+ EXPECT_EQ("incumbent", winner_id);
+ EXPECT_EQ(FILE_PATH_LITERAL("a"), filename.value());
+ EXPECT_EQ(api::FILENAME_CONFLICT_ACTION_OVERWRITE, conflict_action);
+ EXPECT_FALSE(warnings.empty());
+ EXPECT_EQ(extensions::ExtensionWarning::kDownloadFilenameConflict,
+ warnings.begin()->warning_type());
+ EXPECT_EQ("suggester", warnings.begin()->extension_id());
+
+ // Suggester wins
+ warnings.clear();
+ ExtensionDownloadsEventRouter::DetermineFilenameInternal(
+ base::FilePath(FILE_PATH_LITERAL("b")),
+ api::FILENAME_CONFLICT_ACTION_PROMPT,
+ "suggester",
+ base::Time::Now(),
+ "incumbent",
+ base::Time::Now() - base::TimeDelta::FromDays(1),
+ &winner_id,
+ &filename,
+ &conflict_action,
+ &warnings);
+ EXPECT_EQ("suggester", winner_id);
+ EXPECT_EQ(FILE_PATH_LITERAL("b"), filename.value());
+ EXPECT_EQ(api::FILENAME_CONFLICT_ACTION_PROMPT, conflict_action);
+ EXPECT_FALSE(warnings.empty());
+ EXPECT_EQ(extensions::ExtensionWarning::kDownloadFilenameConflict,
+ warnings.begin()->warning_type());
+ EXPECT_EQ("incumbent", warnings.begin()->extension_id());
+}
diff --git a/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc b/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc
index c30884d..fd7264a 100644
--- a/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc
+++ b/chrome/browser/extensions/api/extension_action/script_badge_apitest.cc
@@ -15,7 +15,7 @@
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/web_contents.h"
#include "net/dns/mock_host_resolver.h"
@@ -36,7 +36,7 @@
}
private:
- extensions::Feature::ScopedCurrentChannel trunk_;
+ extensions::ScopedCurrentChannel trunk_;
};
IN_PROC_BROWSER_TEST_F(ScriptBadgeApiTest, Basics) {
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_service_chromeos.cc b/chrome/browser/extensions/api/feedback_private/feedback_service_chromeos.cc
index ba3e1f2..19d6595 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_service_chromeos.cc
+++ b/chrome/browser/extensions/api/feedback_private/feedback_service_chromeos.cc
@@ -8,7 +8,7 @@
#include "base/memory/weak_ptr.h"
#include "base/values.h"
#include "chrome/browser/chromeos/login/user_manager.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/about_system_logs_fetcher.h"
using extensions::api::feedback_private::SystemInformation;
@@ -55,7 +55,8 @@
const GetSystemInformationCallback& callback) {
system_information_callback_ = callback;
- chromeos::SystemLogsFetcher* fetcher = new chromeos::SystemLogsFetcher();
+ chromeos::AboutSystemLogsFetcher* fetcher =
+ new chromeos::AboutSystemLogsFetcher();
fetcher->Fetch(base::Bind(&FeedbackServiceImpl::ProcessSystemLogs,
AsWeakPtr()));
}
diff --git a/chrome/browser/extensions/api/file_system/file_system_api.cc b/chrome/browser/extensions/api/file_system/file_system_api.cc
index fe66380..7ebf9e2 100644
--- a/chrome/browser/extensions/api/file_system/file_system_api.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_api.cc
@@ -6,6 +6,7 @@
#include "apps/saved_files_service.h"
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "base/bind.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
@@ -20,7 +21,6 @@
#include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "chrome/common/chrome_paths.h"
@@ -741,7 +741,8 @@
// platform-app only.
content::WebContents* web_contents = NULL;
if (extension_->is_platform_app()) {
- ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile());
+ apps::ShellWindowRegistry* registry =
+ apps::ShellWindowRegistry::Get(profile());
DCHECK(registry);
ShellWindow* shell_window = registry->GetShellWindowForRenderViewHost(
render_view_host());
diff --git a/chrome/browser/extensions/api/identity/web_auth_flow.cc b/chrome/browser/extensions/api/identity/web_auth_flow.cc
index 7f3ba05..977f1f1 100644
--- a/chrome/browser/extensions/api/identity/web_auth_flow.cc
+++ b/chrome/browser/extensions/api/identity/web_auth_flow.cc
@@ -59,7 +59,7 @@
WebContentsObserver::Observe(NULL);
if (!shell_window_key_.empty()) {
- ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
+ apps::ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
if (shell_window_ && shell_window_->web_contents())
shell_window_->web_contents()->Close();
@@ -67,13 +67,12 @@
}
void WebAuthFlow::Start() {
- ShellWindowRegistry::Get(profile_)->AddObserver(this);
+ apps::ShellWindowRegistry::Get(profile_)->AddObserver(this);
// Attach a random ID string to the window so we can recoginize it
// in OnShellWindowAdded.
std::string random_bytes;
crypto::RandBytes(WriteInto(&random_bytes, 33), 32);
- std::string key;
bool success = base::Base64Encode(random_bytes, &shell_window_key_);
DCHECK(success);
diff --git a/chrome/browser/extensions/api/identity/web_auth_flow.h b/chrome/browser/extensions/api/identity/web_auth_flow.h
index 077b1f0..e1a9852 100644
--- a/chrome/browser/extensions/api/identity/web_auth_flow.h
+++ b/chrome/browser/extensions/api/identity/web_auth_flow.h
@@ -7,7 +7,7 @@
#include <string>
-#include "chrome/browser/extensions/shell_window_registry.h"
+#include "apps/shell_window_registry.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents_observer.h"
@@ -45,7 +45,7 @@
// a window. If a window would be required, the flow fails.
class WebAuthFlow : public content::NotificationObserver,
public content::WebContentsObserver,
- public ShellWindowRegistry::Observer {
+ public apps::ShellWindowRegistry::Observer {
public:
enum Mode {
INTERACTIVE, // Show UI to the user if necessary.
@@ -91,7 +91,7 @@
private:
friend class ::WebAuthFlowTest;
- // ShellWindowRegistry::Observer implementation.
+ // ::ShellWindowRegistry::Observer implementation.
virtual void OnShellWindowAdded(apps::ShellWindow* shell_window) OVERRIDE;
virtual void OnShellWindowIconChanged(apps::ShellWindow* shell_window)
OVERRIDE;
diff --git a/chrome/browser/extensions/api/input/input.cc b/chrome/browser/extensions/api/input/input.cc
index b4d264f..9d0b3cb 100644
--- a/chrome/browser/extensions/api/input/input.cc
+++ b/chrome/browser/extensions/api/input/input.cc
@@ -38,10 +38,27 @@
return false;
}
+bool MoveCursorFunction::RunImpl() {
+#if defined(USE_ASH)
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ int swipe_direction;
+ int modifier_flags;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &swipe_direction));
+ EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, &modifier_flags));
+
+ return keyboard::MoveCursor(swipe_direction, modifier_flags,
+ ash::Shell::GetPrimaryRootWindow());
+#endif
+ error_ = kNotYetImplementedError;
+ return false;
+}
+
InputAPI::InputAPI(Profile* profile) {
ExtensionFunctionRegistry* registry =
ExtensionFunctionRegistry::GetInstance();
registry->RegisterFunction<InsertTextInputFunction>();
+ registry->RegisterFunction<MoveCursorFunction>();
}
InputAPI::~InputAPI() {
diff --git a/chrome/browser/extensions/api/input/input.h b/chrome/browser/extensions/api/input/input.h
index 4cdf3fa..ab5bddb 100644
--- a/chrome/browser/extensions/api/input/input.h
+++ b/chrome/browser/extensions/api/input/input.h
@@ -26,6 +26,19 @@
virtual bool RunImpl() OVERRIDE;
};
+class MoveCursorFunction : public SyncExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION(
+ "experimental.input.virtualKeyboard.moveCursor",
+ EXPERIMENTAL_INPUT_VIRTUALKEYBOARD_MOVECURSOR);
+
+ protected:
+ virtual ~MoveCursorFunction() {}
+
+ // ExtensionFunction.
+ virtual bool RunImpl() OVERRIDE;
+};
+
class InputAPI : public ProfileKeyedAPI {
public:
explicit InputAPI(Profile* profile);
diff --git a/chrome/browser/extensions/api/log_private/log_private_api.h b/chrome/browser/extensions/api/log_private/log_private_api.h
index f6f8911..d9a110f 100644
--- a/chrome/browser/extensions/api/log_private/log_private_api.h
+++ b/chrome/browser/extensions/api/log_private/log_private_api.h
@@ -7,7 +7,7 @@
#include <string>
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/about_system_logs_fetcher.h"
#include "chrome/browser/extensions/api/log_private/filter_handler.h"
#include "chrome/browser/extensions/api/log_private/log_parser.h"
#include "chrome/browser/extensions/extension_function.h"
diff --git a/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc b/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc
index 055c4ac..2e6e343 100644
--- a/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc
+++ b/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc
@@ -11,7 +11,6 @@
#include "base/logging.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
#include "chrome/browser/extensions/api/log_private/filter_handler.h"
#include "chrome/browser/extensions/api/log_private/log_parser.h"
#include "chrome/browser/extensions/api/log_private/syslog_parser.h"
@@ -62,7 +61,8 @@
EXTENSION_FUNCTION_VALIDATE(params.get());
filter_handler_.reset(new FilterHandler(params->filter));
- chromeos::SystemLogsFetcher* fetcher = new chromeos::SystemLogsFetcher();
+ chromeos::AboutSystemLogsFetcher* fetcher =
+ new chromeos::AboutSystemLogsFetcher();
fetcher->Fetch(
base::Bind(&LogPrivateGetHistoricalFunction::OnSystemLogsLoaded, this));
return true;
diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
index 25a47d2..cc5fe09 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
+++ b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
@@ -11,13 +11,13 @@
#include <vector>
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "base/memory/scoped_ptr.h"
#include "base/platform_file.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/media_galleries/media_file_system_registry.h"
#include "chrome/browser/media_galleries/media_galleries_dialog_controller.h"
#include "chrome/browser/storage_monitor/storage_monitor.h"
@@ -214,7 +214,7 @@
// If there is no WebContentsModalDialogManager, then this contents is
// probably the background page for an app. Try to find a shell window to
// host the dialog.
- ShellWindow* window = ShellWindowRegistry::Get(profile())->
+ ShellWindow* window = apps::ShellWindowRegistry::Get(profile())->
GetCurrentShellWindowForApp(GetExtension()->id());
if (window) {
contents = window->web_contents();
diff --git a/chrome/browser/extensions/api/messaging/message_service.cc b/chrome/browser/extensions/api/messaging/message_service.cc
index 65f74ed..00e40f7 100644
--- a/chrome/browser/extensions/api/messaging/message_service.cc
+++ b/chrome/browser/extensions/api/messaging/message_service.cc
@@ -34,6 +34,8 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h"
#include "url/gurl.h"
@@ -321,8 +323,14 @@
channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL,
source_extension_id));
+ // Get handle of the native view and pass it to the native messaging host.
+ gfx::NativeView native_view =
+ content::RenderWidgetHost::FromID(source_process_id, source_routing_id)->
+ GetView()->GetNativeView();
+
scoped_ptr<NativeMessageProcessHost> native_process =
NativeMessageProcessHost::Create(
+ native_view,
base::WeakPtr<NativeMessageProcessHost::Client>(
weak_factory_.GetWeakPtr()),
source_extension_id, native_app_name, receiver_port_id);
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host.cc b/chrome/browser/extensions/api/messaging/native_message_process_host.cc
index 749cb43..40535eb 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host.cc
@@ -8,6 +8,7 @@
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/platform_file.h"
+#include "base/threading/sequenced_worker_pool.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h"
#include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
@@ -77,13 +78,14 @@
// static
scoped_ptr<NativeMessageProcessHost> NativeMessageProcessHost::Create(
+ gfx::NativeView native_view,
base::WeakPtr<Client> weak_client_ui,
const std::string& source_extension_id,
const std::string& native_host_name,
int destination_port) {
return CreateWithLauncher(weak_client_ui, source_extension_id,
native_host_name, destination_port,
- NativeProcessLauncher::CreateDefault());
+ NativeProcessLauncher::CreateDefault(native_view));
}
// static
@@ -136,10 +138,18 @@
}
read_file_ = read_file;
+
+ scoped_refptr<base::TaskRunner> task_runner(
+ content::BrowserThread::GetBlockingPool()->
+ GetTaskRunnerWithShutdownBehavior(
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
+
read_stream_.reset(new net::FileStream(
- read_file, base::PLATFORM_FILE_READ | base::PLATFORM_FILE_ASYNC, NULL));
+ read_file, base::PLATFORM_FILE_READ | base::PLATFORM_FILE_ASYNC, NULL,
+ task_runner));
write_stream_.reset(new net::FileStream(
- write_file, base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC, NULL));
+ write_file, base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC, NULL,
+ task_runner));
WaitRead();
DoWrite();
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host.h b/chrome/browser/extensions/api/messaging/native_message_process_host.h
index 8458b28..a6638a4 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host.h
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host.h
@@ -14,6 +14,7 @@
#include "base/process/process.h"
#include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
#include "content/public/browser/browser_thread.h"
+#include "ui/gfx/native_widget_types.h"
namespace net {
@@ -52,6 +53,7 @@
virtual ~NativeMessageProcessHost();
static scoped_ptr<NativeMessageProcessHost> Create(
+ gfx::NativeView native_view,
base::WeakPtr<Client> weak_client_ui,
const std::string& source_extension_id,
const std::string& native_host_name,
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc b/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
index 8653d10..f92d930 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
@@ -26,7 +26,7 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -144,7 +144,7 @@
// Force the channel to be dev.
base::ScopedTempDir temp_dir_;
- Feature::ScopedCurrentChannel current_channel_;
+ ScopedCurrentChannel current_channel_;
scoped_ptr<NativeMessageProcessHost> native_message_process_host_;
base::FilePath user_data_dir_;
scoped_ptr<base::RunLoop> read_message_run_loop_;
@@ -218,7 +218,7 @@
switches::kNativeMessagingHosts, hosts_option);
native_message_process_host_ = NativeMessageProcessHost::Create(
- AsWeakPtr(), kTestNativeMessagingExtensionId,
+ gfx::NativeView(), AsWeakPtr(), kTestNativeMessagingExtensionId,
kTestNativeMessagingHostName, 0);
ASSERT_TRUE(native_message_process_host_.get());
diff --git a/chrome/browser/extensions/api/messaging/native_process_launcher.cc b/chrome/browser/extensions/api/messaging/native_process_launcher.cc
index 2186e1e..0f8992e 100644
--- a/chrome/browser/extensions/api/messaging/native_process_launcher.cc
+++ b/chrome/browser/extensions/api/messaging/native_process_launcher.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/path_service.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h"
@@ -23,7 +24,9 @@
namespace {
-const char kNativeHostsDirectoryName[] = "native_hosts";
+// Name of the command line switch used to pass handle of the native view to
+// the native messaging host.
+const char kParentWindowSwitchName[] = "parent-window";
base::FilePath GetHostManifestPathFromCommandLine(
const std::string& native_host_name) {
@@ -51,7 +54,7 @@
// Default implementation on NativeProcessLauncher interface.
class NativeProcessLauncherImpl : public NativeProcessLauncher {
public:
- NativeProcessLauncherImpl();
+ explicit NativeProcessLauncherImpl(gfx::NativeView native_view);
virtual ~NativeProcessLauncherImpl();
virtual void Launch(const GURL& origin,
@@ -61,7 +64,7 @@
private:
class Core : public base::RefCountedThreadSafe<Core> {
public:
- Core();
+ explicit Core(gfx::NativeView native_view);
void Launch(const GURL& origin,
const std::string& native_host_name,
LaunchedCallback callback);
@@ -85,6 +88,9 @@
bool detached_;
+ // Handle of the native view corrsponding to the extension.
+ gfx::NativeView native_view_;
+
DISALLOW_COPY_AND_ASSIGN(Core);
};
@@ -93,8 +99,9 @@
DISALLOW_COPY_AND_ASSIGN(NativeProcessLauncherImpl);
};
-NativeProcessLauncherImpl::Core::Core()
- : detached_(false) {
+NativeProcessLauncherImpl::Core::Core(gfx::NativeView native_view)
+ : detached_(false),
+ native_view_(native_view) {
}
NativeProcessLauncherImpl::Core::~Core() {
@@ -182,6 +189,14 @@
CommandLine command_line(host_path);
command_line.AppendArg(origin.spec());
+ // Pass handle of the native view window to the native messaging host. This
+ // way the host will be able to create properly focused UI windows.
+#if defined(OS_WIN)
+ int64 window_handle = reinterpret_cast<intptr_t>(native_view_);
+ command_line.AppendSwitchASCII(kParentWindowSwitchName,
+ base::Int64ToString(window_handle));
+#endif // !defined(OS_WIN)
+
base::PlatformFile read_file;
base::PlatformFile write_file;
if (NativeProcessLauncher::LaunchNativeProcess(
@@ -230,8 +245,9 @@
this, callback, RESULT_SUCCESS, read_file, write_file));
}
-NativeProcessLauncherImpl::NativeProcessLauncherImpl()
- : core_(new Core()) {
+NativeProcessLauncherImpl::NativeProcessLauncherImpl(
+ gfx::NativeView native_view)
+ : core_(new Core(native_view)) {
}
NativeProcessLauncherImpl::~NativeProcessLauncherImpl() {
@@ -247,8 +263,10 @@
} // namespace
// static
-scoped_ptr<NativeProcessLauncher> NativeProcessLauncher::CreateDefault() {
- return scoped_ptr<NativeProcessLauncher>(new NativeProcessLauncherImpl());
+scoped_ptr<NativeProcessLauncher> NativeProcessLauncher::CreateDefault(
+ gfx::NativeView native_view) {
+ return scoped_ptr<NativeProcessLauncher>(
+ new NativeProcessLauncherImpl(native_view));
}
} // namespace extensions
diff --git a/chrome/browser/extensions/api/messaging/native_process_launcher.h b/chrome/browser/extensions/api/messaging/native_process_launcher.h
index 5ab1fce..d2107eb 100644
--- a/chrome/browser/extensions/api/messaging/native_process_launcher.h
+++ b/chrome/browser/extensions/api/messaging/native_process_launcher.h
@@ -9,6 +9,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/platform_file.h"
#include "base/process/process.h"
+#include "ui/gfx/native_widget_types.h"
class CommandLine;
class GURL;
@@ -36,7 +37,8 @@
base::PlatformFile read_file,
base::PlatformFile write_file)> LaunchedCallback;
- static scoped_ptr<NativeProcessLauncher> CreateDefault();
+ static scoped_ptr<NativeProcessLauncher> CreateDefault(
+ gfx::NativeView native_view);
NativeProcessLauncher() {}
virtual ~NativeProcessLauncher() {}
diff --git a/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc b/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
index 1794fc2..d31559a 100644
--- a/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
+++ b/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
@@ -8,6 +8,7 @@
#include "base/metrics/histogram.h"
#include "base/metrics/statistics_recorder.h"
#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/common/metrics/variations/variations_associated_data.h"
#include "content/public/browser/user_metrics.h"
namespace {
@@ -129,6 +130,12 @@
base::FieldTrialList::CreateFieldTrial("apitestfieldtrial2", "group1");
+ std::map<std::string, std::string> params;
+ params["a"] = "aa";
+ params["b"] = "bb";
+ ASSERT_TRUE(chrome_variations::AssociateVariationParams(
+ "apitestfieldtrial2", "group1", params));
+
ASSERT_TRUE(RunComponentExtensionTest("metrics")) << message_;
observer.ValidateUserActions(g_user_actions, arraysize(g_user_actions));
diff --git a/chrome/browser/extensions/api/metrics_private/metrics_private_api.cc b/chrome/browser/extensions/api/metrics_private/metrics_private_api.cc
index f65d80e..8aa2b1b 100644
--- a/chrome/browser/extensions/api/metrics_private/metrics_private_api.cc
+++ b/chrome/browser/extensions/api/metrics_private/metrics_private_api.cc
@@ -12,6 +12,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/common/extensions/api/metrics_private.h"
#include "chrome/common/extensions/extension.h"
+#include "chrome/common/metrics/variations/variations_associated_data.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/user_metrics.h"
@@ -23,6 +24,7 @@
namespace GetIsCrashReportingEnabled =
api::metrics_private::GetIsCrashReportingEnabled;
+namespace GetVariationParams = api::metrics_private::GetVariationParams;
namespace GetFieldTrial = api::metrics_private::GetFieldTrial;
namespace RecordUserAction = api::metrics_private::RecordUserAction;
namespace RecordValue = api::metrics_private::RecordValue;
@@ -76,6 +78,22 @@
return true;
}
+bool MetricsPrivateGetVariationParamsFunction::RunImpl() {
+ scoped_ptr<GetVariationParams::Params> params(
+ GetVariationParams::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+
+ GetVariationParams::Results::Params result;
+ if (!chrome_variations::GetVariationParams(
+ params->name, &result.additional_properties)) {
+ SetError("Variation parameters are unavailable.");
+ return false;
+ }
+
+ SetResult(result.ToValue().release());
+ return true;
+}
+
bool MetricsPrivateRecordUserActionFunction::RunImpl() {
scoped_ptr<RecordUserAction::Params> params(
RecordUserAction::Params::Create(*args_));
diff --git a/chrome/browser/extensions/api/metrics_private/metrics_private_api.h b/chrome/browser/extensions/api/metrics_private/metrics_private_api.h
index 7679aa2..86ff32c 100644
--- a/chrome/browser/extensions/api/metrics_private/metrics_private_api.h
+++ b/chrome/browser/extensions/api/metrics_private/metrics_private_api.h
@@ -37,6 +37,18 @@
virtual bool RunImpl() OVERRIDE;
};
+class MetricsPrivateGetVariationParamsFunction : public SyncExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("metricsPrivate.getVariationParams",
+ METRICSPRIVATE_GETVARIATIONPARAMS)
+
+ protected:
+ virtual ~MetricsPrivateGetVariationParamsFunction() {}
+
+ // ExtensionFunction:
+ virtual bool RunImpl() OVERRIDE;
+};
+
class MetricsPrivateRecordUserActionFunction : public SyncExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("metricsPrivate.recordUserAction",
diff --git a/chrome/browser/extensions/api/system_info/system_info_api.cc b/chrome/browser/extensions/api/system_info/system_info_api.cc
index 22b7fde..546c878 100644
--- a/chrome/browser/extensions/api/system_info/system_info_api.cc
+++ b/chrome/browser/extensions/api/system_info/system_info_api.cc
@@ -29,7 +29,6 @@
namespace extensions {
-using api::system_storage::StorageFreeSpaceChangeInfo;
using api::system_storage::StorageUnitInfo;
using content::BrowserThread;
@@ -39,14 +38,9 @@
return event_name == event_names::kOnDisplayChanged;
}
-bool IsAvailableCapacityChangedEvent(const std::string& event_name) {
- return event_name == event_names::kOnStorageAvailableCapacityChanged;
-}
-
// Event router for systemInfo API. It is a singleton instance shared by
// multiple profiles.
class SystemInfoEventRouter : public gfx::DisplayObserver,
- public StorageFreeSpaceObserver,
public chrome::RemovableStorageObserver {
public:
static SystemInfoEventRouter* GetInstance();
@@ -59,11 +53,6 @@
void RemoveEventListener(const std::string& event_name);
private:
- // StorageFreeSpaceObserver:
- virtual void OnFreeSpaceChanged(const std::string& id,
- double new_value,
- double old_value) OVERRIDE;
-
// gfx::DisplayObserver:
virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE;
virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE;
@@ -80,11 +69,6 @@
void DispatchEvent(const std::string& event_name,
scoped_ptr<base::ListValue> args);
- // The callbacks of querying storage info to start and stop watching the
- // storages. Called from UI thread.
- void StartWatchingStorages(bool success);
- void StopWatchingStorages(bool success);
-
// Called to dispatch the systemInfo.display.onDisplayChanged event.
void OnDisplayChanged();
@@ -103,33 +87,15 @@
}
SystemInfoEventRouter::SystemInfoEventRouter() {
- StorageInfoProvider::Get()->AddObserver(this);
chrome::StorageMonitor::GetInstance()->AddObserver(this);
}
SystemInfoEventRouter::~SystemInfoEventRouter() {
- StorageInfoProvider::Get()->RemoveObserver(this);
if (chrome::StorageMonitor* storage_monitor =
chrome::StorageMonitor::GetInstance())
storage_monitor->RemoveObserver(this);
}
-void SystemInfoEventRouter::StartWatchingStorages(bool success) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (!success)
- return;
-
- StorageInfoProvider::Get()->StartWatchingAllStorages();
-}
-
-void SystemInfoEventRouter::StopWatchingStorages(bool success) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (!success)
- return;
-
- StorageInfoProvider::Get()->StopWatchingAllStorages();
-}
-
void SystemInfoEventRouter::AddEventListener(const std::string& event_name) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -137,15 +103,6 @@
if (watching_event_set_.count(event_name) > 1)
return;
- // Start watching the |event_name| event if the first event listener arrives.
- // For systemInfo.storage event.
- if (IsAvailableCapacityChangedEvent(event_name)) {
- StorageInfoProvider::Get()->StartQueryInfo(
- base::Bind(&SystemInfoEventRouter::StartWatchingStorages,
- base::Unretained(this)));
- return;
- }
-
// For systemInfo.display event.
if (IsDisplayChangedEvent(event_name)) {
#if defined(USE_ASH)
@@ -166,14 +123,6 @@
if (watching_event_set_.count(event_name) > 0)
return;
- // In case of the last event listener is removed, we need to stop watching
- // it to avoid unnecessary overhead.
- if (IsAvailableCapacityChangedEvent(event_name)) {
- StorageInfoProvider::Get()->StartQueryInfo(
- base::Bind(&SystemInfoEventRouter::StopWatchingStorages,
- base::Unretained(this)));
- }
-
if (IsDisplayChangedEvent(event_name)) {
#if defined(USE_ASH)
ash::Shell::GetScreen()->RemoveObserver(this);
@@ -181,19 +130,6 @@
}
}
-// Called on UI thread since the observer is added from UI thread.
-void SystemInfoEventRouter::OnFreeSpaceChanged(
- const std::string& transient_id, double new_value, double old_value) {
- StorageFreeSpaceChangeInfo info;
- info.id = transient_id;
- info.available_capacity = static_cast<double>(new_value);
-
- scoped_ptr<base::ListValue> args(new base::ListValue());
- args->Append(info.ToValue().release());
-
- DispatchEvent(event_names::kOnStorageAvailableCapacityChanged, args.Pass());
-}
-
void SystemInfoEventRouter::OnRemovableStorageAttached(
const chrome::StorageInfo& info) {
StorageUnitInfo unit;
@@ -248,8 +184,6 @@
SystemInfoAPI::SystemInfoAPI(Profile* profile) : profile_(profile) {
ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
- this, event_names::kOnStorageAvailableCapacityChanged);
- ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
this, event_names::kOnStorageAttached);
ExtensionSystem::Get(profile_)->event_router()->RegisterObserver(
this, event_names::kOnStorageDetached);
diff --git a/chrome/browser/extensions/api/system_storage/storage_api_test_util.cc b/chrome/browser/extensions/api/system_storage/storage_api_test_util.cc
new file mode 100644
index 0000000..b5b6c98
--- /dev/null
+++ b/chrome/browser/extensions/api/system_storage/storage_api_test_util.cc
@@ -0,0 +1,29 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/system_storage/storage_api_test_util.h"
+
+#include "base/strings/utf_string_conversions.h"
+
+namespace extensions {
+namespace test {
+
+const struct TestStorageUnitInfo kRemovableStorageData = {
+ "dcim:device:001", "/media/usb1", 4098, 1000
+};
+
+chrome::StorageInfo BuildStorageInfoFromTestStorageUnitInfo(
+ const TestStorageUnitInfo& unit) {
+ return chrome::StorageInfo(
+ unit.device_id,
+ UTF8ToUTF16(unit.name),
+ base::FilePath::StringType(), /* no location */
+ string16(), /* no storage label */
+ string16(), /* no storage vendor */
+ string16(), /* no storage model */
+ unit.capacity);
+}
+
+} // namespace test
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/system_storage/storage_api_test_util.h b/chrome/browser/extensions/api/system_storage/storage_api_test_util.h
new file mode 100644
index 0000000..d47aee8
--- /dev/null
+++ b/chrome/browser/extensions/api/system_storage/storage_api_test_util.h
@@ -0,0 +1,33 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_STORAGE_API_TEST_UTIL_H_
+#define CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_STORAGE_API_TEST_UTIL_H_
+
+#include <vector>
+
+#include "chrome/browser/extensions/api/system_storage/storage_info_provider.h"
+#include "chrome/browser/storage_monitor/storage_info.h"
+
+namespace extensions {
+namespace test {
+
+struct TestStorageUnitInfo {
+ const char* device_id;
+ const char* name;
+ // Total amount of the storage device space, in bytes.
+ double capacity;
+ // The available amount of the storage space, in bytes.
+ double available_capacity;
+};
+
+extern const struct TestStorageUnitInfo kRemovableStorageData;
+
+chrome::StorageInfo BuildStorageInfoFromTestStorageUnitInfo(
+ const TestStorageUnitInfo& unit);
+
+} // namespace test
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_STORAGE_API_TEST_UTIL_H_
diff --git a/chrome/browser/extensions/api/system_storage/storage_free_space_observer.h b/chrome/browser/extensions/api/system_storage/storage_free_space_observer.h
deleted file mode 100644
index f861c97..0000000
--- a/chrome/browser/extensions/api/system_storage/storage_free_space_observer.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#ifndef CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_STORAGE_FREE_SPACE_OBSERVER_H_
-#define CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_STORAGE_FREE_SPACE_OBSERVER_H_
-
-#include <string>
-
-namespace extensions {
-
-// Observes the storage free space changes.
-//
-// StorageInfoProvider class maintains a StorageFreeSpaceObserver list for
-// storage devices' free space change event.
-class StorageFreeSpaceObserver {
- public:
- // Called when the storage free space changes.
- virtual void OnFreeSpaceChanged(const std::string& transient_id,
- double old_value, /* in bytes */
- double new_value /* in bytes */) = 0;
- protected:
- virtual ~StorageFreeSpaceObserver() {}
-};
-
-} // namespace extensions
-
-#endif // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_STORAGE_FREE_SPACE_OBSERVER_H_
-
diff --git a/chrome/browser/extensions/api/system_storage/storage_info_provider.cc b/chrome/browser/extensions/api/system_storage/storage_info_provider.cc
index 2f1b874..fd4208b 100644
--- a/chrome/browser/extensions/api/system_storage/storage_info_provider.cc
+++ b/chrome/browser/extensions/api/system_storage/storage_info_provider.cc
@@ -34,21 +34,11 @@
} // namespace systeminfo
-const int kDefaultPollingIntervalMs = 1000;
-const char kWatchingTokenName[] = "_storage_info_watching_token_";
-
// Static member intialization.
base::LazyInstance<scoped_refptr<StorageInfoProvider> >
StorageInfoProvider::provider_ = LAZY_INSTANCE_INITIALIZER;
-StorageInfoProvider::StorageInfoProvider()
- : observers_(new ObserverListThreadSafe<StorageFreeSpaceObserver>()),
- watching_interval_(kDefaultPollingIntervalMs) {
-}
-
-StorageInfoProvider::StorageInfoProvider(size_t watching_interval)
- : observers_(new ObserverListThreadSafe<StorageFreeSpaceObserver>()),
- watching_interval_(watching_interval) {
+StorageInfoProvider::StorageInfoProvider() {
}
StorageInfoProvider::~StorageInfoProvider() {
@@ -98,170 +88,6 @@
}
}
-void StorageInfoProvider::AddObserver(StorageFreeSpaceObserver* obs) {
- observers_->AddObserver(obs);
-}
-
-void StorageInfoProvider::RemoveObserver(StorageFreeSpaceObserver* obs) {
- observers_->RemoveObserver(obs);
-}
-
-void StorageInfoProvider::StartWatching(const std::string& transient_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- BrowserThread::PostBlockingPoolSequencedTask(
- kWatchingTokenName,
- FROM_HERE,
- base::Bind(&StorageInfoProvider::AddWatchedStorageOnBlockingPool,
- this, transient_id));
-}
-
-void StorageInfoProvider::StopWatching(const std::string& transient_id) {
- base::FilePath mount_path;
- BrowserThread::PostBlockingPoolSequencedTask(
- kWatchingTokenName,
- FROM_HERE,
- base::Bind(&StorageInfoProvider::RemoveWatchedStorageOnBlockingPool,
- this, transient_id));
-}
-
-void StorageInfoProvider::StartWatchingAllStorages() {
- for (StorageUnitInfoList::const_iterator it = info_.begin();
- it != info_.end(); ++it) {
- StartWatching((*it)->id);
- }
-}
-
-void StorageInfoProvider::StopWatchingAllStorages() {
- for (StorageUnitInfoList::const_iterator it = info_.begin();
- it != info_.end(); ++it) {
- StopWatching((*it)->id);
- }
-}
-
-int64 StorageInfoProvider::GetStorageFreeSpaceFromTransientId(
- const std::string& transient_id) {
- std::vector<chrome::StorageInfo> storage_list =
- StorageMonitor::GetInstance()->GetAllAvailableStorages();
-
- std::string device_id =
- StorageMonitor::GetInstance()->GetDeviceIdForTransientId(
- transient_id);
-
- // Lookup the matched storage info by |device_id|.
- for (std::vector<chrome::StorageInfo>::const_iterator it =
- storage_list.begin();
- it != storage_list.end(); ++it) {
- if (device_id == it->device_id())
- return base::SysInfo::AmountOfFreeDiskSpace(
- base::FilePath(it->location()));
- }
-
- return -1;
-}
-
-void StorageInfoProvider::AddWatchedStorageOnBlockingPool(
- const std::string& transient_id) {
- DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
- // If the storage |transient_id| is already being watched.
- if (ContainsKey(storage_transient_id_to_size_map_, transient_id))
- return;
-
- int64 available_bytes = GetStorageFreeSpaceFromTransientId(transient_id);
- if (available_bytes < 0)
- return;
-
- storage_transient_id_to_size_map_[transient_id] = available_bytes;
-
- // If it is the first storage to be watched, we need to start the watching
- // timer.
- if (storage_transient_id_to_size_map_.size() == 1) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&StorageInfoProvider::StartWatchingTimerOnUIThread, this));
- }
-}
-
-void StorageInfoProvider::RemoveWatchedStorageOnBlockingPool(
- const std::string& transient_id) {
- DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
- if (storage_transient_id_to_size_map_.erase(transient_id) == 0)
- return;
-
- // Stop watching timer if there is no storage to be watched.
- if (storage_transient_id_to_size_map_.empty()) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&StorageInfoProvider::StopWatchingTimerOnUIThread, this));
- }
-}
-
-void StorageInfoProvider::CheckWatchedStorages() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- std::vector<chrome::StorageInfo> storage_list =
- StorageMonitor::GetInstance()->GetAllAvailableStorages();
-
- for (std::vector<chrome::StorageInfo>::iterator it = storage_list.begin();
- it != storage_list.end(); ++it) {
- BrowserThread::PostBlockingPoolSequencedTask(
- kWatchingTokenName,
- FROM_HERE,
- base::Bind(&StorageInfoProvider::CheckWatchedStorageOnBlockingPool,
- this,
- StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
- it->device_id())));
- }
-}
-
-void StorageInfoProvider::CheckWatchedStorageOnBlockingPool(
- const std::string& transient_id) {
- DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
- if (!ContainsKey(storage_transient_id_to_size_map_, transient_id))
- return;
-
- double new_available_bytes = GetStorageFreeSpaceFromTransientId(transient_id);
- double old_available_bytes = storage_transient_id_to_size_map_[transient_id];
-
- // No free space change.
- if (new_available_bytes == old_available_bytes)
- return;
-
- if (new_available_bytes < 0) {
- // In case we can't establish the new free space value from |transient_id|,
- // the |transient_id| is currently not available, so we need to remove it
- // from |storage_transient_id_to_size_map_|.
- storage_transient_id_to_size_map_.erase(transient_id);
- if (storage_transient_id_to_size_map_.size() == 0) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&StorageInfoProvider::StopWatchingTimerOnUIThread, this));
- }
- return;
- }
-
- // Ignore free space change event if the old available capacity is 0.
- if (old_available_bytes > 0) {
- observers_->Notify(&StorageFreeSpaceObserver::OnFreeSpaceChanged,
- transient_id,
- old_available_bytes,
- new_available_bytes);
- }
- storage_transient_id_to_size_map_[transient_id] = new_available_bytes;
-}
-
-void StorageInfoProvider::StartWatchingTimerOnUIThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // Start the watching timer if it is not running.
- if (!watching_timer_.IsRunning()) {
- watching_timer_.Start(FROM_HERE,
- base::TimeDelta::FromMilliseconds(watching_interval_),
- this, &StorageInfoProvider::CheckWatchedStorages);
- }
-}
-
-void StorageInfoProvider::StopWatchingTimerOnUIThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- watching_timer_.Stop();
-}
-
// static
StorageInfoProvider* StorageInfoProvider::Get() {
if (provider_.Get().get() == NULL)
diff --git a/chrome/browser/extensions/api/system_storage/storage_info_provider.h b/chrome/browser/extensions/api/system_storage/storage_info_provider.h
index 2dc96f5..859ea87 100644
--- a/chrome/browser/extensions/api/system_storage/storage_info_provider.h
+++ b/chrome/browser/extensions/api/system_storage/storage_info_provider.h
@@ -12,7 +12,6 @@
#include "base/observer_list_threadsafe.h"
#include "base/timer/timer.h"
#include "chrome/browser/extensions/api/system_info/system_info_provider.h"
-#include "chrome/browser/extensions/api/system_storage/storage_free_space_observer.h"
#include "chrome/browser/storage_monitor/removable_storage_observer.h"
#include "chrome/browser/storage_monitor/storage_info.h"
#include "chrome/common/extensions/api/system_storage.h"
@@ -39,34 +38,17 @@
// Get the single shared instance of StorageInfoProvider.
static StorageInfoProvider* Get();
- // Add and remove observer, both can be called from any thread.
- void AddObserver(StorageFreeSpaceObserver* obs);
- void RemoveObserver(StorageFreeSpaceObserver* obs);
-
- // Start and stop watching the given storage |transient_id|.
- void StartWatching(const std::string& transient_id);
- void StopWatching(const std::string& transient_id);
-
- // Start and stop watching all available storages.
- void StartWatchingAllStorages();
- void StopWatchingAllStorages();
-
// SystemInfoProvider implementations
virtual void PrepareQueryOnUIThread() OVERRIDE;
virtual void InitializeProvider(const base::Closure& do_query_info_callback)
OVERRIDE;
- // Get the amount of storage free space from |transient_id|, or -1 on failure.
- virtual int64 GetStorageFreeSpaceFromTransientId(
- const std::string& transient_id);
-
const StorageUnitInfoList& storage_unit_info_list() const;
static void InitializeForTesting(scoped_refptr<StorageInfoProvider> provider);
protected:
StorageInfoProvider();
- explicit StorageInfoProvider(size_t watching_interval);
virtual ~StorageInfoProvider();
@@ -83,49 +65,11 @@
StorageUnitInfoList info_;
private:
- typedef std::map<std::string, double> StorageTransientIdToSizeMap;
-
// SystemInfoProvider implementations.
// Override to query the available capacity of all known storage devices on
// the blocking pool, including fixed and removable devices.
virtual bool QueryInfo() OVERRIDE;
- // Query the new attached removable storage info on the blocking pool.
- void QueryAttachedStorageInfoOnBlockingPool(const std::string& transient_id);
-
- // Posts a task to check for free space changes on the blocking pool.
- // Should be called on the UI thread.
- void CheckWatchedStorages();
-
- // Check if the free space changes for the watched storages by iterating over
- // the |storage_transient_id_to_size_map_|. It is called on blocking pool.
- void CheckWatchedStorageOnBlockingPool(const std::string& transient_id);
-
- // Add the storage identified by |transient_id| into watching list.
- void AddWatchedStorageOnBlockingPool(const std::string& transient_id);
- // Remove the storage identified by |transient_id| from watching list.
- void RemoveWatchedStorageOnBlockingPool(const std::string& transient_id);
-
- void StartWatchingTimerOnUIThread();
- // Force to stop the watching timer or there is no any one storage to be
- // watched. It is called on UI thread.
- void StopWatchingTimerOnUIThread();
-
- // Mapping of the storage being watched and the recent free space value. It
- // is maintained on the blocking pool.
- StorageTransientIdToSizeMap storage_transient_id_to_size_map_;
-
- // The timer used for watching the storage free space changes periodically.
- base::RepeatingTimer<StorageInfoProvider> watching_timer_;
-
- // The thread-safe observer list that observe the changes happening on the
- // storages.
- scoped_refptr<ObserverListThreadSafe<StorageFreeSpaceObserver> > observers_;
-
- // The time interval for watching the free space change, in milliseconds.
- // Only changed for testing purposes.
- size_t watching_interval_;
-
static base::LazyInstance<scoped_refptr<StorageInfoProvider> > provider_;
DISALLOW_COPY_AND_ASSIGN(StorageInfoProvider);
diff --git a/chrome/browser/extensions/api/system_storage/storage_info_provider_unittest.cc b/chrome/browser/extensions/api/system_storage/storage_info_provider_unittest.cc
deleted file mode 100644
index 27896be..0000000
--- a/chrome/browser/extensions/api/system_storage/storage_info_provider_unittest.cc
+++ /dev/null
@@ -1,304 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// StorageInfoProvider unit tests.
-
-#include "base/message_loop/message_loop.h"
-#include "base/stl_util.h"
-#include "chrome/browser/extensions/api/system_storage/storage_info_provider.h"
-#include "chrome/browser/extensions/api/system_storage/test_storage_info_provider.h"
-#include "chrome/browser/storage_monitor/storage_monitor.h"
-#include "chrome/browser/storage_monitor/test_storage_monitor.h"
-#include "content/public/test/test_browser_thread.h"
-#include "content/public/test/test_utils.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace extensions {
-
-using api::system_storage::ParseStorageUnitType;
-using api::system_storage::StorageUnitInfo;
-using api::system_storage::StorageUnitType;
-using base::MessageLoop;
-using chrome::test::TestStorageMonitor;
-using chrome::StorageMonitor;
-using content::BrowserThread;
-using content::RunAllPendingInMessageLoop;
-using content::RunMessageLoop;
-using test::TestStorageUnitInfo;
-using testing::Return;
-using testing::_;
-
-const struct TestStorageUnitInfo kTestingData[] = {
- {"path:device:001", "C:", 1000, 10, 0},
- {"path:device:002", "d:", 2000, 10, 1},
- {"path:device:003", "/home", 3000, 10, 2},
- {"path:device:004", "/", 4000, 10, 3}
-};
-
-// The watching interval for unit test is 1 milliseconds.
-const size_t kWatchingIntervalMs = 1u;
-// The number of times of checking watched storages.
-const int kCheckTimes = 10;
-
-class MockStorageObserver : public StorageFreeSpaceObserver {
- public:
- MockStorageObserver() {}
- virtual ~MockStorageObserver() {}
-
- MOCK_METHOD3(OnFreeSpaceChanged, void(const std::string&,
- double, double));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockStorageObserver);
-};
-
-const int kMaxCheckWatchStorageTimes = 10;
-
-// A testing observer used to provide the statistics of how many times
-// that the storage free space has been changed and check the change against
-// our expectation.
-class TestStorageObserver : public StorageFreeSpaceObserver {
- public:
- TestStorageObserver() : change_times_(0) {
- for (size_t i = 0; i < arraysize(kTestingData); ++i)
- testing_data_.push_back(kTestingData[i]);
- }
-
- virtual ~TestStorageObserver() {}
-
- virtual void OnFreeSpaceChanged(const std::string& transient_id,
- double old_value,
- double new_value) OVERRIDE {
- // The observer is added on UI thread, so the callback should be also
- // called on UI thread.
- ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
- std::string device_id =
- StorageMonitor::GetInstance()->GetDeviceIdForTransientId(transient_id);
- size_t i = 0;
- for (; i < testing_data_.size(); ++i) {
- if (testing_data_[i].device_id == device_id) {
- EXPECT_DOUBLE_EQ(new_value-old_value, testing_data_[i].change_step);
- ++change_times_;
- break;
- }
- }
-
- ASSERT_TRUE(i != testing_data_.size());
- }
-
- private:
- // A copy of |kTestingData|.
- std::vector<TestStorageUnitInfo> testing_data_;
- int change_times_;
-};
-
-class UnitTestStorageInfoProvider : public test::TestStorageInfoProvider {
- public :
- UnitTestStorageInfoProvider(const struct TestStorageUnitInfo* testing_data,
- size_t n)
- : TestStorageInfoProvider(testing_data, n),
- check_watch_storage_times_(0) {}
-
- protected:
- virtual ~UnitTestStorageInfoProvider() {}
-
- private:
- virtual int64 GetStorageFreeSpaceFromTransientId(
- const std::string& transient_id) OVERRIDE {
- int64 available_capacity = -1;
- std::string device_id =
- StorageMonitor::GetInstance()->GetDeviceIdForTransientId(transient_id);
- for (size_t i = 0; i < testing_data_.size(); ++i) {
- if (testing_data_[i].device_id == device_id) {
- available_capacity = testing_data_[i].available_capacity;
- // We simulate free space change by increasing the |available_capacity|
- // with a fixed change step.
- testing_data_[i].available_capacity += testing_data_[i].change_step;
-
- // Add up the counting variable.
- ++check_watch_storage_times_;
-
- // Post a quit task to UI thread for test result verification
- // if |check_watch_storage_times_| is greater than the threshold value
- // |kMaxCheckWatchStorageTimes|.
- if (check_watch_storage_times_ > kMaxCheckWatchStorageTimes) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- MessageLoop::QuitClosure());
- check_watch_storage_times_ = 0;
- }
-
- break;
- }
- }
- return available_capacity;
- }
-
- int check_watch_storage_times_;
-};
-
-class StorageInfoProviderTest : public testing::Test {
- public:
- StorageInfoProviderTest();
- virtual ~StorageInfoProviderTest();
-
- protected:
- virtual void SetUp() OVERRIDE;
- virtual void TearDown() OVERRIDE;
-
- void SetUpAllMockStorageDevices() {
- for (size_t i = 0; i < arraysize(kTestingData); ++i) {
- StorageMonitor::GetInstance()->receiver()->ProcessAttach(
- extensions::test::BuildStorageInfoFromTestStorageUnitInfo(
- kTestingData[i]));
- }
- }
-
- // Run message loop and flush blocking pool to make sure there is no pending
- // tasks on blocking pool.
- static void RunLoopAndFlushBlockingPool();
- static void RunAllPendingAndFlushBlockingPool();
-
- base::MessageLoop message_loop_;
- content::TestBrowserThread ui_thread_;
- scoped_refptr<UnitTestStorageInfoProvider> storage_info_provider_;
-};
-
-StorageInfoProviderTest::StorageInfoProviderTest()
- : message_loop_(base::MessageLoop::TYPE_UI),
- ui_thread_(BrowserThread::UI, &message_loop_) {
-}
-
-StorageInfoProviderTest::~StorageInfoProviderTest() {
-}
-
-void StorageInfoProviderTest::SetUp() {
- ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::UI));
- chrome::test::TestStorageMonitor::CreateAndInstall();
- SetUpAllMockStorageDevices();
- storage_info_provider_ = new UnitTestStorageInfoProvider(
- kTestingData, arraysize(kTestingData));
-}
-
-void StorageInfoProviderTest::TearDown() {
- RunAllPendingAndFlushBlockingPool();
-}
-
-void StorageInfoProviderTest::RunLoopAndFlushBlockingPool() {
- RunMessageLoop();
- content::BrowserThread::GetBlockingPool()->FlushForTesting();
-}
-
-void StorageInfoProviderTest::RunAllPendingAndFlushBlockingPool() {
- RunAllPendingInMessageLoop();
- content::BrowserThread::GetBlockingPool()->FlushForTesting();
-}
-
-TEST_F(StorageInfoProviderTest, WatchingNoChangedStorage) {
- // Case 1: watching a storage that the free space is not changed.
- MockStorageObserver observer;
- storage_info_provider_->AddObserver(&observer);
- std::string transient_id =
- StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
- kTestingData[0].device_id);
- storage_info_provider_->StartWatching(transient_id);
- EXPECT_CALL(observer, OnFreeSpaceChanged(transient_id, _, _))
- .Times(0);
-
- RunLoopAndFlushBlockingPool();
-
- storage_info_provider_->RemoveObserver(&observer);
- storage_info_provider_->StopWatching(transient_id);
- RunAllPendingAndFlushBlockingPool();
-}
-
-TEST_F(StorageInfoProviderTest, WatchingOneStorage) {
- // Case 2: only watching one storage.
- TestStorageObserver observer;
- storage_info_provider_->AddObserver(&observer);
- std::string transient_id =
- StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
- kTestingData[1].device_id);
- storage_info_provider_->StartWatching(transient_id);
- RunLoopAndFlushBlockingPool();
-
- storage_info_provider_->StopWatching(transient_id);
- // Give a chance to run StopWatching task on the blocking pool.
- RunAllPendingAndFlushBlockingPool();
-
- MockStorageObserver mock_observer;
- storage_info_provider_->AddObserver(&mock_observer);
- // The watched storage won't get free space change notification.
- EXPECT_CALL(mock_observer,
- OnFreeSpaceChanged(transient_id, _, _)).Times(0);
- RunAllPendingAndFlushBlockingPool();
-
- storage_info_provider_->RemoveObserver(&observer);
- storage_info_provider_->RemoveObserver(&mock_observer);
-}
-
-TEST_F(StorageInfoProviderTest, WatchingMultipleStorages) {
- // Case 2: watching multiple storages. We ignore the first entry in
- // |kTestingData| since its change_step is zero.
- TestStorageObserver observer;
- storage_info_provider_->AddObserver(&observer);
-
- for (size_t k = 1; k < arraysize(kTestingData); ++k) {
- std::string transient_id =
- StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
- kTestingData[k].device_id);
- storage_info_provider_->StartWatching(transient_id);
- }
- RunLoopAndFlushBlockingPool();
-
- // Stop watching the first storage.
- storage_info_provider_->StopWatching(
- StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
- kTestingData[1].device_id));
- RunAllPendingAndFlushBlockingPool();
-
- MockStorageObserver mock_observer;
- storage_info_provider_->AddObserver(&mock_observer);
- for (size_t k = 2; k < arraysize(kTestingData); ++k) {
- std::string transient_id =
- StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
- kTestingData[k].device_id);
- EXPECT_CALL(mock_observer,
- OnFreeSpaceChanged(transient_id, _, _))
- .WillRepeatedly(Return());
- }
-
- // After stopping watching, the observer won't get change notification.
- EXPECT_CALL(mock_observer,
- OnFreeSpaceChanged(
- StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
- kTestingData[1].device_id),
- _, _))
- .Times(0);
- RunLoopAndFlushBlockingPool();
-
- for (size_t k = 1; k < arraysize(kTestingData); ++k) {
- std::string transient_id =
- StorageMonitor::GetInstance()->GetTransientIdForDeviceId(
- kTestingData[k].device_id);
- storage_info_provider_->StopWatching(transient_id);
- }
- RunAllPendingAndFlushBlockingPool();
- storage_info_provider_->RemoveObserver(&observer);
- storage_info_provider_->RemoveObserver(&mock_observer);
-}
-
-TEST_F(StorageInfoProviderTest, WatchingInvalidStorage) {
- // Case 3: watching an invalid storage.
- std::string invalid_device_id("invalid_id");
- MockStorageObserver mock_observer;
- storage_info_provider_->AddObserver(&mock_observer);
- storage_info_provider_->StartWatching(invalid_device_id);
- EXPECT_CALL(mock_observer,
- OnFreeSpaceChanged(invalid_device_id, _, _)).Times(0);
- RunAllPendingAndFlushBlockingPool();
- storage_info_provider_->RemoveObserver(&mock_observer);
-}
-
-} // namespace extensions
diff --git a/chrome/browser/extensions/api/system_storage/system_storage_api.cc b/chrome/browser/extensions/api/system_storage/system_storage_api.cc
index db28ad8..cf640ab 100644
--- a/chrome/browser/extensions/api/system_storage/system_storage_api.cc
+++ b/chrome/browser/extensions/api/system_storage/system_storage_api.cc
@@ -92,56 +92,4 @@
SendResponse(true);
}
-SystemStorageAddAvailableCapacityWatchFunction::
- SystemStorageAddAvailableCapacityWatchFunction() {
-}
-
-SystemStorageAddAvailableCapacityWatchFunction::
- ~SystemStorageAddAvailableCapacityWatchFunction() {
-}
-
-bool SystemStorageAddAvailableCapacityWatchFunction::RunImpl() {
- // TODO(Haojian): Implement the addAvailableCapacityWatch API.
- return false;
-}
-
-SystemStorageRemoveAvailableCapacityWatchFunction::
- SystemStorageRemoveAvailableCapacityWatchFunction() {
-}
-
-SystemStorageRemoveAvailableCapacityWatchFunction::
- ~SystemStorageRemoveAvailableCapacityWatchFunction() {
-}
-
-bool SystemStorageRemoveAvailableCapacityWatchFunction::RunImpl() {
- // TODO(Haojian): Implement the removeAvailableCapacityWatch API.
- return false;
-}
-
-SystemStorageGetAllAvailableCapacityWatchesFunction
- ::SystemStorageGetAllAvailableCapacityWatchesFunction() {
-}
-
-SystemStorageGetAllAvailableCapacityWatchesFunction
- ::~SystemStorageGetAllAvailableCapacityWatchesFunction() {
-}
-
-bool SystemStorageGetAllAvailableCapacityWatchesFunction::RunImpl() {
- // TODO(Haojian): Implement the getAllAvailableCapacityWatches API.
- return false;
-}
-
-SystemStorageRemoveAllAvailableCapacityWatchesFunction::
- SystemStorageRemoveAllAvailableCapacityWatchesFunction() {
-}
-
-SystemStorageRemoveAllAvailableCapacityWatchesFunction::
- ~SystemStorageRemoveAllAvailableCapacityWatchesFunction() {
-}
-
-bool SystemStorageRemoveAllAvailableCapacityWatchesFunction::RunImpl() {
- // TODO(Haojian): Implement the removeAllAvailableCapacityWatches api.
- return false;
-}
-
} // namespace extensions
diff --git a/chrome/browser/extensions/api/system_storage/system_storage_api.h b/chrome/browser/extensions/api/system_storage/system_storage_api.h
index ba17536..0c346f9 100644
--- a/chrome/browser/extensions/api/system_storage/system_storage_api.h
+++ b/chrome/browser/extensions/api/system_storage/system_storage_api.h
@@ -1,6 +1,7 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+
#ifndef CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_SYSTEM_STORAGE_API_H_
#define CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_SYSTEM_STORAGE_API_H_
@@ -43,54 +44,6 @@
void HandleResponse(chrome::StorageMonitor::EjectStatus status);
};
-class SystemStorageAddAvailableCapacityWatchFunction
- : public AsyncExtensionFunction {
- public:
- DECLARE_EXTENSION_FUNCTION("system.storage.addAvailableCapacityWatch",
- SYSTEM_STORAGE_ADDAVAILABLECAPACITYWATCH);
- SystemStorageAddAvailableCapacityWatchFunction();
-
- private:
- virtual ~SystemStorageAddAvailableCapacityWatchFunction();
- virtual bool RunImpl() OVERRIDE;
-};
-
-class SystemStorageRemoveAvailableCapacityWatchFunction
- : public SyncExtensionFunction {
- public:
- DECLARE_EXTENSION_FUNCTION("system.storage.removeAvailableCapacityWatch",
- SYSTEM_STORAGE_REMOVEAVAILABLECAPACITYWATCH);
- SystemStorageRemoveAvailableCapacityWatchFunction();
-
- private:
- virtual ~SystemStorageRemoveAvailableCapacityWatchFunction();
- virtual bool RunImpl() OVERRIDE;
-};
-
-class SystemStorageGetAllAvailableCapacityWatchesFunction
- : public SyncExtensionFunction {
- public:
- DECLARE_EXTENSION_FUNCTION("system.storage.getAllAvailableCapacityWatches",
- SYSTEM_STORAGE_GETALLAVAILABLECAPACITYWATCHES);
- SystemStorageGetAllAvailableCapacityWatchesFunction();
-
- private:
- virtual ~SystemStorageGetAllAvailableCapacityWatchesFunction();
- virtual bool RunImpl() OVERRIDE;
-};
-
-class SystemStorageRemoveAllAvailableCapacityWatchesFunction
- : public SyncExtensionFunction {
- public:
- DECLARE_EXTENSION_FUNCTION("system.storage.removeAllAvailableCapacityWatches",
- SYSTEM_STORAGE_REMOVEALLAVAILABLECAPACITYWATCHES);
- SystemStorageRemoveAllAvailableCapacityWatchesFunction();
-
- private:
- virtual ~SystemStorageRemoveAllAvailableCapacityWatchesFunction();
- virtual bool RunImpl() OVERRIDE;
-};
-
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_SYSTEM_STORAGE_API_H_
diff --git a/chrome/browser/extensions/api/system_storage/system_storage_apitest.cc b/chrome/browser/extensions/api/system_storage/system_storage_apitest.cc
index a56461e..5cd4fe3 100644
--- a/chrome/browser/extensions/api/system_storage/system_storage_apitest.cc
+++ b/chrome/browser/extensions/api/system_storage/system_storage_apitest.cc
@@ -6,8 +6,8 @@
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/api/system_storage/storage_api_test_util.h"
#include "chrome/browser/extensions/api/system_storage/storage_info_provider.h"
-#include "chrome/browser/extensions/api/system_storage/test_storage_info_provider.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/storage_monitor/storage_info.h"
@@ -17,18 +17,14 @@
namespace {
using chrome::StorageMonitor;
-using extensions::api::system_storage::ParseStorageUnitType;
-using extensions::api::system_storage::StorageUnitInfo;
-using extensions::StorageInfoProvider;
using extensions::StorageUnitInfoList;
using extensions::test::TestStorageUnitInfo;
-using extensions::test::TestStorageInfoProvider;
using extensions::test::kRemovableStorageData;
const struct TestStorageUnitInfo kTestingData[] = {
- {"dcim:device:001", "0xbeaf", 4098, 1000, 0},
- {"path:device:002", "/home", 4098, 1000, 10},
- {"path:device:003", "/data", 10000, 1000, 4097}
+ {"dcim:device:001", "0xbeaf", 4098, 1000},
+ {"path:device:002", "/home", 4098, 1000},
+ {"path:device:003", "/data", 10000, 1000}
};
} // namespace
@@ -70,10 +66,6 @@
IN_PROC_BROWSER_TEST_F(SystemStorageApiTest, Storage) {
SetUpAllMockStorageDevices();
- TestStorageInfoProvider* provider =
- new TestStorageInfoProvider(kTestingData,
- arraysize(kTestingData));
- StorageInfoProvider::InitializeForTesting(provider);
std::vector<linked_ptr<ExtensionTestMessageListener> > device_ids_listeners;
for (size_t i = 0; i < arraysize(kTestingData); ++i) {
linked_ptr<ExtensionTestMessageListener> listener(
diff --git a/chrome/browser/extensions/api/system_storage/system_storage_eject_apitest.cc b/chrome/browser/extensions/api/system_storage/system_storage_eject_apitest.cc
index c91ca29..764fdbb 100644
--- a/chrome/browser/extensions/api/system_storage/system_storage_eject_apitest.cc
+++ b/chrome/browser/extensions/api/system_storage/system_storage_eject_apitest.cc
@@ -7,8 +7,8 @@
#include "base/files/file_path.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/api/system_storage/storage_api_test_util.h"
#include "chrome/browser/extensions/api/system_storage/storage_info_provider.h"
-#include "chrome/browser/extensions/api/system_storage/test_storage_info_provider.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_system.h"
@@ -23,7 +23,6 @@
namespace {
using extensions::test::TestStorageUnitInfo;
-using extensions::test::TestStorageInfoProvider;
using extensions::test::kRemovableStorageData;
} // namespace
diff --git a/chrome/browser/extensions/api/system_storage/test_storage_info_provider.cc b/chrome/browser/extensions/api/system_storage/test_storage_info_provider.cc
deleted file mode 100644
index 3a3e0eb..0000000
--- a/chrome/browser/extensions/api/system_storage/test_storage_info_provider.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/api/system_storage/test_storage_info_provider.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/storage_monitor/storage_monitor.h"
-
-namespace extensions {
-namespace test {
-
-using api::system_storage::ParseStorageUnitType;
-using api::system_storage::StorageUnitInfo;
-
-// Watching interval for testing.
-const size_t kTestingIntervalMS = 10;
-
-const struct TestStorageUnitInfo kRemovableStorageData = {
- "dcim:device:001", "/media/usb1", 4098, 1000, 1
-};
-
-chrome::StorageInfo BuildStorageInfoFromTestStorageUnitInfo(
- const TestStorageUnitInfo& unit) {
- return chrome::StorageInfo(
- unit.device_id,
- UTF8ToUTF16(unit.name),
- base::FilePath::StringType(), /* no location */
- string16(), /* no storage label */
- string16(), /* no storage vendor */
- string16(), /* no storage model */
- unit.capacity);
-}
-
-TestStorageInfoProvider::TestStorageInfoProvider(
- const struct TestStorageUnitInfo* testing_data, size_t n)
- : StorageInfoProvider(kTestingIntervalMS),
- testing_data_(testing_data, testing_data + n) {
-}
-
-TestStorageInfoProvider::~TestStorageInfoProvider() {
-}
-
-int64 TestStorageInfoProvider::GetStorageFreeSpaceFromTransientId(
- const std::string& transient_id) {
- int64 available_capacity = -1;
- std::string device_id =
- chrome::StorageMonitor::GetInstance()->GetDeviceIdForTransientId(
- transient_id);
- for (size_t i = 0; i < testing_data_.size(); ++i) {
- if (testing_data_[i].device_id == device_id) {
- available_capacity = testing_data_[i].available_capacity;
- // We simulate free space change by increasing the |available_capacity|
- // with a fixed change step.
- testing_data_[i].available_capacity += testing_data_[i].change_step;
- break;
- }
- }
- return available_capacity;
-}
-
-} // namespace test
-} // namespace extensions
diff --git a/chrome/browser/extensions/api/system_storage/test_storage_info_provider.h b/chrome/browser/extensions/api/system_storage/test_storage_info_provider.h
deleted file mode 100644
index 7a390b7..0000000
--- a/chrome/browser/extensions/api/system_storage/test_storage_info_provider.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_TEST_STORAGE_INFO_PROVIDER_H_
-#define CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_TEST_STORAGE_INFO_PROVIDER_H_
-
-#include <vector>
-
-#include "chrome/browser/extensions/api/system_storage/storage_info_provider.h"
-#include "chrome/browser/storage_monitor/storage_info.h"
-
-namespace extensions {
-namespace test {
-
-struct TestStorageUnitInfo {
- const char* device_id;
- const char* name;
- // Total amount of the storage device space, in bytes.
- double capacity;
- // The available amount of the storage space, in bytes.
- double available_capacity;
- // The change step of available capacity for simulating the free space change.
- // Each querying operation will increase the |available_capacity| with this
- // value.
- int change_step;
-};
-
-extern const struct TestStorageUnitInfo kRemovableStorageData;
-
-chrome::StorageInfo BuildStorageInfoFromTestStorageUnitInfo(
- const TestStorageUnitInfo& unit);
-
-class TestStorageInfoProvider : public extensions::StorageInfoProvider {
- public:
- TestStorageInfoProvider(const struct TestStorageUnitInfo* testing_data,
- size_t n);
-
- protected:
- virtual ~TestStorageInfoProvider();
-
- // StorageInfoProvider implementations.
- virtual int64 GetStorageFreeSpaceFromTransientId(
- const std::string& transient_id) OVERRIDE;
-
- std::vector<struct TestStorageUnitInfo> testing_data_;
-};
-
-} // namespace test
-} // namespace extensions
-#endif // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_STORAGE_TEST_STORAGE_INFO_PROVIDER_H_
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
index 34f7803..25f17c4 100644
--- a/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
+++ b/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
@@ -21,10 +21,10 @@
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/features/base_feature_provider.h"
-#include "chrome/common/extensions/features/simple_feature.h"
+#include "chrome/common/extensions/features/feature.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
+#include "extensions/common/features/feature_provider.h"
using extensions::api::tab_capture::MediaStreamConstraint;
@@ -80,7 +80,7 @@
active_tab_permission_granter()->IsGranted(extension) &&
CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kWhitelistedExtensionID) != extension_id &&
- !BaseFeatureProvider::GetPermissionFeatures()->GetFeature("tabCapture")->
+ !FeatureProvider::GetByName("permission")->GetFeature("tabCapture")->
IsIdInWhitelist(extension_id)) {
error_ = kGrantError;
return false;
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc
index cbe4a0d..d574db9 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -93,9 +93,9 @@
#endif // OS_WIN
#if defined(USE_ASH)
+#include "apps/shell_window_registry.h"
#include "ash/ash_switches.h"
#include "chrome/browser/extensions/api/tabs/ash_panel_contents.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#endif
using apps::ShellWindow;
diff --git a/chrome/browser/extensions/api/usb/usb_api.cc b/chrome/browser/extensions/api/usb/usb_api.cc
index a6c8ae8..878e362 100644
--- a/chrome/browser/extensions/api/usb/usb_api.cc
+++ b/chrome/browser/extensions/api/usb/usb_api.cc
@@ -89,7 +89,7 @@
static const int kMaxPackets = 4 * 1024 * 1024;
static const int kMaxPacketLength = 64 * 1024;
-static UsbDeviceHandle* device_for_test_ = NULL;
+static UsbDevice* device_for_test_ = NULL;
static bool ConvertDirectionToApi(const UsbEndpointDirection& input,
Direction* output) {
@@ -410,7 +410,7 @@
UsbFindDevicesFunction::~UsbFindDevicesFunction() {}
-void UsbFindDevicesFunction::SetDeviceForTest(UsbDeviceHandle* device) {
+void UsbFindDevicesFunction::SetDeviceForTest(UsbDevice* device) {
device_for_test_ = device;
}
@@ -426,7 +426,7 @@
if (device_for_test_) {
UsbDeviceResource* const resource = new UsbDeviceResource(
extension_->id(),
- device_for_test_);
+ device_for_test_->Open());
Device device;
result_->Append(PopulateDevice(manager_->Add(resource), 0, 0));
@@ -472,23 +472,26 @@
this)));
}
-
void UsbFindDevicesFunction::OnEnumerationCompleted(
ScopedDeviceVector devices) {
+ for (size_t i = 0; i < devices->size(); ++i) {
+ scoped_refptr<UsbDeviceHandle> device_handle =
+ devices->at(i)->Open();
+ if (device_handle)
+ device_handles_.push_back(device_handle);
+ }
+
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
- base::Bind(&UsbFindDevicesFunction::OnCompleted,
- this,
- base::Passed(devices.Pass())));
+ base::Bind(&UsbFindDevicesFunction::OnCompleted, this));
}
-void UsbFindDevicesFunction::OnCompleted(
- ScopedDeviceVector devices) {
- for (size_t i = 0; i < devices->size(); ++i) {
- UsbDeviceHandle* const device = devices->at(i).get();
+void UsbFindDevicesFunction::OnCompleted() {
+ for (size_t i = 0; i < device_handles_.size(); ++i) {
+ UsbDeviceHandle* const device_handle = device_handles_[i].get();
UsbDeviceResource* const resource =
- new UsbDeviceResource(extension_->id(), device);
+ new UsbDeviceResource(extension_->id(), device_handle);
result_->Append(PopulateDevice(manager_->Add(resource),
parameters_->options.vendor_id,
@@ -521,8 +524,8 @@
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::FILE,
FROM_HERE,
- base::Bind(&UsbDeviceHandle::ListInterfaces,
- resource->device(),
+ base::Bind(&UsbDevice::ListInterfaces,
+ resource->device()->device(),
config_),
base::Bind(&UsbListInterfacesFunction::OnCompleted, this));
}
@@ -652,10 +655,10 @@
FROM_HERE,
base::Bind(&UsbDeviceHandle::Close, resource->device()),
base::Bind(&UsbCloseDeviceFunction::OnCompleted, this));
- RemoveUsbDeviceResource(parameters_->device.handle);
}
void UsbCloseDeviceFunction::OnCompleted() {
+ RemoveUsbDeviceResource(parameters_->device.handle);
AsyncWorkCompleted();
}
diff --git a/chrome/browser/extensions/api/usb/usb_api.h b/chrome/browser/extensions/api/usb/usb_api.h
index 65c713e..2f779ff 100644
--- a/chrome/browser/extensions/api/usb/usb_api.h
+++ b/chrome/browser/extensions/api/usb/usb_api.h
@@ -11,6 +11,7 @@
#include "base/memory/ref_counted.h"
#include "chrome/browser/extensions/api/api_function.h"
#include "chrome/browser/extensions/api/api_resource_manager.h"
+#include "chrome/browser/usb/usb_device.h"
#include "chrome/browser/usb/usb_device_handle.h"
#include "chrome/common/extensions/api/usb.h"
#include "net/base/io_buffer.h"
@@ -63,7 +64,7 @@
UsbFindDevicesFunction();
- static void SetDeviceForTest(UsbDeviceHandle* device);
+ static void SetDeviceForTest(UsbDevice* device);
protected:
virtual ~UsbFindDevicesFunction();
@@ -72,21 +73,25 @@
virtual void AsyncWorkStart() OVERRIDE;
private:
- typedef scoped_ptr<std::vector<scoped_refptr<UsbDeviceHandle> > >
+ typedef scoped_ptr<std::vector<scoped_refptr<UsbDevice> > >
ScopedDeviceVector;
+ // This should be run on the FILE thread.
// Wait for GetDeviceService to return and start enumeration on FILE thread.
void EnumerateDevices(uint16_t vendor_id,
uint16_t product_id,
int interface_id,
UsbService* service);
+
// Relay the result on IO thread to OnCompleted.
void OnEnumerationCompleted(ScopedDeviceVector devices);
+ // This should be run on the IO thread.
// Create ApiResources and reply.
- void OnCompleted(ScopedDeviceVector devices);
+ void OnCompleted();
scoped_ptr<base::ListValue> result_;
+ std::vector<scoped_refptr<UsbDeviceHandle> > device_handles_;
scoped_ptr<extensions::api::usb::FindDevices::Params> parameters_;
};
@@ -271,11 +276,11 @@
virtual void AsyncWorkStart() OVERRIDE;
private:
- // FILE thread.
+ // This should be run on the FILE thread.
void OnStartResest(UsbDeviceResource* resource);
void OnCompletedFileThread(bool success);
- // IO thread.
+ // This should be run on the IO thread.
void OnCompleted(bool success);
void OnError();
diff --git a/chrome/browser/extensions/api/usb/usb_apitest.cc b/chrome/browser/extensions/api/usb/usb_apitest.cc
index af0039c..3af2e2e 100644
--- a/chrome/browser/extensions/api/usb/usb_apitest.cc
+++ b/chrome/browser/extensions/api/usb/usb_apitest.cc
@@ -5,12 +5,14 @@
#include "chrome/browser/extensions/api/usb/usb_api.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/ui/browser.h"
+#include "content/public/browser/browser_thread.h"
#include "net/base/io_buffer.h"
#include "testing/gmock/include/gmock/gmock.h"
using testing::AnyNumber;
using testing::_;
using testing::Return;
+using content::BrowserThread;
namespace {
@@ -27,6 +29,7 @@
#pragma warning(push)
#pragma warning(disable:4373)
#endif
+
class MockUsbDeviceHandle : public UsbDeviceHandle {
public:
MockUsbDeviceHandle() : UsbDeviceHandle() {}
@@ -54,11 +57,36 @@
MOCK_METHOD0(ResetDevice, bool());
- MOCK_METHOD1(ListInterfaces, bool(UsbConfigDescriptor* config));
+ void set_device(UsbDevice* device) { device_ = device; }
protected:
virtual ~MockUsbDeviceHandle() {}
};
+
+class MockUsbDevice : public UsbDevice {
+ public:
+ explicit MockUsbDevice(MockUsbDeviceHandle* mock_handle)
+ : UsbDevice(),
+ mock_handle_(mock_handle) {
+ mock_handle->set_device(this);
+ }
+
+ virtual scoped_refptr<UsbDeviceHandle> Open() OVERRIDE {
+ return mock_handle_;
+ }
+
+ virtual bool Close(scoped_refptr<UsbDeviceHandle> handle) OVERRIDE {
+ EXPECT_TRUE(false) << "Should not be reached";
+ return false;
+ }
+
+ MOCK_METHOD1(ListInterfaces, bool(UsbConfigDescriptor* config));
+
+ private:
+ MockUsbDeviceHandle* mock_handle_;
+ virtual ~MockUsbDevice() {}
+};
+
#if defined(OS_WIN)
#pragma warning(pop)
#endif
@@ -66,22 +94,24 @@
class UsbApiTest : public ExtensionApiTest {
public:
virtual void SetUpOnMainThread() OVERRIDE {
- mock_device_ = new MockUsbDeviceHandle();
+ mock_device_handle_ = new MockUsbDeviceHandle();
+ mock_device_ = new MockUsbDevice(mock_device_handle_.get());
extensions::UsbFindDevicesFunction::SetDeviceForTest(mock_device_.get());
}
protected:
- scoped_refptr<MockUsbDeviceHandle> mock_device_;
+ scoped_refptr<MockUsbDeviceHandle> mock_device_handle_;
+ scoped_refptr<MockUsbDevice> mock_device_;
};
} // namespace
IN_PROC_BROWSER_TEST_F(UsbApiTest, DeviceHandling) {
- EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
- EXPECT_CALL(*mock_device_.get(), ResetDevice())
+ EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
+ EXPECT_CALL(*mock_device_handle_.get(), ResetDevice())
.WillOnce(Return(true))
.WillOnce(Return(false));
- EXPECT_CALL(*mock_device_.get(),
+ EXPECT_CALL(*mock_device_handle_.get(),
InterruptTransfer(USB_DIRECTION_OUTBOUND, 2, _, 1, _, _))
.WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED));
ASSERT_TRUE(RunExtensionTest("usb/device_handling"));
@@ -90,12 +120,12 @@
IN_PROC_BROWSER_TEST_F(UsbApiTest, ListInterfaces) {
EXPECT_CALL(*mock_device_.get(), ListInterfaces(_))
.WillOnce(Return(false));
- EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
+ EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
ASSERT_TRUE(RunExtensionTest("usb/list_interfaces"));
}
IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferEvent) {
- EXPECT_CALL(*mock_device_.get(),
+ EXPECT_CALL(*mock_device_handle_.get(),
ControlTransfer(USB_DIRECTION_OUTBOUND,
UsbDeviceHandle::STANDARD,
UsbDeviceHandle::DEVICE,
@@ -107,36 +137,36 @@
_,
_))
.WillOnce(InvokeUsbTransferCallback<9>(USB_TRANSFER_COMPLETED));
- EXPECT_CALL(*mock_device_.get(),
+ EXPECT_CALL(*mock_device_handle_.get(),
BulkTransfer(USB_DIRECTION_OUTBOUND, 1, _, 1, _, _))
.WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED));
- EXPECT_CALL(*mock_device_.get(),
+ EXPECT_CALL(*mock_device_handle_.get(),
InterruptTransfer(USB_DIRECTION_OUTBOUND, 2, _, 1, _, _))
.WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED));
- EXPECT_CALL(*mock_device_.get(),
+ EXPECT_CALL(*mock_device_handle_.get(),
IsochronousTransfer(USB_DIRECTION_OUTBOUND, 3, _, 1, 1, 1, _, _))
.WillOnce(InvokeUsbTransferCallback<7>(USB_TRANSFER_COMPLETED));
- EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
+ EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
ASSERT_TRUE(RunExtensionTest("usb/transfer_event"));
}
IN_PROC_BROWSER_TEST_F(UsbApiTest, ZeroLengthTransfer) {
- EXPECT_CALL(*mock_device_.get(), BulkTransfer(_, _, _, 0, _, _))
+ EXPECT_CALL(*mock_device_handle_.get(), BulkTransfer(_, _, _, 0, _, _))
.WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED));
- EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
+ EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
ASSERT_TRUE(RunExtensionTest("usb/zero_length_transfer"));
}
IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferFailure) {
- EXPECT_CALL(*mock_device_.get(), BulkTransfer(_, _, _, _, _, _))
+ EXPECT_CALL(*mock_device_handle_.get(), BulkTransfer(_, _, _, _, _, _))
.WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED))
.WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_ERROR))
.WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_TIMEOUT));
- EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
+ EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
ASSERT_TRUE(RunExtensionTest("usb/transfer_failure"));
}
IN_PROC_BROWSER_TEST_F(UsbApiTest, InvalidLengthTransfer) {
- EXPECT_CALL(*mock_device_.get(), Close()).Times(AnyNumber());
+ EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
ASSERT_TRUE(RunExtensionTest("usb/invalid_length_transfer"));
}
diff --git a/chrome/browser/extensions/api/usb/usb_device_resource.cc b/chrome/browser/extensions/api/usb/usb_device_resource.cc
index 685d24d..f086300 100644
--- a/chrome/browser/extensions/api/usb/usb_device_resource.cc
+++ b/chrome/browser/extensions/api/usb/usb_device_resource.cc
@@ -13,6 +13,9 @@
#include "chrome/browser/extensions/api/api_resource.h"
#include "chrome/browser/usb/usb_device_handle.h"
#include "chrome/common/extensions/api/usb.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
namespace extensions {
@@ -31,6 +34,9 @@
scoped_refptr<UsbDeviceHandle> device)
: ApiResource(owner_extension_id), device_(device) {}
-UsbDeviceResource::~UsbDeviceResource() {}
+UsbDeviceResource::~UsbDeviceResource() {
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&UsbDeviceHandle::Close, device_));
+}
} // namespace extensions
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 590c681..73c80f1 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
@@ -37,6 +37,8 @@
namespace extensions {
+#if !defined(OS_ANDROID)
+
namespace helpers = web_navigation_api_helpers;
namespace keys = web_navigation_api_constants;
@@ -858,4 +860,6 @@
ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this);
}
+#endif // OS_ANDROID
+
} // namespace extensions
diff --git a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
index f108480..07cc111 100644
--- a/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
+++ b/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
@@ -571,10 +571,12 @@
if (approval_->enable_launcher)
AppListService::Get()->EnableAppList(profile());
- if (apps::IsAppLauncherEnabled()) {
+ if (apps::IsAppLauncherEnabled() && approval_->manifest->is_app()) {
// Show the app list to show download is progressing. Don't show the app
// list on first app install so users can be trained to open it themselves.
- if (approval_->manifest->is_app() && !approval_->enable_launcher)
+ if (approval_->enable_launcher)
+ AppListService::Get()->CreateForProfile(profile());
+ else
AppListService::Get()->ShowForProfile(profile());
}
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index a80d1e0..68d715b 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -72,23 +72,31 @@
} // namespace
// static
+scoped_refptr<CrxInstaller> CrxInstaller::CreateSilent(
+ ExtensionService* frontend) {
+ return new CrxInstaller(frontend->AsWeakPtr(),
+ scoped_ptr<ExtensionInstallPrompt>(),
+ NULL);
+}
+
+// static
scoped_refptr<CrxInstaller> CrxInstaller::Create(
ExtensionService* frontend,
- ExtensionInstallPrompt* client) {
- return new CrxInstaller(frontend->AsWeakPtr(), client, NULL);
+ scoped_ptr<ExtensionInstallPrompt> client) {
+ return new CrxInstaller(frontend->AsWeakPtr(), client.Pass(), NULL);
}
// static
scoped_refptr<CrxInstaller> CrxInstaller::Create(
ExtensionService* service,
- ExtensionInstallPrompt* client,
+ scoped_ptr<ExtensionInstallPrompt> client,
const WebstoreInstaller::Approval* approval) {
- return new CrxInstaller(service->AsWeakPtr(), client, approval);
+ return new CrxInstaller(service->AsWeakPtr(), client.Pass(), approval);
}
CrxInstaller::CrxInstaller(
base::WeakPtr<ExtensionService> service_weak,
- ExtensionInstallPrompt* client,
+ scoped_ptr<ExtensionInstallPrompt> client,
const WebstoreInstaller::Approval* approval)
: install_directory_(service_weak->install_directory()),
install_source_(Manifest::INTERNAL),
@@ -97,7 +105,8 @@
delete_source_(false),
create_app_shortcut_(false),
service_weak_(service_weak),
- client_(client),
+ // See header file comment on |client_| for why we use a raw pointer here.
+ client_(client.release()),
apps_require_extension_mime_type_(false),
allow_silent_install_(false),
install_cause_(extension_misc::INSTALL_CAUSE_UNSET),
@@ -560,13 +569,6 @@
ExtensionService::RecordPermissionMessagesHistogram(
extension(), histogram_name.c_str());
- // Kill the theme loading bubble.
- content::NotificationService* service =
- content::NotificationService::current();
- service->Notify(chrome::NOTIFICATION_NO_THEME_DETECTED,
- content::Source<CrxInstaller>(this),
- content::NotificationService::NoDetails());
-
NotifyCrxInstallComplete(false);
}
diff --git a/chrome/browser/extensions/crx_installer.h b/chrome/browser/extensions/crx_installer.h
index 6f71868..d2bcbbb 100644
--- a/chrome/browser/extensions/crx_installer.h
+++ b/chrome/browser/extensions/crx_installer.h
@@ -76,18 +76,21 @@
NumOffStoreInstallAllowReasons
};
- // Extensions will be installed into service->install_directory(),
- // then registered with |service|. Any install UI will be displayed
- // using |client|. Pass NULL for |client| for silent install
+ // Extensions will be installed into service->install_directory(), then
+ // registered with |service|. This does a silent install - see below for
+ // other options.
+ static scoped_refptr<CrxInstaller> CreateSilent(ExtensionService* service);
+
+ // Same as above, but use |client| to generate a confirmation prompt.
static scoped_refptr<CrxInstaller> Create(
ExtensionService* service,
- ExtensionInstallPrompt* client);
+ scoped_ptr<ExtensionInstallPrompt> client);
// Same as the previous method, except use the |approval| to bypass the
// prompt. Note that the caller retains ownership of |approval|.
static scoped_refptr<CrxInstaller> Create(
ExtensionService* service,
- ExtensionInstallPrompt* client,
+ scoped_ptr<ExtensionInstallPrompt> client,
const WebstoreInstaller::Approval* approval);
// Install the crx in |source_file|.
@@ -199,7 +202,7 @@
friend class ExtensionCrxInstallerTest;
CrxInstaller(base::WeakPtr<ExtensionService> service_weak,
- ExtensionInstallPrompt* client,
+ scoped_ptr<ExtensionInstallPrompt> client,
const WebstoreInstaller::Approval* approval);
virtual ~CrxInstaller();
diff --git a/chrome/browser/extensions/crx_installer_browsertest.cc b/chrome/browser/extensions/crx_installer_browsertest.cc
index 112772f..c288691 100644
--- a/chrome/browser/extensions/crx_installer_browsertest.cc
+++ b/chrome/browser/extensions/crx_installer_browsertest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/memory/ref_counted.h"
#include "chrome/browser/download/download_crx_util.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_browsertest.h"
@@ -29,19 +30,54 @@
namespace {
-// Observer waits for exactly one download to finish.
+class MockInstallPrompt;
+
+// This class holds information about things that happen with a
+// MockInstallPrompt. We create the MockInstallPrompt but need to pass
+// ownership of it to CrxInstaller, so it isn't safe to hang this data on
+// MockInstallPrompt itself becuase we can't guarantee it's lifetime.
+class MockPromptProxy :
+ public base::RefCountedThreadSafe<MockPromptProxy> {
+ public:
+ explicit MockPromptProxy(content::WebContents* web_contents);
+
+ bool did_succeed() const { return !extension_id_.empty(); }
+ const std::string& extension_id() { return extension_id_; }
+ bool confirmation_requested() const { return confirmation_requested_; }
+ const string16& error() const { return error_; }
+
+ // To have any effect, this should be called before CreatePrompt.
+ void set_record_oauth2_grant(bool record_oauth2_grant) {
+ record_oauth2_grant_.reset(new bool(record_oauth2_grant));
+ }
+
+ void set_extension_id(const std::string& id) { extension_id_ = id; }
+ void set_confirmation_requested() { confirmation_requested_ = true; }
+ void set_error(const string16& error) { error_ = error; }
+
+ scoped_ptr<ExtensionInstallPrompt> CreatePrompt();
+
+ private:
+ friend class base::RefCountedThreadSafe<MockPromptProxy>;
+ virtual ~MockPromptProxy();
+
+ // Data used to create a prompt.
+ content::WebContents* web_contents_;
+ scoped_ptr<bool> record_oauth2_grant_;
+
+ // Data reported back to us by the prompt we created.
+ bool confirmation_requested_;
+ std::string extension_id_;
+ string16 error_;
+};
class MockInstallPrompt : public ExtensionInstallPrompt {
public:
- explicit MockInstallPrompt(content::WebContents* web_contents) :
+ MockInstallPrompt(content::WebContents* web_contents,
+ MockPromptProxy* proxy) :
ExtensionInstallPrompt(web_contents),
- confirmation_requested_(false),
- extension_(NULL) {}
+ proxy_(proxy) {}
- bool did_succeed() const { return !!extension_; }
- const Extension* extension() const { return extension_; }
- bool confirmation_requested() const { return confirmation_requested_; }
- const string16& error() const { return error_; }
void set_record_oauth2_grant(bool record) { record_oauth2_grant_ = record; }
// Overriding some of the ExtensionInstallUI API.
@@ -49,27 +85,43 @@
Delegate* delegate,
const Extension* extension,
const ShowDialogCallback& show_dialog_callback) OVERRIDE {
- confirmation_requested_ = true;
+ proxy_->set_confirmation_requested();
delegate->InstallUIProceed();
}
virtual void OnInstallSuccess(const Extension* extension,
SkBitmap* icon) OVERRIDE {
- extension_ = extension;
+ proxy_->set_extension_id(extension->id());
base::MessageLoopForUI::current()->Quit();
}
virtual void OnInstallFailure(const CrxInstallerError& error) OVERRIDE {
- error_ = error.message();
+ proxy_->set_error(error.message());
base::MessageLoopForUI::current()->Quit();
}
private:
- bool confirmation_requested_;
- string16 error_;
- const Extension* extension_;
+ scoped_refptr<MockPromptProxy> proxy_;
};
-MockInstallPrompt* CreateMockInstallPromptForBrowser(Browser* browser) {
- return new MockInstallPrompt(
+
+MockPromptProxy::MockPromptProxy(content::WebContents* web_contents) :
+ web_contents_(web_contents),
+ confirmation_requested_(false) {
+}
+
+MockPromptProxy::~MockPromptProxy() {}
+
+scoped_ptr<ExtensionInstallPrompt> MockPromptProxy::CreatePrompt() {
+ scoped_ptr<MockInstallPrompt> prompt(
+ new MockInstallPrompt(web_contents_, this));
+ if (record_oauth2_grant_.get())
+ prompt->set_record_oauth2_grant(*record_oauth2_grant_.get());
+ return prompt.PassAs<ExtensionInstallPrompt>();
+}
+
+
+scoped_refptr<MockPromptProxy> CreateMockPromptProxyForBrowser(
+ Browser* browser) {
+ return new MockPromptProxy(
browser->tab_strip_model()->GetActiveWebContents());
}
@@ -82,7 +134,7 @@
scoped_refptr<CrxInstaller> InstallWithPrompt(
const std::string& ext_relpath,
const std::string& id,
- MockInstallPrompt* mock_install_prompt) {
+ scoped_refptr<MockPromptProxy> mock_install_prompt) {
ExtensionService* service = extensions::ExtensionSystem::Get(
browser()->profile())->extension_service();
base::FilePath ext_path = test_data_dir_.AppendASCII(ext_relpath);
@@ -103,7 +155,7 @@
scoped_refptr<CrxInstaller> installer(
CrxInstaller::Create(service,
- mock_install_prompt, /* ownership transferred */
+ mock_install_prompt->CreatePrompt(),
approval.get() /* keep ownership */));
installer->set_allow_silent_install(true);
installer->set_is_gallery_install(true);
@@ -124,15 +176,16 @@
ExtensionService* service = extensions::ExtensionSystem::Get(
browser()->profile())->extension_service();
- MockInstallPrompt* mock_prompt =
- CreateMockInstallPromptForBrowser(browser());
+ scoped_refptr<MockPromptProxy> mock_prompt =
+ CreateMockPromptProxyForBrowser(browser());
+
mock_prompt->set_record_oauth2_grant(record_oauth2_grant);
scoped_refptr<CrxInstaller> installer =
InstallWithPrompt("browsertest/scopes", std::string(), mock_prompt);
scoped_refptr<PermissionSet> permissions =
service->extension_prefs()->GetGrantedPermissions(
- mock_prompt->extension()->id());
+ mock_prompt->extension_id());
ASSERT_TRUE(permissions.get());
}
@@ -171,8 +224,8 @@
browser()->profile())->extension_service();
// Even whitelisted extensions with NPAPI should not prompt.
- MockInstallPrompt* mock_prompt =
- CreateMockInstallPromptForBrowser(browser());
+ scoped_refptr<MockPromptProxy> mock_prompt =
+ CreateMockPromptProxyForBrowser(browser());
scoped_refptr<CrxInstaller> installer =
InstallWithPrompt("uitest/plugins", id, mock_prompt);
EXPECT_FALSE(mock_prompt->confirmation_requested());
@@ -225,9 +278,10 @@
std::string crx_path_string(crx_path.value().begin(), crx_path.value().end());
GURL url = GURL(std::string("file:///").append(crx_path_string));
- MockInstallPrompt* mock_prompt =
- CreateMockInstallPromptForBrowser(browser());
- download_crx_util::SetMockInstallPromptForTesting(mock_prompt);
+ scoped_refptr<MockPromptProxy> mock_prompt =
+ CreateMockPromptProxyForBrowser(browser());
+ download_crx_util::SetMockInstallPromptForTesting(
+ mock_prompt->CreatePrompt());
LOG(ERROR) << "PackAndInstallExtension: Getting download manager";
content::DownloadManager* download_manager =
@@ -278,10 +332,11 @@
const bool kTestData[] = {false, true};
for (size_t i = 0; i < arraysize(kTestData); ++i) {
- MockInstallPrompt* mock_prompt =
- CreateMockInstallPromptForBrowser(browser());
+ scoped_refptr<MockPromptProxy> mock_prompt =
+ CreateMockPromptProxyForBrowser(browser());
+
scoped_refptr<CrxInstaller> crx_installer(
- CrxInstaller::Create(service, mock_prompt));
+ CrxInstaller::Create(service, mock_prompt->CreatePrompt()));
crx_installer->set_install_cause(
extension_misc::INSTALL_CAUSE_USER_DOWNLOAD);
diff --git a/chrome/browser/extensions/error_console/error_console.cc b/chrome/browser/extensions/error_console/error_console.cc
index 94eedd8..cff063c 100644
--- a/chrome/browser/extensions/error_console/error_console.cc
+++ b/chrome/browser/extensions/error_console/error_console.cc
@@ -4,12 +4,14 @@
#include "chrome/browser/extensions/error_console/error_console.h"
-#include <algorithm>
+#include <list>
+#include "base/lazy_instance.h"
+#include "base/stl_util.h"
#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/error_console/extension_error.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/extensions/extension.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
@@ -17,6 +19,29 @@
namespace extensions {
+namespace {
+
+const size_t kMaxErrorsPerExtension = 100;
+
+// Iterate through an error list and remove and delete all errors which were
+// from an incognito context.
+void DeleteIncognitoErrorsFromList(ErrorConsole::ErrorList* list) {
+ ErrorConsole::ErrorList::iterator iter = list->begin();
+ while (iter != list->end()) {
+ if ((*iter)->from_incognito()) {
+ delete *iter;
+ iter = list->erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
+base::LazyInstance<ErrorConsole::ErrorList> g_empty_error_list =
+ LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
void ErrorConsole::Observer::OnErrorConsoleDestroyed() {
}
@@ -24,10 +49,14 @@
registrar_.Add(this,
chrome::NOTIFICATION_PROFILE_DESTROYED,
content::NotificationService::AllBrowserContextsAndSources());
+ registrar_.Add(this,
+ chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
+ content::Source<Profile>(profile_));
}
ErrorConsole::~ErrorConsole() {
FOR_EACH_OBSERVER(Observer, observers_, OnErrorConsoleDestroyed());
+ RemoveAllErrors();
}
// static
@@ -35,31 +64,28 @@
return ExtensionSystem::Get(profile)->error_console();
}
-void ErrorConsole::ReportError(scoped_ptr<ExtensionError> error) {
+void ErrorConsole::ReportError(scoped_ptr<const ExtensionError> scoped_error) {
DCHECK(thread_checker_.CalledOnValidThread());
- errors_.push_back(error.release());
- FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(errors_.back()));
-}
-ErrorConsole::WeakErrorList ErrorConsole::GetErrorsForExtension(
- const std::string& extension_id) const {
- WeakErrorList result;
- for (ErrorList::const_iterator iter = errors_.begin();
- iter != errors_.end(); ++iter) {
- if ((*iter)->extension_id() == extension_id)
- result.push_back(*iter);
+ const ExtensionError* error = scoped_error.release();
+ // If there are too many errors for an extension already, limit ourselves to
+ // the most recent ones.
+ ErrorList* error_list = &errors_[error->extension_id()];
+ if (error_list->size() >= kMaxErrorsPerExtension) {
+ delete error_list->front();
+ error_list->pop_front();
}
- return result;
+ error_list->push_back(error);
+
+ FOR_EACH_OBSERVER(Observer, observers_, OnErrorAdded(error));
}
-void ErrorConsole::RemoveError(const ExtensionError* error) {
- ErrorList::iterator iter = std::find(errors_.begin(), errors_.end(), error);
- CHECK(iter != errors_.end());
- errors_.erase(iter);
-}
-
-void ErrorConsole::RemoveAllErrors() {
- errors_.clear();
+const ErrorConsole::ErrorList& ErrorConsole::GetErrorsForExtension(
+ const std::string& extension_id) const {
+ ErrorMap::const_iterator iter = errors_.find(extension_id);
+ if (iter != errors_.end())
+ return iter->second;
+ return g_empty_error_list.Get();
}
void ErrorConsole::AddObserver(Observer* observer) {
@@ -73,19 +99,26 @@
}
void ErrorConsole::RemoveIncognitoErrors() {
- WeakErrorList to_remove;
- for (ErrorList::const_iterator iter = errors_.begin();
+ for (ErrorMap::iterator iter = errors_.begin();
iter != errors_.end(); ++iter) {
- if ((*iter)->from_incognito())
- to_remove.push_back(*iter);
+ DeleteIncognitoErrorsFromList(&(iter->second));
}
+}
- for (WeakErrorList::const_iterator iter = to_remove.begin();
- iter != to_remove.end(); ++iter) {
- RemoveError(*iter);
+void ErrorConsole::RemoveErrorsForExtension(const std::string& extension_id) {
+ ErrorMap::iterator iter = errors_.find(extension_id);
+ if (iter != errors_.end()) {
+ STLDeleteContainerPointers(iter->second.begin(), iter->second.end());
+ errors_.erase(iter);
}
}
+void ErrorConsole::RemoveAllErrors() {
+ for (ErrorMap::iterator iter = errors_.begin(); iter != errors_.end(); ++iter)
+ STLDeleteContainerPointers(iter->second.begin(), iter->second.end());
+ errors_.clear();
+}
+
void ErrorConsole::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
@@ -98,6 +131,12 @@
RemoveIncognitoErrors();
break;
}
+ case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
+ // No need to check the profile here, since we registered to only receive
+ // notifications from our own.
+ RemoveErrorsForExtension(
+ content::Details<Extension>(details).ptr()->id());
+ break;
default:
NOTREACHED();
}
diff --git a/chrome/browser/extensions/error_console/error_console.h b/chrome/browser/extensions/error_console/error_console.h
index 80b2f96..c60bda9 100644
--- a/chrome/browser/extensions/error_console/error_console.h
+++ b/chrome/browser/extensions/error_console/error_console.h
@@ -5,16 +5,17 @@
#ifndef CHROME_BROWSER_EXTENSIONS_ERROR_CONSOLE_ERROR_CONSOLE_H_
#define CHROME_BROWSER_EXTENSIONS_ERROR_CONSOLE_ERROR_CONSOLE_H_
-#include <vector>
+#include <deque>
+#include <map>
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
#include "base/observer_list.h"
#include "base/strings/string16.h"
#include "base/threading/thread_checker.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
+#include "extensions/browser/extension_error.h"
namespace content {
class NotificationDetails;
@@ -26,17 +27,16 @@
namespace extensions {
class ErrorConsoleUnitTest;
-class ExtensionError;
// The ErrorConsole is a central object to which all extension errors are
// reported. This includes errors detected in extensions core, as well as
// runtime Javascript errors.
// This class is owned by ExtensionSystem, making it, in effect, a
// BrowserContext-keyed service.
-class ErrorConsole : content::NotificationObserver {
+class ErrorConsole : public content::NotificationObserver {
public:
- typedef ScopedVector<ExtensionError> ErrorList;
- typedef std::vector<const ExtensionError*> WeakErrorList;
+ typedef std::deque<const ExtensionError*> ErrorList;
+ typedef std::map<std::string, ErrorList> ErrorMap;
class Observer {
public:
@@ -55,24 +55,18 @@
static ErrorConsole* Get(Profile* profile);
// Report an extension error, and add it to the list.
- void ReportError(scoped_ptr<ExtensionError> error);
+ void ReportError(scoped_ptr<const ExtensionError> error);
// Get a collection of weak pointers to all errors relating to the extension
// with the given |extension_id|.
- WeakErrorList GetErrorsForExtension(const std::string& extension_id) const;
-
- // Remove an error from the list of observed errors.
- void RemoveError(const ExtensionError* error);
-
- // Remove all errors from the list of observed errors.
- void RemoveAllErrors();
+ const ErrorList& GetErrorsForExtension(const std::string& extension_id) const;
// Add or remove observers of the ErrorConsole to be notified of any errors
// added.
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
- const ErrorList& errors() { return errors_; }
+ const ErrorMap& errors() { return errors_; }
private:
FRIEND_TEST_ALL_PREFIXES(ErrorConsoleUnitTest, AddAndRemoveErrors);
@@ -81,6 +75,12 @@
// the incognito profile is destroyed.
void RemoveIncognitoErrors();
+ // Remove all errors relating to a particular |extension_id|.
+ void RemoveErrorsForExtension(const std::string& extension_id);
+
+ // Remove all errors for all extensions.
+ void RemoveAllErrors();
+
// content::NotificationObserver implementation.
virtual void Observe(int type,
const content::NotificationSource& source,
@@ -93,7 +93,7 @@
ObserverList<Observer> observers_;
// The errors which we have received so far.
- ErrorList errors_;
+ ErrorMap errors_;
// The profile with which the ErrorConsole is associated. Only collect errors
// from extensions and RenderViews associated with this Profile (and it's
diff --git a/chrome/browser/extensions/error_console/error_console_unittest.cc b/chrome/browser/extensions/error_console/error_console_unittest.cc
index 0d27ff2..62b5320 100644
--- a/chrome/browser/extensions/error_console/error_console_unittest.cc
+++ b/chrome/browser/extensions/error_console/error_console_unittest.cc
@@ -4,12 +4,16 @@
#include "chrome/browser/extensions/error_console/error_console.h"
+#include "base/json/json_writer.h"
+#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/extensions/error_console/extension_error.h"
#include "chrome/test/base/testing_profile.h"
-#include "extensions/common/id_util.h"
+#include "content/public/common/url_constants.h"
+#include "extensions/browser/extension_error.h"
+#include "extensions/common/constants.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::string16;
@@ -19,12 +23,32 @@
namespace {
-scoped_ptr<ExtensionError> CreateNewManifestError(bool from_incognito) {
- return scoped_ptr<ExtensionError>(
- new ManifestParsingError(from_incognito,
- UTF8ToUTF16("source"),
- UTF8ToUTF16("message"),
- 0u /* line number */ ));
+const char kExecutionContextURLKey[] = "executionContextURL";
+const char kStackTraceKey[] = "stackTrace";
+
+string16 CreateErrorDetails(const std::string& extension_id) {
+ base::DictionaryValue value;
+ value.SetString(
+ kExecutionContextURLKey,
+ std::string(kExtensionScheme) +
+ content::kStandardSchemeSeparator +
+ extension_id);
+ value.Set(kStackTraceKey, new ListValue);
+ std::string json_utf8;
+ base::JSONWriter::Write(&value, &json_utf8);
+ return UTF8ToUTF16(json_utf8);
+}
+
+scoped_ptr<const ExtensionError> CreateNewRuntimeError(
+ bool from_incognito,
+ const std::string& extension_id,
+ const string16& message) {
+ return scoped_ptr<const ExtensionError>(new JavascriptRuntimeError(
+ from_incognito,
+ UTF8ToUTF16("source"),
+ message,
+ logging::LOG_INFO,
+ CreateErrorDetails(extension_id)));
}
} // namespace
@@ -49,26 +73,81 @@
const size_t kNumTotalErrors = 6;
const size_t kNumNonIncognitoErrors = 3;
+ const char kId[] = "id";
// Populate with both incognito and non-incognito errors (evenly distributed).
- for (size_t i = 0; i < kNumTotalErrors; ++i)
- error_console_->ReportError(CreateNewManifestError(i % 2 == 0));
+ for (size_t i = 0; i < kNumTotalErrors; ++i) {
+ error_console_->ReportError(
+ CreateNewRuntimeError(i % 2 == 0, kId, string16()));
+ }
- ASSERT_EQ(kNumTotalErrors, error_console_->errors().size());
+ // There should only be one entry in the map, since errors are stored in lists
+ // keyed by extension id.
+ ASSERT_EQ(1u, error_console_->errors().size());
+
+ ASSERT_EQ(kNumTotalErrors, error_console_->GetErrorsForExtension(kId).size());
// Remove the incognito errors; three errors should remain, and all should
// be from non-incognito contexts.
error_console_->RemoveIncognitoErrors();
- ASSERT_EQ(kNumNonIncognitoErrors, error_console_->errors().size());
- for (size_t i = 0; i < error_console_->errors().size(); ++i)
- ASSERT_FALSE(error_console_->errors()[i]->from_incognito());
+ const ErrorConsole::ErrorList& errors =
+ error_console_->GetErrorsForExtension(kId);
+ ASSERT_EQ(kNumNonIncognitoErrors, errors.size());
+ for (size_t i = 0; i < errors.size(); ++i)
+ ASSERT_FALSE(errors[i]->from_incognito());
- // Remove an error by address.
- error_console_->RemoveError(error_console_->errors()[1]);
- ASSERT_EQ(kNumNonIncognitoErrors - 1, error_console_->errors().size());
+ // Add another error for a different extension id.
+ const char kSecondId[] = "id2";
+ error_console_->ReportError(
+ CreateNewRuntimeError(false, kSecondId, string16()));
- // Remove all remaining errors.
+ // There should be two entries now, one for each id, and there should be one
+ // error for the second extension.
+ ASSERT_EQ(2u, error_console_->errors().size());
+ ASSERT_EQ(1u, error_console_->GetErrorsForExtension(kSecondId).size());
+
+ // Remove all errors for the second id.
+ error_console_->RemoveErrorsForExtension(kSecondId);
+ ASSERT_EQ(1u, error_console_->errors().size());
+ ASSERT_EQ(0u, error_console_->GetErrorsForExtension(kSecondId).size());
+ // First extension should be unaffected.
+ ASSERT_EQ(kNumNonIncognitoErrors,
+ error_console_->GetErrorsForExtension(kId).size());
+
+ // Remove remaining errors.
error_console_->RemoveAllErrors();
ASSERT_EQ(0u, error_console_->errors().size());
+ ASSERT_EQ(0u, error_console_->GetErrorsForExtension(kId).size());
+}
+
+// Test that if we add enough errors, only the most recent
+// kMaxErrorsPerExtension are kept.
+TEST_F(ErrorConsoleUnitTest, ExcessiveErrorsGetCropped) {
+ ASSERT_EQ(0u, error_console_->errors().size());
+
+ // This constant matches one of the same name in error_console.cc.
+ const size_t kMaxErrorsPerExtension = 100;
+ const size_t kNumExtraErrors = 5;
+ const char kId[] = "id";
+
+ // Add new errors, with each error's message set to its number.
+ for (size_t i = 0; i < kMaxErrorsPerExtension + kNumExtraErrors; ++i) {
+ error_console_->ReportError(
+ CreateNewRuntimeError(false, kId, base::UintToString16(i)));
+ }
+
+ ASSERT_EQ(1u, error_console_->errors().size());
+
+ const ErrorConsole::ErrorList& errors =
+ error_console_->GetErrorsForExtension(kId);
+ ASSERT_EQ(kMaxErrorsPerExtension, errors.size());
+
+ // We should have popped off errors in the order they arrived, so the
+ // first stored error should be the 6th reported (zero-based)...
+ ASSERT_EQ(errors.front()->message(),
+ base::UintToString16(kNumExtraErrors));
+ // ..and the last stored should be the 105th reported.
+ ASSERT_EQ(errors.back()->message(),
+ base::UintToString16(kMaxErrorsPerExtension + kNumExtraErrors - 1));
}
} // namespace extensions
diff --git a/chrome/browser/extensions/extension_bindings_apitest.cc b/chrome/browser/extensions/extension_bindings_apitest.cc
index 1eb5f90..61b5799 100644
--- a/chrome/browser/extensions/extension_bindings_apitest.cc
+++ b/chrome/browser/extensions/extension_bindings_apitest.cc
@@ -9,11 +9,18 @@
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/test/browser_test_utils.h"
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ExceptionInHandlerShouldNotCrash) {
+namespace extensions {
+namespace {
+
+class ExtensionBindingsApiTest : public ExtensionApiTest {};
+
+IN_PROC_BROWSER_TEST_F(ExtensionBindingsApiTest,
+ ExceptionInHandlerShouldNotCrash) {
ASSERT_TRUE(RunExtensionSubtest(
"bindings/exception_in_handler_should_not_crash",
"page.html")) << message_;
@@ -21,6 +28,7 @@
// Tests that an error raised during an async function still fires
// the callback, but sets chrome.runtime.lastError.
+// FIXME should be in ExtensionBindingsApiTest.
IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, LastError) {
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("browsertest").AppendASCII("last_error")));
@@ -36,8 +44,38 @@
EXPECT_TRUE(result);
}
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, InternalAPIsNotOnChromeObject) {
+// Regression test that we don't delete our own bindings with about:blank
+// iframes.
+IN_PROC_BROWSER_TEST_F(ExtensionBindingsApiTest, AboutBlankIframe) {
+ ResultCatcher catcher;
+ ExtensionTestMessageListener listener("load", true);
+
+ ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("bindings")
+ .AppendASCII("about_blank_iframe")));
+
+ ASSERT_TRUE(listener.WaitUntilSatisfied());
+
+ const Extension* extension = LoadExtension(
+ test_data_dir_.AppendASCII("bindings")
+ .AppendASCII("internal_apis_not_on_chrome_object"));
+ ASSERT_TRUE(extension);
+ listener.Reply(extension->id());
+
+ ASSERT_TRUE(catcher.GetNextResult()) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionBindingsApiTest,
+ InternalAPIsNotOnChromeObject) {
ASSERT_TRUE(RunExtensionSubtest(
"bindings/internal_apis_not_on_chrome_object",
"page.html")) << message_;
}
+
+// Tests that we don't override events when bindings are re-injected.
+// Regression test for http://crbug.com/269149.
+IN_PROC_BROWSER_TEST_F(ExtensionBindingsApiTest, EventOverriding) {
+ ASSERT_TRUE(RunExtensionTest("bindings/event_overriding")) << message_;
+}
+
+} // namespace
+} // namespace extensions
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc
index 05e426c..2ebf2dc 100644
--- a/chrome/browser/extensions/extension_browsertest.cc
+++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -406,15 +406,15 @@
size_t num_before = service->extensions()->size();
{
- ExtensionInstallPrompt* install_ui = NULL;
+ scoped_ptr<ExtensionInstallPrompt> install_ui;
if (ui_type == INSTALL_UI_TYPE_CANCEL) {
- install_ui = new MockAbortExtensionInstallPrompt();
+ install_ui.reset(new MockAbortExtensionInstallPrompt());
} else if (ui_type == INSTALL_UI_TYPE_NORMAL) {
- install_ui = new ExtensionInstallPrompt(
- browser->tab_strip_model()->GetActiveWebContents());
+ install_ui.reset(new ExtensionInstallPrompt(
+ browser->tab_strip_model()->GetActiveWebContents()));
} else if (ui_type == INSTALL_UI_TYPE_AUTO_CONFIRM) {
- install_ui = new MockAutoConfirmExtensionInstallPrompt(
- browser->tab_strip_model()->GetActiveWebContents());
+ install_ui.reset(new MockAutoConfirmExtensionInstallPrompt(
+ browser->tab_strip_model()->GetActiveWebContents()));
}
// TODO(tessamac): Update callers to always pass an unpacked extension
@@ -427,7 +427,7 @@
return NULL;
scoped_refptr<extensions::CrxInstaller> installer(
- extensions::CrxInstaller::Create(service, install_ui));
+ extensions::CrxInstaller::Create(service, install_ui.Pass()));
installer->set_expected_id(id);
installer->set_is_gallery_install(from_webstore);
installer->set_install_source(install_source);
@@ -534,6 +534,8 @@
content::NotificationRegistrar registrar;
registrar.Add(this, content::NOTIFICATION_LOAD_STOP,
content::NotificationService::AllSources());
+ registrar.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
+ content::NotificationService::AllSources());
ExtensionProcessManager* manager =
extensions::ExtensionSystem::Get(profile())->process_manager();
@@ -751,7 +753,8 @@
}
case content::NOTIFICATION_LOAD_STOP:
- VLOG(1) << "Got LOAD_STOP notification.";
+ case content::NOTIFICATION_WEB_CONTENTS_DESTROYED:
+ VLOG(1) << "Got LOAD_STOP or WEB_CONTENTS_DESTROYED notification.";
base::MessageLoopForUI::current()->Quit();
break;
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h
index 2640696..cc715e7 100644
--- a/chrome/browser/extensions/extension_browsertest.h
+++ b/chrome/browser/extensions/extension_browsertest.h
@@ -16,7 +16,7 @@
#include "chrome/browser/ui/browser.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/feature_switch.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/common/extensions/manifest.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/browser/notification_details.h"
@@ -297,7 +297,7 @@
int target_visible_page_action_count_;
// Make the current channel "dev" for the duration of the test.
- extensions::Feature::ScopedCurrentChannel current_channel_;
+ extensions::ScopedCurrentChannel current_channel_;
// Disable external install UI.
extensions::FeatureSwitch::ScopedOverride
diff --git a/chrome/browser/extensions/extension_function_histogram_value.h b/chrome/browser/extensions/extension_function_histogram_value.h
index 3408bd6..1defcb8 100644
--- a/chrome/browser/extensions/extension_function_histogram_value.h
+++ b/chrome/browser/extensions/extension_function_histogram_value.h
@@ -574,10 +574,10 @@
FILEBROWSERPRIVATE_GETSHAREURL,
SYSTEM_STORAGE_GETINFO,
SYSTEM_STORAGE_EJECTDEVICE,
- SYSTEM_STORAGE_ADDAVAILABLECAPACITYWATCH,
- SYSTEM_STORAGE_REMOVEAVAILABLECAPACITYWATCH,
- SYSTEM_STORAGE_GETALLAVAILABLECAPACITYWATCHES,
- SYSTEM_STORAGE_REMOVEALLAVAILABLECAPACITYWATCHES,
+ DELETED_SYSTEM_STORAGE_ADDAVAILABLECAPACITYWATCH,
+ DELETED_SYSTEM_STORAGE_REMOVEAVAILABLECAPACITYWATCH,
+ DELETED_SYSTEM_STORAGE_GETALLAVAILABLECAPACITYWATCHES,
+ DELETED_SYSTEM_STORAGE_REMOVEALLAVAILABLECAPACITYWATCHES,
DOWNLOADS_REMOVEFILE,
DOWNLOADS_SHOWDEFAULTFOLDER,
INFOBARS_SHOW,
@@ -588,6 +588,8 @@
RECOVERYPRIVATE_DESTROYPARTITIONS,
FEEDBACKPRIVATE_GETSTRINGS,
LOGPRIVATE_GETHISTORICAL,
+ EXPERIMENTAL_INPUT_VIRTUALKEYBOARD_MOVECURSOR,
+ METRICSPRIVATE_GETVARIATIONPARAMS,
ENUM_BOUNDARY // Last entry: Add new entries above.
};
diff --git a/chrome/browser/extensions/extension_functional_browsertest.cc b/chrome/browser/extensions/extension_functional_browsertest.cc
index 25ceba5..38a8650 100644
--- a/chrome/browser/extensions/extension_functional_browsertest.cc
+++ b/chrome/browser/extensions/extension_functional_browsertest.cc
@@ -27,7 +27,7 @@
content::NotificationService::AllSources());
scoped_refptr<extensions::CrxInstaller> installer(
- extensions::CrxInstaller::Create(service, NULL));
+ extensions::CrxInstaller::CreateSilent(service));
installer->set_is_gallery_install(false);
installer->set_allow_silent_install(true);
installer->set_install_source(Manifest::INTERNAL);
diff --git a/chrome/browser/extensions/extension_messages_apitest.cc b/chrome/browser/extensions/extension_messages_apitest.cc
index 466ca2f..7726d6e 100644
--- a/chrome/browser/extensions/extension_messages_apitest.cc
+++ b/chrome/browser/extensions/extension_messages_apitest.cc
@@ -342,10 +342,8 @@
EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
CanConnectAndSendMessages(not_connectable->id()));
- // Unloading the extension is the same as it never existing - so the bindings
- // will no longer exist.
DisableExtension(chromium_connectable->id());
- EXPECT_EQ(NAMESPACE_NOT_DEFINED,
+ EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
CanConnectAndSendMessages(chromium_connectable->id()));
EnableExtension(chromium_connectable->id());
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 4deba6c..325bea2 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -59,7 +59,6 @@
#include "chrome/browser/extensions/management_policy.h"
#include "chrome/browser/extensions/pending_extension_manager.h"
#include "chrome/browser/extensions/permissions_updater.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/extensions/unpacked_installer.h"
#include "chrome/browser/extensions/update_observer.h"
#include "chrome/browser/extensions/updater/extension_updater.h"
@@ -80,7 +79,7 @@
#include "chrome/common/extensions/extension_manifest_constants.h"
#include "chrome/common/extensions/extension_messages.h"
#include "chrome/common/extensions/feature_switch.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/common/extensions/incognito_handler.h"
#include "chrome/common/extensions/manifest.h"
#include "chrome/common/extensions/manifest_handlers/app_isolation_info.h"
@@ -627,11 +626,12 @@
// We want a silent install only for non-pending extensions and
// pending extensions that have install_silently set.
- ExtensionInstallPrompt* client = NULL;
+ scoped_ptr<ExtensionInstallPrompt> client;
if (pending_extension_info && !pending_extension_info->install_silently())
- client = ExtensionInstallUI::CreateInstallPromptWithProfile(profile_);
+ client.reset(ExtensionInstallUI::CreateInstallPromptWithProfile(profile_));
- scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(this, client));
+ scoped_refptr<CrxInstaller> installer(
+ CrxInstaller::Create(this, client.Pass()));
installer->set_expected_id(id);
if (pending_extension_info) {
installer->set_install_source(pending_extension_info->install_source());
@@ -2035,13 +2035,17 @@
}
bool is_extension_upgrade = false;
- if (const Extension* old = GetInstalledExtension(extension->id())) {
- is_extension_upgrade = true;
- DCHECK_NE(extension, old);
+ bool is_extension_installed = false;
+ const Extension* old = GetInstalledExtension(extension->id());
+ if (old) {
+ is_extension_installed = true;
+ int version_compare_result =
+ extension->version()->CompareTo(*(old->version()));
+ is_extension_upgrade = version_compare_result > 0;
// Other than for unpacked extensions, CrxInstaller should have guaranteed
// that we aren't downgrading.
if (!Manifest::IsUnpackedLocation(extension->location()))
- CHECK_GE(extension->version()->CompareTo(*(old->version())), 0);
+ CHECK_GE(version_compare_result, 0);
}
SetBeingUpgraded(extension, is_extension_upgrade);
@@ -2056,9 +2060,9 @@
// Check if the extension's privileges have changed and mark the
// extension disabled if necessary.
- CheckPermissionsIncrease(extension, is_extension_upgrade);
+ CheckPermissionsIncrease(extension, is_extension_installed);
- if (is_extension_upgrade && !reloading) {
+ if (is_extension_installed && !reloading) {
// To upgrade an extension in place, unload the old one and then load the
// new one. ReloadExtension disables the extension, which is sufficient.
UnloadExtension(extension->id(), extension_misc::UNLOAD_REASON_UPDATE);
@@ -2161,7 +2165,7 @@
}
void ExtensionService::CheckPermissionsIncrease(const Extension* extension,
- bool is_extension_upgrade) {
+ bool is_extension_installed) {
UpdateActivePermissions(extension);
// We keep track of all permissions the user has granted each extension.
@@ -2188,7 +2192,7 @@
int disable_reasons = extension_prefs_->GetDisableReasons(extension->id());
bool auto_grant_permission =
- (!is_extension_upgrade && extension->was_installed_by_default()) ||
+ (!is_extension_installed && extension->was_installed_by_default()) ||
chrome::IsRunningInForcedAppMode();
// Silently grant all active permissions to default apps only on install.
// After install they should behave like other apps.
@@ -2216,7 +2220,7 @@
extension->GetActivePermissions().get(), extension->GetType());
}
- if (is_extension_upgrade) {
+ if (is_extension_installed) {
// If the extension was already disabled, suppress any alerts for becoming
// disabled on permissions increase.
bool previously_disabled =
@@ -2725,7 +2729,7 @@
}
// no client (silent install)
- scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(this, NULL));
+ scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(this));
installer->set_install_source(location);
installer->set_expected_id(id);
installer->set_expected_version(*version);
@@ -2815,7 +2819,7 @@
// Extensions need to know the channel for API restrictions.
process->Send(new ExtensionMsg_SetChannel(
- extensions::Feature::GetCurrentChannel()));
+ extensions::GetCurrentChannel()));
// Platform apps need to know the system font.
scoped_ptr<base::DictionaryValue> fonts(new base::DictionaryValue);
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 8932576..d6a837b 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -766,7 +766,7 @@
// Disables the extension if the privilege level has increased
// (e.g., due to an upgrade).
void CheckPermissionsIncrease(const extensions::Extension* extension,
- bool is_upgrade);
+ bool is_extension_installed);
// Helper that updates the active extension list used for crash reporting.
void UpdateActiveExtensionsInCrashReporter();
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index bf6c949..c0d461e 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -91,7 +91,6 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_constants.h"
-#include "content/public/test/test_browser_thread.h"
#include "content/public/test/test_utils.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension_resource.h"
@@ -440,15 +439,10 @@
// Our message loop may be used in tests which require it to be an IO loop.
ExtensionServiceTestBase::ExtensionServiceTestBase()
- : loop_(base::MessageLoop::TYPE_IO),
+ : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
service_(NULL),
management_policy_(NULL),
- expected_extensions_count_(0),
- ui_thread_(BrowserThread::UI, &loop_),
- db_thread_(BrowserThread::DB, &loop_),
- file_thread_(BrowserThread::FILE, &loop_),
- file_user_blocking_thread_(BrowserThread::FILE_USER_BLOCKING, &loop_),
- io_thread_(BrowserThread::IO, &loop_) {
+ expected_extensions_count_(0) {
base::FilePath test_data_dir;
if (!PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)) {
ADD_FAILURE();
@@ -458,13 +452,7 @@
}
ExtensionServiceTestBase::~ExtensionServiceTestBase() {
- // Drop our reference to ExtensionService and TestingProfile, so that they
- // can be destroyed while BrowserThreads and MessageLoop are still around
- // (they are used in the destruction process).
service_ = NULL;
- base::MessageLoop::current()->RunUntilIdle();
- profile_.reset(NULL);
- base::MessageLoop::current()->RunUntilIdle();
}
void ExtensionServiceTestBase::InitializeExtensionService(
@@ -476,7 +464,7 @@
// TestingPrefServiceSyncable instance.
if (!params.pref_file.empty()) {
builder.WithUserFilePrefs(params.pref_file,
- loop_.message_loop_proxy().get());
+ base::MessageLoopProxy::current().get());
scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
new user_prefs::PrefRegistrySyncable);
scoped_ptr<PrefServiceSyncable> prefs(
@@ -500,7 +488,8 @@
CommandLine::ForCurrentProcess(),
params.extensions_install_dir,
params.autoupdate_enabled);
- service_->SetFileTaskRunnerForTesting(loop_.message_loop_proxy().get());
+ service_->SetFileTaskRunnerForTesting(
+ base::MessageLoopProxy::current().get());
service_->set_extensions_enabled(true);
service_->set_show_extensions_prompts(false);
service_->set_install_updates_when_idle_for_test(false);
@@ -694,8 +683,8 @@
}
// Create a CrxInstaller and start installation. To allow the install
- // to happen, use loop_.RunUntilIdle();. Most tests will not use this
- // method directly. Instead, use InstallCrx(), which waits for
+ // to happen, use base::RunLoop().RunUntilIdle();. Most tests will not use
+ // this method directly. Instead, use InstallCrx(), which waits for
// the crx to be installed and does extra error checking.
void StartCRXInstall(const base::FilePath& crx_path) {
StartCRXInstall(crx_path, Extension::NO_FLAGS);
@@ -704,7 +693,7 @@
void StartCRXInstall(const base::FilePath& crx_path, int creation_flags) {
ASSERT_TRUE(base::PathExists(crx_path))
<< "Path does not exist: "<< crx_path.value().c_str();
- scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(service_, NULL));
+ scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(service_));
installer->set_creation_flags(creation_flags);
if (!(creation_flags & Extension::WAS_INSTALLED_BY_DEFAULT)) {
installer->set_allow_silent_install(true);
@@ -790,7 +779,7 @@
EXPECT_TRUE(base::PathExists(crx_path))
<< "Path does not exist: "<< crx_path.value().c_str();
// no client (silent install)
- scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(service_, NULL));
+ scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(service_));
installer->set_install_source(install_location);
installer->InstallCrx(crx_path);
@@ -911,7 +900,7 @@
chrome::NOTIFICATION_CRX_INSTALLER_DONE,
content::Source<extensions::CrxInstaller>(installer)).Wait();
} else {
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
std::vector<string16> errors = GetErrors();
@@ -994,7 +983,7 @@
// The extension should not be in the service anymore.
EXPECT_FALSE(service_->GetInstalledExtension(id));
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// The directory should be gone.
EXPECT_FALSE(base::PathExists(extension_path));
@@ -1399,7 +1388,7 @@
// be called, call it manually instead.
service_->GarbageCollectExtensions();
// Wait for GarbageCollectExtensions task to complete.
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
base::FileEnumerator dirs(extensions_install_dir_, false,
base::FileEnumerator::DIRECTORIES);
@@ -1437,7 +1426,7 @@
service_->GarbageCollectExtensions();
// Wait for GarbageCollectExtensions task to complete.
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Verify that the pending update for the first extension didn't get
// deleted.
@@ -1475,7 +1464,7 @@
// be called, call it manually instead.
service_->GarbageCollectExtensions();
// Wait for GarbageCollectExtensions task to complete.
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Verify that the pending update for the first extension got installed.
EXPECT_FALSE(base::PathExists(extensions_install_dir_.AppendASCII(
@@ -1511,7 +1500,7 @@
service_->Init();
// Wait for GarbageCollectExtensions task to complete.
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// These extensions are used by the extensions we test below, they must be
// installed.
@@ -1751,7 +1740,7 @@
service_->OnExternalExtensionFileFound(good_crx, &version,
path, Manifest::EXTERNAL_PREF,
Extension::NO_FLAGS, false);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_TRUE(NULL == service_->GetExtensionById(good_crx, false));
ValidateIntegerPref(good_crx, "location",
Extension::EXTERNAL_EXTENSION_UNINSTALLED);
@@ -1762,7 +1751,7 @@
service_->OnExternalExtensionFileFound(good_crx, &version,
path, Manifest::EXTERNAL_PREF,
Extension::NO_FLAGS, false);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_TRUE(NULL == service_->GetExtensionById(good_crx, false));
ValidateIntegerPref(good_crx, "location",
Extension::EXTERNAL_EXTENSION_UNINSTALLED);
@@ -1879,13 +1868,13 @@
.AppendASCII("user_script_basic.user.js");
ASSERT_TRUE(base::PathExists(path));
- scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(service_, NULL));
+ scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(service_));
installer->set_allow_silent_install(true);
installer->InstallUserScript(
path,
GURL("http://www.aaronboodman.com/scripts/user_script_basic.user.js"));
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
std::vector<string16> errors = GetErrors();
EXPECT_TRUE(installed_) << "Nothing was installed.";
EXPECT_FALSE(was_update_) << path.value();
@@ -1909,10 +1898,10 @@
service_->set_browser_terminating_for_test(true);
base::FilePath path = data_dir_.AppendASCII("good.crx");
- scoped_refptr<CrxInstaller> installer(CrxInstaller::Create(service_, NULL));
+ scoped_refptr<CrxInstaller> installer(CrxInstaller::CreateSilent(service_));
installer->set_allow_silent_install(true);
installer->InstallCrx(path);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(installed_) << "Extension installed during shutdown.";
ASSERT_EQ(0u, loaded_.size()) << "Extension loaded during shutdown.";
@@ -2402,7 +2391,7 @@
.AppendASCII("theme_i18n");
extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, GetErrors().size());
ASSERT_EQ(1u, loaded_.size());
EXPECT_EQ(1u, service_->extensions()->size());
@@ -2444,7 +2433,7 @@
base::CopyFile(manifest_no_key, manifest_path);
extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, GetErrors().size());
ASSERT_EQ(1u, loaded_.size());
EXPECT_EQ(1u, service_->extensions()->size());
@@ -2488,7 +2477,7 @@
// Load extension.
InitializeEmptyExtensionService();
extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(GetErrors().empty());
ASSERT_EQ(1u, loaded_.size());
@@ -2831,7 +2820,7 @@
base::FilePath path = data_dir_.AppendASCII("good.crx");
UpdateExtension(good_crx, path, UPDATED);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_EQ(0u, service_->extensions()->size());
ASSERT_FALSE(installed_);
@@ -2936,7 +2925,7 @@
ASSERT_TRUE(serializer.Serialize(manifest));
extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, GetErrors().size());
ASSERT_EQ(1u, loaded_.size());
@@ -2950,7 +2939,7 @@
ASSERT_TRUE(serializer.Serialize(manifest));
extensions::UnpackedInstaller::Create(service_)->Load(extension_path);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, GetErrors().size());
ASSERT_EQ(1u, loaded_.size());
@@ -2986,7 +2975,7 @@
// The extension that has a plugin should not install.
extensions::UnpackedInstaller::Create(service_)->Load(
extension_with_plugin_path);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, GetErrors().size());
EXPECT_EQ(0u, loaded_.size());
EXPECT_EQ(0u, service_->extensions()->size());
@@ -2996,7 +2985,7 @@
ExtensionErrorReporter::GetInstance()->ClearErrors();
extensions::UnpackedInstaller::Create(service_)->Load(
extension_no_plugin_path);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, GetErrors().size());
EXPECT_EQ(1u, loaded_.size());
EXPECT_EQ(1u, service_->extensions()->size());
@@ -3011,7 +3000,7 @@
ExtensionErrorReporter::GetInstance()->ClearErrors();
extensions::UnpackedInstaller::Create(service_)->Load(
extension_with_plugin_path);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, GetErrors().size());
EXPECT_EQ(2u, loaded_.size());
EXPECT_EQ(2u, service_->extensions()->size());
@@ -3034,7 +3023,7 @@
"cancel");
service_->ReloadExtension(good1);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, loaded_.size());
EXPECT_EQ(2u, service_->extensions()->size());
EXPECT_EQ(0u, service_->disabled_extensions()->size());
@@ -3277,7 +3266,7 @@
"v1");
// Make sure pref is updated
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// blacklist is set for good0,1,2
ValidateBooleanPref(good0, "blacklist", true);
@@ -3314,7 +3303,7 @@
"v1");
// Make sure pref is updated
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Now, the good_crx is blacklisted.
ValidateBooleanPref(good_crx, "blacklist", true);
@@ -3326,7 +3315,7 @@
"v2");
// Make sure pref is updated
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// blacklist value should not be set for good_crx
EXPECT_FALSE(IsPrefExist(good_crx, "blacklist"));
}
@@ -3375,7 +3364,7 @@
"v1");
// Make sure pref is updated
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// The good_crx is blacklisted and the whitelist doesn't negate it.
ValidateBooleanPref(good_crx, "blacklist", true);
@@ -3401,7 +3390,7 @@
"v1");
// Make sure pref is updated
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ValidateBooleanPref(good1, "blacklist", true);
@@ -3471,7 +3460,7 @@
}
// Extension should not be running now.
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, service_->extensions()->size());
}
@@ -3515,7 +3504,7 @@
ListValue* blacklist = update.Get();
blacklist->Append(Value::CreateStringValue(good0));
}
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_EQ(1u, service_->extensions()->size());
EXPECT_TRUE(service_->GetExtensionById(good0, false));
}
@@ -3564,7 +3553,7 @@
ListValue* blacklist = update.Get();
blacklist->Append(Value::CreateStringValue(good0));
}
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_EQ(1u, service_->extensions()->size());
EXPECT_TRUE(service_->GetExtensionById(good_crx, false));
}
@@ -3907,7 +3896,7 @@
.AppendASCII(extension_id)
.AppendASCII("1.0.0.0");
extensions::UnpackedInstaller::Create(service_)->Load(ext);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, service_->extensions()->size());
EXPECT_EQ(0u, service_->disabled_extensions()->size());
@@ -3924,7 +3913,7 @@
service_->ReloadExtension(extension_id);
// Finish reloading
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Extension should be enabled again.
EXPECT_EQ(1u, service_->extensions()->size());
@@ -4062,7 +4051,7 @@
base::FilePath path = data_dir_.AppendASCII("requirements")
.AppendASCII("v2_bad_requirements");
extensions::UnpackedInstaller::Create(service_)->Load(path);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, GetErrors().size());
EXPECT_EQ(0u, service_->extensions()->size());
}
@@ -4112,14 +4101,14 @@
ext_url, "dummy=value", options,
base::Bind(&ExtensionCookieCallback::SetCookieCallback,
base::Unretained(&callback)));
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(callback.result_);
cookie_monster->GetAllCookiesForURLAsync(
ext_url,
base::Bind(&ExtensionCookieCallback::GetAllCookiesCallback,
base::Unretained(&callback)));
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1U, callback.list_.size());
// Open a database.
@@ -4160,14 +4149,14 @@
// Uninstall the extension.
service_->UninstallExtension(good_crx, false, NULL);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Check that the cookie is gone.
cookie_monster->GetAllCookiesForURLAsync(
ext_url,
base::Bind(&ExtensionCookieCallback::GetAllCookiesCallback,
base::Unretained(&callback)));
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0U, callback.list_.size());
// The database should have vanished as well.
@@ -4228,14 +4217,14 @@
origin1, "dummy=value", options,
base::Bind(&ExtensionCookieCallback::SetCookieCallback,
base::Unretained(&callback)));
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(callback.result_);
cookie_monster->GetAllCookiesForURLAsync(
origin1,
base::Bind(&ExtensionCookieCallback::GetAllCookiesCallback,
base::Unretained(&callback)));
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1U, callback.list_.size());
// Open a database.
@@ -4286,7 +4275,7 @@
origin1,
base::Bind(&ExtensionCookieCallback::GetAllCookiesCallback,
base::Unretained(&callback)));
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1U, callback.list_.size());
// Now uninstall the other. Storage should be cleared for the apps.
@@ -4300,7 +4289,7 @@
origin1,
base::Bind(&ExtensionCookieCallback::GetAllCookiesCallback,
base::Unretained(&callback)));
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0U, callback.list_.size());
// The database should have vanished as well.
@@ -4326,7 +4315,7 @@
.AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
.AppendASCII("1.0.0.0");
extensions::UnpackedInstaller::Create(service_)->Load(ext1);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, GetErrors().size());
ASSERT_EQ(1u, loaded_.size());
EXPECT_EQ(Manifest::UNPACKED, loaded_[0]->location());
@@ -4340,7 +4329,7 @@
.AppendASCII("cccccccccccccccccccccccccccccccc")
.AppendASCII("1");
extensions::UnpackedInstaller::Create(service_)->Load(no_manifest);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, GetErrors().size());
ASSERT_EQ(1u, loaded_.size());
EXPECT_EQ(1u, service_->extensions()->size());
@@ -4349,7 +4338,7 @@
std::string id = loaded_[0]->id();
EXPECT_FALSE(unloaded_id_.length());
service_->UninstallExtension(id, false, NULL);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(id, unloaded_id_);
ASSERT_EQ(0u, loaded_.size());
EXPECT_EQ(0u, service_->extensions()->size());
@@ -4362,7 +4351,7 @@
base::FilePath no_id_ext = data_dir_.AppendASCII("no_id");
extensions::UnpackedInstaller::Create(service_)->Load(no_id_ext);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0u, GetErrors().size());
ASSERT_EQ(1u, loaded_.size());
ASSERT_TRUE(Extension::IdIsValid(loaded_[0]->id()));
@@ -4374,7 +4363,7 @@
// If we reload the same path, we should get the same extension ID.
extensions::UnpackedInstaller::Create(service_)->Load(no_id_ext);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_EQ(1u, loaded_.size());
ASSERT_EQ(previous_id, loaded_[0]->id());
}
@@ -4412,7 +4401,7 @@
// loaded again.
loaded_.clear();
service_->ReloadExtensions();
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_EQ(0u, GetErrors().size());
ASSERT_EQ(1u, loaded_.size());
ValidatePrefKeyCount(1);
@@ -4441,7 +4430,7 @@
bool no_uninstall =
management_policy_->MustRemainEnabled(loaded_[0].get(), NULL);
service_->UninstallExtension(id, false, NULL);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
base::FilePath install_path = extensions_install_dir_.AppendASCII(id);
if (no_uninstall) {
@@ -4452,7 +4441,7 @@
ASSERT_FALSE(base::PathExists(install_path));
loaded_.clear();
service_->CheckForExternalUpdates();
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_EQ(0u, loaded_.size());
ValidatePrefKeyCount(1);
ValidateIntegerPref(good_crx, "state",
@@ -4482,7 +4471,7 @@
loaded_.clear();
service_->OnExternalProviderReady(provider);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_EQ(0u, loaded_.size());
ValidatePrefKeyCount(0);
@@ -4503,7 +4492,7 @@
// User uninstalls.
loaded_.clear();
service_->UninstallExtension(id, false, NULL);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_EQ(0u, loaded_.size());
// Then remove the extension from the extension provider.
@@ -4512,7 +4501,7 @@
// Should still be at 0.
loaded_.clear();
extensions::InstalledLoader(service_).LoadAllExtensions();
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_EQ(0u, loaded_.size());
ValidatePrefKeyCount(1);
@@ -4607,7 +4596,7 @@
// Verify that it's not the disabled extensions flag causing it not to load.
set_extensions_enabled(true);
service_->ReloadExtensions();
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_EQ(0u, GetErrors().size());
ASSERT_EQ(0u, loaded_.size());
@@ -4630,7 +4619,7 @@
provider->set_visit_count(0);
service_->CheckForExternalUpdates();
service_->CheckForExternalUpdates();
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Two calls should cause two checks for external extensions.
EXPECT_EQ(2, provider->visit_count());
@@ -4662,7 +4651,7 @@
provider->set_visit_count(0);
service_->CheckForExternalUpdates();
service_->CheckForExternalUpdates();
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Two calls should cause two checks for external extensions.
// Because the external source no longer includes good_crx,
@@ -4935,9 +4924,7 @@
ExtensionErrorReporter::Init(false); // no noisy errors
ExtensionsReadyRecorder recorder;
scoped_ptr<TestingProfile> profile(new TestingProfile());
- base::MessageLoop loop;
- content::TestBrowserThread ui_thread(BrowserThread::UI, &loop);
- content::TestBrowserThread file_thread(BrowserThread::FILE, &loop);
+ content::TestBrowserThreadBundle thread_bundle_;
#if defined OS_CHROMEOS
chromeos::ScopedTestDeviceSettingsService device_settings_service;
chromeos::ScopedTestCrosSettings cros_settings;
@@ -4958,7 +4945,7 @@
false);
EXPECT_TRUE(service->extensions_enabled());
service->Init();
- loop.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recorder.ready());
#if defined OS_CHROMEOS
user_manager.reset();
@@ -4976,7 +4963,7 @@
false);
EXPECT_FALSE(service->extensions_enabled());
service->Init();
- loop.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recorder.ready());
recorder.set_ready(false);
@@ -4990,7 +4977,7 @@
false);
EXPECT_FALSE(service->extensions_enabled());
service->Init();
- loop.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recorder.ready());
recorder.set_ready(false);
@@ -5005,14 +4992,14 @@
false);
EXPECT_FALSE(service->extensions_enabled());
service->Init();
- loop.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(recorder.ready());
// Explicitly delete all the resources used in this test.
profile.reset();
service = NULL;
// Execute any pending deletion tasks.
- loop.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
// Test loading extensions that require limited and unlimited storage quotas.
@@ -5037,7 +5024,7 @@
extensions::UnpackedInstaller::Create(service_)->Load(limited_quota_ext);
extensions::UnpackedInstaller::Create(service_)->Load(unlimited_quota_ext);
extensions::UnpackedInstaller::Create(service_)->Load(unlimited_quota_ext2);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
ASSERT_EQ(3u, loaded_.size());
EXPECT_TRUE(profile_.get());
@@ -6203,7 +6190,7 @@
InstallCRX(path, INSTALL_NEW);
service_->CheckForExternalUpdates();
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(extensions::HasExternalInstallError(service_));
// A hosted app, installed externally.
@@ -6378,7 +6365,7 @@
false /* has requirement errors */,
extensions::Blacklist::BLACKLISTED,
false /* wait for idle */);
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Extension was installed but not loaded.
EXPECT_TRUE(notifications.CheckNotifications(
diff --git a/chrome/browser/extensions/extension_service_unittest.h b/chrome/browser/extensions/extension_service_unittest.h
index 884681e..9db4618 100644
--- a/chrome/browser/extensions/extension_service_unittest.h
+++ b/chrome/browser/extensions/extension_service_unittest.h
@@ -13,7 +13,7 @@
#include "base/message_loop/message_loop.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/common/extensions/feature_switch.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_CHROMEOS)
@@ -68,7 +68,7 @@
void InitializeExtensionServiceHelper(bool autoupdate_enabled,
bool is_first_run);
- base::MessageLoop loop_;
+ content::TestBrowserThreadBundle thread_bundle_;
base::ShadowingAtExitManager at_exit_manager_;
base::ScopedTempDir temp_dir_;
scoped_ptr<TestingProfile> profile_;
@@ -78,11 +78,6 @@
ExtensionService* service_;
extensions::ManagementPolicy* management_policy_;
size_t expected_extensions_count_;
- content::TestBrowserThread ui_thread_;
- content::TestBrowserThread db_thread_;
- content::TestBrowserThread file_thread_;
- content::TestBrowserThread file_user_blocking_thread_;
- content::TestBrowserThread io_thread_;
#if defined OS_CHROMEOS
chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
diff --git a/chrome/browser/extensions/extension_system.cc b/chrome/browser/extensions/extension_system.cc
index ebbd3c4..0639302 100644
--- a/chrome/browser/extensions/extension_system.cc
+++ b/chrome/browser/extensions/extension_system.cc
@@ -40,7 +40,7 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/common/extensions/manifest.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/url_data_source.h"
@@ -62,8 +62,8 @@
ExtensionSystem::ExtensionSystem() {
// Only set if it hasn't already been set (e.g. by a test).
- if (Feature::GetCurrentChannel() == Feature::GetDefaultChannel())
- Feature::SetCurrentChannel(chrome::VersionInfo::GetChannel());
+ if (GetCurrentChannel() == GetDefaultChannel())
+ SetCurrentChannel(chrome::VersionInfo::GetChannel());
}
ExtensionSystem::~ExtensionSystem() {
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc
index b5d5ab9..8b427ab 100644
--- a/chrome/browser/extensions/extension_tab_util.cc
+++ b/chrome/browser/extensions/extension_tab_util.cc
@@ -5,8 +5,8 @@
#include "chrome/browser/extensions/extension_tab_util.h"
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/extensions/window_controller.h"
#include "chrome/browser/extensions/window_controller_list.h"
@@ -44,8 +44,8 @@
extensions::WindowController* GetShellWindowController(
const WebContents* contents) {
Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
- extensions::ShellWindowRegistry* registry =
- extensions::ShellWindowRegistry::Get(profile);
+ apps::ShellWindowRegistry* registry =
+ apps::ShellWindowRegistry::Get(profile);
if (!registry)
return NULL;
ShellWindow* shell_window =
diff --git a/chrome/browser/extensions/extension_warning_set.cc b/chrome/browser/extensions/extension_warning_set.cc
index 662e09c..67e90a3 100644
--- a/chrome/browser/extensions/extension_warning_set.cc
+++ b/chrome/browser/extensions/extension_warning_set.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/extensions/extension_warning_set.h"
+#include "base/files/file_path.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/common/extensions/extension.h"
@@ -157,6 +158,24 @@
message_parameters);
}
+// static
+ExtensionWarning ExtensionWarning::CreateDownloadFilenameConflictWarning(
+ const std::string& losing_extension_id,
+ const std::string& winning_extension_id,
+ const base::FilePath& losing_filename,
+ const base::FilePath& winning_filename) {
+ std::vector<std::string> message_parameters;
+ message_parameters.push_back(UTF16ToUTF8(losing_filename.LossyDisplayName()));
+ message_parameters.push_back(kTranslate + winning_extension_id);
+ message_parameters.push_back(UTF16ToUTF8(
+ winning_filename.LossyDisplayName()));
+ return ExtensionWarning(
+ kDownloadFilenameConflict,
+ losing_extension_id,
+ IDS_EXTENSION_WARNINGS_DOWNLOAD_FILENAME_CONFLICT,
+ message_parameters);
+}
+
std::string ExtensionWarning::GetLocalizedMessage(
const ExtensionSet* extensions) const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
diff --git a/chrome/browser/extensions/extension_warning_set.h b/chrome/browser/extensions/extension_warning_set.h
index c0510f1..9e00823 100644
--- a/chrome/browser/extensions/extension_warning_set.h
+++ b/chrome/browser/extensions/extension_warning_set.h
@@ -13,6 +13,10 @@
// TODO(battre) Remove the Extension prefix.
+namespace base {
+class FilePath;
+}
+
class ExtensionSet;
namespace extensions {
@@ -37,6 +41,9 @@
// The extension repeatedly flushed WebKit's in-memory cache, which slows
// down the overall performance.
kRepeatedCacheFlushes,
+ // The extension failed to determine the filename of a download because
+ // another extension with higher precedence determined a different filename.
+ kDownloadFilenameConflict,
kMaxWarningType
};
@@ -69,6 +76,11 @@
const std::string& winning_extension_id);
static ExtensionWarning CreateRepeatedCacheFlushesWarning(
const std::string& extension_id);
+ static ExtensionWarning CreateDownloadFilenameConflictWarning(
+ const std::string& losing_extension_id,
+ const std::string& winning_extension_id,
+ const base::FilePath& losing_filename,
+ const base::FilePath& winning_filename);
// Returns the specific warning type.
WarningType warning_type() const { return type_; }
diff --git a/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc b/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc
index 20bd554..3cfba4c 100644
--- a/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc
+++ b/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc
@@ -79,7 +79,7 @@
InitServiceWithExternalProviders();
service_->CheckForExternalUpdates();
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(service_->GetInstalledExtension(kExternalAppId));
}
diff --git a/chrome/browser/extensions/platform_app_browsertest.cc b/chrome/browser/extensions/platform_app_browsertest.cc
index 1f124a8..8126988 100644
--- a/chrome/browser/extensions/platform_app_browsertest.cc
+++ b/chrome/browser/extensions/platform_app_browsertest.cc
@@ -5,6 +5,7 @@
#include "apps/launcher.h"
#include "apps/native_app_window.h"
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/file_util.h"
@@ -28,7 +29,6 @@
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/extensions/platform_app_browsertest_util.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/tab_contents/render_view_context_menu.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/extensions/application_launch.h"
@@ -48,6 +48,7 @@
#include "url/gurl.h"
using apps::ShellWindow;
+using apps::ShellWindowRegistry;
using content::WebContents;
using web_modal::WebContentsModalDialogManager;
diff --git a/chrome/browser/extensions/platform_app_browsertest_util.cc b/chrome/browser/extensions/platform_app_browsertest_util.cc
index b896892..3348a00 100644
--- a/chrome/browser/extensions/platform_app_browsertest_util.cc
+++ b/chrome/browser/extensions/platform_app_browsertest_util.cc
@@ -6,11 +6,11 @@
#include "apps/app_window_contents.h"
#include "apps/native_app_window.h"
+#include "apps/shell_window_registry.h"
#include "base/command_line.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/extensions/api/tabs/tabs_api.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/ui/apps/chrome_shell_window_delegate.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/extensions/application_launch.h"
@@ -20,6 +20,7 @@
#include "extensions/common/switches.h"
using apps::ShellWindow;
+using apps::ShellWindowRegistry;
using content::WebContents;
namespace utils = extension_function_test_utils;
diff --git a/chrome/browser/extensions/script_badge_controller_unittest.cc b/chrome/browser/extensions/script_badge_controller_unittest.cc
index 9b0eddc..01bfd60 100644
--- a/chrome/browser/extensions/script_badge_controller_unittest.cc
+++ b/chrome/browser/extensions/script_badge_controller_unittest.cc
@@ -19,7 +19,7 @@
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_builder.h"
#include "chrome/common/extensions/feature_switch.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/common/extensions/value_builder.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_profile.h"
@@ -105,7 +105,7 @@
private:
FeatureSwitch::ScopedOverride feature_override_;
- Feature::ScopedCurrentChannel current_channel_;
+ ScopedCurrentChannel current_channel_;
#if defined OS_CHROMEOS
chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
diff --git a/chrome/browser/extensions/startup_helper.cc b/chrome/browser/extensions/startup_helper.cc
index 09f45f3..0362c95 100644
--- a/chrome/browser/extensions/startup_helper.cc
+++ b/chrome/browser/extensions/startup_helper.cc
@@ -18,9 +18,8 @@
#include "chrome/browser/extensions/webstore_startup_installer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/chrome_manifest_handlers.h"
+#include "chrome/common/extensions/chrome_extensions_client.h"
#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/permissions/chrome_api_permissions.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "ipc/ipc_message.h"
@@ -38,9 +37,7 @@
namespace extensions {
StartupHelper::StartupHelper() : pack_job_succeeded_(false) {
- PermissionsInfo::GetInstance()->InitializeWithDelegate(
- ChromeAPIPermissions());
- RegisterChromeManifestHandlers();
+ ExtensionsClient::Set(ChromeExtensionsClient::GetInstance());
}
void StartupHelper::OnPackSuccess(
diff --git a/chrome/browser/extensions/updater/extension_updater_unittest.cc b/chrome/browser/extensions/updater/extension_updater_unittest.cc
index 3c78899..8b8cb2d 100644
--- a/chrome/browser/extensions/updater/extension_updater_unittest.cc
+++ b/chrome/browser/extensions/updater/extension_updater_unittest.cc
@@ -1218,9 +1218,9 @@
extension_service->set_show_extensions_prompts(false);
scoped_refptr<CrxInstaller> fake_crx1(
- CrxInstaller::Create(extension_service, NULL));
+ CrxInstaller::CreateSilent(extension_service));
scoped_refptr<CrxInstaller> fake_crx2(
- CrxInstaller::Create(extension_service, NULL));
+ CrxInstaller::CreateSilent(extension_service));
if (updates_start_running) {
// Add fake CrxInstaller to be returned by service.UpdateExtension().
diff --git a/chrome/browser/extensions/web_view_interactive_browsertest.cc b/chrome/browser/extensions/web_view_interactive_browsertest.cc
index 95fcfb8..170fb9b 100644
--- a/chrome/browser/extensions/web_view_interactive_browsertest.cc
+++ b/chrome/browser/extensions/web_view_interactive_browsertest.cc
@@ -3,11 +3,11 @@
// found in the LICENSE file.
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/extensions/platform_app_browsertest_util.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/test_launcher_utils.h"
#include "chrome/test/base/ui_test_utils.h"
@@ -59,8 +59,8 @@
}
gfx::NativeWindow GetPlatformAppWindow() {
- const extensions::ShellWindowRegistry::ShellWindowList& shell_windows =
- extensions::ShellWindowRegistry::Get(
+ const apps::ShellWindowRegistry::ShellWindowList& shell_windows =
+ apps::ShellWindowRegistry::Get(
browser()->profile())->shell_windows();
return (*shell_windows.begin())->GetNativeWindow();
}
diff --git a/chrome/browser/extensions/webstore_installer.cc b/chrome/browser/extensions/webstore_installer.cc
index dd23748..f9bced0 100644
--- a/chrome/browser/extensions/webstore_installer.cc
+++ b/chrome/browser/extensions/webstore_installer.cc
@@ -17,6 +17,7 @@
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/download/download_crx_util.h"
#include "chrome/browser/download/download_prefs.h"
+#include "chrome/browser/download/download_stats.h"
#include "chrome/browser/download/download_util.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/install_tracker.h"
@@ -421,8 +422,7 @@
// The download url for the given extension is contained in |download_url_|.
// We will navigate the current tab to this url to start the download. The
// download system will then pass the crx to the CrxInstaller.
- download_util::RecordDownloadSource(
- download_util::INITIATED_BY_WEBSTORE_INSTALLER);
+ RecordDownloadSource(DOWNLOAD_INITIATED_BY_WEBSTORE_INSTALLER);
int render_process_host_id =
controller_->GetWebContents()->GetRenderProcessHost()->GetID();
int render_view_host_routing_id =
diff --git a/chrome/browser/extensions/window_open_apitest.cc b/chrome/browser/extensions/window_open_apitest.cc
index 4991a97..b16edc1 100644
--- a/chrome/browser/extensions/window_open_apitest.cc
+++ b/chrome/browser/extensions/window_open_apitest.cc
@@ -28,7 +28,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#if defined(USE_ASH)
-#include "chrome/browser/extensions/shell_window_registry.h"
+#include "apps/shell_window_registry.h"
#endif
#if defined(USE_ASH) && !defined(OS_WIN)
@@ -53,7 +53,7 @@
int GetPanelCount(Browser* browser) {
#if defined(USE_ASH_PANELS)
- return static_cast<int>(extensions::ShellWindowRegistry::Get(
+ return static_cast<int>(apps::ShellWindowRegistry::Get(
browser->profile())->shell_windows().size());
#else
return PanelManager::GetInstance()->num_panels();
diff --git a/chrome/browser/feedback/feedback_data.cc b/chrome/browser/feedback/feedback_data.cc
index 4b4c71f..b0f3770 100644
--- a/chrome/browser/feedback/feedback_data.cc
+++ b/chrome/browser/feedback/feedback_data.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/feedback/feedback_util.h"
+#include "chrome/browser/feedback/tracing_manager.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "content/public/browser/browser_thread.h"
@@ -28,6 +29,8 @@
const char kMultilineStartString[] = "---------- START ----------\n";
const char kMultilineEndString[] = "---------- END ----------\n\n";
+const char kTraceFilename[] = "tracing.log\n";
+
std::string LogsToString(chromeos::SystemLogsResponse* sys_info) {
std::string syslogs_string;
for (chromeos::SystemLogsResponse::const_iterator it = sys_info->begin();
@@ -67,6 +70,7 @@
feedback_page_data_complete_(false) {
#if defined(OS_CHROMEOS)
sys_info_.reset(NULL);
+ trace_id_ = 0;
attached_filedata_.reset(NULL);
send_sys_info_ = true;
read_attached_file_complete_ = false;
@@ -94,6 +98,19 @@
void FeedbackData::FeedbackPageDataComplete() {
#if defined(OS_CHROMEOS)
+ if (trace_id_ != 0) {
+ TracingManager* manager = TracingManager::Get();
+ // When there is a trace id attached to this report, fetch it and attach it
+ // as a file. In this case, return early and retry this function later.
+ if (manager &&
+ manager->GetTraceData(
+ trace_id_,
+ base::Bind(&FeedbackData::OnGetTraceData, this))) {
+ return;
+ } else {
+ trace_id_ = 0;
+ }
+ }
if (attached_filename_.size() &&
base::FilePath::IsSeparator(attached_filename_[0]) &&
!attached_filedata_.get()) {
@@ -167,7 +184,8 @@
}
void FeedbackData::StartSyslogsCollection() {
- chromeos::SystemLogsFetcher* fetcher = new chromeos::SystemLogsFetcher();
+ chromeos::ScrubbedSystemLogsFetcher* fetcher =
+ new chromeos::ScrubbedSystemLogsFetcher();
fetcher->Fetch(base::Bind(&FeedbackData::CompressSyslogs, this));
}
@@ -178,4 +196,15 @@
attached_filedata_->clear();
}
}
+
+void FeedbackData::OnGetTraceData(
+ scoped_refptr<base::RefCountedString> trace_data) {
+ scoped_ptr<std::string> data(new std::string(trace_data->data()));
+
+ set_attached_filename(kTraceFilename);
+ set_attached_filedata(data.Pass());
+ trace_id_ = 0;
+ FeedbackPageDataComplete();
+}
+
#endif
diff --git a/chrome/browser/feedback/feedback_data.h b/chrome/browser/feedback/feedback_data.h
index 111721b..449035f 100644
--- a/chrome/browser/feedback/feedback_data.h
+++ b/chrome/browser/feedback/feedback_data.h
@@ -13,10 +13,15 @@
#include "url/gurl.h"
#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/scrubbed_system_logs_fetcher.h"
#endif
class Profile;
+#if defined(OS_CHROMEOS)
+namespace base {
+class RefCountedString;
+}
+#endif
class FeedbackData : public base::RefCountedThreadSafe<FeedbackData> {
public:
@@ -69,6 +74,7 @@
chromeos::SystemLogsResponse* sys_info() const {
return send_sys_info_ ? sys_info_.get() : NULL;
}
+ const int trace_id() const { return trace_id_; }
const std::string timestamp() const { return timestamp_; }
std::string* compressed_logs() const { return compressed_logs_.get(); }
#endif
@@ -96,6 +102,7 @@
void set_screenshot_url(const GURL& url) { screenshot_url_ = url; }
#if defined(OS_CHROMEOS)
void set_sys_info(scoped_ptr<chromeos::SystemLogsResponse> sys_info);
+ void set_trace_id(int trace_id) { trace_id_ = trace_id; }
void set_send_sys_info(bool send_sys_info) { send_sys_info_ = send_sys_info; }
void set_timestamp(const std::string& timestamp) {
timestamp_ = timestamp;
@@ -109,6 +116,7 @@
#if defined(OS_CHROMEOS)
void ReadAttachedFile(const base::FilePath& from);
+ void OnGetTraceData(scoped_refptr<base::RefCountedString> trace_data);
#endif
Profile* profile_;
@@ -130,6 +138,7 @@
// we don't send the logs with the report.
scoped_ptr<chromeos::SystemLogsResponse> sys_info_;
+ int trace_id_;
std::string timestamp_;
scoped_ptr<std::string> compressed_logs_;
diff --git a/chrome/browser/feedback/tracing_manager.cc b/chrome/browser/feedback/tracing_manager.cc
index 3ea14cf..3a8a4cc 100644
--- a/chrome/browser/feedback/tracing_manager.cc
+++ b/chrome/browser/feedback/tracing_manager.cc
@@ -96,8 +96,8 @@
std::string output_val;
FeedbackUtil::ZipString(data_, &output_val);
- scoped_refptr<base::RefCountedString> output;
- output->TakeString(&output_val);
+ scoped_refptr<base::RefCountedString> output(
+ base::RefCountedString::TakeString(&output_val));
trace_data_[current_trace_id_] = output;
diff --git a/chrome/browser/first_run/first_run.cc b/chrome/browser/first_run/first_run.cc
index e7a6fcc..6b9e650 100644
--- a/chrome/browser/first_run/first_run.cc
+++ b/chrome/browser/first_run/first_run.cc
@@ -598,9 +598,10 @@
const CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kForceFirstRun)) {
internal::first_run_ = internal::FIRST_RUN_TRUE;
- } else if (command_line->HasSwitch(switches::kNoFirstRun)) {
+ } else if (command_line->HasSwitch(switches::kCancelFirstRun)) {
internal::first_run_ = internal::FIRST_RUN_CANCEL;
- } else if (internal::GetFirstRunSentinelFilePath(&first_run_sentinel) &&
+ } else if (!command_line->HasSwitch(switches::kNoFirstRun) &&
+ internal::GetFirstRunSentinelFilePath(&first_run_sentinel) &&
!base::PathExists(first_run_sentinel)) {
internal::first_run_ = internal::FIRST_RUN_TRUE;
}
@@ -608,6 +609,11 @@
return internal::first_run_ == internal::FIRST_RUN_TRUE;
}
+bool IsFirstRunSuppressed(const CommandLine& command_line) {
+ return command_line.HasSwitch(switches::kCancelFirstRun) ||
+ command_line.HasSwitch(switches::kNoFirstRun);
+}
+
void CreateSentinelIfNeeded() {
if (IsChromeFirstRun() ||
internal::first_run_ == internal::FIRST_RUN_CANCEL) {
diff --git a/chrome/browser/first_run/first_run.h b/chrome/browser/first_run/first_run.h
index 9f86f83..b180e29 100644
--- a/chrome/browser/first_run/first_run.h
+++ b/chrome/browser/first_run/first_run.h
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
+class CommandLine;
class GURL;
class Profile;
@@ -84,6 +85,10 @@
// Returns true if this is the first time chrome is run for this user.
bool IsChromeFirstRun();
+// Returns true if |command_line|'s switches explicitly specify that first run
+// should be suppressed in the current run.
+bool IsFirstRunSuppressed(const CommandLine& command_line);
+
// Creates the first run sentinel if needed. This should only be called after
// the process singleton has been grabbed by the current process
// (http://crbug.com/264694).
diff --git a/chrome/browser/first_run/first_run_browsertest.cc b/chrome/browser/first_run/first_run_browsertest.cc
index b6fd6fd..62b439b 100644
--- a/chrome/browser/first_run/first_run_browsertest.cc
+++ b/chrome/browser/first_run/first_run_browsertest.cc
@@ -146,7 +146,7 @@
// Internet Explorer always exists and always has something to import.
EXPECT_GT(source_profile_count, 0);
#endif
- if (source_profile_count == 0)
+ if (source_profile_count == 1)
return expected_import_state & ~first_run::AUTO_IMPORT_PROFILE_IMPORTED;
return expected_import_state;
diff --git a/chrome/browser/google/google_util_chromeos.cc b/chrome/browser/google/google_util_chromeos.cc
index b39d910..06232e4 100644
--- a/chrome/browser/google/google_util_chromeos.cc
+++ b/chrome/browser/google/google_util_chromeos.cc
@@ -46,16 +46,16 @@
} // namespace
void ClearBrandForCurrentSession() {
- DCHECK(
- !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
- content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK(!content::BrowserThread::IsThreadInitialized(
+ content::BrowserThread::UI) ||
+ content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
g_brand_empty = true;
}
std::string GetBrand() {
- DCHECK(
- !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
- content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK(!content::BrowserThread::IsThreadInitialized(
+ content::BrowserThread::UI) ||
+ content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (g_brand_empty)
return std::string();
DCHECK(g_browser_process->local_state());
diff --git a/chrome/browser/history/download_database.cc b/chrome/browser/history/download_database.cc
index 12745ca..369c8c2 100644
--- a/chrome/browser/history/download_database.cc
+++ b/chrome/browser/history/download_database.cc
@@ -40,28 +40,31 @@
static const char kSchema[] =
"CREATE TABLE downloads ("
- "id INTEGER PRIMARY KEY," // Primary key.
+ "id INTEGER PRIMARY KEY," // Primary key.
"current_path LONGVARCHAR NOT NULL," // Current disk location
- "target_path LONGVARCHAR NOT NULL," // Final disk location
- "start_time INTEGER NOT NULL," // When the download was started.
- "received_bytes INTEGER NOT NULL," // Total size downloaded.
- "total_bytes INTEGER NOT NULL," // Total size of the download.
- "state INTEGER NOT NULL," // 1=complete, 4=interrupted
- "danger_type INTEGER NOT NULL, " // Not dangerous, danger type, validated.
- "interrupt_reason INTEGER NOT NULL,"
- "end_time INTEGER NOT NULL," // When the download completed.
- "opened INTEGER NOT NULL," // 1 if it has ever been opened else 0
- "referrer VARCHAR NOT NULL," // HTTP Referrer
- "by_ext_id VARCHAR NOT NULL," // ID of extension that started the download
- "by_ext_name VARCHAR NOT NULL)"; // name of extension
+ "target_path LONGVARCHAR NOT NULL," // Final disk location
+ "start_time INTEGER NOT NULL," // When the download was started.
+ "received_bytes INTEGER NOT NULL," // Total size downloaded.
+ "total_bytes INTEGER NOT NULL," // Total size of the download.
+ "state INTEGER NOT NULL," // 1=complete, 4=interrupted
+ "danger_type INTEGER NOT NULL, " // Danger type, validated.
+ "interrupt_reason INTEGER NOT NULL," // content::DownloadInterruptReason
+ "end_time INTEGER NOT NULL," // When the download completed.
+ "opened INTEGER NOT NULL," // 1 if it has ever been opened else 0
+ "referrer VARCHAR NOT NULL," // HTTP Referrer
+ "by_ext_id VARCHAR NOT NULL," // ID of extension that started the
+ // download
+ "by_ext_name VARCHAR NOT NULL," // name of extension
+ "etag VARCHAR NOT NULL," // ETag
+ "last_modified VARCHAR NOT NULL)"; // Last-Modified header
static const char kUrlChainSchema[] =
"CREATE TABLE downloads_url_chains ("
- "id INTEGER NOT NULL," // downloads.id.
- "chain_index INTEGER NOT NULL," // Index of url in chain
- // 0 is initial target,
- // MAX is target after redirects.
- "url LONGVARCHAR NOT NULL, " // URL.
+ "id INTEGER NOT NULL," // downloads.id.
+ "chain_index INTEGER NOT NULL," // Index of url in chain
+ // 0 is initial target,
+ // MAX is target after redirects.
+ "url LONGVARCHAR NOT NULL, " // URL.
"PRIMARY KEY (id, chain_index) )";
#if defined(OS_POSIX)
@@ -233,19 +236,19 @@
// since the Windows Epoch). Note that this is dependent on the
// internal representation of base::Time and needs to change if that changes.
sql::Statement statement_populate(GetDB().GetUniqueStatement(
- "INSERT INTO downloads "
- "( id, current_path, target_path, start_time, received_bytes, total_bytes, "
- " state, danger_type, interrupt_reason, end_time, opened, referrer, "
- " by_ext_id, by_ext_name ) "
- "SELECT id, full_path, full_path, "
- " CASE start_time WHEN 0 THEN 0 ELSE "
- " (start_time + 11644473600) * 1000000 END, "
- " received_bytes, total_bytes, "
- " state, ?, ?, "
- " CASE end_time WHEN 0 THEN 0 ELSE "
- " (end_time + 11644473600) * 1000000 END, "
- " opened, \"\", \"\", \"\" "
- "FROM downloads_tmp"));
+ "INSERT INTO downloads "
+ "( id, current_path, target_path, start_time, received_bytes, "
+ " total_bytes, state, danger_type, interrupt_reason, end_time, opened, "
+ " referrer, by_ext_id, by_ext_name, etag, last_modified ) "
+ "SELECT id, full_path, full_path, "
+ " CASE start_time WHEN 0 THEN 0 ELSE "
+ " (start_time + 11644473600) * 1000000 END, "
+ " received_bytes, total_bytes, "
+ " state, ?, ?, "
+ " CASE end_time WHEN 0 THEN 0 ELSE "
+ " (end_time + 11644473600) * 1000000 END, "
+ " opened, \"\", \"\", \"\", \"\", \"\" "
+ "FROM downloads_tmp"));
statement_populate.BindInt(0, content::DOWNLOAD_INTERRUPT_REASON_NONE);
statement_populate.BindInt(1, kDangerTypeNotDangerous);
if (!statement_populate.Run())
@@ -276,6 +279,11 @@
EnsureColumnExists("by_ext_name", "VARCHAR NOT NULL DEFAULT \"\"");
}
+bool DownloadDatabase::MigrateDownloadValidators() {
+ return EnsureColumnExists("etag", "VARCHAR NOT NULL DEFAULT \"\"") &&
+ EnsureColumnExists("last_modified", "VARCHAR NOT NULL DEFAULT \"\"");
+}
+
bool DownloadDatabase::InitDownloadTable() {
if (GetDB().DoesTableExist("downloads")) {
return EnsureColumnExists("end_time", "INTEGER NOT NULL DEFAULT 0") &&
@@ -324,7 +332,7 @@
sql::Statement statement_main(GetDB().GetCachedStatement(SQL_FROM_HERE,
"SELECT id, current_path, target_path, start_time, received_bytes, "
"total_bytes, state, danger_type, interrupt_reason, end_time, opened, "
- "referrer, by_ext_id, by_ext_name "
+ "referrer, by_ext_id, by_ext_name, etag, last_modified "
"FROM downloads ORDER BY start_time"));
while (statement_main.Step()) {
@@ -355,6 +363,8 @@
info->referrer_url = GURL(statement_main.ColumnString(column++));
info->by_ext_id = statement_main.ColumnString(column++);
info->by_ext_name = statement_main.ColumnString(column++);
+ info->etag = statement_main.ColumnString(column++);
+ info->last_modified = statement_main.ColumnString(column++);
// If the record is corrupted, note that and drop it.
// http://crbug.com/251269
@@ -457,8 +467,9 @@
sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
"UPDATE downloads "
"SET current_path=?, target_path=?, received_bytes=?, state=?, "
- "danger_type=?, interrupt_reason=?, end_time=?, total_bytes=?, "
- "opened=?, by_ext_id=?, by_ext_name=? WHERE id=?"));
+ "danger_type=?, interrupt_reason=?, end_time=?, total_bytes=?, "
+ "opened=?, by_ext_id=?, by_ext_name=?, etag=?, last_modified=? "
+ "WHERE id=?"));
int column = 0;
BindFilePath(statement, data.current_path, column++);
BindFilePath(statement, data.target_path, column++);
@@ -471,6 +482,8 @@
statement.BindInt(column++, (data.opened ? 1 : 0));
statement.BindString(column++, data.by_ext_id);
statement.BindString(column++, data.by_ext_name);
+ statement.BindString(column++, data.etag);
+ statement.BindString(column++, data.last_modified);
statement.BindInt(column++, data.id);
return statement.Run();
@@ -511,8 +524,9 @@
"INSERT INTO downloads "
"(id, current_path, target_path, start_time, "
" received_bytes, total_bytes, state, danger_type, interrupt_reason, "
- " end_time, opened, referrer, by_ext_id, by_ext_name) "
- "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"));
+ " end_time, opened, referrer, by_ext_id, by_ext_name, etag, "
+ " last_modified) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"));
int column = 0;
statement_insert.BindInt(column++, info.id);
@@ -529,6 +543,8 @@
statement_insert.BindString(column++, info.referrer_url.spec());
statement_insert.BindString(column++, info.by_ext_id);
statement_insert.BindString(column++, info.by_ext_name);
+ statement_insert.BindString(column++, info.etag);
+ statement_insert.BindString(column++, info.last_modified);
if (!statement_insert.Run()) {
// GetErrorCode() returns a bitmask where the lower byte is a more general
// code and the upper byte is a more specific code. In order to save
diff --git a/chrome/browser/history/download_database.h b/chrome/browser/history/download_database.h
index adf4651..36f27f2 100644
--- a/chrome/browser/history/download_database.h
+++ b/chrome/browser/history/download_database.h
@@ -69,6 +69,10 @@
// columns to the downloads table.
bool MigrateDownloadedByExtension();
+ // Returns true if able to successfully add the etag and last-modified columns
+ // to the downloads table.
+ bool MigrateDownloadValidators();
+
// Creates the downloads table if needed.
bool InitDownloadTable();
diff --git a/chrome/browser/history/download_row.cc b/chrome/browser/history/download_row.cc
index 864c56b..fe44c13 100644
--- a/chrome/browser/history/download_row.cc
+++ b/chrome/browser/history/download_row.cc
@@ -23,6 +23,8 @@
const GURL& referrer,
const base::Time& start,
const base::Time& end,
+ const std::string& etag,
+ const std::string& last_modified,
int64 received,
int64 total,
content::DownloadItem::DownloadState download_state,
@@ -38,6 +40,8 @@
referrer_url(referrer),
start_time(start),
end_time(end),
+ etag(etag),
+ last_modified(last_modified),
received_bytes(received),
total_bytes(total),
state(download_state),
diff --git a/chrome/browser/history/download_row.h b/chrome/browser/history/download_row.h
index a5336bb..d38eec5 100644
--- a/chrome/browser/history/download_row.h
+++ b/chrome/browser/history/download_row.h
@@ -28,6 +28,8 @@
const GURL& referrer,
const base::Time& start,
const base::Time& end,
+ const std::string& etag,
+ const std::string& last_modified,
int64 received,
int64 total,
content::DownloadItem::DownloadState download_state,
@@ -61,6 +63,12 @@
// The time when the download completed.
base::Time end_time;
+ // Contents of most recently seen ETag header.
+ std::string etag;
+
+ // Contents of most recently seen Last-Modified header.
+ std::string last_modified;
+
// The number of bytes received (so far).
int64 received_bytes;
diff --git a/chrome/browser/history/history_database.cc b/chrome/browser/history/history_database.cc
index ee3baae..ca2d4ab 100644
--- a/chrome/browser/history/history_database.cc
+++ b/chrome/browser/history/history_database.cc
@@ -27,13 +27,13 @@
// Current version number. We write databases at the "current" version number,
// but any previous version that can read the "compatible" one can make do with
// or database without *too* many bad effects.
-static const int kCurrentVersionNumber = 27;
-static const int kCompatibleVersionNumber = 16;
-static const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold";
+const int kCurrentVersionNumber = 28;
+const int kCompatibleVersionNumber = 16;
+const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold";
// Key in the meta table used to determine if we need to migrate thumbnails out
// of history.
-static const char kNeedsThumbnailMigrationKey[] = "needs_thumbnail_migration";
+const char kNeedsThumbnailMigrationKey[] = "needs_thumbnail_migration";
} // namespace
@@ -439,6 +439,15 @@
meta_table_.SetVersionNumber(cur_version);
}
+ if (cur_version == 27) {
+ if (!MigrateDownloadValidators()) {
+ LOG(WARNING) << "Unable to migrate history to version 28";
+ return sql::INIT_FAILURE;
+ }
+ cur_version++;
+ meta_table_.SetVersionNumber(cur_version);
+ }
+
// When the version is too old, we just try to continue anyway, there should
// not be a released product that makes a database too old for us to handle.
LOG_IF(WARNING, cur_version < GetCurrentVersion()) <<
diff --git a/chrome/browser/history/history_unittest.cc b/chrome/browser/history/history_unittest.cc
index c18d908..28db9ba 100644
--- a/chrome/browser/history/history_unittest.cc
+++ b/chrome/browser/history/history_unittest.cc
@@ -173,6 +173,8 @@
GURL("http://referrer.com/"),
time,
time,
+ std::string(),
+ std::string(),
0,
512,
state,
@@ -551,6 +553,71 @@
}
}
+TEST_F(HistoryBackendDBTest, MigrateDownloadValidators) {
+ Time now(base::Time::Now());
+ ASSERT_NO_FATAL_FAILURE(CreateDBVersion(27));
+ {
+ sql::Connection db;
+ ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
+ {
+ sql::Statement s(db.GetUniqueStatement(
+ "INSERT INTO downloads (id, current_path, target_path, start_time, "
+ "received_bytes, total_bytes, state, danger_type, interrupt_reason, "
+ "end_time, opened, referrer, by_ext_id, by_ext_name) VALUES "
+ "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"));
+ s.BindInt64(0, 1);
+ s.BindString(1, "current_path");
+ s.BindString(2, "target_path");
+ s.BindInt64(3, now.ToTimeT());
+ s.BindInt64(4, 100);
+ s.BindInt64(5, 100);
+ s.BindInt(6, 1);
+ s.BindInt(7, 0);
+ s.BindInt(8, 0);
+ s.BindInt64(9, now.ToTimeT());
+ s.BindInt(10, 1);
+ s.BindString(11, "referrer");
+ s.BindString(12, "by extension ID");
+ s.BindString(13, "by extension name");
+ ASSERT_TRUE(s.Run());
+ }
+ {
+ sql::Statement s(db.GetUniqueStatement(
+ "INSERT INTO downloads_url_chains (id, chain_index, url) VALUES "
+ "(?, ?, ?)"));
+ s.BindInt64(0, 4);
+ s.BindInt64(1, 0);
+ s.BindString(2, "url");
+ ASSERT_TRUE(s.Run());
+ }
+ }
+ // Re-open the db using the HistoryDatabase, which should migrate to the
+ // current version, creating the etag and last_modified columns.
+ CreateBackendAndDatabase();
+ DeleteBackend();
+ {
+ // Re-open the db for manual manipulation.
+ sql::Connection db;
+ ASSERT_TRUE(db.Open(history_dir_.Append(chrome::kHistoryFilename)));
+ // The version should have been updated.
+ int cur_version = HistoryDatabase::GetCurrentVersion();
+ ASSERT_LE(28, cur_version);
+ {
+ sql::Statement s(db.GetUniqueStatement(
+ "SELECT value FROM meta WHERE key = 'version'"));
+ EXPECT_TRUE(s.Step());
+ EXPECT_EQ(cur_version, s.ColumnInt(0));
+ }
+ {
+ sql::Statement s(db.GetUniqueStatement(
+ "SELECT etag, last_modified from downloads"));
+ EXPECT_TRUE(s.Step());
+ EXPECT_EQ(std::string(), s.ColumnString(0));
+ EXPECT_EQ(std::string(), s.ColumnString(1));
+ }
+ }
+}
+
TEST_F(HistoryBackendDBTest, ConfirmDownloadRowCreateAndDelete) {
// Create the DB.
CreateBackendAndDatabase();
@@ -609,6 +676,8 @@
GURL(std::string()),
now,
now,
+ std::string(),
+ std::string(),
0,
512,
DownloadItem::COMPLETE,
diff --git a/chrome/browser/history/in_memory_url_index.cc b/chrome/browser/history/in_memory_url_index.cc
index 0f6ee80..9eba62e 100644
--- a/chrome/browser/history/in_memory_url_index.cc
+++ b/chrome/browser/history/in_memory_url_index.cc
@@ -45,7 +45,7 @@
whitelist->insert(std::string(chrome::kFtpScheme));
whitelist->insert(std::string(chrome::kHttpScheme));
whitelist->insert(std::string(chrome::kHttpsScheme));
- whitelist->insert(std::string(chrome::kMailToScheme));
+ whitelist->insert(std::string(content::kMailToScheme));
}
// Restore/SaveCacheObserver ---------------------------------------------------
diff --git a/chrome/browser/history/scored_history_match.cc b/chrome/browser/history/scored_history_match.cc
index 3563a9d..3fb8e77 100644
--- a/chrome/browser/history/scored_history_match.cc
+++ b/chrome/browser/history/scored_history_match.cc
@@ -256,9 +256,9 @@
// be on it." The first part is necessary so unit tests pass. (Many
// unit tests don't set up the threading naming system; hence
// CurrentlyOn(UI thread) will fail.)
- DCHECK(
- !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
- content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK(!content::BrowserThread::IsThreadInitialized(
+ content::BrowserThread::UI) ||
+ content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (raw_term_score_to_topicality_score == NULL) {
raw_term_score_to_topicality_score = new float[kMaxRawTermScore];
FillInTermScoreToTopicalityScoreArray();
@@ -400,9 +400,9 @@
// be on it." The first part is necessary so unit tests pass. (Many
// unit tests don't set up the threading naming system; hence
// CurrentlyOn(UI thread) will fail.)
- DCHECK(
- !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
- content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK(!content::BrowserThread::IsThreadInitialized(
+ content::BrowserThread::UI) ||
+ content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (days_ago_to_recency_score == NULL) {
days_ago_to_recency_score = new float[kDaysToPrecomputeRecencyScoresFor];
FillInDaysAgoToRecencyScoreArray();
diff --git a/chrome/browser/history/shortcuts_backend.cc b/chrome/browser/history/shortcuts_backend.cc
index dfa7257..6bb8c0c 100644
--- a/chrome/browser/history/shortcuts_backend.cc
+++ b/chrome/browser/history/shortcuts_backend.cc
@@ -266,7 +266,7 @@
}
void ShortcutsBackend::ShutdownOnUIThread() {
- DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+ DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
notification_registrar_.RemoveAll();
}
diff --git a/chrome/browser/history/web_history_service_factory.cc b/chrome/browser/history/web_history_service_factory.cc
index 00c1bf5..bd0194b 100644
--- a/chrome/browser/history/web_history_service_factory.cc
+++ b/chrome/browser/history/web_history_service_factory.cc
@@ -7,7 +7,7 @@
#include "base/command_line.h"
#include "chrome/browser/content_settings/cookie_settings.h"
#include "chrome/browser/history/web_history_service.h"
-#include "chrome/browser/signin/token_service_factory.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/common/chrome_switches.h"
@@ -59,8 +59,8 @@
: BrowserContextKeyedServiceFactory(
"WebHistoryServiceFactory",
BrowserContextDependencyManager::GetInstance()) {
- DependsOn(TokenServiceFactory::GetInstance());
DependsOn(CookieSettings::Factory::GetInstance());
+ DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance());
}
WebHistoryServiceFactory::~WebHistoryServiceFactory() {
diff --git a/chrome/browser/importer/importer_list.cc b/chrome/browser/importer/importer_list.cc
index 1863d4a..598843e 100644
--- a/chrome/browser/importer/importer_list.cc
+++ b/chrome/browser/importer/importer_list.cc
@@ -175,6 +175,12 @@
#else
DetectFirefoxProfiles(locale, &profiles);
#endif
+ importer::SourceProfile* bookmarks_file = new importer::SourceProfile;
+ bookmarks_file->importer_name =
+ l10n_util::GetStringUTF16(IDS_IMPORT_FROM_BOOKMARKS_HTML_FILE);
+ bookmarks_file->importer_type = importer::TYPE_BOOKMARKS_FILE;
+ bookmarks_file->services_supported = importer::FAVORITES;
+ profiles.push_back(bookmarks_file);
// TODO(jhawkins): Remove this condition once DetectSourceProfilesHack is
// removed.
diff --git a/chrome/browser/importer/in_process_importer_bridge.cc b/chrome/browser/importer/in_process_importer_bridge.cc
index 61d09d2..4fe6785 100644
--- a/chrome/browser/importer/in_process_importer_bridge.cc
+++ b/chrome/browser/importer/in_process_importer_bridge.cc
@@ -118,7 +118,6 @@
typedef std::map<std::string, TemplateURL*> SearchEnginesMap;
SearchEnginesMap search_engine_for_url;
- std::string content;
FirefoxURLParameterFilter param_filter;
// The first XML file represents the default search engine in Firefox 3, so we
// need to keep it on top of the list.
diff --git a/chrome/browser/infobars/infobars_browsertest.cc b/chrome/browser/infobars/infobars_browsertest.cc
index 3a5d3ab..aa68737 100644
--- a/chrome/browser/infobars/infobars_browsertest.cc
+++ b/chrome/browser/infobars/infobars_browsertest.cc
@@ -41,10 +41,10 @@
chrome::NOTIFICATION_EXTENSION_LOADED,
content::NotificationService::AllSources());
- ExtensionInstallPrompt* client = new ExtensionInstallPrompt(
- browser()->tab_strip_model()->GetActiveWebContents());
+ scoped_ptr<ExtensionInstallPrompt> client(new ExtensionInstallPrompt(
+ browser()->tab_strip_model()->GetActiveWebContents()));
scoped_refptr<extensions::CrxInstaller> installer(
- extensions::CrxInstaller::Create(service, client));
+ extensions::CrxInstaller::Create(service, client.Pass()));
installer->set_install_cause(extension_misc::INSTALL_CAUSE_AUTOMATION);
installer->InstallCrx(path);
diff --git a/chrome/browser/managed_mode/managed_mode_interstitial.cc b/chrome/browser/managed_mode/managed_mode_interstitial.cc
index e74e665..b3daecc 100644
--- a/chrome/browser/managed_mode/managed_mode_interstitial.cc
+++ b/chrome/browser/managed_mode/managed_mode_interstitial.cc
@@ -41,8 +41,8 @@
Profile::FromBrowserContext(web_contents->GetBrowserContext());
languages_ = profile->GetPrefs()->GetString(prefs::kAcceptLanguages);
- interstitial_page_ = content::InterstitialPage::Create(
- web_contents, true, url_, this);
+ interstitial_page_ =
+ content::InterstitialPage::Create(web_contents, true, url_, this);
interstitial_page_->Show();
}
@@ -57,10 +57,18 @@
Profile::FromBrowserContext(web_contents_->GetBrowserContext());
ManagedUserService* managed_user_service =
ManagedUserServiceFactory::GetForProfile(profile);
+
+ bool allow_access_requests = managed_user_service->AccessRequestsEnabled();
+ strings.SetBoolean("allowAccessRequests", allow_access_requests);
+
string16 custodian = UTF8ToUTF16(managed_user_service->GetCustodianName());
strings.SetString(
"blockPageMessage",
- l10n_util::GetStringFUTF16(IDS_BLOCK_INTERSTITIAL_MESSAGE, custodian));
+ allow_access_requests
+ ? l10n_util::GetStringFUTF16(IDS_BLOCK_INTERSTITIAL_MESSAGE,
+ custodian)
+ : l10n_util::GetStringUTF16(
+ IDS_BLOCK_INTERSTITIAL_MESSAGE_ACCESS_REQUESTS_DISABLED));
strings.SetString("backButton", l10n_util::GetStringUTF16(IDS_BACK_BUTTON));
strings.SetString(
@@ -74,9 +82,8 @@
webui::SetFontAndTextDirection(&strings);
- base::StringPiece html(
- ResourceBundle::GetSharedInstance().GetRawDataResource(
- IDR_MANAGED_MODE_BLOCK_INTERSTITIAL_HTML));
+ base::StringPiece html(ResourceBundle::GetSharedInstance().GetRawDataResource(
+ IDR_MANAGED_MODE_BLOCK_INTERSTITIAL_HTML));
webui::UseVersion2 version;
return webui::GetI18nTemplateHtml(html, &strings);
@@ -118,15 +125,13 @@
NOTREACHED();
}
-void ManagedModeInterstitial::OnProceed() {
- NOTREACHED();
-}
+void ManagedModeInterstitial::OnProceed() { NOTREACHED(); }
void ManagedModeInterstitial::OnDontProceed() {
DispatchContinueRequest(false);
}
void ManagedModeInterstitial::DispatchContinueRequest(bool continue_request) {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(callback_, continue_request));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE, base::Bind(callback_, continue_request));
}
diff --git a/chrome/browser/managed_mode/managed_user_service.cc b/chrome/browser/managed_mode/managed_user_service.cc
index 90ad387..f42f768 100644
--- a/chrome/browser/managed_mode/managed_user_service.cc
+++ b/chrome/browser/managed_mode/managed_user_service.cc
@@ -51,6 +51,10 @@
#include "policy/policy_constants.h"
#include "ui/base/l10n/l10n_util.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/user_manager.h"
+#endif
+
using base::DictionaryValue;
using base::Value;
using content::BrowserThread;
@@ -238,13 +242,25 @@
}
std::string ManagedUserService::GetCustodianEmailAddress() const {
+#if defined(OS_CHROMEOS)
+ return chromeos::UserManager::Get()->
+ GetManagerDisplayEmailForManagedUser(
+ chromeos::UserManager::Get()->GetActiveUser()->email());
+#else
return profile_->GetPrefs()->GetString(prefs::kManagedUserCustodianEmail);
+#endif
}
std::string ManagedUserService::GetCustodianName() const {
+#if defined(OS_CHROMEOS)
+ return UTF16ToUTF8(chromeos::UserManager::Get()->
+ GetManagerDisplayNameForManagedUser(
+ chromeos::UserManager::Get()->GetActiveUser()->email()));
+#else
std::string name = profile_->GetPrefs()->GetString(
prefs::kManagedUserCustodianName);
return name.empty() ? GetCustodianEmailAddress() : name;
+#endif
}
void ManagedUserService::AddNavigationBlockedCallback(
@@ -261,6 +277,11 @@
}
}
+void ManagedUserService::AddInitCallback(
+ const base::Closure& callback) {
+ init_callbacks_.push_back(callback);
+}
+
std::string ManagedUserService::GetDebugPolicyProviderName() const {
// Save the string space in official builds.
#ifdef NDEBUG
@@ -432,6 +453,16 @@
url_filter_context_.LoadWhitelists(GetActiveSiteLists());
}
+bool ManagedUserService::AccessRequestsEnabled() {
+ ProfileSyncService* service =
+ ProfileSyncServiceFactory::GetForProfile(profile_);
+ GoogleServiceAuthError::State state = service->GetAuthError().state();
+ // We allow requesting access if Sync is working or has a transient error.
+ return (state == GoogleServiceAuthError::NONE ||
+ state == GoogleServiceAuthError::CONNECTION_FAILED ||
+ state == GoogleServiceAuthError::SERVICE_UNAVAILABLE);
+}
+
void ManagedUserService::AddAccessRequest(const GURL& url) {
// Normalize the URL.
GURL normalized_url = ManagedModeURLFilter::Normalize(url);
@@ -570,6 +601,14 @@
UpdateSiteLists();
UpdateManualHosts();
UpdateManualURLs();
+
+ // Call the callbacks to notify that the ManagedUserService has been
+ // initialized.
+ for (std::vector<base::Closure>::iterator it = init_callbacks_.begin();
+ it != init_callbacks_.end();
+ ++it) {
+ it->Run();
+ }
}
void ManagedUserService::RegisterAndInitSync(
diff --git a/chrome/browser/managed_mode/managed_user_service.h b/chrome/browser/managed_mode/managed_user_service.h
index 0d01b6c..6dc4b56 100644
--- a/chrome/browser/managed_mode/managed_user_service.h
+++ b/chrome/browser/managed_mode/managed_user_service.h
@@ -83,6 +83,9 @@
// be fast.
void GetCategoryNames(CategoryList* list);
+ // Whether the user can request access to blocked URLs.
+ bool AccessRequestsEnabled();
+
// Adds an access request for the given URL. The requests are stored using
// a prefix followed by a URIEncoded version of the URL. Each entry contains
// a dictionary which currently has the timestamp of the request in it.
@@ -141,6 +144,8 @@
void AddNavigationBlockedCallback(const NavigationBlockedCallback& callback);
void DidBlockNavigation(content::WebContents* web_contents);
+ void AddInitCallback(const base::Closure& callback);
+
// extensions::ManagementPolicy::Provider implementation:
virtual std::string GetDebugPolicyProviderName() const OVERRIDE;
virtual bool UserMayLoad(const extensions::Extension* extension,
@@ -254,6 +259,8 @@
bool waiting_for_sync_initialization_;
bool is_profile_active_;
+ std::vector<base::Closure> init_callbacks_;
+
std::vector<NavigationBlockedCallback> navigation_blocked_callbacks_;
// Sets a profile in elevated state for testing if set to true.
diff --git a/chrome/browser/media/chrome_webrtc_audio_quality_browsertest.cc b/chrome/browser/media/chrome_webrtc_audio_quality_browsertest.cc
new file mode 100644
index 0000000..1ca2cf2
--- /dev/null
+++ b/chrome/browser/media/chrome_webrtc_audio_quality_browsertest.cc
@@ -0,0 +1,450 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/path_service.h"
+#include "base/process/launch.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/media/webrtc_browsertest_base.h"
+#include "chrome/browser/media/webrtc_browsertest_common.h"
+#include "chrome/browser/profiles/profile.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_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/perf/perf_test.h"
+#include "chrome/test/ui/ui_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+static const base::FilePath::CharType kPeerConnectionServer[] =
+#if defined(OS_WIN)
+ FILE_PATH_LITERAL("peerconnection_server.exe");
+#else
+ FILE_PATH_LITERAL("peerconnection_server");
+#endif
+
+static const base::FilePath::CharType kMediaPath[] =
+ FILE_PATH_LITERAL("pyauto_private/webrtc/");
+static const base::FilePath::CharType kToolsPath[] =
+ FILE_PATH_LITERAL("pyauto_private/media/tools");
+static const base::FilePath::CharType kReferenceFile[] =
+#if defined (OS_WIN)
+ FILE_PATH_LITERAL("human-voice-win.wav");
+#else
+ FILE_PATH_LITERAL("human-voice-linux.wav");
+#endif
+
+static const char kMainWebrtcTestHtmlPage[] =
+ "files/webrtc/webrtc_audio_quality_test.html";
+
+base::FilePath GetTestDataDir() {
+ base::FilePath source_dir;
+ PathService::Get(chrome::DIR_TEST_DATA, &source_dir);
+ return source_dir;
+}
+
+// Test we can set up a WebRTC call and play audio through it.
+//
+// This test will only work on machines that have been configured to record
+// their own input.
+//
+// On Linux:
+// 1. # sudo apt-get install pavucontrol
+// 2. For the user who will run the test: # pavucontrol
+// 3. In a separate terminal, # arecord dummy
+// 4. In pavucontrol, go to the recording tab.
+// 5. For the ALSA plug-in [aplay]: ALSA Capture from, change from <x> to
+// <Monitor of x>, where x is whatever your primary sound device is called.
+// This test expects the device id to be render.monitor - if it's something
+// else, the microphone level will not get forced to 100% appropriately.
+// See ForceMicrophoneVolumeTo100% for more details. You can list the
+// available monitor devices on your system by running the command
+// pacmd list-sources | grep name | grep monitor.
+// 6. Try launching chrome as the target user on the target machine, try
+// playing, say, a YouTube video, and record with # arecord -f dat tmp.dat.
+// Verify the recording with aplay (should have recorded what you played
+// from chrome).
+//
+// On Windows 7:
+// 1. Control panel > Sound > Manage audio devices.
+// 2. In the recording tab, right-click in an empty space in the pane with the
+// devices. Tick 'show disabled devices'.
+// 3. You should see a 'stero mix' device - this is what your speakers output.
+// Right click > Properties.
+// 4. In the Listen tab for the mix device, check the 'listen to this device'
+// checkbox. Ensure the mix device is the default recording device.
+// 5. Launch chrome and try playing a video with sound. You should see
+// in the volume meter for the mix device. Configure the mix device to have
+// 50 / 100 in level. Also go into the playback tab, right-click Speakers,
+// and set that level to 50 / 100. Otherwise you will get distortion in
+// the recording.
+class WebrtcAudioQualityBrowserTest : public WebRtcTestBase {
+ public:
+ WebrtcAudioQualityBrowserTest()
+ : peerconnection_server_(base::kNullProcessHandle) {}
+
+ virtual void SetUp() OVERRIDE {
+ RunPeerConnectionServer();
+ InProcessBrowserTest::SetUp();
+ }
+
+ virtual void TearDown() OVERRIDE {
+ ShutdownPeerConnectionServer();
+ InProcessBrowserTest::TearDown();
+ }
+
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ // TODO(phoglund): check that user actually has the requisite devices and
+ // print a nice message if not; otherwise the test just times out which can
+ // be confusing.
+ // This test expects real device handling and requires a real webcam / audio
+ // device; it will not work with fake devices.
+ EXPECT_FALSE(command_line->HasSwitch(
+ switches::kUseFakeDeviceForMediaStream));
+ EXPECT_FALSE(command_line->HasSwitch(
+ switches::kUseFakeUIForMediaStream));
+
+ // Ensure we have the stuff we need.
+ base::FilePath reference_file =
+ GetTestDataDir().Append(kMediaPath).Append(kReferenceFile);
+ EXPECT_TRUE(base::PathExists(reference_file))
+ << "Cannot find the reference file to be used for audio quality "
+ << "comparison: " << reference_file.value();
+ }
+
+ void AddAudioFile(const base::FilePath& input_file_relative,
+ content::WebContents* tab_contents) {
+ EXPECT_EQ("ok-added", ExecuteJavascript(
+ base::StringPrintf("addAudioFile('%s')",
+ input_file_relative.value().c_str()), tab_contents));
+ }
+
+ void PlayAudioFile(content::WebContents* tab_contents) {
+ EXPECT_EQ("ok-playing", ExecuteJavascript("playAudioFile()", tab_contents));
+ }
+
+ // Convenience method which executes the provided javascript in the context
+ // of the provided web contents and returns what it evaluated to.
+ std::string ExecuteJavascript(const std::string& javascript,
+ content::WebContents* tab_contents) {
+ std::string result;
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ tab_contents, javascript, &result));
+ return result;
+ }
+
+ // Ensures we didn't get any errors asynchronously (e.g. while no javascript
+ // call from this test was outstanding).
+ // TODO(phoglund): this becomes obsolete when we switch to communicating with
+ // the DOM message queue.
+ void AssertNoAsynchronousErrors(content::WebContents* tab_contents) {
+ EXPECT_EQ("ok-no-errors",
+ ExecuteJavascript("getAnyTestFailures()", tab_contents));
+ }
+
+ // The peer connection server lets our two tabs find each other and talk to
+ // each other (e.g. it is the application-specific "signaling solution").
+ void ConnectToPeerConnectionServer(const std::string peer_name,
+ content::WebContents* tab_contents) {
+ std::string javascript = base::StringPrintf(
+ "connect('http://localhost:8888', '%s');", peer_name.c_str());
+ EXPECT_EQ("ok-connected", ExecuteJavascript(javascript, tab_contents));
+ }
+
+ void EstablishCall(content::WebContents* from_tab,
+ content::WebContents* to_tab) {
+ EXPECT_EQ("ok-negotiating",
+ ExecuteJavascript("negotiateCall()", from_tab));
+
+ // Ensure the call gets up on both sides.
+ EXPECT_TRUE(PollingWaitUntil("getPeerConnectionReadyState()",
+ "active", from_tab));
+ EXPECT_TRUE(PollingWaitUntil("getPeerConnectionReadyState()",
+ "active", to_tab));
+ }
+
+ void HangUp(content::WebContents* from_tab) {
+ EXPECT_EQ("ok-call-hung-up", ExecuteJavascript("hangUp()", from_tab));
+ }
+
+ void WaitUntilHangupVerified(content::WebContents* tab_contents) {
+ EXPECT_TRUE(PollingWaitUntil("getPeerConnectionReadyState()",
+ "no-peer-connection", tab_contents));
+ }
+
+ base::FilePath CreateTemporaryWaveFile() {
+ base::FilePath filename;
+ EXPECT_TRUE(file_util::CreateTemporaryFile(&filename));
+ base::FilePath wav_filename =
+ filename.AddExtension(FILE_PATH_LITERAL(".wav"));
+ EXPECT_TRUE(base::Move(filename, wav_filename));
+ return wav_filename;
+ }
+
+ private:
+ void RunPeerConnectionServer() {
+ base::FilePath peerconnection_server;
+ EXPECT_TRUE(PathService::Get(base::DIR_MODULE, &peerconnection_server));
+ peerconnection_server = peerconnection_server.Append(kPeerConnectionServer);
+
+ EXPECT_TRUE(base::PathExists(peerconnection_server)) <<
+ "Missing peerconnection_server. You must build "
+ "it so it ends up next to the browser test binary.";
+ EXPECT_TRUE(base::LaunchProcess(
+ CommandLine(peerconnection_server),
+ base::LaunchOptions(),
+ &peerconnection_server_)) << "Failed to launch peerconnection_server.";
+ }
+
+ void ShutdownPeerConnectionServer() {
+ EXPECT_TRUE(base::KillProcess(peerconnection_server_, 0, false)) <<
+ "Failed to shut down peerconnection_server!";
+ }
+
+ base::ProcessHandle peerconnection_server_;
+};
+
+class AudioRecorder {
+ public:
+ AudioRecorder(): recording_application_(base::kNullProcessHandle) {}
+ ~AudioRecorder() {}
+
+ void StartRecording(int duration_sec, const base::FilePath& output_file,
+ bool mono) {
+ EXPECT_EQ(base::kNullProcessHandle, recording_application_)
+ << "Tried to record, but is already recording.";
+
+ CommandLine command_line(CommandLine::NO_PROGRAM);
+#if defined(OS_WIN)
+ NOTREACHED(); // TODO(phoglund): implement.
+#else
+ int num_channels = mono ? 1 : 2;
+ command_line.SetProgram(base::FilePath("arecord"));
+ command_line.AppendArg("-d");
+ command_line.AppendArg(base::StringPrintf("%d", duration_sec));
+ command_line.AppendArg("-f");
+ command_line.AppendArg("dat");
+ command_line.AppendArg("-c");
+ command_line.AppendArg(base::StringPrintf("%d", num_channels));
+ command_line.AppendArgPath(output_file);
+#endif
+
+ LOG(INFO) << "Running " << command_line.GetCommandLineString();
+ EXPECT_TRUE(base::LaunchProcess(
+ command_line,
+ base::LaunchOptions(),
+ &recording_application_)) << "Failed to launch recording application.";
+ }
+
+ void WaitForRecordingToEnd() {
+ int exit_code;
+ EXPECT_TRUE(base::WaitForExitCode(recording_application_, &exit_code)) <<
+ "Failed to wait for recording to end.";
+ EXPECT_EQ(0, exit_code);
+ }
+ private:
+ base::ProcessHandle recording_application_;
+};
+
+void ForceMicrophoneVolumeTo100Percent() {
+#if defined(OS_WIN)
+ NOTREACHED(); // TODO(phoglund): implement.
+#else
+ const std::string kRecordingDeviceId = "render.monitor";
+ const std::string kHundredPercentVolume = "65536";
+
+ CommandLine command_line(base::FilePath(FILE_PATH_LITERAL("pacmd")));
+ command_line.AppendArg("set-source-volume");
+ command_line.AppendArg(kRecordingDeviceId);
+ command_line.AppendArg(kHundredPercentVolume);
+ LOG(INFO) << "Running " << command_line.GetCommandLineString();
+ std::string result;
+ if (!base::GetAppOutput(command_line, &result)) {
+ // It's hard to figure out for instance the default PA recording device name
+ // for different systems, so just warn here. Users will most often have a
+ // reasonable mic level on their systems.
+ LOG(WARNING) << "Failed to set mic volume to 100% on your system. " <<
+ "The test may fail or have results distorted; please ensure that " <<
+ "your mic level is 100% manually.";
+ }
+#endif
+}
+
+// Removes silence from beginning and end of the |input_audio_file| and writes
+// the result to the |output_audio_file|.
+void RemoveSilence(const base::FilePath& input_file,
+ const base::FilePath& output_file) {
+ // SOX documentation for silence command: http://sox.sourceforge.net/sox.html
+ // To remove the silence from both beginning and end of the audio file, we
+ // call sox silence command twice: once on normal file and again on its
+ // reverse, then we reverse the final output.
+ // Silence parameters are (in sequence):
+ // ABOVE_PERIODS: The period for which silence occurs. Value 1 is used for
+ // silence at beginning of audio.
+ // DURATION: the amount of time in seconds that non-silence must be detected
+ // before sox stops trimming audio.
+ // THRESHOLD: value used to indicate what sample value is treates as silence.
+ const char* kAbovePeriods = "1";
+ const char* kDuration = "2";
+ const char* kTreshold = "5%";
+
+ CommandLine command_line(base::FilePath(FILE_PATH_LITERAL("sox")));
+ command_line.AppendArgPath(input_file);
+ command_line.AppendArgPath(output_file);
+ command_line.AppendArg("silence");
+ command_line.AppendArg(kAbovePeriods);
+ command_line.AppendArg(kDuration);
+ command_line.AppendArg(kTreshold);
+ command_line.AppendArg("reverse");
+ command_line.AppendArg("silence");
+ command_line.AppendArg(kAbovePeriods);
+ command_line.AppendArg(kDuration);
+ command_line.AppendArg(kTreshold);
+ command_line.AppendArg("reverse");
+
+ LOG(INFO) << "Running " << command_line.GetCommandLineString();
+ std::string result;
+ EXPECT_TRUE(base::GetAppOutput(command_line, &result))
+ << "Failed to launch sox.";
+ LOG(INFO) << "Output was:\n\n" << result;
+}
+
+bool CanParseAsFloat(const std::string& value) {
+ return atof(value.c_str()) != 0 || value == "0";
+}
+
+// Runs PESQ to compare |reference_file| to a |actual_file|. The |sample_rate|
+// can be either 16000 or 8000.
+//
+// PESQ is only mono-aware, so the files should preferably be recorded in mono.
+// Furthermore it expects the file to be 16 rather than 32 bits, even though
+// 32 bits might work. The audio bandwidth of the two files should be the same
+// e.g. don't compare a 32 kHz file to a 8 kHz file.
+//
+// The raw score in MOS is written to |raw_mos|, whereas the MOS-LQO score is
+// written to mos_lqo. The scores are returned as floats in string form (e.g.
+// "3.145", etc).
+void RunPesq(const base::FilePath& reference_file,
+ const base::FilePath& actual_file,
+ int sample_rate, std::string* raw_mos, std::string* mos_lqo) {
+ // PESQ will break if the paths are too long (!).
+ EXPECT_LT(reference_file.value().length(), 128u);
+ EXPECT_LT(actual_file.value().length(), 128u);
+
+ base::FilePath pesq_path =
+ GetTestDataDir().Append(kToolsPath).Append(FILE_PATH_LITERAL("pesq"));
+ CommandLine command_line(pesq_path);
+ command_line.AppendArg(base::StringPrintf("+%d", sample_rate));
+ command_line.AppendArgPath(reference_file);
+ command_line.AppendArgPath(actual_file);
+
+ LOG(INFO) << "Running " << command_line.GetCommandLineString();
+ std::string result;
+ EXPECT_TRUE(base::GetAppOutput(command_line, &result))
+ << "Failed to launch pesq.";
+ LOG(INFO) << "Output was:\n\n" << result;
+
+ const std::string result_anchor = "Prediction (Raw MOS, MOS-LQO): = ";
+ std::size_t anchor_pos = result.find(result_anchor);
+ EXPECT_NE(std::string::npos, anchor_pos);
+
+ // There are two tab-separated numbers on the format x.xxx, e.g. 5 chars each.
+ std::size_t first_number_pos = anchor_pos + result_anchor.length();
+ *raw_mos = result.substr(first_number_pos, 5);
+ EXPECT_TRUE(CanParseAsFloat(*raw_mos)) << "Failed to parse raw MOS number.";
+ *mos_lqo = result.substr(first_number_pos + 5 + 1, 5);
+ EXPECT_TRUE(CanParseAsFloat(*mos_lqo)) << "Failed to parse MOS LQO number.";
+}
+
+#if defined(OS_LINUX)
+// Only implemented on Linux for now.
+#define MAYBE_MANUAL_TestAudioQuality MANUAL_TestAudioQuality
+#else
+#define MAYBE_MANUAL_TestAudioQuality DISABLED_MANUAL_TestAudioQuality
+#endif
+
+IN_PROC_BROWSER_TEST_F(WebrtcAudioQualityBrowserTest,
+ MAYBE_MANUAL_TestAudioQuality) {
+ EXPECT_TRUE(test_server()->Start());
+
+ ForceMicrophoneVolumeTo100Percent();
+
+ ui_test_utils::NavigateToURL(
+ browser(), test_server()->GetURL(kMainWebrtcTestHtmlPage));
+ content::WebContents* left_tab =
+ browser()->tab_strip_model()->GetActiveWebContents();
+
+ chrome::AddBlankTabAt(browser(), -1, true);
+ content::WebContents* right_tab =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ ui_test_utils::NavigateToURL(
+ browser(), test_server()->GetURL(kMainWebrtcTestHtmlPage));
+
+ ConnectToPeerConnectionServer("peer 1", left_tab);
+ ConnectToPeerConnectionServer("peer 2", right_tab);
+
+ EXPECT_EQ("ok-peerconnection-created",
+ ExecuteJavascript("preparePeerConnection()", left_tab));
+
+ base::FilePath reference_file =
+ base::FilePath(kMediaPath).Append(kReferenceFile);
+
+ // The javascript will load the reference file relative to its location,
+ // which is in /webrtc on the web server. Therefore, prepend a '..' traversal.
+ AddAudioFile(base::FilePath(FILE_PATH_LITERAL("..")).Append(reference_file),
+ left_tab);
+
+ EstablishCall(left_tab, right_tab);
+
+ // Note: the media flow isn't necessarily established on the connection just
+ // because the ready state is ok on both sides. We sleep a bit between call
+ // establishment and playing to avoid cutting of the beginning of the audio
+ // file.
+ SleepInJavascript(left_tab, 2000);
+
+ base::FilePath recording = CreateTemporaryWaveFile();
+
+ // Note: the sound clip is about 10 seconds: record for 15 seconds to get some
+ // safety margins on each side.
+ AudioRecorder recorder;
+ static int kRecordingTimeSeconds = 15;
+ recorder.StartRecording(kRecordingTimeSeconds, recording, true);
+
+ PlayAudioFile(left_tab);
+
+ recorder.WaitForRecordingToEnd();
+ LOG(INFO) << "Done recording to " << recording.value() << std::endl;
+
+ AssertNoAsynchronousErrors(left_tab);
+ AssertNoAsynchronousErrors(right_tab);
+
+ HangUp(left_tab);
+ WaitUntilHangupVerified(left_tab);
+ WaitUntilHangupVerified(right_tab);
+
+ AssertNoAsynchronousErrors(left_tab);
+ AssertNoAsynchronousErrors(right_tab);
+
+ base::FilePath trimmed_recording = CreateTemporaryWaveFile();
+
+ RemoveSilence(recording, trimmed_recording);
+ LOG(INFO) << "Trimmed silence: " << trimmed_recording.value() << std::endl;
+
+ std::string raw_mos;
+ std::string mos_lqo;
+ base::FilePath reference_file_in_test_dir =
+ GetTestDataDir().Append(reference_file);
+ RunPesq(reference_file_in_test_dir, trimmed_recording, 16000, &raw_mos,
+ &mos_lqo);
+
+ perf_test::PrintResult("audio_pesq", "", "raw_mos", raw_mos, "score", true);
+ perf_test::PrintResult("audio_pesq", "", "mos_lqo", mos_lqo, "score", true);
+
+ EXPECT_TRUE(base::DeleteFile(recording, false));
+ EXPECT_TRUE(base::DeleteFile(trimmed_recording, false));
+}
diff --git a/chrome/browser/media/desktop_media_picker.h b/chrome/browser/media/desktop_media_picker.h
index 8720698..18f8ab3 100644
--- a/chrome/browser/media/desktop_media_picker.h
+++ b/chrome/browser/media/desktop_media_picker.h
@@ -8,15 +8,17 @@
#include "base/basictypes.h"
#include "base/callback_forward.h"
#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/media/desktop_media_picker_model.h"
+#include "base/strings/string16.h"
+#include "content/public/common/desktop_media_id.h"
#include "ui/gfx/native_widget_types.h"
+class DesktopMediaPickerModel;
// Abstract interface for desktop media picker UI. It's used by Desktop Media
// API to let user choose a desktop media source.
class DesktopMediaPicker {
public:
- typedef base::Callback<void(DesktopMediaPickerModel::SourceId)> DoneCallback;
+ typedef base::Callback<void(content::DesktopMediaID)> DoneCallback;
// Creates default implementation of DesktopMediaPicker for the current
// platform.
diff --git a/chrome/browser/media/desktop_media_picker_model.cc b/chrome/browser/media/desktop_media_picker_model.cc
index 37f4959..878d04f 100644
--- a/chrome/browser/media/desktop_media_picker_model.cc
+++ b/chrome/browser/media/desktop_media_picker_model.cc
@@ -22,6 +22,7 @@
#include "ui/gfx/skia_util.h"
using content::BrowserThread;
+using content::DesktopMediaID;
namespace {
@@ -74,34 +75,13 @@
} // namespace
-DesktopMediaPickerModel::SourceId::SourceId()
- : type(content::MEDIA_NO_SERVICE),
- id(0) {
-}
-
-DesktopMediaPickerModel::SourceId::SourceId(content::MediaStreamType type,
- intptr_t id)
- : type(type),
- id(id) {
-}
-
-DesktopMediaPickerModel::Source::Source(SourceId id, const string16 name)
+DesktopMediaPickerModel::Source::Source(DesktopMediaID id, const string16& name)
: id(id),
name(name) {
}
-bool DesktopMediaPickerModel::SourceId::operator<(
- const DesktopMediaPickerModel::SourceId& other) const {
- return type < other.type || (type == other.type && id < other.id);
-}
-
-bool DesktopMediaPickerModel::SourceId::operator==(
- const DesktopMediaPickerModel::SourceId& other) const {
- return type == other.type && id == other.id;
-}
-
DesktopMediaPickerModel::SourceDescription::SourceDescription(
- DesktopMediaPickerModel::SourceId id,
+ DesktopMediaID id,
const string16& name)
: id(id),
name(name) {
@@ -118,7 +98,7 @@
void Refresh(const gfx::Size& thumbnail_size);
private:
- typedef std::map<SourceId, uint32> ImageHashesMap;
+ typedef std::map<DesktopMediaID, uint32> ImageHashesMap;
// webrtc::DesktopCapturer::Callback interface.
virtual webrtc::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE;
@@ -156,8 +136,8 @@
if (screen_capturer_) {
// TODO(sergeyu): Enumerate each screen when ScreenCapturer supports it.
- sources.push_back(SourceDescription(SourceId(
- content::MEDIA_SCREEN_VIDEO_CAPTURE, 0),
+ sources.push_back(SourceDescription(DesktopMediaID(
+ DesktopMediaID::TYPE_SCREEN, 0),
l10n_util::GetStringUTF16(IDS_DESKTOP_MEDIA_PICKER_SCREEN_NAME)));
}
@@ -167,8 +147,7 @@
for (webrtc::WindowCapturer::WindowList::iterator it = windows.begin();
it != windows.end(); ++it) {
sources.push_back(SourceDescription(
- DesktopMediaPickerModel::SourceId(
- content::MEDIA_WINDOW_VIDEO_CAPTURE, it->id),
+ DesktopMediaID(DesktopMediaID::TYPE_WINDOW, it->id),
base::UTF8ToUTF16(it->title)));
}
}
@@ -188,12 +167,12 @@
for (size_t i = 0; i < sources.size(); ++i) {
SourceDescription& source = sources[i];
switch (source.id.type) {
- case content::MEDIA_SCREEN_VIDEO_CAPTURE:
+ case DesktopMediaID::TYPE_SCREEN:
screen_capturer_->Capture(webrtc::DesktopRegion());
DCHECK(current_frame_);
break;
- case content::MEDIA_WINDOW_VIDEO_CAPTURE:
+ case DesktopMediaID::TYPE_WINDOW:
if (!window_capturer_->SelectWindow(source.id.id))
continue;
window_capturer_->Capture(webrtc::DesktopRegion());
diff --git a/chrome/browser/media/desktop_media_picker_model.h b/chrome/browser/media/desktop_media_picker_model.h
index 8dfe9b7..494a325 100644
--- a/chrome/browser/media/desktop_media_picker_model.h
+++ b/chrome/browser/media/desktop_media_picker_model.h
@@ -9,7 +9,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
-#include "content/public/common/media_stream_request.h"
+#include "content/public/common/desktop_media_id.h"
#include "ui/gfx/image/image_skia.h"
namespace webrtc {
@@ -35,23 +35,12 @@
virtual void OnSourceThumbnailChanged(int index) = 0;
};
- // Type used to identify desktop media sources.
- struct SourceId {
- SourceId();
- SourceId(content::MediaStreamType type, intptr_t id);
- bool operator<(const SourceId& other) const;
- bool operator==(const SourceId& other) const;
-
- content::MediaStreamType type;
- intptr_t id;
- };
-
// Struct used to represent each entry in the model.
struct Source {
- Source(SourceId id, const string16 name);
+ Source(content::DesktopMediaID id, const string16& name);
// Id of the source.
- SourceId id;
+ content::DesktopMediaID id;
// Name of the source that should be shown to the user.
string16 name;
@@ -97,9 +86,9 @@
// Struct used to represent sources list the model gets from the Worker.
struct SourceDescription {
- SourceDescription(SourceId id, const string16& name);
+ SourceDescription(content::DesktopMediaID id, const string16& name);
- SourceId id;
+ content::DesktopMediaID id;
string16 name;
};
diff --git a/chrome/browser/media/desktop_media_picker_model_unittest.cc b/chrome/browser/media/desktop_media_picker_model_unittest.cc
index 6cd5fa1..3d2112c 100644
--- a/chrome/browser/media/desktop_media_picker_model_unittest.cc
+++ b/chrome/browser/media/desktop_media_picker_model_unittest.cc
@@ -186,9 +186,9 @@
message_loop_.Run();
- EXPECT_EQ(model_.source(0).id.type, content::MEDIA_SCREEN_VIDEO_CAPTURE);
+ EXPECT_EQ(model_.source(0).id.type, content::DesktopMediaID::TYPE_SCREEN);
EXPECT_EQ(model_.source(0).id.id, 0);
- EXPECT_EQ(model_.source(1).id.type, content::MEDIA_WINDOW_VIDEO_CAPTURE);
+ EXPECT_EQ(model_.source(1).id.type, content::DesktopMediaID::TYPE_WINDOW);
EXPECT_EQ(model_.source(1).id.id, 0);
EXPECT_EQ(model_.source(1).name, UTF8ToUTF16(window.title));
}
@@ -217,7 +217,7 @@
message_loop_.Run();
- EXPECT_EQ(model_.source(0).id.type, content::MEDIA_WINDOW_VIDEO_CAPTURE);
+ EXPECT_EQ(model_.source(0).id.type, content::DesktopMediaID::TYPE_WINDOW);
}
TEST_F(DesktopMediaPickerModelTest, ScreenOnly) {
@@ -236,7 +236,7 @@
message_loop_.Run();
- EXPECT_EQ(model_.source(0).id.type, content::MEDIA_SCREEN_VIDEO_CAPTURE);
+ EXPECT_EQ(model_.source(0).id.type, content::DesktopMediaID::TYPE_SCREEN);
}
TEST_F(DesktopMediaPickerModelTest, AddWindow) {
@@ -276,7 +276,7 @@
message_loop_.Run();
- EXPECT_EQ(model_.source(1).id.type, content::MEDIA_WINDOW_VIDEO_CAPTURE);
+ EXPECT_EQ(model_.source(1).id.type, content::DesktopMediaID::TYPE_WINDOW);
EXPECT_EQ(model_.source(1).id.id, 0);
}
diff --git a/chrome/browser/media/media_capture_devices_dispatcher.cc b/chrome/browser/media/media_capture_devices_dispatcher.cc
index 03ca4c5..936257e 100644
--- a/chrome/browser/media/media_capture_devices_dispatcher.cc
+++ b/chrome/browser/media/media_capture_devices_dispatcher.cc
@@ -30,6 +30,7 @@
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/desktop_media_id.h"
#include "content/public/common/media_stream_request.h"
#include "extensions/common/constants.h"
#include "grit/generated_resources.h"
@@ -179,7 +180,7 @@
const extensions::Extension* extension) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (request.video_type == content::MEDIA_SCREEN_VIDEO_CAPTURE ||
+ if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE ||
request.audio_type == content::MEDIA_SYSTEM_AUDIO_CAPTURE) {
ProcessScreenCaptureAccessRequest(
web_contents, request, callback, extension);
@@ -197,10 +198,41 @@
const content::MediaStreamRequest& request,
const content::MediaResponseCallback& callback,
const extensions::Extension* extension) {
- const bool component_extension =
- extension && extension->location() == extensions::Manifest::COMPONENT;
-
content::MediaStreamDevices devices;
+ scoped_ptr<content::MediaStreamUI> ui;
+
+ if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE) {
+ callback.Run(devices, ui.Pass());
+ return;
+ }
+
+ content::DesktopMediaID media_id =
+ content::DesktopMediaID::Parse(request.requested_video_device_id);
+ if (media_id.is_null()) {
+ LOG(ERROR) << "Invalid desktop media ID: "
+ << request.requested_video_device_id;
+ callback.Run(devices, ui.Pass());
+ return;
+ }
+
+ const bool system_audio_capture_requested =
+ request.audio_type == content::MEDIA_SYSTEM_AUDIO_CAPTURE;
+
+#if defined(USE_CRAS)
+ const bool system_audio_capture_supported = true;
+#else
+ const bool system_audio_capture_supported = false;
+#endif
+
+ // Reject request when audio capture was requested but is not supported on
+ // this system.
+ if (system_audio_capture_requested && !system_audio_capture_supported) {
+ callback.Run(devices, ui.Pass());
+ return;
+ }
+
+ const bool component_extension =
+ extension && extension->location() == extensions::Manifest::COMPONENT;
const bool screen_capture_enabled =
CommandLine::ForCurrentProcess()->HasSwitch(
@@ -213,27 +245,11 @@
CommandLine::ForCurrentProcess()->HasSwitch(
switches::kAllowHttpScreenCapture);
- const bool screen_video_capture_requested =
- request.video_type == content::MEDIA_SCREEN_VIDEO_CAPTURE;
-
- const bool system_audio_capture_requested =
- request.audio_type == content::MEDIA_SYSTEM_AUDIO_CAPTURE;
-
-#if defined(USE_CRAS)
- const bool system_audio_capture_supported = true;
-#else
- const bool system_audio_capture_supported = false;
-#endif
-
// Approve request only when the following conditions are met:
// 1. Screen capturing is enabled via command line switch or white-listed for
// the given origin.
// 2. Request comes from a page with a secure origin or from an extension.
- // 3. Video capture is requested for screen video.
- // 4. Audio capture is either not requested, or requested for system audio.
- if (screen_capture_enabled && origin_is_secure &&
- screen_video_capture_requested &&
- (!system_audio_capture_requested || system_audio_capture_supported)) {
+ if (screen_capture_enabled && origin_is_secure) {
// For component extensions, bypass message box.
bool user_approved = false;
if (!component_extension) {
@@ -254,7 +270,7 @@
if (user_approved || component_extension) {
devices.push_back(content::MediaStreamDevice(
- content::MEDIA_SCREEN_VIDEO_CAPTURE, std::string(), "Screen"));
+ content::MEDIA_DESKTOP_VIDEO_CAPTURE, media_id.ToString(), "Screen"));
if (system_audio_capture_requested) {
#if defined(USE_CRAS)
// Use the special loopback device ID for system audio capture.
@@ -267,7 +283,6 @@
}
}
- scoped_ptr<content::MediaStreamUI> ui;
// Unless we're being invoked from a component extension, register to display
// the notification for stream capture.
if (!devices.empty() && !component_extension) {
@@ -282,6 +297,7 @@
ui = ScreenCaptureNotificationUI::Create(l10n_util::GetStringFUTF16(
IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT, UTF8ToUTF16(title)));
}
+
callback.Run(devices, ui.Pass());
}
diff --git a/chrome/browser/media/webrtc_browsertest_common.h b/chrome/browser/media/webrtc_browsertest_common.h
index 34b9c6a..23ec4e7 100644
--- a/chrome/browser/media/webrtc_browsertest_common.h
+++ b/chrome/browser/media/webrtc_browsertest_common.h
@@ -13,6 +13,10 @@
class WebContents;
}
+// Executes javascript code which will sleep for |timeout_msec| milliseconds.
+// Returns true on success.
+bool SleepInJavascript(content::WebContents* tab_contents, int timeout_msec);
+
// This function will execute the provided |javascript| until it causes a call
// to window.domAutomationController.send() with |evaluates_to| as the message.
// That is, we are NOT checking what the javascript evaluates to. Returns false
diff --git a/chrome/browser/media_galleries/fileapi/media_file_validator_unittest.cc b/chrome/browser/media_galleries/fileapi/media_file_validator_browsertest.cc
similarity index 78%
rename from chrome/browser/media_galleries/fileapi/media_file_validator_unittest.cc
rename to chrome/browser/media_galleries/fileapi/media_file_validator_browsertest.cc
index 5fde5e4..91901bf 100644
--- a/chrome/browser/media_galleries/fileapi/media_file_validator_unittest.cc
+++ b/chrome/browser/media_galleries/fileapi/media_file_validator_browsertest.cc
@@ -9,6 +9,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/path_service.h"
#include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/test/browser_test.h"
@@ -32,7 +33,7 @@
"\x01\0\x01\0\x2F\x9D\xCE\xE7s\xA8((((\x01\x9CK(\0"
"\x05\xCE\xB3l\0\0\xFE\xD8\x80\0\0";
-const char kInvalidImage[] = "Not an image";
+const char kInvalidMediaFile[] = "Not a media file";
const int64 kNoFileSize = -1;
@@ -55,6 +56,13 @@
callback.Run(false);
}
+base::FilePath GetMediaTestDir() {
+ base::FilePath test_file;
+ if (!PathService::Get(base::DIR_SOURCE_ROOT, &test_file))
+ return base::FilePath();
+ return test_file.AppendASCII("media").AppendASCII("test").AppendASCII("data");
+}
+
} // namespace
namespace chrome {
@@ -78,6 +86,19 @@
loop_runner_->Run();
}
+ // Write |source| into |filename| in a test file system and try to move it
+ // into a media file system. The result is compared to |expected_result|.
+ void MoveTestFromFile(const std::string& filename,
+ const base::FilePath& source, bool expected_result) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&MediaFileValidatorTest::SetupFromFileOnFileThread,
+ base::Unretained(this), filename, source, expected_result));
+ loop_runner_ = new content::MessageLoopRunner;
+ loop_runner_->Run();
+ }
+
private:
// Create the test files, filesystem objects, etc.
void SetupOnFileThread(const std::string& filename,
@@ -129,6 +150,14 @@
base::Unretained(this), expected_result)));
}
+ void SetupFromFileOnFileThread(const std::string& filename,
+ const base::FilePath& source,
+ bool expected_result) {
+ std::string content;
+ ASSERT_TRUE(file_util::ReadFileToString(source, &content));
+ SetupOnFileThread(filename, content, expected_result);
+ }
+
// Check that exactly one of |move_src_| and |move_dest_| exists.
// |src_expected| indicates which one should exist. When complete,
// |callback| is called with success/failure.
@@ -212,17 +241,43 @@
DISALLOW_COPY_AND_ASSIGN(MediaFileValidatorTest);
};
+IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, UnsupportedExtension) {
+ MoveTest("a.txt", std::string(kValidImage, arraysize(kValidImage)), false);
+}
+
IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, ValidImage) {
MoveTest("a.webp", std::string(kValidImage, arraysize(kValidImage)), true);
}
IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, InvalidImage) {
- MoveTest("a.webp", std::string(kInvalidImage, arraysize(kInvalidImage)),
- false);
+ MoveTest("a.webp", std::string(kInvalidMediaFile,
+ arraysize(kInvalidMediaFile)), false);
}
-IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, UnsupportedExtension) {
- MoveTest("a.txt", std::string(kValidImage, arraysize(kValidImage)), false);
+IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, InvalidAudio) {
+ MoveTest("a.ogg", std::string(kInvalidMediaFile,
+ arraysize(kInvalidMediaFile)), false);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, ValidAudio) {
+ base::FilePath test_file = GetMediaTestDir();
+ ASSERT_FALSE(test_file.empty());
+ test_file = test_file.AppendASCII("sfx.ogg");
+ MoveTestFromFile("sfx.ogg", test_file, true);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, InvalidVideo) {
+ base::FilePath test_file = GetMediaTestDir();
+ ASSERT_FALSE(test_file.empty());
+ test_file = test_file.AppendASCII("no_streams.webm");
+ MoveTestFromFile("no_streams.webm", test_file, false);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaFileValidatorTest, ValidVideo) {
+ base::FilePath test_file = GetMediaTestDir();
+ ASSERT_FALSE(test_file.empty());
+ test_file = test_file.AppendASCII("bear-320x240-multitrack.webm");
+ MoveTestFromFile("multitrack.webm", test_file, true);
}
} // namespace chrome
diff --git a/chrome/browser/media_galleries/fileapi/media_file_validator_factory.cc b/chrome/browser/media_galleries/fileapi/media_file_validator_factory.cc
index e180460..ead22c1 100644
--- a/chrome/browser/media_galleries/fileapi/media_file_validator_factory.cc
+++ b/chrome/browser/media_galleries/fileapi/media_file_validator_factory.cc
@@ -6,6 +6,7 @@
#include "base/files/file_path.h"
#include "base/platform_file.h"
+#include "chrome/browser/media_galleries/fileapi/supported_audio_video_checker.h"
#include "chrome/browser/media_galleries/fileapi/supported_image_type_validator.h"
#include "webkit/browser/fileapi/copy_or_move_file_validator.h"
#include "webkit/browser/fileapi/file_system_url.h"
@@ -50,7 +51,8 @@
base::FilePath src_path = src.virtual_path();
if (SupportedImageTypeValidator::SupportsFileType(src_path))
return new SupportedImageTypeValidator(platform_path);
- // TODO(vandebo): Support other file types.
+ if (SupportedAudioVideoChecker::SupportsFileType(src_path))
+ return new SupportedAudioVideoChecker(platform_path);
return new InvalidFileValidator();
}
diff --git a/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.cc b/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.cc
new file mode 100644
index 0000000..dbc55b0
--- /dev/null
+++ b/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.cc
@@ -0,0 +1,91 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media_galleries/fileapi/safe_audio_video_checker.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/process/process_handle.h"
+#include "chrome/common/chrome_utility_messages.h"
+#include "content/public/browser/child_process_data.h"
+#include "content/public/browser/utility_process_host.h"
+#include "content/public/browser/browser_thread.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_platform_file.h"
+
+SafeAudioVideoChecker::SafeAudioVideoChecker(
+ const base::PlatformFile& file,
+ const fileapi::CopyOrMoveFileValidator::ResultCallback& callback)
+ : state_(INITIAL_STATE),
+ file_(file),
+ file_closer_(&file_),
+ callback_(callback) {
+ DCHECK(!callback.is_null());
+}
+
+void SafeAudioVideoChecker::Start() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ if (state_ != INITIAL_STATE)
+ return;
+ state_ = PINGED_STATE;
+
+ DCHECK(file_closer_);
+ if (*file_closer_.get() == base::kInvalidPlatformFileValue) {
+ callback_.Run(base::PLATFORM_FILE_ERROR_SECURITY);
+ state_ = FINISHED_STATE;
+ return;
+ }
+
+ utility_process_host_ = content::UtilityProcessHost::Create(
+ this, base::MessageLoopProxy::current())->AsWeakPtr();
+ utility_process_host_->EnableZygote();
+ utility_process_host_->Send(new ChromeUtilityMsg_StartupPing);
+}
+
+SafeAudioVideoChecker::~SafeAudioVideoChecker() {}
+
+void SafeAudioVideoChecker::OnProcessStarted() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ if (state_ != PINGED_STATE)
+ return;
+ state_ = STARTED_STATE;
+
+ if (utility_process_host_->GetData().handle == base::kNullProcessHandle)
+ DLOG(ERROR) << "Child process handle is null";
+ IPC::PlatformFileForTransit file_for_transit =
+ IPC::GetFileHandleForProcess(*file_closer_.release(),
+ utility_process_host_->GetData().handle,
+ true /* close_source_handle */);
+ const int64 kFileDecodeTimeInMS = 250;
+ utility_process_host_->Send(new ChromeUtilityMsg_CheckMediaFile(
+ kFileDecodeTimeInMS, file_for_transit));
+}
+
+void SafeAudioVideoChecker::OnCheckingFinished(bool valid) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ if (state_ != STARTED_STATE)
+ return;
+ state_ = FINISHED_STATE;
+
+ callback_.Run(valid ? base::PLATFORM_FILE_OK
+ : base::PLATFORM_FILE_ERROR_SECURITY);
+}
+
+void SafeAudioVideoChecker::OnProcessCrashed(int exit_code) {
+ OnCheckingFinished(false);
+}
+
+bool SafeAudioVideoChecker::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(SafeAudioVideoChecker, message)
+ IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted,
+ OnProcessStarted)
+ IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_CheckMediaFile_Finished,
+ OnCheckingFinished)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
diff --git a/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.h b/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.h
new file mode 100644
index 0000000..5ce8dfb
--- /dev/null
+++ b/chrome/browser/media_galleries/fileapi/safe_audio_video_checker.h
@@ -0,0 +1,72 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_AUDIO_VIDEO_CHECKER_H_
+#define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_AUDIO_VIDEO_CHECKER_H_
+
+#include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "base/files/scoped_platform_file_closer.h"
+#include "base/memory/weak_ptr.h"
+#include "base/platform_file.h"
+#include "content/public/browser/utility_process_host_client.h"
+#include "webkit/browser/fileapi/copy_or_move_file_validator.h"
+
+namespace content {
+class UtilityProcessHost;
+}
+
+// Uses a utility process to validate a media file. If the callback returns
+// PLATFORM_FILE_OK, then the file appears to be a valid media file. This does
+// not attempt to decode the entire file, which may take a considerable amount
+// of time. This class may be constructed on any thread, but should run on the
+// IO thread.
+class SafeAudioVideoChecker : public content::UtilityProcessHostClient {
+ public:
+ // Takes responsibility for closing |file|.
+ SafeAudioVideoChecker(
+ const base::PlatformFile& file,
+ const fileapi::CopyOrMoveFileValidator::ResultCallback& callback);
+
+ // Must be called on the IO thread.
+ void Start();
+
+ private:
+ enum State {
+ INITIAL_STATE,
+ PINGED_STATE,
+ STARTED_STATE,
+ FINISHED_STATE
+ };
+
+ virtual ~SafeAudioVideoChecker();
+
+ // Starts validation once the utility process has been started.
+ virtual void OnProcessStarted();
+
+ // Notification of the result from the utility process.
+ void OnCheckingFinished(bool valid);
+
+ // UtilityProcessHostClient implementation.
+ virtual void OnProcessCrashed(int exit_code) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ State state_;
+
+ // This should be accessed through |file_closer_| to ensure it hasn't already
+ // been closed.
+ base::PlatformFile file_;
+
+ // Ensures that |file_| is closed if the utility process is not started for
+ // some reason.
+ base::ScopedPlatformFileCloser file_closer_;
+
+ const fileapi::CopyOrMoveFileValidator::ResultCallback callback_;
+
+ base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(SafeAudioVideoChecker);
+};
+
+#endif // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SAFE_AUDIO_VIDEO_CHECKER_H_
diff --git a/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.cc b/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.cc
new file mode 100644
index 0000000..bed3c23
--- /dev/null
+++ b/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.cc
@@ -0,0 +1,96 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media_galleries/fileapi/supported_audio_video_checker.h"
+
+#include <set>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/lazy_instance.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "chrome/browser/media_galleries/fileapi/safe_audio_video_checker.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/mime_util.h"
+
+namespace {
+
+class SupportedAudioVideoExtensions {
+ public:
+ SupportedAudioVideoExtensions() {
+ std::vector<base::FilePath::StringType> extensions;
+ net::GetExtensionsForMimeType("audio/*", &extensions);
+ net::GetExtensionsForMimeType("video/*", &extensions);
+ for (size_t i = 0; i < extensions.size(); ++i) {
+ std::string mime_type;
+ if (net::GetWellKnownMimeTypeFromExtension(extensions[i], &mime_type) &&
+ net::IsSupportedMimeType(mime_type)) {
+ audio_video_extensions_.insert(
+ base::FilePath::kExtensionSeparator + extensions[i]);
+ }
+ }
+ };
+
+ bool HasSupportedAudioVideoExtension(const base::FilePath& file) {
+ return ContainsKey(audio_video_extensions_, file.Extension());
+ }
+
+ private:
+ std::set<base::FilePath::StringType> audio_video_extensions_;
+
+ DISALLOW_COPY_AND_ASSIGN(SupportedAudioVideoExtensions);
+};
+
+base::LazyInstance<SupportedAudioVideoExtensions> g_audio_video_extensions =
+ LAZY_INSTANCE_INITIALIZER;
+
+base::PlatformFile OpenOnFileThread(const base::FilePath& path) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+ return base::CreatePlatformFile(
+ path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
+ NULL /*created*/, NULL /*error_code*/);
+}
+
+} // namespace
+
+SupportedAudioVideoChecker::~SupportedAudioVideoChecker() {}
+
+// static
+bool SupportedAudioVideoChecker::SupportsFileType(const base::FilePath& path) {
+ return g_audio_video_extensions.Get().HasSupportedAudioVideoExtension(path);
+}
+
+void SupportedAudioVideoChecker::StartPreWriteValidation(
+ const fileapi::CopyOrMoveFileValidator::ResultCallback& result_callback) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ DCHECK(callback_.is_null());
+ callback_ = result_callback;
+
+ content::BrowserThread::PostTaskAndReplyWithResult(
+ content::BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&OpenOnFileThread, path_),
+ base::Bind(&SupportedAudioVideoChecker::OnFileOpen,
+ weak_factory_.GetWeakPtr()));
+}
+
+SupportedAudioVideoChecker::SupportedAudioVideoChecker(
+ const base::FilePath& path)
+ : path_(path),
+ weak_factory_(this) {
+}
+
+void SupportedAudioVideoChecker::OnFileOpen(const base::PlatformFile& file) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ if (file == base::kInvalidPlatformFileValue) {
+ callback_.Run(base::PLATFORM_FILE_ERROR_SECURITY);
+ return;
+ }
+
+ safe_checker_ = new SafeAudioVideoChecker(file, callback_);
+ safe_checker_->Start();
+}
diff --git a/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.h b/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.h
new file mode 100644
index 0000000..d2dad4f
--- /dev/null
+++ b/chrome/browser/media_galleries/fileapi/supported_audio_video_checker.h
@@ -0,0 +1,49 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SUPPORTED_AUDIO_VIDEO_CHECKER_H_
+#define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SUPPORTED_AUDIO_VIDEO_CHECKER_H_
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/platform_file.h"
+#include "chrome/browser/media_galleries/fileapi/av_scanning_file_validator.h"
+
+class SafeAudioVideoChecker;
+
+namespace chrome {
+class MediaFileValidatorFactory;
+}
+
+// Uses SafeAudioVideoChecker to validate supported audio and video files in
+// the utility process and then uses AVScanningFileValidator to ask the OS to
+// virus scan them. The entire file is not decoded so a positive result from
+// this class does not make the file safe to use in the browser process.
+class SupportedAudioVideoChecker : public chrome::AVScanningFileValidator {
+ public:
+ virtual ~SupportedAudioVideoChecker();
+
+ static bool SupportsFileType(const base::FilePath& path);
+
+ virtual void StartPreWriteValidation(
+ const ResultCallback& result_callback) OVERRIDE;
+
+ private:
+ friend class chrome::MediaFileValidatorFactory;
+
+ explicit SupportedAudioVideoChecker(const base::FilePath& file);
+
+ void OnFileOpen(const base::PlatformFile& file);
+
+ base::FilePath path_;
+ fileapi::CopyOrMoveFileValidator::ResultCallback callback_;
+ scoped_refptr<SafeAudioVideoChecker> safe_checker_;
+ base::WeakPtrFactory<SupportedAudioVideoChecker> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SupportedAudioVideoChecker);
+};
+
+#endif // CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_SUPPORTED_AUDIO_VIDEO_CHECKER_H_
diff --git a/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc b/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
index 5215905..e36df44 100644
--- a/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
+++ b/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
@@ -9,7 +9,6 @@
#include "base/command_line.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_system.h"
@@ -22,7 +21,7 @@
#include "chrome/common/extensions/background_info.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "grit/generated_resources.h"
#include "sync/api/string_ordinal.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -72,17 +71,11 @@
DeviceIdPrefIdsMap;
MediaGalleriesPreferencesTest()
- : ui_thread_(content::BrowserThread::UI, &loop_),
- file_thread_(content::BrowserThread::FILE, &loop_),
- profile_(new TestingProfile()),
+ : profile_(new TestingProfile()),
default_galleries_count_(0) {
}
virtual ~MediaGalleriesPreferencesTest() {
- // TestExtensionSystem uses DeleteSoon, so we need to delete the profile
- // and then run the message queue to clean up.
- profile_.reset();
- base::MessageLoop::current()->RunUntilIdle();
}
virtual void SetUp() OVERRIDE {
@@ -240,9 +233,7 @@
private:
// Needed for extension service & friends to work.
- base::MessageLoop loop_;
- content::TestBrowserThread ui_thread_;
- content::TestBrowserThread file_thread_;
+ content::TestBrowserThreadBundle thread_bundle_;
#if defined OS_CHROMEOS
chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
diff --git a/chrome/browser/metrics/metrics_log.cc b/chrome/browser/metrics/metrics_log.cc
index bb9d550..bebdad2 100644
--- a/chrome/browser/metrics/metrics_log.cc
+++ b/chrome/browser/metrics/metrics_log.cc
@@ -163,6 +163,9 @@
case AutocompleteInput::INSTANT_NEW_TAB_PAGE_WITH_FAKEBOX_AS_STARTING_FOCUS:
return OmniboxEventProto::
INSTANT_NEW_TAB_PAGE_WITH_FAKEBOX_AS_STARTING_FOCUS;
+ case AutocompleteInput::SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT:
+ return OmniboxEventProto::
+ SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT;
}
return OmniboxEventProto::INVALID_SPEC;
}
@@ -859,11 +862,11 @@
omnibox_event->set_input_type(AsOmniboxEventInputType(log.input_type));
// The view code to hide the top result is currently only implemented on the
- // Mac.
-#if defined(OS_MACOSX)
+ // Mac and for views.
+#if defined(OS_MACOSX) || defined(TOOLKIT_VIEWS)
omnibox_event->set_is_top_result_hidden_in_dropdown(
log.result.ShouldHideTopMatch());
-#endif // defined(OS_MACOSX)
+#endif // defined(OS_MACOSX) || defined(TOOLKIT_VIEWS)
for (AutocompleteResult::const_iterator i(log.result.begin());
i != log.result.end(); ++i) {
diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc
index 3e8d17a..5c6a8e2 100644
--- a/chrome/browser/metrics/metrics_service.cc
+++ b/chrome/browser/metrics/metrics_service.cc
@@ -1514,16 +1514,6 @@
IncrementLongPrefsValue(prefs::kUninstallMetricsPageLoadCount);
// We need to save the prefs, as page load count is a critical stat, and it
// might be lost due to a crash :-(.
-
- // Track whether the page loaded is a search results page.
- if (web_contents) {
- SearchTabHelper* search_tab_helper =
- SearchTabHelper::FromWebContents(web_contents);
- if (search_tab_helper) {
- if (search_tab_helper->model()->mode().is_search_results())
- content::RecordAction(content::UserMetricsAction("PageLoadSRP"));
- }
- }
}
void MetricsService::LogRendererCrash(content::RenderProcessHost* host,
diff --git a/chrome/browser/metrics/proto/study.proto b/chrome/browser/metrics/proto/study.proto
index 6a3d2b1..fdaa41f 100644
--- a/chrome/browser/metrics/proto/study.proto
+++ b/chrome/browser/metrics/proto/study.proto
@@ -93,6 +93,9 @@
// Possible Chrome release channels.
// See: http://dev.chromium.org/getting-involved/dev-channel
enum Channel {
+ // UNKNOWN value is defined here for the benefit of code using this enum
+ // type, but is not actually meant to be encoded in the protobuf.
+ UNKNOWN = -1;
CANARY = 0;
DEV = 1;
BETA = 2;
diff --git a/chrome/browser/metrics/variations/variations_seed_processor.cc b/chrome/browser/metrics/variations/variations_seed_processor.cc
index dfc351f..3600a7e 100644
--- a/chrome/browser/metrics/variations/variations_seed_processor.cc
+++ b/chrome/browser/metrics/variations/variations_seed_processor.cc
@@ -12,7 +12,6 @@
#include "base/metrics/field_trial.h"
#include "base/stl_util.h"
#include "base/version.h"
-#include "chrome/browser/browser_process.h"
#include "chrome/browser/metrics/proto/trials_seed.pb.h"
#include "chrome/common/metrics/variations/variations_associated_data.h"
@@ -20,25 +19,6 @@
namespace {
-// Maps Study_Channel enum values to corresponding chrome::VersionInfo::Channel
-// enum values.
-chrome::VersionInfo::Channel ConvertStudyChannelToVersionChannel(
- Study_Channel study_channel) {
- switch (study_channel) {
- case Study_Channel_CANARY:
- return chrome::VersionInfo::CHANNEL_CANARY;
- case Study_Channel_DEV:
- return chrome::VersionInfo::CHANNEL_DEV;
- case Study_Channel_BETA:
- return chrome::VersionInfo::CHANNEL_BETA;
- case Study_Channel_STABLE:
- return chrome::VersionInfo::CHANNEL_STABLE;
- }
- // All enum values of |study_channel| were handled above.
- NOTREACHED();
- return chrome::VersionInfo::CHANNEL_UNKNOWN;
-}
-
Study_Platform GetCurrentPlatform() {
#if defined(OS_WIN)
return Study_Platform_PLATFORM_WINDOWS;
@@ -76,8 +56,10 @@
const TrialsSeed& seed,
const std::string& locale,
const base::Time& reference_date,
- const chrome::VersionInfo& version_info,
- chrome::VersionInfo::Channel channel) {
+ const base::Version& version,
+ Study_Channel channel) {
+ DCHECK(version.IsValid());
+
// Add expired studies (in a disabled state) only after all the non-expired
// studies have been added (and do not add an expired study if a corresponding
// non-expired study got added). This way, if there's both an expired and a
@@ -87,7 +69,7 @@
for (int i = 0; i < seed.study_size(); ++i) {
const Study& study = seed.study(i);
- if (!ShouldAddStudy(study, locale, reference_date, version_info, channel))
+ if (!ShouldAddStudy(study, locale, reference_date, version, channel))
continue;
if (IsStudyExpired(study, reference_date)) {
@@ -104,15 +86,14 @@
}
}
-bool VariationsSeedProcessor::CheckStudyChannel(
- const Study_Filter& filter,
- chrome::VersionInfo::Channel channel) {
+bool VariationsSeedProcessor::CheckStudyChannel(const Study_Filter& filter,
+ Study_Channel channel) {
// An empty channel list matches all channels.
if (filter.channel_size() == 0)
return true;
for (int i = 0; i < filter.channel_size(); ++i) {
- if (ConvertStudyChannelToVersionChannel(filter.channel(i)) == channel)
+ if (filter.channel(i) == channel)
return true;
}
return false;
@@ -160,13 +141,7 @@
bool VariationsSeedProcessor::CheckStudyVersion(
const Study_Filter& filter,
- const std::string& version_string) {
- const Version version(version_string);
- if (!version.IsValid()) {
- NOTREACHED();
- return false;
- }
-
+ const base::Version& version) {
if (filter.has_min_version()) {
if (version.CompareToWildcardString(filter.min_version()) < 0)
return false;
@@ -276,8 +251,8 @@
const Study& study,
const std::string& locale,
const base::Time& reference_date,
- const chrome::VersionInfo& version_info,
- chrome::VersionInfo::Channel channel) {
+ const base::Version& version,
+ Study_Channel channel) {
if (study.has_filter()) {
if (!CheckStudyChannel(study.filter(), channel)) {
DVLOG(1) << "Filtered out study " << study.name() << " due to channel.";
@@ -294,7 +269,7 @@
return false;
}
- if (!CheckStudyVersion(study.filter(), version_info.Version())) {
+ if (!CheckStudyVersion(study.filter(), version)) {
DVLOG(1) << "Filtered out study " << study.name() << " due to version.";
return false;
}
diff --git a/chrome/browser/metrics/variations/variations_seed_processor.h b/chrome/browser/metrics/variations/variations_seed_processor.h
index fff3915..074d1af 100644
--- a/chrome/browser/metrics/variations/variations_seed_processor.h
+++ b/chrome/browser/metrics/variations/variations_seed_processor.h
@@ -11,9 +11,9 @@
#include "base/gtest_prod_util.h"
#include "base/metrics/field_trial.h"
#include "base/time/time.h"
+#include "base/version.h"
#include "chrome/browser/metrics/proto/study.pb.h"
#include "chrome/browser/metrics/proto/trials_seed.pb.h"
-#include "chrome/common/chrome_version_info.h"
namespace chrome_variations {
@@ -28,8 +28,8 @@
void CreateTrialsFromSeed(const TrialsSeed& seed,
const std::string& locale,
const base::Time& reference_date,
- const chrome::VersionInfo& version_info,
- chrome::VersionInfo::Channel channel);
+ const base::Version& version,
+ Study_Channel channel);
private:
FRIEND_TEST_ALL_PREFIXES(VariationsSeedProcessorTest, CheckStudyChannel);
@@ -50,8 +50,7 @@
FRIEND_TEST_ALL_PREFIXES(VariationsSeedProcessorTest, VariationParams);
// Checks whether a study is applicable for the given |channel| per |filter|.
- bool CheckStudyChannel(const Study_Filter& filter,
- chrome::VersionInfo::Channel channel);
+ bool CheckStudyChannel(const Study_Filter& filter, Study_Channel channel);
// Checks whether a study is applicable for the given |locale| per |filter|.
bool CheckStudyLocale(const Study_Filter& filter, const std::string& locale);
@@ -65,7 +64,7 @@
// Checks whether a study is applicable for the given version per |filter|.
bool CheckStudyVersion(const Study_Filter& filter,
- const std::string& version_string);
+ const base::Version& version);
// Creates and registers a field trial from the |study| data. Disables the
// trial if |is_expired| is true.
@@ -81,8 +80,8 @@
bool ShouldAddStudy(const Study& study,
const std::string& locale,
const base::Time& reference_date,
- const chrome::VersionInfo& version_info,
- chrome::VersionInfo::Channel channel);
+ const base::Version& version,
+ Study_Channel channel);
// Validates the sanity of |study| and computes the total probability.
bool ValidateStudyAndComputeTotalProbability(
diff --git a/chrome/browser/metrics/variations/variations_seed_processor_unittest.cc b/chrome/browser/metrics/variations/variations_seed_processor_unittest.cc
index ce2da44..1ab7c62 100644
--- a/chrome/browser/metrics/variations/variations_seed_processor_unittest.cc
+++ b/chrome/browser/metrics/variations/variations_seed_processor_unittest.cc
@@ -8,8 +8,7 @@
#include "base/command_line.h"
#include "base/strings/string_split.h"
-#include "chrome/common/chrome_version_info.h"
-#include "chrome/common/metrics/variations/variations_util.h"
+#include "chrome/common/metrics/variations/variations_associated_data.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chrome_variations {
@@ -66,34 +65,27 @@
TEST(VariationsSeedProcessorTest, CheckStudyChannel) {
VariationsSeedProcessor seed_processor;
- const chrome::VersionInfo::Channel channels[] = {
- chrome::VersionInfo::CHANNEL_CANARY,
- chrome::VersionInfo::CHANNEL_DEV,
- chrome::VersionInfo::CHANNEL_BETA,
- chrome::VersionInfo::CHANNEL_STABLE,
- };
- const Study_Channel study_channels[] = {
+ const Study_Channel channels[] = {
Study_Channel_CANARY,
Study_Channel_DEV,
Study_Channel_BETA,
Study_Channel_STABLE,
};
- ASSERT_EQ(arraysize(channels), arraysize(study_channels));
bool channel_added[arraysize(channels)] = { 0 };
Study_Filter filter;
- // Check in the forwarded order. The loop cond is <= arraysize(study_channels)
+ // Check in the forwarded order. The loop cond is <= arraysize(channels)
// instead of < so that the result of adding the last channel gets checked.
- for (size_t i = 0; i <= arraysize(study_channels); ++i) {
+ for (size_t i = 0; i <= arraysize(channels); ++i) {
for (size_t j = 0; j < arraysize(channels); ++j) {
const bool expected = channel_added[j] || filter.channel_size() == 0;
const bool result = seed_processor.CheckStudyChannel(filter, channels[j]);
EXPECT_EQ(expected, result) << "Case " << i << "," << j << " failed!";
}
- if (i < arraysize(study_channels)) {
- filter.add_channel(study_channels[i]);
+ if (i < arraysize(channels)) {
+ filter.add_channel(channels[i]);
channel_added[i] = true;
}
}
@@ -101,16 +93,16 @@
// Do the same check in the reverse order.
filter.clear_channel();
memset(&channel_added, 0, sizeof(channel_added));
- for (size_t i = 0; i <= arraysize(study_channels); ++i) {
+ for (size_t i = 0; i <= arraysize(channels); ++i) {
for (size_t j = 0; j < arraysize(channels); ++j) {
const bool expected = channel_added[j] || filter.channel_size() == 0;
const bool result = seed_processor.CheckStudyChannel(filter, channels[j]);
EXPECT_EQ(expected, result) << "Case " << i << "," << j << " failed!";
}
- if (i < arraysize(study_channels)) {
- const int index = arraysize(study_channels) - i - 1;
- filter.add_channel(study_channels[index]);
+ if (i < arraysize(channels)) {
+ const int index = arraysize(channels) - i - 1;
+ filter.add_channel(channels[index]);
channel_added[index] = true;
}
}
@@ -275,12 +267,13 @@
Study_Filter filter;
// Min/max version not set should result in true.
- EXPECT_TRUE(seed_processor.CheckStudyVersion(filter, "1.2.3"));
+ EXPECT_TRUE(seed_processor.CheckStudyVersion(filter, base::Version("1.2.3")));
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(min_test_cases); ++i) {
filter.set_min_version(min_test_cases[i].min_version);
const bool result =
- seed_processor.CheckStudyVersion(filter, min_test_cases[i].version);
+ seed_processor.CheckStudyVersion(filter,
+ Version(min_test_cases[i].version));
EXPECT_EQ(min_test_cases[i].expected_result, result) <<
"Min. version case " << i << " failed!";
}
@@ -289,7 +282,8 @@
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(max_test_cases); ++i) {
filter.set_max_version(max_test_cases[i].max_version);
const bool result =
- seed_processor.CheckStudyVersion(filter, max_test_cases[i].version);
+ seed_processor.CheckStudyVersion(filter,
+ Version(max_test_cases[i].version));
EXPECT_EQ(max_test_cases[i].expected_result, result) <<
"Max version case " << i << " failed!";
}
@@ -302,13 +296,15 @@
if (!min_test_cases[i].expected_result) {
const bool result =
- seed_processor.CheckStudyVersion(filter, min_test_cases[i].version);
+ seed_processor.CheckStudyVersion(
+ filter, Version(min_test_cases[i].version));
EXPECT_FALSE(result) << "Case " << i << "," << j << " failed!";
}
if (!max_test_cases[j].expected_result) {
const bool result =
- seed_processor.CheckStudyVersion(filter, max_test_cases[j].version);
+ seed_processor.CheckStudyVersion(
+ filter, Version(max_test_cases[j].version));
EXPECT_FALSE(result) << "Case " << i << "," << j << " failed!";
}
}
@@ -413,14 +409,15 @@
const base::Time year_ago =
base::Time::Now() - base::TimeDelta::FromDays(365);
+ const base::Version version("20.0.0.0");
+
// Check that adding [expired, non-expired] activates the non-expired one.
ASSERT_EQ(std::string(), base::FieldTrialList::FindFullName(kTrialName));
{
base::FieldTrialList field_trial_list(NULL);
study1->set_expiry_date(TimeToProtoTime(year_ago));
seed_processor.CreateTrialsFromSeed(seed, "en-CA", base::Time::Now(),
- chrome::VersionInfo(),
- chrome::VersionInfo::GetChannel());
+ version, Study_Channel_STABLE);
EXPECT_EQ(kGroup1Name, base::FieldTrialList::FindFullName(kTrialName));
}
@@ -431,8 +428,7 @@
study1->clear_expiry_date();
study2->set_expiry_date(TimeToProtoTime(year_ago));
seed_processor.CreateTrialsFromSeed(seed, "en-CA", base::Time::Now(),
- chrome::VersionInfo(),
- chrome::VersionInfo::GetChannel());
+ version, Study_Channel_STABLE);
EXPECT_EQ(kGroup1Name, base::FieldTrialList::FindFullName(kTrialName));
}
}
diff --git a/chrome/browser/metrics/variations/variations_service.cc b/chrome/browser/metrics/variations/variations_service.cc
index d4a23a3..973d009 100644
--- a/chrome/browser/metrics/variations/variations_service.cc
+++ b/chrome/browser/metrics/variations/variations_service.cc
@@ -59,24 +59,32 @@
// that channel value. Otherwise, if the fake channel flag is provided, this
// will return the fake channel. Failing that, this will return the UNKNOWN
// channel.
-chrome::VersionInfo::Channel GetChannelForVariations() {
- chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
- if (channel != chrome::VersionInfo::CHANNEL_UNKNOWN)
- return channel;
- std::string forced_channel =
+Study_Channel GetChannelForVariations() {
+ switch (chrome::VersionInfo::GetChannel()) {
+ case chrome::VersionInfo::CHANNEL_CANARY:
+ return Study_Channel_CANARY;
+ case chrome::VersionInfo::CHANNEL_DEV:
+ return Study_Channel_DEV;
+ case chrome::VersionInfo::CHANNEL_BETA:
+ return Study_Channel_BETA;
+ case chrome::VersionInfo::CHANNEL_STABLE:
+ return Study_Channel_STABLE;
+ case chrome::VersionInfo::CHANNEL_UNKNOWN:
+ break;
+ }
+ const std::string forced_channel =
CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kFakeVariationsChannel);
if (forced_channel == "stable")
- channel = chrome::VersionInfo::CHANNEL_STABLE;
- else if (forced_channel == "beta")
- channel = chrome::VersionInfo::CHANNEL_BETA;
- else if (forced_channel == "dev")
- channel = chrome::VersionInfo::CHANNEL_DEV;
- else if (forced_channel == "canary")
- channel = chrome::VersionInfo::CHANNEL_CANARY;
- else
- DVLOG(1) << "Invalid channel provided: " << forced_channel;
- return channel;
+ return Study_Channel_STABLE;
+ if (forced_channel == "beta")
+ return Study_Channel_BETA;
+ if (forced_channel == "dev")
+ return Study_Channel_DEV;
+ if (forced_channel == "canary")
+ return Study_Channel_CANARY;
+ DVLOG(1) << "Invalid channel provided: " << forced_channel;
+ return Study_Channel_UNKNOWN;
}
// Returns a string that will be used for the value of the 'osname' URL param
@@ -196,9 +204,13 @@
if (!current_version_info.is_valid())
return false;
+ const base::Version current_version(current_version_info.Version());
+ if (!current_version.IsValid())
+ return false;
+
VariationsSeedProcessor().CreateTrialsFromSeed(
seed, g_browser_process->GetApplicationLocale(), reference_date,
- current_version_info, GetChannelForVariations());
+ current_version, GetChannelForVariations());
// Log the "freshness" of the seed that was just used. The freshness is the
// time between the last successful seed download and now.
diff --git a/chrome/browser/nacl_host/nacl_host_message_filter.cc b/chrome/browser/nacl_host/nacl_host_message_filter.cc
index c7c7935..784f9f9 100644
--- a/chrome/browser/nacl_host/nacl_host_message_filter.cc
+++ b/chrome/browser/nacl_host/nacl_host_message_filter.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/nacl_host/pnacl_host.h"
#include "components/nacl/common/nacl_host_messages.h"
#include "extensions/common/constants.h"
+#include "ipc/ipc_platform_file.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
@@ -134,12 +135,13 @@
// NaClHostMsg_NaClCreateTemporaryFile sync message.
void NaClHostMessageFilter::SyncReturnTemporaryFile(
IPC::Message* reply_msg,
- IPC::PlatformFileForTransit fd) {
- if (fd == IPC::InvalidPlatformFileForTransit()) {
+ base::PlatformFile fd) {
+ if (fd == base::kInvalidPlatformFileValue) {
reply_msg->set_reply_error();
} else {
NaClHostMsg_NaClCreateTemporaryFile::WriteReplyParams(
- reply_msg, fd);
+ reply_msg,
+ IPC::GetFileHandleForProcess(fd, PeerHandle(), true));
}
Send(reply_msg);
}
@@ -147,22 +149,21 @@
void NaClHostMessageFilter::OnNaClCreateTemporaryFile(
IPC::Message* reply_msg) {
PnaclHost::GetInstance()->CreateTemporaryFile(
- PeerHandle(),
base::Bind(&NaClHostMessageFilter::SyncReturnTemporaryFile,
this,
reply_msg));
}
-// For now, GetNexeFd cache requests always set is_hit to false and returns
-// a new temporary file via a NaClViewMsg_NexeTempFileReply message.
-// A future CL will implement the cache lookup logic (and use the currently-
-// unused parameters)
-// See also https://code.google.com/p/nativeclient/issues/detail?id=3372
void NaClHostMessageFilter::AsyncReturnTemporaryFile(
int pp_instance,
- IPC::PlatformFileForTransit fd,
+ base::PlatformFile fd,
bool is_hit) {
- Send(new NaClViewMsg_NexeTempFileReply(pp_instance, is_hit, fd));
+ Send(new NaClViewMsg_NexeTempFileReply(
+ pp_instance,
+ is_hit,
+ // Don't close our copy of the handle, because PnaclHost will use it
+ // when the translation finishes.
+ IPC::GetFileHandleForProcess(fd, PeerHandle(), false)));
}
void NaClHostMessageFilter::OnGetNexeFd(
@@ -175,11 +176,12 @@
BadMessageReceived();
return;
}
+
PnaclHost::GetInstance()->GetNexeFd(
render_process_id_,
- PeerHandle(),
render_view_id,
pp_instance,
+ off_the_record_,
cache_info,
base::Bind(&NaClHostMessageFilter::AsyncReturnTemporaryFile,
this,
diff --git a/chrome/browser/nacl_host/nacl_host_message_filter.h b/chrome/browser/nacl_host/nacl_host_message_filter.h
index 7d31a90..4c05f22 100644
--- a/chrome/browser/nacl_host/nacl_host_message_filter.h
+++ b/chrome/browser/nacl_host/nacl_host_message_filter.h
@@ -7,8 +7,8 @@
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
+#include "base/platform_file.h"
#include "content/public/browser/browser_message_filter.h"
-#include "ipc/ipc_platform_file.h"
class ExtensionInfoMap;
class GURL;
@@ -70,9 +70,9 @@
int instance,
const nacl::PnaclInstallProgress& progress);
void SyncReturnTemporaryFile(IPC::Message* reply_msg,
- IPC::PlatformFileForTransit fd);
+ base::PlatformFile fd);
void AsyncReturnTemporaryFile(int pp_instance,
- IPC::PlatformFileForTransit fd,
+ base::PlatformFile fd,
bool is_hit);
#endif
int render_process_id_;
diff --git a/chrome/browser/nacl_host/pnacl_host.cc b/chrome/browser/nacl_host/pnacl_host.cc
index 9bb5b72..2468f9d 100644
--- a/chrome/browser/nacl_host/pnacl_host.cc
+++ b/chrome/browser/nacl_host/pnacl_host.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/nacl_host/pnacl_host.h"
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/logging.h"
@@ -13,6 +14,7 @@
#include "chrome/browser/nacl_host/nacl_browser.h"
#include "chrome/browser/nacl_host/pnacl_translation_cache.h"
#include "content/public/browser/browser_thread.h"
+#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
using content::BrowserThread;
@@ -20,6 +22,8 @@
namespace {
static const base::FilePath::CharType kTranslationCacheDirectoryName[] =
FILE_PATH_LITERAL("PnaclTranslationCache");
+// Delay to wait for initialization of the cache backend
+static const int kTranslationCacheInitializationDelayMs = 20;
}
PnaclHost::PnaclHost()
@@ -29,7 +33,16 @@
PnaclHost* PnaclHost::GetInstance() { return Singleton<PnaclHost>::get(); }
-PnaclHost::PendingTranslation::PendingTranslation() {}
+PnaclHost::PendingTranslation::PendingTranslation()
+ : process_handle(base::kNullProcessHandle),
+ render_view_id(0),
+ nexe_fd(base::kInvalidPlatformFileValue),
+ got_nexe_fd(false),
+ got_cache_reply(false),
+ got_cache_hit(false),
+ is_incognito(false),
+ callback(NexeFdCallback()),
+ cache_info(nacl::PnaclCacheInfo()) {}
PnaclHost::PendingTranslation::~PendingTranslation() {}
/////////////////////////////////////// Initialization
@@ -53,19 +66,24 @@
return cache_file_path.Append(kTranslationCacheDirectoryName);
}
-void PnaclHost::OnCacheInitialized(int error) {
+void PnaclHost::OnCacheInitialized(int net_error) {
+ DCHECK(thread_checker_.CalledOnValidThread());
// If the cache was cleared before the load completed, ignore.
if (cache_state_ == CacheReady)
return;
- if (error != net::OK) {
- LOG(ERROR) << "PNaCl translation cache initalization failure: " << error
- << "\n";
+ if (net_error != net::OK) {
+ // This will cause the cache to attempt to re-init on the next call to
+ // GetNexeFd.
+ cache_state_ = CacheUninitialized;
} else {
cache_state_ = CacheReady;
}
}
void PnaclHost::Init() {
+ // Extra check that we're on the real IO thread since this version of
+ // Init isn't used in unit tests.
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(thread_checker_.CalledOnValidThread());
base::FilePath cache_path(GetCachePath());
if (cache_path.empty() || cache_state_ != CacheUninitialized)
@@ -74,7 +92,7 @@
cache_state_ = CacheInitializing;
disk_cache_->InitCache(
cache_path,
- true,
+ false,
base::Bind(&PnaclHost::OnCacheInitialized, weak_factory_.GetWeakPtr()));
}
@@ -94,9 +112,8 @@
///////////////////////////////////////// Temp files
// Create a temporary file on the blocking pool
-IPC::PlatformFileForTransit PnaclHost::DoCreateTemporaryFile(
- base::ProcessHandle process_handle,
- base::FilePath temp_dir) {
+// static
+base::PlatformFile PnaclHost::DoCreateTemporaryFile(base::FilePath temp_dir) {
DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
base::FilePath file_path;
@@ -104,9 +121,10 @@
? file_util::CreateTemporaryFile(&file_path)
: file_util::CreateTemporaryFileInDir(temp_dir, &file_path);
- if (!rv)
- return IPC::InvalidPlatformFileForTransit();
-
+ if (!rv) {
+ LOG(ERROR) << "PnaclHost:: Temp file creation failed.";
+ return base::kInvalidPlatformFileValue;
+ }
base::PlatformFileError error;
base::PlatformFile file_handle(base::CreatePlatformFile(
file_path,
@@ -116,96 +134,442 @@
NULL,
&error));
- if (error != base::PLATFORM_FILE_OK)
- return IPC::InvalidPlatformFileForTransit();
+ if (error != base::PLATFORM_FILE_OK) {
+ LOG(ERROR) << "PnaclHost: Temp file open failed: " << error;
+ return base::kInvalidPlatformFileValue;
+ }
- // Do any DuplicateHandle magic that is necessary first.
- return IPC::GetFileHandleForProcess(file_handle, process_handle, true);
+ return file_handle;
}
-void PnaclHost::CreateTemporaryFile(base::ProcessHandle process_handle,
- TempFileCallback cb) {
+void PnaclHost::CreateTemporaryFile(TempFileCallback cb) {
if (!base::PostTaskAndReplyWithResult(
BrowserThread::GetBlockingPool(),
FROM_HERE,
- base::Bind(
- &PnaclHost::DoCreateTemporaryFile, process_handle, temp_dir_),
+ base::Bind(&PnaclHost::DoCreateTemporaryFile, temp_dir_),
cb)) {
DCHECK(thread_checker_.CalledOnValidThread());
- cb.Run(IPC::InvalidPlatformFileForTransit());
+ cb.Run(base::kInvalidPlatformFileValue);
}
}
///////////////////////////////////////// GetNexeFd implementation
-
-void PnaclHost::ReturnMiss(TranslationID id, IPC::PlatformFileForTransit fd) {
- DCHECK(thread_checker_.CalledOnValidThread());
- PendingTranslationMap::iterator entry(pending_translations_.find(id));
- if (entry == pending_translations_.end()) {
- LOG(ERROR) << "PnaclHost::ReturnMiss: Failed to find TranslationID "
- << id.first << "," << id.second;
- return;
- }
- NexeFdCallback cb(entry->second.callback);
- if (fd == IPC::InvalidPlatformFileForTransit()) {
- pending_translations_.erase(entry);
- } else {
- entry->second.nexe_fd = fd;
- }
- cb.Run(fd, false);
-}
+////////////////////// Common steps
void PnaclHost::GetNexeFd(int render_process_id,
- base::ProcessHandle process_handle,
int render_view_id,
int pp_instance,
+ bool is_incognito,
const nacl::PnaclCacheInfo& cache_info,
const NexeFdCallback& cb) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (cache_state_ != CacheReady)
+ if (cache_state_ == CacheUninitialized) {
+ Init();
+ }
+ if (cache_state_ != CacheReady) {
+ // If the backend hasn't yet initialized, try the request again later.
+ BrowserThread::PostDelayedTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&PnaclHost::GetNexeFd,
+ weak_factory_.GetWeakPtr(),
+ render_process_id,
+ render_view_id,
+ pp_instance,
+ is_incognito,
+ cache_info,
+ cb),
+ base::TimeDelta::FromMilliseconds(
+ kTranslationCacheInitializationDelayMs));
return;
+ }
+
+ TranslationID id(render_process_id, pp_instance);
+ PendingTranslationMap::iterator entry = pending_translations_.find(id);
+ if (entry != pending_translations_.end()) {
+ // Existing translation must have been abandonded. Clean it up.
+ LOG(ERROR) << "PnaclHost::GetNexeFd for already-pending translation";
+ pending_translations_.erase(entry);
+ }
+
+ std::string cache_key(disk_cache_->GetKey(cache_info));
+ if (cache_key.empty()) {
+ LOG(ERROR) << "PnaclHost::GetNexeFd: Invalid cache info";
+ cb.Run(base::kInvalidPlatformFileValue, false);
+ return;
+ }
+
PendingTranslation pt;
pt.render_view_id = render_view_id;
pt.callback = cb;
pt.cache_info = cache_info;
-
- pending_translations_[TranslationID(render_process_id, pp_instance)] = pt;
-
- CreateTemporaryFile(
- process_handle,
- base::Bind(&PnaclHost::ReturnMiss,
- weak_factory_.GetWeakPtr(),
- TranslationID(render_process_id, pp_instance)));
+ pt.cache_key = cache_key;
+ pt.is_incognito = is_incognito;
+ pending_translations_[id] = pt;
+ SendCacheQueryAndTempFileRequest(cache_key, id);
}
-/////////////////// Cleanup
+// Dispatch the cache read request and the temp file creation request
+// simultaneously; currently we need a temp file regardless of whether the
+// request hits.
+void PnaclHost::SendCacheQueryAndTempFileRequest(const std::string& cache_key,
+ const TranslationID& id) {
+ disk_cache_->GetNexe(
+ cache_key,
+ base::Bind(
+ &PnaclHost::OnCacheQueryReturn, weak_factory_.GetWeakPtr(), id));
+ CreateTemporaryFile(
+ base::Bind(&PnaclHost::OnTempFileReturn, weak_factory_.GetWeakPtr(), id));
+}
+
+// Callback from the translation cache query. |id| is bound from
+// SendCacheQueryAndTempFileRequest, |net_error| is a net::Error code (which for
+// our purposes means a hit if it's net::OK (i.e. 0). |buffer| is allocated
+// by PnaclTranslationCache and now belongs to PnaclHost.
+// (Bound callbacks must re-lookup the TranslationID because the translation
+// could be cancelled before they get called).
+void PnaclHost::OnCacheQueryReturn(
+ const TranslationID& id,
+ int net_error,
+ scoped_refptr<net::DrainableIOBuffer> buffer) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ PendingTranslationMap::iterator entry(pending_translations_.find(id));
+ if (entry == pending_translations_.end()) {
+ LOG(ERROR) << "PnaclHost::OnCacheQueryReturn: id not found";
+ return;
+ }
+ PendingTranslation* pt = &entry->second;
+ pt->got_cache_reply = true;
+ pt->got_cache_hit = (net_error == net::OK);
+ if (pt->got_cache_hit)
+ pt->nexe_read_buffer = buffer;
+ CheckCacheQueryReady(entry);
+}
+
+// Callback from temp file creation. |id| is bound from
+// SendCacheQueryAndTempFileRequest, and fd is the created file descriptor.
+// If there was an error, fd is kInvalidPlatformFileValue.
+// (Bound callbacks must re-lookup the TranslationID because the translation
+// could be cancelled before they get called).
+void PnaclHost::OnTempFileReturn(const TranslationID& id,
+ base::PlatformFile fd) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ PendingTranslationMap::iterator entry(pending_translations_.find(id));
+ if (entry == pending_translations_.end()) {
+ // The renderer may have signaled an error or closed while the temp
+ // file was being created.
+ LOG(ERROR) << "PnaclHost::OnTempFileReturn: id not found";
+ BrowserThread::PostBlockingPoolTask(
+ FROM_HERE, base::Bind(base::IgnoreResult(base::ClosePlatformFile), fd));
+ return;
+ }
+ if (fd == base::kInvalidPlatformFileValue) {
+ // This translation will fail, but we need to retry any translation
+ // waiting for its result.
+ LOG(ERROR) << "PnaclHost::OnTempFileReturn: temp file creation failed";
+ std::string key(entry->second.cache_key);
+ bool is_incognito = entry->second.is_incognito;
+ entry->second.callback.Run(fd, false);
+ pending_translations_.erase(entry);
+ // No translations will be waiting for an incongnito translation
+ if (!is_incognito)
+ RequeryMatchingTranslations(key);
+ return;
+ }
+ PendingTranslation* pt = &entry->second;
+ pt->got_nexe_fd = true;
+ pt->nexe_fd = fd;
+ CheckCacheQueryReady(entry);
+}
+
+// Check whether both the cache query and the temp file have returned, and check
+// whether we actually got a hit or not.
+void PnaclHost::CheckCacheQueryReady(
+ const PendingTranslationMap::iterator& entry) {
+ PendingTranslation* pt = &entry->second;
+ if (!(pt->got_cache_reply && pt->got_nexe_fd))
+ return;
+ if (!pt->got_cache_hit) {
+ // Check if there is already a pending translation for this file. If there
+ // is, we will wait for it to come back, to avoid redundant translations.
+ for (PendingTranslationMap::iterator it = pending_translations_.begin();
+ it != pending_translations_.end();
+ ++it) {
+ // Another translation matches if it's a request for the same file,
+ if (it->second.cache_key == entry->second.cache_key &&
+ // and it's not this translation,
+ it->first != entry->first &&
+ // and it's not incognito,
+ !it->second.is_incognito &&
+ // and if it's already gotten past this check and returned the miss.
+ it->second.got_cache_reply &&
+ it->second.got_nexe_fd) {
+ return;
+ }
+ }
+ ReturnMiss(entry);
+ return;
+ }
+
+ if (!base::PostTaskAndReplyWithResult(
+ BrowserThread::GetBlockingPool(),
+ FROM_HERE,
+ base::Bind(
+ &PnaclHost::CopyBufferToFile, pt->nexe_fd, pt->nexe_read_buffer),
+ base::Bind(&PnaclHost::OnBufferCopiedToTempFile,
+ weak_factory_.GetWeakPtr(),
+ entry->first))) {
+ pt->callback.Run(base::kInvalidPlatformFileValue, false);
+ }
+}
+
+//////////////////// GetNexeFd miss path
+// Return the temp fd to the renderer, reporting a miss.
+void PnaclHost::ReturnMiss(const PendingTranslationMap::iterator& entry) {
+ // Return the fd
+ PendingTranslation* pt = &entry->second;
+ NexeFdCallback cb(pt->callback);
+ if (pt->nexe_fd == base::kInvalidPlatformFileValue) {
+ // Bad FD is unrecoverable, so clear out the entry
+ pending_translations_.erase(entry);
+ }
+ cb.Run(pt->nexe_fd, false);
+}
+
+// On error, just return a null refptr.
+// static
+scoped_refptr<net::DrainableIOBuffer> PnaclHost::CopyFileToBuffer(
+ base::PlatformFile fd) {
+ base::PlatformFileInfo info;
+ scoped_refptr<net::DrainableIOBuffer> buffer;
+ bool error = false;
+ if (!base::GetPlatformFileInfo(fd, &info) ||
+ info.size >= std::numeric_limits<int>::max()) {
+ LOG(ERROR) << "PnaclHost: GetPlatformFileInfo failed";
+ error = true;
+ } else {
+ buffer = new net::DrainableIOBuffer(
+ new net::IOBuffer(static_cast<int>(info.size)), info.size);
+ if (base::ReadPlatformFile(fd, 0, buffer->data(), buffer->size()) !=
+ info.size) {
+ LOG(ERROR) << "PnaclHost: CopyFileToBuffer write failed";
+ error = true;
+ }
+ }
+ if (error) {
+ buffer = NULL;
+ }
+ base::ClosePlatformFile(fd);
+ return buffer;
+}
+
+// Called by the renderer in the miss path to report a finished translation
void PnaclHost::TranslationFinished(int render_process_id,
int pp_instance,
bool success) {
DCHECK(thread_checker_.CalledOnValidThread());
if (cache_state_ != CacheReady)
return;
- PendingTranslationMap::iterator it(pending_translations_.find(
- TranslationID(render_process_id, pp_instance)));
- if (it == pending_translations_.end()) {
+ TranslationID id(render_process_id, pp_instance);
+ PendingTranslationMap::iterator entry(pending_translations_.find(id));
+ if (entry == pending_translations_.end()) {
LOG(ERROR) << "TranslationFinished: TranslationID " << render_process_id
<< "," << pp_instance << " not found.";
- } else {
- pending_translations_.erase(it);
+ return;
+ }
+ bool store_nexe = true;
+ // If this is a premature response (i.e. we haven't returned a temp file
+ // yet) or if it's an unsuccessful translation, or if we are incognito,
+ // don't store in the cache.
+ // TODO(dschuff): use a separate in-memory cache for incognito
+ // translations.
+ if (!entry->second.got_nexe_fd || !entry->second.got_cache_reply ||
+ !success || entry->second.is_incognito) {
+ store_nexe = false;
+ } else if (!base::PostTaskAndReplyWithResult(
+ BrowserThread::GetBlockingPool(),
+ FROM_HERE,
+ base::Bind(&PnaclHost::CopyFileToBuffer,
+ entry->second.nexe_fd),
+ base::Bind(&PnaclHost::StoreTranslatedNexe,
+ weak_factory_.GetWeakPtr(),
+ id))) {
+ store_nexe = false;
+ }
+
+ if (!store_nexe) {
+ // If store_nexe is true, the fd will be closed by CopyFileToBuffer.
+ if (entry->second.got_nexe_fd) {
+ BrowserThread::PostBlockingPoolTask(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(base::ClosePlatformFile),
+ entry->second.nexe_fd));
+ }
+ pending_translations_.erase(entry);
}
}
-void PnaclHost::RendererClosing(int render_process_id) {
+// Store the translated nexe in the translation cache. Called back with the
+// TranslationID from the host and the result of CopyFileToBuffer.
+// (Bound callbacks must re-lookup the TranslationID because the translation
+// could be cancelled before they get called).
+void PnaclHost::StoreTranslatedNexe(
+ TranslationID id,
+ scoped_refptr<net::DrainableIOBuffer> buffer) {
+ DCHECK(thread_checker_.CalledOnValidThread());
if (cache_state_ != CacheReady)
return;
+ PendingTranslationMap::iterator it(pending_translations_.find(id));
+ if (it == pending_translations_.end()) {
+ LOG(ERROR) << "StoreTranslatedNexe: TranslationID " << id.first << ","
+ << id.second << " not found.";
+ return;
+ }
+
+ if (buffer.get() == NULL) {
+ LOG(ERROR) << "Error reading translated nexe";
+ return;
+ }
+
+ disk_cache_->StoreNexe(it->second.cache_key,
+ buffer,
+ base::Bind(&PnaclHost::OnTranslatedNexeStored,
+ weak_factory_.GetWeakPtr(),
+ it->first));
+}
+
+// After we know the nexe has been stored, we can clean up, and unblock any
+// outstanding requests for the same file.
+// (Bound callbacks must re-lookup the TranslationID because the translation
+// could be cancelled before they get called).
+void PnaclHost::OnTranslatedNexeStored(const TranslationID& id, int net_error) {
+ PendingTranslationMap::iterator entry(pending_translations_.find(id));
+ if (entry == pending_translations_.end()) {
+ return;
+ }
+ std::string key(entry->second.cache_key);
+ pending_translations_.erase(entry);
+ RequeryMatchingTranslations(key);
+}
+
+// Check if any pending translations match |key|. If so, re-issue the cache
+// query. In the overlapped miss case, we expect a hit this time, but a miss
+// is also possible in case of an error.
+void PnaclHost::RequeryMatchingTranslations(const std::string& key) {
+ // Check for outstanding misses to this same file
+ for (PendingTranslationMap::iterator it = pending_translations_.begin();
+ it != pending_translations_.end();
+ ++it) {
+ if (it->second.cache_key == key) {
+ // Re-send the cache read request. This time we expect a hit, but if
+ // something goes wrong, it will just handle it like a miss.
+ it->second.got_cache_reply = false;
+ disk_cache_->GetNexe(key,
+ base::Bind(&PnaclHost::OnCacheQueryReturn,
+ weak_factory_.GetWeakPtr(),
+ it->first));
+ }
+ }
+}
+
+//////////////////// GetNexeFd hit path
+
+// static
+int PnaclHost::CopyBufferToFile(base::PlatformFile fd,
+ scoped_refptr<net::DrainableIOBuffer> buffer) {
+ return base::WritePlatformFile(fd, 0, buffer->data(), buffer->size());
+}
+
+void PnaclHost::OnBufferCopiedToTempFile(const TranslationID& id,
+ int file_error) {
DCHECK(thread_checker_.CalledOnValidThread());
+ PendingTranslationMap::iterator entry(pending_translations_.find(id));
+ if (entry == pending_translations_.end()) {
+ return;
+ }
+ if (file_error == -1) {
+ // Write error on the temp file. Request a new file and start over.
+ LOG(ERROR) << "PnaclHost::OnBufferCopiedToTempFile write error";
+ BrowserThread::PostBlockingPoolTask(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(base::ClosePlatformFile),
+ entry->second.nexe_fd));
+ entry->second.got_nexe_fd = false;
+ CreateTemporaryFile(base::Bind(&PnaclHost::OnTempFileReturn,
+ weak_factory_.GetWeakPtr(),
+ entry->first));
+ return;
+ }
+ base::PlatformFile fd = entry->second.nexe_fd;
+ entry->second.callback.Run(fd, true);
+ BrowserThread::PostBlockingPoolTask(
+ FROM_HERE, base::Bind(base::IgnoreResult(base::ClosePlatformFile), fd));
+ pending_translations_.erase(entry);
+}
+
+///////////////////
+
+void PnaclHost::RendererClosing(int render_process_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (cache_state_ != CacheReady)
+ return;
for (PendingTranslationMap::iterator it = pending_translations_.begin();
it != pending_translations_.end();) {
PendingTranslationMap::iterator to_erase(it++);
if (to_erase->first.first == render_process_id) {
- // clean up the open files
+ // Clean up the open files.
+ BrowserThread::PostBlockingPoolTask(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(base::ClosePlatformFile),
+ to_erase->second.nexe_fd));
+ std::string key(to_erase->second.cache_key);
+ bool is_incognito = to_erase->second.is_incognito;
pending_translations_.erase(to_erase);
+ // No translations will be blocked waiting for an incongnito translation
+ if (!is_incognito)
+ RequeryMatchingTranslations(key);
}
}
+ if (pending_translations_.empty()) {
+ cache_state_ = CacheUninitialized;
+ // Freeing the backend causes it to flush to disk, so do it when the
+ // last renderer closes rather than on destruction.
+ disk_cache_.reset();
+ }
+}
+
+////////////////// Cache data removal
+void PnaclHost::ClearTranslationCacheEntriesBetween(
+ base::Time initial_time,
+ base::Time end_time,
+ const base::Closure& callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (cache_state_ == CacheUninitialized) {
+ Init();
+ }
+ if (cache_state_ == CacheInitializing) {
+ // If the backend hasn't yet initialized, try the request again later.
+ BrowserThread::PostDelayedTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&PnaclHost::ClearTranslationCacheEntriesBetween,
+ weak_factory_.GetWeakPtr(),
+ initial_time,
+ end_time,
+ callback),
+ base::TimeDelta::FromMilliseconds(
+ kTranslationCacheInitializationDelayMs));
+ return;
+ }
+ int rv = disk_cache_->DoomEntriesBetween(
+ initial_time,
+ end_time,
+ base::Bind(&PnaclHost::OnEntriesDoomed, callback));
+ if (rv != net::ERR_IO_PENDING)
+ OnEntriesDoomed(callback, rv);
+}
+
+// static
+void PnaclHost::OnEntriesDoomed(const base::Closure& callback, int net_error) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback);
}
diff --git a/chrome/browser/nacl_host/pnacl_host.h b/chrome/browser/nacl_host/pnacl_host.h
index 2093b44..3c0d2e8 100644
--- a/chrome/browser/nacl_host/pnacl_host.h
+++ b/chrome/browser/nacl_host/pnacl_host.h
@@ -15,6 +15,10 @@
#include "components/nacl/common/pnacl_types.h"
#include "ipc/ipc_platform_file.h"
+namespace net {
+class DrainableIOBuffer;
+}
+
namespace pnacl {
class PnaclHostTest;
class PnaclTranslationCache;
@@ -25,28 +29,28 @@
// called on the IO thread.
class PnaclHost {
public:
- typedef base::Callback<void(IPC::PlatformFileForTransit)> TempFileCallback;
- typedef base::Callback<void(IPC::PlatformFileForTransit, bool is_hit)>
- NexeFdCallback;
+ typedef base::Callback<void(base::PlatformFile)> TempFileCallback;
+ typedef base::Callback<void(base::PlatformFile, bool is_hit)> NexeFdCallback;
static PnaclHost* GetInstance();
PnaclHost();
~PnaclHost();
+
+ // Initialize cache backend. GetNexeFd will also initialize the backend if
+ // necessary, but calling Init ahead of time will minimize the latency.
void Init();
// Creates a temporary file that will be deleted when the last handle
- // is closed, or earlier. Returns a PlatformFileForTransit usable by the
- // process identified by |process_handle|.
- void CreateTemporaryFile(base::ProcessHandle process_handle,
- TempFileCallback cb);
+ // is closed, or earlier. Returns a PlatformFile handle.
+ void CreateTemporaryFile(TempFileCallback cb);
// Create a temporary file, which will be deleted by the time the last
// handle is closed (or earlier on POSIX systems), to use for the nexe
// with the cache information given in |cache_info|. The specific instance
// is identified by the combination of |render_process_id| and |pp_instance|.
- // Returns by calling |cb| with a PlatformFileForTransit usable by the process
- // identified by |process_handle|. If the nexe is already present
+ // Returns by calling |cb| with a PlatformFile handle.
+ // If the nexe is already present
// in the cache, |is_hit| is set to true and the contents of the nexe
// have been copied into the temporary file. Otherwise |is_hit| is set to
// false and the temporary file will be writeable.
@@ -55,10 +59,16 @@
// If the cache request was a miss, the caller is expected to call
// TranslationFinished after it finishes translation to allow the nexe to be
// stored in the cache.
+ // The returned temp fd may be closed at any time by PnaclHost, so it should
+ // be duplicated (e.g. with IPC::GetFileHandleForProcess) before the callback
+ // returns.
+ // If |is_incognito| is true, the nexe will not be stored
+ // in the cache, but the renderer is still expected to call
+ // TranslationFinished.
void GetNexeFd(int render_process_id,
- base::ProcessHandle process_handle,
int render_view_id,
int pp_instance,
+ bool is_incognito,
const nacl::PnaclCacheInfo& cache_info,
const NexeFdCallback& cb);
@@ -70,9 +80,21 @@
bool success);
// Called when the renderer identified by |render_process_id| is closing.
- // Clean up any outstanding translations for that renderer.
+ // Clean up any outstanding translations for that renderer. If there are no
+ // more pending translations, the backend is freed, allowing it to flush.
void RendererClosing(int render_process_id);
+ // Doom all entries between |initial_time| and |end_time|. Like disk_cache_,
+ // PnaclHost supports supports unbounded deletes in either direction by using
+ // null Time values for either argument. |callback| will be called on the UI
+ // thread when finished.
+ void ClearTranslationCacheEntriesBetween(base::Time initial_time,
+ base::Time end_time,
+ const base::Closure& callback);
+
+ // Return the number of tracked translations or FD requests currently pending.
+ size_t pending_translations() { return pending_translations_.size(); }
+
private:
// PnaclHost is a singleton because there is only one translation cache, and
// so that the BrowsingDataRemover can clear it even if no translation has
@@ -84,13 +106,20 @@
CacheInitializing,
CacheReady
};
- struct PendingTranslation {
+ class PendingTranslation {
public:
PendingTranslation();
~PendingTranslation();
+ base::ProcessHandle process_handle;
int render_view_id;
- IPC::PlatformFileForTransit nexe_fd;
+ base::PlatformFile nexe_fd;
+ bool got_nexe_fd;
+ bool got_cache_reply;
+ bool got_cache_hit;
+ bool is_incognito;
+ scoped_refptr<net::DrainableIOBuffer> nexe_read_buffer;
NexeFdCallback callback;
+ std::string cache_key;
nacl::PnaclCacheInfo cache_info;
};
@@ -98,11 +127,34 @@
typedef std::map<TranslationID, PendingTranslation> PendingTranslationMap;
void InitForTest(base::FilePath temp_dir);
- void OnCacheInitialized(int error);
- static IPC::PlatformFileForTransit DoCreateTemporaryFile(
- base::ProcessHandle process_handle,
- base::FilePath temp_dir_);
- void ReturnMiss(TranslationID id, IPC::PlatformFileForTransit fd);
+ void OnCacheInitialized(int net_error);
+
+ static base::PlatformFile DoCreateTemporaryFile(base::FilePath temp_dir_);
+
+ // GetNexeFd common steps
+ void SendCacheQueryAndTempFileRequest(const std::string& key,
+ const TranslationID& id);
+ void OnCacheQueryReturn(const TranslationID& id,
+ int net_error,
+ scoped_refptr<net::DrainableIOBuffer> buffer);
+ void OnTempFileReturn(const TranslationID& id, base::PlatformFile fd);
+ void CheckCacheQueryReady(const PendingTranslationMap::iterator& entry);
+
+ // GetNexeFd miss path
+ void ReturnMiss(const PendingTranslationMap::iterator& entry);
+ static scoped_refptr<net::DrainableIOBuffer> CopyFileToBuffer(
+ base::PlatformFile fd);
+ void StoreTranslatedNexe(TranslationID id,
+ scoped_refptr<net::DrainableIOBuffer>);
+ void OnTranslatedNexeStored(const TranslationID& id, int net_error);
+ void RequeryMatchingTranslations(const std::string& key);
+
+ // GetNexeFd hit path
+ static int CopyBufferToFile(base::PlatformFile fd,
+ scoped_refptr<net::DrainableIOBuffer> buffer);
+ void OnBufferCopiedToTempFile(const TranslationID& id, int file_error);
+
+ static void OnEntriesDoomed(const base::Closure& callback, int net_error);
CacheState cache_state_;
base::FilePath temp_dir_;
diff --git a/chrome/browser/nacl_host/pnacl_host_unittest.cc b/chrome/browser/nacl_host/pnacl_host_unittest.cc
index cb5e8ef..0ad9cd5 100644
--- a/chrome/browser/nacl_host/pnacl_host_unittest.cc
+++ b/chrome/browser/nacl_host/pnacl_host_unittest.cc
@@ -4,20 +4,29 @@
#include "chrome/browser/nacl_host/pnacl_host.h"
+#include <stdio.h>
#include "base/bind.h"
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/nacl_host/pnacl_translation_cache.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/base/test_completion_callback.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(OS_WIN)
+#define snprintf _snprintf
+#endif
+
namespace pnacl {
class PnaclHostTest : public testing::Test {
protected:
PnaclHostTest()
- : temp_callback_count_(0),
+ : host_(NULL),
+ temp_callback_count_(0),
+ write_callback_count_(0),
thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
virtual void SetUp() {
host_ = new PnaclHost();
@@ -26,78 +35,339 @@
EXPECT_EQ(host_->cache_state_, PnaclHost::CacheReady);
}
virtual void TearDown() {
- ExpectPendingTranslations(0);
+ EXPECT_EQ(0U, host_->pending_translations());
delete host_;
}
- // Utilities for inspecting internal state of the pnacl host
- void ExpectPendingTranslations(size_t count) {
- EXPECT_EQ(count, host_->pending_translations_.size());
+ // Flush the blocking pool first, then any tasks it posted to the IO thread.
+ // Do 2 rounds of flushing, because some operations require 2 trips back and
+ // forth between the threads.
+ void FlushQueues() {
+ content::BrowserThread::GetBlockingPool()->FlushForTesting();
+ base::RunLoop().RunUntilIdle();
+ content::BrowserThread::GetBlockingPool()->FlushForTesting();
+ base::RunLoop().RunUntilIdle();
}
- void ExpectCallbackCount(int count) {
- EXPECT_EQ(count, temp_callback_count_);
+ int GetCacheSize() {
+ return host_->disk_cache_->Size();
}
public: // Required for derived classes to bind this method
- void CallbackExpectMiss(IPC::PlatformFileForTransit fd, bool is_hit) {
- temp_callback_count_++;
+ // Callbacks used by tests which call GetNexeFd.
+ // CallbackExpectMiss checks that the fd is valid and a miss is reported,
+ // and also writes some data into the file, which is read back by
+ // CallbackExpectHit
+ void CallbackExpectMiss(base::PlatformFile fd, bool is_hit) {
EXPECT_FALSE(is_hit);
- EXPECT_FALSE(fd == IPC::InvalidPlatformFileForTransit());
+ ASSERT_FALSE(fd == base::kInvalidPlatformFileValue);
+ base::PlatformFileInfo info;
+ EXPECT_TRUE(base::GetPlatformFileInfo(fd, &info));
+ EXPECT_FALSE(info.is_directory);
+ EXPECT_EQ(0LL, info.size);
+ char str[16];
+ memset(str, 0x0, 16);
+ snprintf(str, 16, "testdata%d", ++write_callback_count_);
+ EXPECT_EQ(16, base::WritePlatformFile(fd, 0, str, 16));
+ temp_callback_count_++;
+ }
+ void CallbackExpectHit(base::PlatformFile fd, bool is_hit) {
+ EXPECT_TRUE(is_hit);
+ ASSERT_FALSE(fd == base::kInvalidPlatformFileValue);
+ base::PlatformFileInfo info;
+ EXPECT_TRUE(base::GetPlatformFileInfo(fd, &info));
+ EXPECT_FALSE(info.is_directory);
+ EXPECT_EQ(16LL, info.size);
+ char data[16];
+ memset(data, 0x0, 16);
+ char str[16];
+ memset(str, 0x0, 16);
+ snprintf(str, 16, "testdata%d", write_callback_count_);
+ EXPECT_EQ(16, base::ReadPlatformFile(fd, 0, data, 16));
+ EXPECT_STREQ(str, data);
+ temp_callback_count_++;
}
protected:
PnaclHost* host_;
int temp_callback_count_;
+ int write_callback_count_;
content::TestBrowserThreadBundle thread_bundle_;
base::ScopedTempDir temp_dir_;
};
-#define EXPECT_PENDING_TRANSLATIONS(n) \
- do { \
- SCOPED_TRACE(""); \
- ExpectPendingTranslations(n); \
+static nacl::PnaclCacheInfo GetTestCacheInfo() {
+ nacl::PnaclCacheInfo info;
+ info.pexe_url = GURL("http://www.google.com");
+ info.abi_version = 0;
+ info.opt_level = 0;
+ return info;
+}
+
+#define GET_NEXE_FD(renderer, instance, incognito, info, expect_hit)\
+ do { \
+ SCOPED_TRACE(""); \
+ host_->GetNexeFd( \
+ renderer, \
+ 0, /* ignore render_view_id for now */ \
+ instance, \
+ incognito, \
+ info, \
+ base::Bind(expect_hit ? &PnaclHostTest::CallbackExpectHit \
+ : &PnaclHostTest::CallbackExpectMiss, \
+ base::Unretained(this))); \
} while (0)
-// We don't do actual caching yet, but just return a new temp file with a miss
TEST_F(PnaclHostTest, BasicMiss) {
- nacl::PnaclCacheInfo info;
- host_->GetNexeFd(
- 0,
- base::ProcessHandle(),
- 0,
- 0,
- info,
- base::Bind(&PnaclHostTest::CallbackExpectMiss, base::Unretained(this)));
-
- EXPECT_PENDING_TRANSLATIONS(1);
- content::BrowserThread::GetBlockingPool()->FlushForTesting();
- base::RunLoop().RunUntilIdle();
- EXPECT_PENDING_TRANSLATIONS(1);
- ExpectCallbackCount(1);
+ nacl::PnaclCacheInfo info = GetTestCacheInfo();
+ // Test cold miss.
+ GET_NEXE_FD(0, 0, false, info, false);
+ EXPECT_EQ(1U, host_->pending_translations());
+ FlushQueues();
+ EXPECT_EQ(1U, host_->pending_translations());
+ EXPECT_EQ(1, temp_callback_count_);
host_->TranslationFinished(0, 0, true);
- EXPECT_PENDING_TRANSLATIONS(0);
+ FlushQueues();
+ EXPECT_EQ(0U, host_->pending_translations());
+ // Test that a different cache info field also misses.
+ info.etag = std::string("something else");
+ GET_NEXE_FD(0, 0, false, info, false);
+ FlushQueues();
+ EXPECT_EQ(2, temp_callback_count_);
+ EXPECT_EQ(1U, host_->pending_translations());
host_->RendererClosing(0);
}
TEST_F(PnaclHostTest, BadArguments) {
- nacl::PnaclCacheInfo info;
- host_->GetNexeFd(
- 0,
- base::ProcessHandle(),
- 0,
- 0,
- info,
- base::Bind(&PnaclHostTest::CallbackExpectMiss, base::Unretained(this)));
-
- EXPECT_PENDING_TRANSLATIONS(1);
+ nacl::PnaclCacheInfo info = GetTestCacheInfo();
+ GET_NEXE_FD(0, 0, false, info, false);
+ EXPECT_EQ(1U, host_->pending_translations());
host_->TranslationFinished(0, 1, true); // nonexistent translation
- EXPECT_PENDING_TRANSLATIONS(1);
+ EXPECT_EQ(1U, host_->pending_translations());
host_->RendererClosing(1); // nonexistent renderer
- EXPECT_PENDING_TRANSLATIONS(1);
- content::BrowserThread::GetBlockingPool()->FlushForTesting();
- base::RunLoop().RunUntilIdle();
- ExpectCallbackCount(1);
+ EXPECT_EQ(1U, host_->pending_translations());
+ FlushQueues();
+ EXPECT_EQ(1, temp_callback_count_);
host_->RendererClosing(0); // close without finishing
- EXPECT_PENDING_TRANSLATIONS(0);
+}
+
+TEST_F(PnaclHostTest, BasicHit) {
+ nacl::PnaclCacheInfo info = GetTestCacheInfo();
+ GET_NEXE_FD(0, 0, false, info, false);
+ FlushQueues();
+ EXPECT_EQ(1, temp_callback_count_);
+ host_->TranslationFinished(0, 0, true);
+ FlushQueues();
+ GET_NEXE_FD(0, 1, false, info, true);
+ FlushQueues();
+ EXPECT_EQ(2, temp_callback_count_);
+ EXPECT_EQ(0U, host_->pending_translations());
+}
+
+TEST_F(PnaclHostTest, TranslationErrors) {
+ nacl::PnaclCacheInfo info = GetTestCacheInfo();
+ info.pexe_url = GURL("http://www.google.com");
+ GET_NEXE_FD(0, 0, false, info, false);
+ // Early abort, before temp file request returns
+ host_->TranslationFinished(0, 0, false);
+ FlushQueues();
+ EXPECT_EQ(0U, host_->pending_translations());
+ EXPECT_EQ(0, temp_callback_count_);
+ // Check that another request for the same info misses successfully.
+ GET_NEXE_FD(0, 0, false, info, false);
+ FlushQueues();
+ host_->TranslationFinished(0, 0, true);
+ FlushQueues();
+ EXPECT_EQ(1, temp_callback_count_);
+ EXPECT_EQ(0U, host_->pending_translations());
+
+ // Now try sending the error after the temp file request returns
+ info.abi_version = 222;
+ GET_NEXE_FD(0, 0, false, info, false);
+ FlushQueues();
+ EXPECT_EQ(2, temp_callback_count_);
+ host_->TranslationFinished(0, 0, false);
+ FlushQueues();
+ EXPECT_EQ(0U, host_->pending_translations());
+ // Check another successful miss
+ GET_NEXE_FD(0, 0, false, info, false);
+ FlushQueues();
+ EXPECT_EQ(3, temp_callback_count_);
+ host_->TranslationFinished(0, 0, false);
+ EXPECT_EQ(0U, host_->pending_translations());
+}
+
+TEST_F(PnaclHostTest, OverlappedMissesAfterTempReturn) {
+ nacl::PnaclCacheInfo info = GetTestCacheInfo();
+ GET_NEXE_FD(0, 0, false, info, false);
+ FlushQueues();
+ EXPECT_EQ(1, temp_callback_count_);
+ EXPECT_EQ(1U, host_->pending_translations());
+ // Test that a second request for the same nexe while the first one is still
+ // outstanding eventually hits.
+ GET_NEXE_FD(0, 1, false, info, true);
+ FlushQueues();
+ EXPECT_EQ(2U, host_->pending_translations());
+ // The temp file should not be returned to the second request until after the
+ // first is finished translating.
+ EXPECT_EQ(1, temp_callback_count_);
+ host_->TranslationFinished(0, 0, true);
+ FlushQueues();
+ EXPECT_EQ(2, temp_callback_count_);
+ EXPECT_EQ(0U, host_->pending_translations());
+}
+
+TEST_F(PnaclHostTest, OverlappedMissesBeforeTempReturn) {
+ nacl::PnaclCacheInfo info = GetTestCacheInfo();
+ GET_NEXE_FD(0, 0, false, info, false);
+ // Send the 2nd fd request before the first one returns a temp file.
+ GET_NEXE_FD(0, 1, false, info, true);
+ FlushQueues();
+ EXPECT_EQ(1, temp_callback_count_);
+ EXPECT_EQ(2U, host_->pending_translations());
+ FlushQueues();
+ EXPECT_EQ(2U, host_->pending_translations());
+ EXPECT_EQ(1, temp_callback_count_);
+ host_->TranslationFinished(0, 0, true);
+ FlushQueues();
+ EXPECT_EQ(2, temp_callback_count_);
+ EXPECT_EQ(0U, host_->pending_translations());
+}
+
+TEST_F(PnaclHostTest, OverlappedHitsBeforeTempReturn) {
+ nacl::PnaclCacheInfo info = GetTestCacheInfo();
+ // Store one in the cache and complete it.
+ GET_NEXE_FD(0, 0, false, info, false);
+ FlushQueues();
+ EXPECT_EQ(1, temp_callback_count_);
+ host_->TranslationFinished(0, 0, true);
+ FlushQueues();
+ EXPECT_EQ(0U, host_->pending_translations());
+ GET_NEXE_FD(0, 0, false, info, true);
+ // Request the second before the first temp file returns.
+ GET_NEXE_FD(0, 1, false, info, true);
+ FlushQueues();
+ EXPECT_EQ(3, temp_callback_count_);
+ EXPECT_EQ(0U, host_->pending_translations());
+}
+
+TEST_F(PnaclHostTest, OverlappedHitsAfterTempReturn) {
+ nacl::PnaclCacheInfo info = GetTestCacheInfo();
+ // Store one in the cache and complete it.
+ GET_NEXE_FD(0, 0, false, info, false);
+ FlushQueues();
+ EXPECT_EQ(1, temp_callback_count_);
+ host_->TranslationFinished(0, 0, true);
+ FlushQueues();
+ EXPECT_EQ(0U, host_->pending_translations());
+ GET_NEXE_FD(0, 0, false, info, true);
+ FlushQueues();
+ GET_NEXE_FD(0, 1, false, info, true);
+ FlushQueues();
+ EXPECT_EQ(3, temp_callback_count_);
+ EXPECT_EQ(0U, host_->pending_translations());
+}
+
+TEST_F(PnaclHostTest, OverlappedMissesRendererClosing) {
+ nacl::PnaclCacheInfo info = GetTestCacheInfo();
+ GET_NEXE_FD(0, 0, false, info, false);
+ // Send the 2nd fd request from a different renderer.
+ // Test that it eventually gets an fd after the first renderer closes.
+ GET_NEXE_FD(1, 1, false, info, false);
+ FlushQueues();
+ EXPECT_EQ(1, temp_callback_count_);
+ EXPECT_EQ(2U, host_->pending_translations());
+ FlushQueues();
+ EXPECT_EQ(2U, host_->pending_translations());
+ EXPECT_EQ(1, temp_callback_count_);
+ host_->RendererClosing(0);
+ FlushQueues();
+ EXPECT_EQ(2, temp_callback_count_);
+ EXPECT_EQ(1U, host_->pending_translations());
+ host_->RendererClosing(1);
+}
+
+TEST_F(PnaclHostTest, Incognito) {
+ nacl::PnaclCacheInfo info = GetTestCacheInfo();
+ GET_NEXE_FD(0, 0, true, info, false);
+ FlushQueues();
+ EXPECT_EQ(1, temp_callback_count_);
+ host_->TranslationFinished(0, 0, true);
+ FlushQueues();
+ // Check that an incognito translation is not stored in the cache
+ GET_NEXE_FD(0, 0, false, info, false);
+ FlushQueues();
+ EXPECT_EQ(2, temp_callback_count_);
+ host_->TranslationFinished(0, 0, true);
+ FlushQueues();
+ // Check that an incognito translation can hit from a normal one.
+ GET_NEXE_FD(0, 0, true, info, true);
+ FlushQueues();
+ EXPECT_EQ(3, temp_callback_count_);
+}
+
+TEST_F(PnaclHostTest, IncognitoOverlappedMiss) {
+ nacl::PnaclCacheInfo info = GetTestCacheInfo();
+ GET_NEXE_FD(0, 0, true, info, false);
+ GET_NEXE_FD(0, 1, false, info, false);
+ FlushQueues();
+ // Check that both translations have returned misses, (i.e. that the
+ // second one has not blocked on the incognito one)
+ EXPECT_EQ(2, temp_callback_count_);
+ host_->TranslationFinished(0, 0, true);
+ host_->TranslationFinished(0, 1, true);
+ FlushQueues();
+ EXPECT_EQ(0U, host_->pending_translations());
+
+ // Same test, but issue the 2nd request after the first has returned a miss.
+ info.abi_version = 222;
+ GET_NEXE_FD(0, 0, true, info, false);
+ FlushQueues();
+ EXPECT_EQ(3, temp_callback_count_);
+ GET_NEXE_FD(0, 1, false, info, false);
+ FlushQueues();
+ EXPECT_EQ(4, temp_callback_count_);
+ host_->RendererClosing(0);
+}
+
+TEST_F(PnaclHostTest, IncognitoSecondOverlappedMiss) {
+ // If the non-incognito request comes first, it should
+ // behave exactly like OverlappedMissBeforeTempReturn
+ nacl::PnaclCacheInfo info = GetTestCacheInfo();
+ GET_NEXE_FD(0, 0, false, info, false);
+ // Send the 2nd fd request before the first one returns a temp file.
+ GET_NEXE_FD(0, 1, true, info, true);
+ FlushQueues();
+ EXPECT_EQ(1, temp_callback_count_);
+ EXPECT_EQ(2U, host_->pending_translations());
+ FlushQueues();
+ EXPECT_EQ(2U, host_->pending_translations());
+ EXPECT_EQ(1, temp_callback_count_);
+ host_->TranslationFinished(0, 0, true);
+ FlushQueues();
+ EXPECT_EQ(2, temp_callback_count_);
+ EXPECT_EQ(0U, host_->pending_translations());
+}
+
+TEST_F(PnaclHostTest, ClearTranslationCache) {
+ nacl::PnaclCacheInfo info = GetTestCacheInfo();
+ // Add 2 entries in the cache
+ GET_NEXE_FD(0, 0, false, info, false);
+ info.abi_version = 222;
+ GET_NEXE_FD(0, 1, false, info, false);
+ FlushQueues();
+ EXPECT_EQ(2, temp_callback_count_);
+ host_->TranslationFinished(0, 0, true);
+ host_->TranslationFinished(0, 1, true);
+ FlushQueues();
+ EXPECT_EQ(0U, host_->pending_translations());
+ EXPECT_EQ(2, GetCacheSize());
+ net::TestCompletionCallback cb;
+ // Since we are using a memory backend, the clear should happen immediately.
+ host_->ClearTranslationCacheEntriesBetween(base::Time(), base::Time(),
+ base::Bind(cb.callback(), 0));
+ EXPECT_EQ(0, cb.GetResult(net::ERR_IO_PENDING));
+ // Check that the translation cache has been cleared
+ EXPECT_EQ(0, GetCacheSize());
+ host_->RendererClosing(0);
}
} // namespace pnacl
diff --git a/chrome/browser/nacl_host/pnacl_translation_cache.cc b/chrome/browser/nacl_host/pnacl_translation_cache.cc
index fa548f1..508c665 100644
--- a/chrome/browser/nacl_host/pnacl_translation_cache.cc
+++ b/chrome/browser/nacl_host/pnacl_translation_cache.cc
@@ -26,9 +26,8 @@
} // namespace
namespace pnacl {
-// These are in pnacl namespace instead of static so they can be used
+// This is in pnacl namespace instead of static so they can be used
// by the unit test.
-const int kMaxDiskCacheSize = 1000 * 1024 * 1024;
const int kMaxMemCacheSize = 100 * 1024 * 1024;
//////////////////////////////////////////////////////////////////////
@@ -156,10 +155,10 @@
// OpenEntry, CreateEntry, WriteEntry, ReadEntry and CloseEntry are only called
// from DispatchNext, so they know that cache_ is still valid.
void PnaclTranslationCacheEntry::OpenEntry() {
- int rv = cache_->backend()
- ->OpenEntry(key_,
- &entry_,
- base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this));
+ int rv = cache_->backend()->OpenEntry(
+ key_,
+ &entry_,
+ base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this));
if (rv != net::ERR_IO_PENDING)
DispatchNext(rv);
}
@@ -199,8 +198,11 @@
void PnaclTranslationCacheEntry::CloseEntry(int rv) {
DCHECK(entry_);
- if (rv < 0)
+ if (rv < 0) {
+ LOG(ERROR) << "PnaclTranslationCache: failed to close entry: "
+ << net::ErrorToString(rv);
entry_->Doom();
+ }
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE, base::Bind(&CloseDiskCacheEntry, entry_));
Finish(rv);
@@ -228,7 +230,7 @@
switch (step_) {
case UNINITIALIZED:
- LOG(ERROR) << "Unexpected step in DispatchNext";
+ LOG(ERROR) << "PnaclTranslationCache: DispatchNext called uninitialized";
break;
case OPEN_ENTRY:
@@ -243,6 +245,11 @@
WriteEntry(0, io_buf_->size());
}
} else {
+ if (rv != net::ERR_FAILED) {
+ // ERROR_FAILED is what we expect if the entry doesn't exist.
+ LOG(ERROR) << "PnaclTranslationCache: OpenEntry failed: "
+ << net::ErrorToString(rv);
+ }
if (is_read_) {
// Just a cache miss, not necessarily an error.
entry_ = NULL;
@@ -259,7 +266,8 @@
step_ = TRANSFER_ENTRY;
WriteEntry(io_buf_->BytesConsumed(), io_buf_->BytesRemaining());
} else {
- LOG(ERROR) << "Failed to Create a PNaCl Translation Cache Entry";
+ LOG(ERROR) << "PnaclTranslationCache: Failed to Create Entry: "
+ << net::ErrorToString(rv);
Finish(rv);
}
break;
@@ -269,8 +277,8 @@
// We do not call DispatchNext directly if WriteEntry/ReadEntry returns
// ERR_IO_PENDING, and the callback should not return that value either.
LOG(ERROR)
- << "Failed to complete write to PNaCl Translation Cache Entry: "
- << rv;
+ << "PnaclTranslationCache: Failed to complete write to entry: "
+ << net::ErrorToString(rv);
step_ = CLOSE_ENTRY;
CloseEntry(rv);
break;
@@ -343,6 +351,10 @@
}
void PnaclTranslationCache::OnCreateBackendComplete(int rv) {
+ if (rv < 0) {
+ LOG(ERROR) << "PnaclTranslationCache: backend init failed:"
+ << net::ErrorToString(rv);
+ }
// Invoke our client's callback function.
if (!init_callback_.is_null()) {
init_callback_.Run(rv);
@@ -383,7 +395,7 @@
if (in_memory_) {
rv = InitWithMemBackend(kMaxMemCacheSize, callback);
} else {
- rv = InitWithDiskBackend(cache_directory, kMaxDiskCacheSize, callback);
+ rv = InitWithDiskBackend(cache_directory, 0, callback);
}
return rv;
@@ -400,9 +412,8 @@
if (!info.pexe_url.is_valid() || info.abi_version < 0 || info.opt_level < 0)
return std::string();
std::string retval("ABI:");
- retval += IntToString(info.abi_version) + ";" +
- "opt:" + IntToString(info.opt_level) + ";" +
- "URL:";
+ retval += IntToString(info.abi_version) + ";" + "opt:" +
+ IntToString(info.opt_level) + ";" + "URL:";
// Filter the username, password, and ref components from the URL
GURL::Replacements replacements;
replacements.ClearUsername();
@@ -419,12 +430,20 @@
memset(&exploded, 0, sizeof(exploded));
}
retval += "modified:" + IntToString(exploded.year) + ":" +
- IntToString(exploded.month) + ":" +
- IntToString(exploded.day_of_month) + ":" +
- IntToString(exploded.hour) + ":" + IntToString(exploded.minute) + ":" +
- IntToString(exploded.second) + ":" +
- IntToString(exploded.millisecond) + ":UTC;";
+ IntToString(exploded.month) + ":" +
+ IntToString(exploded.day_of_month) + ":" +
+ IntToString(exploded.hour) + ":" + IntToString(exploded.minute) +
+ ":" + IntToString(exploded.second) + ":" +
+ IntToString(exploded.millisecond) + ":UTC;";
retval += "etag:" + info.etag;
return retval;
}
+
+int PnaclTranslationCache::DoomEntriesBetween(
+ base::Time initial,
+ base::Time end,
+ const CompletionCallback& callback) {
+ return disk_cache_->DoomEntriesBetween(initial, end, callback);
+}
+
} // namespace pnacl
diff --git a/chrome/browser/nacl_host/pnacl_translation_cache.h b/chrome/browser/nacl_host/pnacl_translation_cache.h
index 8f2d9ac..8b9ffe9 100644
--- a/chrome/browser/nacl_host/pnacl_translation_cache.h
+++ b/chrome/browser/nacl_host/pnacl_translation_cache.h
@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
#include "net/base/cache_type.h"
namespace base {
@@ -71,6 +72,12 @@
// Return the cache key for |info|
static std::string GetKey(const nacl::PnaclCacheInfo& info);
+ // Doom all entries between |initial| and |end|. If the return value is
+ // net::ERR_IO_PENDING, |callback| will be invoked when the operation
+ // completes.
+ int DoomEntriesBetween(base::Time initial, base::Time end,
+ const CompletionCallback& callback);
+
private:
friend class PnaclTranslationCacheEntry;
friend class PnaclTranslationCacheTest;
diff --git a/chrome/browser/notifications/message_center_notification_manager.cc b/chrome/browser/notifications/message_center_notification_manager.cc
index 5661734..2054a7f 100644
--- a/chrome/browser/notifications/message_center_notification_manager.cc
+++ b/chrome/browser/notifications/message_center_notification_manager.cc
@@ -307,7 +307,7 @@
NotificationMap::const_iterator iter =
profile_notifications_.find(notification_id);
if (iter != profile_notifications_.end())
- RemoveProfileNotification(iter->second, by_user);
+ RemoveProfileNotification(iter->second);
#if defined(OS_WIN)
CheckFirstRunTimer();
@@ -549,9 +549,7 @@
}
void MessageCenterNotificationManager::RemoveProfileNotification(
- ProfileNotification* profile_notification,
- bool by_user) {
- profile_notification->notification().Close(by_user);
+ ProfileNotification* profile_notification) {
std::string id = profile_notification->notification().notification_id();
profile_notifications_.erase(id);
delete profile_notification;
diff --git a/chrome/browser/notifications/message_center_notification_manager.h b/chrome/browser/notifications/message_center_notification_manager.h
index be2621e..4589645 100644
--- a/chrome/browser/notifications/message_center_notification_manager.h
+++ b/chrome/browser/notifications/message_center_notification_manager.h
@@ -192,8 +192,7 @@
// Helpers that add/remove the notification from local map and MessageCenter.
// They take ownership of profile_notification object.
void AddProfileNotification(ProfileNotification* profile_notification);
- void RemoveProfileNotification(ProfileNotification* profile_notification,
- bool by_user);
+ void RemoveProfileNotification(ProfileNotification* profile_notification);
// Returns the ProfileNotification for the |id|, or NULL if no such
// notification is found.
diff --git a/chrome/browser/notifications/message_center_settings_controller.cc b/chrome/browser/notifications/message_center_settings_controller.cc
index ef91c33..66175a7 100644
--- a/chrome/browser/notifications/message_center_settings_controller.cc
+++ b/chrome/browser/notifications/message_center_settings_controller.cc
@@ -132,6 +132,11 @@
return *(notifier_groups_[index]);
}
+bool MessageCenterSettingsController::IsNotifierGroupActiveAt(
+ size_t index) const {
+ return current_notifier_group_ == index;
+}
+
const message_center::NotifierGroup&
MessageCenterSettingsController::GetActiveNotifierGroup() const {
DCHECK_LT(current_notifier_group_, notifier_groups_.size());
diff --git a/chrome/browser/notifications/message_center_settings_controller.h b/chrome/browser/notifications/message_center_settings_controller.h
index 4adc136..03f7552 100644
--- a/chrome/browser/notifications/message_center_settings_controller.h
+++ b/chrome/browser/notifications/message_center_settings_controller.h
@@ -50,6 +50,7 @@
virtual size_t GetNotifierGroupCount() const OVERRIDE;
virtual const message_center::NotifierGroup& GetNotifierGroupAt(
size_t index) const OVERRIDE;
+ virtual bool IsNotifierGroupActiveAt(size_t index) const OVERRIDE;
virtual void SwitchToNotifierGroup(size_t index) OVERRIDE;
virtual const message_center::NotifierGroup& GetActiveNotifierGroup() const
OVERRIDE;
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.cc
index 794cb5f..49f594b 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.cc
@@ -65,7 +65,7 @@
void ChromeNotifierDelegate::Close(bool by_user) {
if (by_user)
- chrome_notifier_->MarkNotificationAsDismissed(notification_id_);
+ chrome_notifier_->MarkNotificationAsRead(notification_id_);
}
} // namespace notifier
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_browsertest.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_browsertest.cc
index d35e532..7532501 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_browsertest.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_browsertest.cc
@@ -34,8 +34,8 @@
virtual ~StubChromeNotifierService() {}
- virtual void MarkNotificationAsDismissed(const std::string& id) OVERRIDE {
- dismissed_id_ = id;
+ virtual void MarkNotificationAsRead(const std::string& id) OVERRIDE {
+ read_id_ = id;
}
notifier::SyncedNotification* CreateNotification(
@@ -62,10 +62,10 @@
kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread);
}
- const std::string& dismissed_id() { return dismissed_id_; }
+ const std::string& read_id() { return read_id_; }
private:
- std::string dismissed_id_;
+ std::string read_id_;
};
class ChromeNotifierDelegateBrowserTest : public InProcessBrowserTest {};
@@ -153,8 +153,8 @@
new notifier::ChromeNotifierDelegate(id, ¬ifier);
delegate->Close(false);
- ASSERT_EQ("", notifier.dismissed_id());
+ ASSERT_EQ("", notifier.read_id());
delegate->Close(true);
- ASSERT_EQ(kTestNotificationId, notifier.dismissed_id());
+ ASSERT_EQ(kTestNotificationId, notifier.read_id());
}
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
index cc07213..6341a3f 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
@@ -102,7 +102,12 @@
if (incoming->GetReadState() == SyncedNotification::kDismissed) {
// If it is marked as read on the server, but not the client.
found->NotificationHasBeenDismissed();
- // Tell the Notification UI Manager to mark it read.
+ // Tell the Notification UI Manager to remove it.
+ notification_manager_->CancelById(found->GetKey());
+ } else if (incoming->GetReadState() == SyncedNotification::kRead) {
+ // If it is marked as read on the server, but not the client.
+ found->NotificationHasBeenRead();
+ // Tell the Notification UI Manager to remove it.
notification_manager_->CancelById(found->GetKey());
} else {
// If it is marked as read on the client, but not the server.
@@ -122,7 +127,7 @@
found->Update(sync_data);
// Tell the notification manager to update the notification.
- Display(found);
+ UpdateInMessageCenter(found);
}
}
}
@@ -147,10 +152,9 @@
syncer::SyncDataList sync_data;
// Copy our native format data into a SyncDataList format.
- for (std::vector<SyncedNotification*>::const_iterator it =
- notification_data_.begin();
- it != notification_data_.end();
- ++it) {
+ ScopedVector<SyncedNotification>::const_iterator it =
+ notification_data_.begin();
+ for (; it != notification_data_.end(); ++it) {
sync_data.push_back(CreateSyncDataFromNotification(**it));
}
@@ -177,15 +181,38 @@
continue;
}
+ const std::string& key = new_notification->GetKey();
+ DCHECK_GT(key.length(), 0U);
+ SyncedNotification* found = FindNotificationById(key);
+
switch (change_type) {
case syncer::SyncChange::ACTION_ADD:
- // TODO(petewil): Update the notification if it already exists
- // as opposed to adding it.
- Add(new_notification.Pass());
+ // Intentional fall through, cases are identical.
+ case syncer::SyncChange::ACTION_UPDATE:
+ if (found == NULL) {
+ Add(new_notification.Pass());
+ break;
+ }
+ // Update it in our store.
+ found->Update(sync_data);
+ // Tell the notification manager to update the notification.
+ UpdateInMessageCenter(found);
break;
- // TODO(petewil): Implement code to add delete and update actions.
+
+ case syncer::SyncChange::ACTION_DELETE:
+ if (found == NULL) {
+ break;
+ }
+ // Remove it from our store.
+ FreeNotificationById(key);
+ // Remove it from the message center.
+ UpdateInMessageCenter(new_notification.get());
+ // TODO(petewil): Do I need to remember that it was deleted in case the
+ // add arrives after the delete? If so, how long do I need to remember?
+ break;
default:
+ NOTREACHED();
break;
}
}
@@ -225,12 +252,16 @@
return scoped_ptr<SyncedNotification>();
}
- // TODO(petewil): Is this the right set? Should I add more?
bool is_well_formed_unread_notification =
(static_cast<SyncedNotification::ReadState>(
specifics.coalesced_notification().read_state()) ==
SyncedNotification::kUnread &&
specifics.coalesced_notification().has_render_info());
+ bool is_well_formed_read_notification =
+ (static_cast<SyncedNotification::ReadState>(
+ specifics.coalesced_notification().read_state()) ==
+ SyncedNotification::kRead &&
+ specifics.coalesced_notification().has_render_info());
bool is_well_formed_dismissed_notification =
(static_cast<SyncedNotification::ReadState>(
specifics.coalesced_notification().read_state()) ==
@@ -238,12 +269,15 @@
// If the notification is poorly formed, return a null pointer.
if (!is_well_formed_unread_notification &&
+ !is_well_formed_read_notification &&
!is_well_formed_dismissed_notification) {
DVLOG(1) << "Synced Notification is not well formed."
<< " unread well formed? "
<< is_well_formed_unread_notification
<< " dismissed well formed? "
- << is_well_formed_dismissed_notification;
+ << is_well_formed_dismissed_notification
+ << " read well formed? "
+ << is_well_formed_read_notification;
return scoped_ptr<SyncedNotification>();
}
@@ -261,10 +295,9 @@
// TODO(petewil): We can make a performance trade off here.
// While the vector has good locality of reference, a map has faster lookup.
// Based on how big we expect this to get, maybe change this to a map.
- for (std::vector<SyncedNotification*>::const_iterator it =
- notification_data_.begin();
- it != notification_data_.end();
- ++it) {
+ ScopedVector<SyncedNotification>::const_iterator it =
+ notification_data_.begin();
+ for (; it != notification_data_.end(); ++it) {
SyncedNotification* notification = *it;
if (notification_id == notification->GetKey())
return *it;
@@ -273,6 +306,18 @@
return NULL;
}
+void ChromeNotifierService::FreeNotificationById(
+ const std::string& notification_id) {
+ ScopedVector<SyncedNotification>::iterator it = notification_data_.begin();
+ for (; it != notification_data_.end(); ++it) {
+ SyncedNotification* notification = *it;
+ if (notification_id == notification->GetKey()) {
+ notification_data_.erase(it);
+ return;
+ }
+ }
+}
+
void ChromeNotifierService::GetSyncedNotificationServices(
std::vector<message_center::Notifier*>* notifiers) {
// TODO(mukai|petewil): Check the profile's eligibility before adding the
@@ -305,13 +350,13 @@
notifiers->push_back(notifier_service);
}
-void ChromeNotifierService::MarkNotificationAsDismissed(
+void ChromeNotifierService::MarkNotificationAsRead(
const std::string& key) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
SyncedNotification* notification = FindNotificationById(key);
CHECK(notification != NULL);
- notification->NotificationHasBeenDismissed();
+ notification->NotificationHasBeenRead();
syncer::SyncChangeList new_changes;
syncer::SyncData sync_data = CreateSyncDataFromNotification(*notification);
@@ -340,24 +385,38 @@
return;
}
- Display(notification_copy);
+ UpdateInMessageCenter(notification_copy);
}
void ChromeNotifierService::AddForTest(
scoped_ptr<notifier::SyncedNotification> notification) {
- notification_data_.push_back(notification.release());
- }
+ notification_data_.push_back(notification.release());
+}
-void ChromeNotifierService::Display(SyncedNotification* notification) {
+void ChromeNotifierService::UpdateInMessageCenter(
+ SyncedNotification* notification) {
// If the feature is disabled, exit now.
if (!notifier::ChromeNotifierServiceFactory::UseSyncedNotifications(
- CommandLine::ForCurrentProcess()))
+ CommandLine::ForCurrentProcess()))
return;
+ notification->LogNotification();
+
+ if (notification->GetReadState() == SyncedNotification::kUnread) {
+ // If the message is unread, update it.
+ Display(notification);
+ } else {
+ // If the message is read or deleted, dismiss it from the center.
+ // We intentionally ignore errors if it is not in the center.
+ notification_manager_->CancelById(notification->GetKey());
+ }
+}
+
+void ChromeNotifierService::Display(SyncedNotification* notification) {
// Set up to fetch the bitmaps.
notification->QueueBitmapFetchJobs(notification_manager_,
- this,
- profile_);
+ this,
+ profile_);
// Our tests cannot use the network for reliability reasons.
if (avoid_bitmap_fetching_for_test_) {
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
index 13a21f0..61ff02b 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
@@ -67,7 +67,7 @@
// Called when we dismiss a notification. This is virtual so that test
// subclasses can override it.
- virtual void MarkNotificationAsDismissed(const std::string& id);
+ virtual void MarkNotificationAsRead(const std::string& id);
// Called when a notier is enabled or disabled.
void OnSyncedNotificationServiceEnabled(
@@ -91,9 +91,15 @@
// Add a notification to our list. This takes ownership of the pointer.
void Add(scoped_ptr<notifier::SyncedNotification> notification);
+ // Display this notification in the notification center, or remove it.
+ void UpdateInMessageCenter(notifier::SyncedNotification* notification);
+
// Display a notification in the notification center (eventually).
void Display(notifier::SyncedNotification* notification);
+ // Remove a notification from our store.
+ void FreeNotificationById(const std::string& notification_id);
+
// Back pointer to the owning profile.
Profile* const profile_;
NotificationUIManager* const notification_manager_;
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc
index 17fe01f..5f5ced5 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc
@@ -310,6 +310,103 @@
// this test more robust.
}
+// Process sync changes when there is no local data.
+TEST_F(ChromeNotifierServiceTest, ProcessSyncChangesNonEmptyModel) {
+ StubNotificationUIManager notification_manager;
+ ChromeNotifierService notifier(NULL, ¬ification_manager);
+ notifier.set_avoid_bitmap_fetching_for_test(true);
+
+ // Create some local fake data.
+ scoped_ptr<SyncedNotification> n1(CreateNotification(
+ kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread));
+ notifier.AddForTest(n1.Pass());
+ scoped_ptr<SyncedNotification> n2(CreateNotification(
+ kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kUnread));
+ notifier.AddForTest(n2.Pass());
+ scoped_ptr<SyncedNotification> n3(CreateNotification(
+ kTitle3, kText3, kIconUrl3, kImageUrl3, kAppId3, kKey3, kUnread));
+ notifier.AddForTest(n3.Pass());
+
+ notifier.MergeDataAndStartSyncing(
+ SYNCED_NOTIFICATIONS,
+ SyncDataList(),
+ PassProcessor(),
+ scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
+
+ // Set up some ADDs, some UPDATES, and some DELETEs
+ SyncChangeList changes;
+ changes.push_back(CreateSyncChange(
+ SyncChange::ACTION_ADD, CreateNotification(
+ kTitle4, kText4, kIconUrl4, kImageUrl4, kAppId4, kKey4, kUnread)));
+ changes.push_back(CreateSyncChange(
+ SyncChange::ACTION_UPDATE, CreateNotification(
+ kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kRead)));
+ changes.push_back(CreateSyncChange(
+ SyncChange::ACTION_DELETE, CreateNotification(
+ kTitle3, kText3, kIconUrl3, kImageUrl3, kAppId3, kKey3, kDismissed)));
+
+ // Simulate incoming new notifications at runtime.
+ notifier.ProcessSyncChanges(FROM_HERE, changes);
+
+ // We should find notifications 1, 2, and 4, but not 3.
+ EXPECT_EQ(3U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
+ EXPECT_TRUE(notifier.FindNotificationById(kKey1));
+ EXPECT_TRUE(notifier.FindNotificationById(kKey2));
+ EXPECT_FALSE(notifier.FindNotificationById(kKey3));
+ EXPECT_TRUE(notifier.FindNotificationById(kKey4));
+}
+
+// Process sync changes that arrive before the change they are supposed to
+// modify.
+TEST_F(ChromeNotifierServiceTest, ProcessSyncChangesOutOfOrder) {
+ StubNotificationUIManager notification_manager;
+ ChromeNotifierService notifier(NULL, ¬ification_manager);
+ notifier.set_avoid_bitmap_fetching_for_test(true);
+
+ // Create some local fake data.
+ scoped_ptr<SyncedNotification> n1(CreateNotification(
+ kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread));
+ notifier.AddForTest(n1.Pass());
+ scoped_ptr<SyncedNotification> n2(CreateNotification(
+ kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kUnread));
+ notifier.AddForTest(n2.Pass());
+ scoped_ptr<SyncedNotification> n3(CreateNotification(
+ kTitle3, kText3, kIconUrl3, kImageUrl3, kAppId3, kKey3, kUnread));
+ notifier.AddForTest(n3.Pass());
+
+ notifier.MergeDataAndStartSyncing(
+ SYNCED_NOTIFICATIONS,
+ SyncDataList(),
+ PassProcessor(),
+ scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
+
+ SyncChangeList changes;
+ // UPDATE a notification we have not seen an add for.
+ changes.push_back(CreateSyncChange(
+ SyncChange::ACTION_UPDATE, CreateNotification(
+ kTitle4, kText4, kIconUrl4, kImageUrl4, kAppId4, kKey4, kUnread)));
+ // ADD a notification that we already have.
+ changes.push_back(CreateSyncChange(
+ SyncChange::ACTION_ADD, CreateNotification(
+ kTitle2, kText2, kIconUrl2, kImageUrl2, kAppId2, kKey2, kRead)));
+ // DELETE a notification we have not seen yet.
+ changes.push_back(CreateSyncChange(
+ SyncChange::ACTION_DELETE, CreateNotification(
+ kTitle5, kText5, kIconUrl5, kImageUrl5, kAppId5, kKey5, kDismissed)));
+
+ // Simulate incoming new notifications at runtime.
+ notifier.ProcessSyncChanges(FROM_HERE, changes);
+
+ // We should find notifications 1, 2, 3, and 4, but not 5.
+ EXPECT_EQ(4U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
+ EXPECT_TRUE(notifier.FindNotificationById(kKey1));
+ EXPECT_TRUE(notifier.FindNotificationById(kKey2));
+ EXPECT_TRUE(notifier.FindNotificationById(kKey3));
+ EXPECT_TRUE(notifier.FindNotificationById(kKey4));
+ EXPECT_FALSE(notifier.FindNotificationById(kKey5));
+}
+
+
// Model has some notifications, some of them are local only. Sync has some
// notifications. No items match up.
TEST_F(ChromeNotifierServiceTest, LocalRemoteBothNonEmptyNoOverlap) {
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification.cc b/chrome/browser/notifications/sync_notifier/synced_notification.cc
index 5c427ff..abffe93 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification.cc
+++ b/chrome/browser/notifications/sync_notifier/synced_notification.cc
@@ -191,7 +191,7 @@
if (SyncedNotification::kRead == GetReadState() ||
SyncedNotification::kDismissed == GetReadState() ) {
notification_manager->CancelById(GetKey());
- DVLOG(2) << "Dismissed notification arrived"
+ DVLOG(2) << "Dismissed or read notification arrived"
<< GetHeading() << " " << GetText();
return;
}
@@ -376,6 +376,19 @@
return false;
}
+void SyncedNotification::LogNotification() {
+ std::string readStateString("Unread");
+ if (SyncedNotification::kRead == GetReadState())
+ readStateString = "Read";
+ else if (SyncedNotification::kDismissed == GetReadState())
+ readStateString = "Dismissed";
+
+ DVLOG(2) << " Notification: Heading is " << GetHeading()
+ << " description is " << GetDescription()
+ << " key is " << GetKey()
+ << " read state is " << readStateString;
+}
+
// Set the read state on the notification, returns true for success.
void SyncedNotification::SetReadState(const ReadState& read_state) {
@@ -393,6 +406,10 @@
NOTREACHED();
}
+void SyncedNotification::NotificationHasBeenRead() {
+ SetReadState(kRead);
+}
+
void SyncedNotification::NotificationHasBeenDismissed() {
SetReadState(kDismissed);
}
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification.h b/chrome/browser/notifications/sync_notifier/synced_notification.h
index cba6863..0a6842d 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification.h
+++ b/chrome/browser/notifications/sync_notifier/synced_notification.h
@@ -79,6 +79,7 @@
bool EqualsIgnoringReadState(const SyncedNotification& other) const;
+ void NotificationHasBeenRead();
void NotificationHasBeenDismissed();
// Fill up the queue of bitmaps to fetch.
@@ -99,6 +100,9 @@
// of the sync data.
sync_pb::EntitySpecifics GetEntitySpecifics() const;
+ // Write a notification to the console log.
+ void LogNotification();
+
private:
// Helper function to mark a notification as read or dismissed.
void SetReadState(const ReadState& read_state);
diff --git a/chrome/browser/omnibox/omnibox_field_trial.cc b/chrome/browser/omnibox/omnibox_field_trial.cc
index 83b9143..ffd2f72 100644
--- a/chrome/browser/omnibox/omnibox_field_trial.cc
+++ b/chrome/browser/omnibox/omnibox_field_trial.cc
@@ -8,8 +8,11 @@
#include "base/metrics/field_trial.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "chrome/browser/autocomplete/autocomplete_input.h"
+#include "chrome/browser/search/search.h"
#include "chrome/common/metrics/metrics_util.h"
#include "chrome/common/metrics/variations/variation_ids.h"
#include "chrome/common/metrics/variations/variations_util.h"
@@ -21,11 +24,12 @@
const char kHUPCreateShorterMatchFieldTrialName[] =
"OmniboxHUPCreateShorterMatch";
const char kStopTimerFieldTrialName[] = "OmniboxStopTimer";
-const char kShortcutsScoringFieldTrialName[] = "OmniboxShortcutsScoring";
const char kBundledExperimentFieldTrialName[] = "OmniboxBundledExperimentV1";
// Rule names used by the bundled experiment.
+const char kShortcutsScoringMaxRelevanceRule[] = "ShortcutsScoringMaxRelevance";
const char kSearchHistoryRule[] = "SearchHistory";
+const char kDemoteByTypeRule[] = "DemoteByType";
// The autocomplete dynamic field trial name prefix. Each field trial is
// configured dynamically and is retrieved automatically by Chrome during
@@ -132,14 +136,9 @@
continue;
int types = 0;
if (!base::StringToInt(base::StringPiece(
- group_name.substr(strlen(kDisabledProviders))), &types)) {
- LOG(WARNING) << "Malformed DisabledProviders string: " << group_name;
+ group_name.substr(strlen(kDisabledProviders))), &types))
continue;
- }
- if (types == 0)
- LOG(WARNING) << "Expecting a non-zero bitmap; group = " << group_name;
- else
- provider_types |= types;
+ provider_types |= types;
}
return provider_types;
}
@@ -204,20 +203,18 @@
return false;
}
-// If the active group name starts with "MaxRelevance_", extract the
-// int that immediately following that, returning true on success.
-bool OmniboxFieldTrial::ShortcutsScoringMaxRelevance(int* max_relevance) {
- std::string group_name =
- base::FieldTrialList::FindFullName(kShortcutsScoringFieldTrialName);
- const char kMaxRelevanceGroupPrefix[] = "MaxRelevance_";
- if (!StartsWithASCII(group_name, kMaxRelevanceGroupPrefix, true))
+bool OmniboxFieldTrial::ShortcutsScoringMaxRelevance(
+ AutocompleteInput::PageClassification current_page_classification,
+ int* max_relevance) {
+ // The value of the rule is a string that encodes an integer containing
+ // the max relevance.
+ const std::string& max_relevance_str =
+ OmniboxFieldTrial::GetValueForRuleInContext(
+ kShortcutsScoringMaxRelevanceRule, current_page_classification);
+ if (max_relevance_str.empty())
return false;
- if (!base::StringToInt(base::StringPiece(
- group_name.substr(strlen(kMaxRelevanceGroupPrefix))),
- max_relevance)) {
- LOG(WARNING) << "Malformed MaxRelevance string: " << group_name;
+ if (!base::StringToInt(max_relevance_str, max_relevance))
return false;
- }
return true;
}
@@ -233,25 +230,67 @@
kSearchHistoryRule, current_page_classification) == "Disable";
}
+void OmniboxFieldTrial::GetDemotionsByType(
+ AutocompleteInput::PageClassification current_page_classification,
+ DemotionMultipliers* demotions_by_type) {
+ demotions_by_type->clear();
+ const std::string demotion_rule =
+ OmniboxFieldTrial::GetValueForRuleInContext(
+ kDemoteByTypeRule,
+ current_page_classification);
+ // The value of the DemoteByType rule is a comma-separated list of
+ // {ResultType + ":" + Number} where ResultType is an AutocompleteMatchType::
+ // Type enum represented as an integer and Number is an integer number
+ // between 0 and 100 inclusive. Relevance scores of matches of that result
+ // type are multiplied by Number / 100. 100 means no change.
+ base::StringPairs kv_pairs;
+ if (base::SplitStringIntoKeyValuePairs(demotion_rule, ':', ',', &kv_pairs)) {
+ for (base::StringPairs::const_iterator it = kv_pairs.begin();
+ it != kv_pairs.end(); ++it) {
+ // This is a best-effort conversion; we trust the hand-crafted parameters
+ // downloaded from the server to be perfect. There's no need for handle
+ // errors smartly.
+ int k, v;
+ base::StringToInt(it->first, &k);
+ base::StringToInt(it->second, &v);
+ (*demotions_by_type)[static_cast<AutocompleteMatchType::Type>(k)] =
+ static_cast<float>(v) / 100.0f;
+ }
+ }
+}
+
// Background and implementation details:
//
// Each experiment group in any field trial can come with an optional set of
// parameters (key-value pairs). In the bundled omnibox experiment
// (kBundledExperimentFieldTrialName), each experiment group comes with a
// list of parameters in the form:
-// key=<Rule>:<AutocompleteInput::PageClassification (as an int)>
+// key=<Rule>:
+// <AutocompleteInput::PageClassification (as an int)>:
+// <whether Instant Extended is enabled (as a 1 or 0)>
+// (note that there are no linebreaks in keys; this format is for
+// presentation only>
// value=<arbitrary string>
-// The AutocompleteInput::PageClassification can also be "*", which means
-// this rule applies in all page classification contexts.
+// Both the AutocompleteInput::PageClassification and the Instant Extended
+// entries can be "*", which means this rule applies for all values of the
+// matching portion of the context.
// One example parameter is
-// key=SearchHistory:6
+// key=SearchHistory:6:1
// value=PreventInlining
// This means in page classification context 6 (a search result page doing
-// search term replacement), the SearchHistory experiment should
-// PreventInlining.
+// search term replacement) with Instant Extended enabled, the SearchHistory
+// experiment should PreventInlining.
+//
+// When an exact match to the rule in the current context is missing, we
+// give preference to a wildcard rule that matches the instant extended
+// context over a wildcard rule that matches the page classification
+// context. Hopefully, though, users will write their field trial configs
+// so as not to rely on this fall back order.
//
// In short, this function tries to find the value associated with key
-// |rule|:|page_classification|, failing that it looks up |rule|:*,
+// |rule|:|page_classification|:|instant_extended|, failing that it looks up
+// |rule|:*:|instant_extended|, failing that it looks up
+// |rule|:|page_classification|:*, failing that it looks up |rule|:*:*,
// and failing that it returns the empty string.
std::string OmniboxFieldTrial::GetValueForRuleInContext(
const std::string& rule,
@@ -261,13 +300,24 @@
¶ms)) {
return std::string();
}
+ const std::string page_classification_str =
+ base::IntToString(static_cast<int>(page_classification));
+ const std::string instant_extended =
+ chrome::IsInstantExtendedAPIEnabled() ? "1" : "0";
// Look up rule in this exact context.
- std::map<std::string, std::string>::iterator it =
- params.find(rule + ":" + base::IntToString(
- static_cast<int>(page_classification)));
+ std::map<std::string, std::string>::iterator it = params.find(
+ rule + ":" + page_classification_str + ":" + instant_extended);
+ if (it != params.end())
+ return it->second;
+ // Fall back to the global page classification context.
+ it = params.find(rule + ":*:" + instant_extended);
+ if (it != params.end())
+ return it->second;
+ // Fall back to the global instant extended context.
+ it = params.find(rule + ":" + page_classification_str + ":*");
if (it != params.end())
return it->second;
// Look up rule in the global context.
- it = params.find(rule + ":*");
+ it = params.find(rule + ":*:*");
return (it != params.end()) ? it->second : std::string();
}
diff --git a/chrome/browser/omnibox/omnibox_field_trial.h b/chrome/browser/omnibox/omnibox_field_trial.h
index 1ad3b16..cde6259 100644
--- a/chrome/browser/omnibox/omnibox_field_trial.h
+++ b/chrome/browser/omnibox/omnibox_field_trial.h
@@ -5,16 +5,23 @@
#ifndef CHROME_BROWSER_OMNIBOX_OMNIBOX_FIELD_TRIAL_H_
#define CHROME_BROWSER_OMNIBOX_OMNIBOX_FIELD_TRIAL_H_
+#include <map>
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "chrome/browser/autocomplete/autocomplete_input.h"
+#include "chrome/common/autocomplete_match_type.h"
// This class manages the Omnibox field trials.
class OmniboxFieldTrial {
public:
+ // A mapping that contains multipliers indicating that matches of the
+ // specified type should have their relevance score multiplied by the
+ // given number. Omitted types are assumed to have multipliers of 1.0.
+ typedef std::map<AutocompleteMatchType::Type, float> DemotionMultipliers;
+
// Creates the static field trial groups.
// *** MUST NOT BE CALLED MORE THAN ONCE. ***
static void ActivateStaticTrials();
@@ -87,20 +94,22 @@
static bool InZeroSuggestFieldTrial();
// ---------------------------------------------------------
- // For the ShortcutsScoring field trial.
+ // For the ShortcutsScoringMaxRelevance experiment that's part of the
+ // bundled omnibox field trial.
- // If the field trial is active and the user is in an experiment
- // group, extract from the experiment group name the maximum
- // relevance score ShortcutsProvider:: CalculateScore() can return.
- // Returns true on a successful extraction. If the extraction failed,
- // if the field trial is not active, etc., returns false.
- // CalculateScore()'s return value is a product of this maximum
- // relevance score and some attenuating factors that are all between
- // 0 and 1. (Note that Shortcuts results may have their scores
- // reduced later if the assigned score is higher than allowed for
- // non-inlineable results. Shortcuts results are not allowed to be
+ // If the user is in an experiment group that, given the provided
+ // |current_page_classification| context, changes the maximum relevance
+ // ShortcutsProvider::CalculateScore() is supposed to assign, extract
+ // that maximum relevance score and put in in |max_relevance|. Returns
+ // true on a successful extraction. CalculateScore()'s return value is
+ // a product of this maximum relevance score and some attenuating factors
+ // that are all between 0 and 1. (Note that Shortcuts results may have
+ // their scores reduced later if the assigned score is higher than allowed
+ // for non-inlineable results. Shortcuts results are not allowed to be
// inlined.)
- static bool ShortcutsScoringMaxRelevance(int* max_relevance);
+ static bool ShortcutsScoringMaxRelevance(
+ AutocompleteInput::PageClassification current_page_classification,
+ int* max_relevance);
// ---------------------------------------------------------
// For the SearchHistory experiment that's part of the bundled omnibox
@@ -118,8 +127,20 @@
static bool SearchHistoryDisable(
AutocompleteInput::PageClassification current_page_classification);
+ // ---------------------------------------------------------
+ // For the DemoteByType experiment that's part of the bundled omnibox field
+ // trial.
+
+ // If the user is in an experiment group that, in the provided
+ // |current_page_classification| context, demotes the relevance scores
+ // of certain types of matches, populates the |demotions_by_type| map
+ // appropriately. Otherwise, clears |demotions_by_type|.
+ static void GetDemotionsByType(
+ AutocompleteInput::PageClassification current_page_classification,
+ DemotionMultipliers* demotions_by_type);
+
private:
- FRIEND_TEST_ALL_PREFIXES(OmniboxFieldTrialTest, GetValueForRuleInContext);
+ friend class OmniboxFieldTrialTest;
// The bundled omnibox experiment comes with a set of parameters
// (key-value pairs). Each key indicates a certain rule that applies in
@@ -129,14 +150,13 @@
// prevent search history matches from inlining.
//
// This function returns the value associated with the |rule| that applies
- // in the current context (which currently only consists of
- // |page_classification| but will soon contain other features, some not
- // passed in as parameters, such as whether Instant Extended is enabled).
- // If no such rule exists in the current context, looks for that rule in
- // the global context and return its value if found. If the rule remains
- // unfound in the global context, returns the empty string. For more
- // details, see the implementation. How to interpret the value is left
- // to the caller; this is rule-dependent.
+ // in the current context (which currently consists of |page_classification|
+ // and whether Instant Extended is enabled). If no such rule exists in the
+ // current context, fall back to the rule in various wildcard contexts and
+ // return its value if found. If the rule remains unfound in the global
+ // context, returns the empty string. For more details, including how we
+ // prioritize different wildcard contexts, see the implementation. How to
+ // interpret the value is left to the caller; this is rule-dependent.
static std::string GetValueForRuleInContext(
const std::string& rule,
AutocompleteInput::PageClassification page_classification);
diff --git a/chrome/browser/omnibox/omnibox_field_trial_unittest.cc b/chrome/browser/omnibox/omnibox_field_trial_unittest.cc
index 9ccb00f..22a5387 100644
--- a/chrome/browser/omnibox/omnibox_field_trial_unittest.cc
+++ b/chrome/browser/omnibox/omnibox_field_trial_unittest.cc
@@ -5,32 +5,30 @@
#include "chrome/browser/omnibox/omnibox_field_trial.h"
#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/memory/scoped_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/strings/string16.h"
+#include "chrome/browser/autocomplete/autocomplete_input.h"
+#include "chrome/browser/search/search.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/metrics/entropy_provider.h"
#include "chrome/common/metrics/variations/variations_util.h"
#include "testing/gtest/include/gtest/gtest.h"
class OmniboxFieldTrialTest : public testing::Test {
public:
- OmniboxFieldTrialTest() {}
-
- static void SetUpTestCase() {
+ OmniboxFieldTrialTest() {
ResetFieldTrialList();
}
- static void TearDownTestCase() {
- delete field_trial_list_;
- field_trial_list_ = NULL;
- }
-
- static void ResetFieldTrialList() {
- // It's important to delete the old pointer first which sets
- // FieldTrialList::global_ to NULL.
- if (field_trial_list_)
- delete field_trial_list_;
- field_trial_list_ = new base::FieldTrialList(
- new metrics::SHA1EntropyProvider("foo"));
+ void ResetFieldTrialList() {
+ // Destroy the existing FieldTrialList before creating a new one to avoid
+ // a DCHECK.
+ field_trial_list_.reset();
+ field_trial_list_.reset(new base::FieldTrialList(
+ new metrics::SHA1EntropyProvider("foo")));
+ chrome_variations::testing::ClearAllVariationParams();
OmniboxFieldTrial::ActivateDynamicTrials();
}
@@ -43,15 +41,45 @@
return trial;
}
+ // EXPECTS that demotions[match_type] exists with value expected_value.
+ static void VerifyDemotion(
+ const OmniboxFieldTrial::DemotionMultipliers& demotions,
+ AutocompleteMatchType::Type match_type,
+ float expected_value);
+
+ // EXPECT()s that OmniboxFieldTrial::GetValueForRuleInContext(|rule|,
+ // |page_classification|) returns |rule_value|.
+ static void ExpectRuleValue(
+ const std::string& rule_value,
+ const std::string& rule,
+ AutocompleteInput::PageClassification page_classification);
+
private:
- // Needed for Activate{Static/Dynamic}Trials().
- static base::FieldTrialList* field_trial_list_;
+ scoped_ptr<base::FieldTrialList> field_trial_list_;
DISALLOW_COPY_AND_ASSIGN(OmniboxFieldTrialTest);
};
// static
-base::FieldTrialList* OmniboxFieldTrialTest::field_trial_list_ = NULL;
+void OmniboxFieldTrialTest::VerifyDemotion(
+ const OmniboxFieldTrial::DemotionMultipliers& demotions,
+ AutocompleteMatchType::Type match_type,
+ float expected_value) {
+ OmniboxFieldTrial::DemotionMultipliers::const_iterator demotion_it =
+ demotions.find(match_type);
+ ASSERT_TRUE(demotion_it != demotions.end());
+ EXPECT_FLOAT_EQ(expected_value, demotion_it->second);
+}
+
+// static
+void OmniboxFieldTrialTest::ExpectRuleValue(
+ const std::string& rule_value,
+ const std::string& rule,
+ AutocompleteInput::PageClassification page_classification) {
+ EXPECT_EQ(rule_value,
+ OmniboxFieldTrial::GetValueForRuleInContext(
+ rule, page_classification));
+}
// Test if GetDisabledProviderTypes() properly parses various field trial
// group names.
@@ -131,20 +159,62 @@
}
}
+TEST_F(OmniboxFieldTrialTest, GetDemotionsByTypeWithFallback) {
+ // Must be the same as kBundledExperimentFieldTrialName
+ // defined in omnibox_field_trial.cc.
+ const std::string kTrialName = "OmniboxBundledExperimentV1";
+ // Must be the same as kDemoteByTypeRule defined in
+ // omnibox_field_trial.cc.
+ const std::string kRuleName = "DemoteByType";
+ {
+ std::map<std::string, std::string> params;
+ params[kRuleName + ":1:*"] = "1:50,2:0";
+ params[kRuleName + ":3:*"] = "5:100";
+ params[kRuleName + ":*:*"] = "1:25";
+ ASSERT_TRUE(chrome_variations::AssociateVariationParams(
+ kTrialName, "A", params));
+ }
+ base::FieldTrialList::CreateFieldTrial(kTrialName, "A");
+ OmniboxFieldTrial::DemotionMultipliers demotions_by_type;
+ OmniboxFieldTrial::GetDemotionsByType(
+ AutocompleteInput::NEW_TAB_PAGE, &demotions_by_type);
+ ASSERT_EQ(2u, demotions_by_type.size());
+ VerifyDemotion(demotions_by_type, AutocompleteMatchType::HISTORY_URL, 0.5);
+ VerifyDemotion(demotions_by_type, AutocompleteMatchType::HISTORY_TITLE, 0.0);
+ OmniboxFieldTrial::GetDemotionsByType(
+ AutocompleteInput::HOMEPAGE, &demotions_by_type);
+ ASSERT_EQ(1u, demotions_by_type.size());
+ VerifyDemotion(demotions_by_type, AutocompleteMatchType::NAVSUGGEST, 1.0);
+ OmniboxFieldTrial::GetDemotionsByType(
+ AutocompleteInput::BLANK, &demotions_by_type);
+ ASSERT_EQ(1u, demotions_by_type.size());
+ VerifyDemotion(demotions_by_type, AutocompleteMatchType::HISTORY_URL, 0.25);
+}
+
TEST_F(OmniboxFieldTrialTest, GetValueForRuleInContext) {
+ // This test starts with Instant Extended off (the default state), then
+ // enables Instant Extended and tests again on the same rules.
+
// Must be the same as kBundledExperimentFieldTrialName
// defined in omnibox_field_trial.cc.
const std::string kTrialName = "OmniboxBundledExperimentV1";
{
std::map<std::string, std::string> params;
- // Rule 1 has some exact matches and a global fallback.
- params["rule1:1"] = "rule1-1-value"; // NEW_TAB_PAGE
- params["rule1:3"] = "rule1-3-value"; // HOMEPAGE
- params["rule1:*"] = "rule1-*-value"; // global
- // Rule 2 has no exact matches but has a global fallback.
- params["rule2:*"] = "rule2-*-value"; // global
- // Rule 3 has an exact match but no global fallback.
- params["rule3:4"] = "rule3-4-value"; // OTHER
+ // Rule 1 has some exact matches and fallbacks at every level.
+ params["rule1:1:0"] = "rule1-1-0-value"; // NEW_TAB_PAGE
+ params["rule1:3:0"] = "rule1-3-0-value"; // HOMEPAGE
+ params["rule1:4:1"] = "rule1-4-1-value"; // OTHER
+ params["rule1:4:*"] = "rule1-4-*-value"; // OTHER
+ params["rule1:*:1"] = "rule1-*-1-value"; // global
+ params["rule1:*:*"] = "rule1-*-*-value"; // global
+ // Rule 2 has no exact matches but has fallbacks.
+ params["rule2:*:0"] = "rule2-*-0-value"; // global
+ params["rule2:1:*"] = "rule2-1-*-value"; // NEW_TAB_PAGE
+ params["rule2:*:*"] = "rule2-*-*-value"; // global
+ // Rule 3 has only a global fallback.
+ params["rule3:*:*"] = "rule3-*-*-value"; // global
+ // Rule 4 has an exact match but no fallbacks.
+ params["rule4:4:0"] = "rule4-4-0-value"; // OTHER
// Add a malformed rule to make sure it doesn't screw things up.
params["unrecognized"] = "unrecognized-value";
ASSERT_TRUE(chrome_variations::AssociateVariationParams(
@@ -153,51 +223,84 @@
base::FieldTrialList::CreateFieldTrial(kTrialName, "A");
+ // Tests with Instant Extended disabled.
// Tests for rule 1.
- EXPECT_EQ(
- "rule1-1-value",
- OmniboxFieldTrial::GetValueForRuleInContext(
- "rule1", AutocompleteInput::NEW_TAB_PAGE)); // exact match
- EXPECT_EQ(
- "rule1-*-value",
- OmniboxFieldTrial::GetValueForRuleInContext(
- "rule1", AutocompleteInput::BLANK)); // fallback to global
- EXPECT_EQ(
- "rule1-3-value",
- OmniboxFieldTrial::GetValueForRuleInContext(
- "rule1", AutocompleteInput::HOMEPAGE)); // exact match
- EXPECT_EQ(
- "rule1-*-value",
- OmniboxFieldTrial::GetValueForRuleInContext(
- "rule1", AutocompleteInput::OTHER)); // fallback to global
-
+ ExpectRuleValue("rule1-1-0-value",
+ "rule1", AutocompleteInput::NEW_TAB_PAGE); // exact match
+ ExpectRuleValue("rule1-1-0-value",
+ "rule1", AutocompleteInput::NEW_TAB_PAGE); // exact match
+ ExpectRuleValue("rule1-*-*-value",
+ "rule1", AutocompleteInput::BLANK); // fallback to global
+ ExpectRuleValue("rule1-3-0-value",
+ "rule1", AutocompleteInput::HOMEPAGE); // exact match
+ ExpectRuleValue("rule1-4-*-value",
+ "rule1", AutocompleteInput::OTHER); // partial fallback
+ ExpectRuleValue("rule1-*-*-value",
+ "rule1",
+ AutocompleteInput:: // fallback to global
+ SEARCH_RESULT_PAGE_DOING_SEARCH_TERM_REPLACEMENT);
// Tests for rule 2.
- EXPECT_EQ(
- "rule2-*-value",
- OmniboxFieldTrial::GetValueForRuleInContext(
- "rule2", AutocompleteInput::HOMEPAGE)); // fallback to global
- EXPECT_EQ(
- "rule2-*-value",
- OmniboxFieldTrial::GetValueForRuleInContext(
- "rule2", AutocompleteInput::OTHER)); // fallback to global
+ ExpectRuleValue("rule2-*-0-value",
+ "rule2", AutocompleteInput::HOMEPAGE); // partial fallback
+ ExpectRuleValue("rule2-*-0-value",
+ "rule2", AutocompleteInput::OTHER); // partial fallback
// Tests for rule 3.
- EXPECT_EQ(
- "",
- OmniboxFieldTrial::GetValueForRuleInContext(
- "rule3", AutocompleteInput::BLANK)); // no global fallback
- EXPECT_EQ(
- "",
- OmniboxFieldTrial::GetValueForRuleInContext(
- "rule3", AutocompleteInput::HOMEPAGE)); // no global fallback
- EXPECT_EQ(
- "rule3-4-value",
- OmniboxFieldTrial::GetValueForRuleInContext(
- "rule3", AutocompleteInput::OTHER)); // exact match
+ ExpectRuleValue("rule3-*-*-value",
+ "rule3", AutocompleteInput::HOMEPAGE); // fallback to global
+ ExpectRuleValue("rule3-*-*-value",
+ "rule3", AutocompleteInput::OTHER); // fallback to global
- // Tests for rule 4 (a missing rule).
- EXPECT_EQ(
- "",
- OmniboxFieldTrial::GetValueForRuleInContext(
- "rule4", AutocompleteInput::OTHER)); // no rule at all
+ // Tests for rule 4.
+ ExpectRuleValue("",
+ "rule4", AutocompleteInput::BLANK); // no global fallback
+ ExpectRuleValue("",
+ "rule4", AutocompleteInput::HOMEPAGE); // no global fallback
+ ExpectRuleValue("rule4-4-0-value",
+ "rule4", AutocompleteInput::OTHER); // exact match
+
+ // Tests for rule 5 (a missing rule).
+ ExpectRuleValue("",
+ "rule5", AutocompleteInput::OTHER); // no rule at all
+
+ // Now change the Instant Extended state and run analogous tests.
+ // Instant Extended only works on non-mobile platforms.
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+ chrome::ResetInstantExtendedOptInStateGateForTest();
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableInstantExtendedAPI);
+
+ // Tests with Instant Extended enabled.
+ // Tests for rule 1.
+ ExpectRuleValue("rule1-4-1-value",
+ "rule1", AutocompleteInput::OTHER); // exact match
+ ExpectRuleValue("rule1-*-1-value",
+ "rule1", AutocompleteInput::BLANK); // partial fallback
+ ExpectRuleValue("rule1-*-1-value",
+ "rule1",
+ AutocompleteInput::NEW_TAB_PAGE); // partial fallback
+
+ // Tests for rule 2.
+ ExpectRuleValue("rule2-1-*-value",
+ "rule2",
+ AutocompleteInput::NEW_TAB_PAGE); // partial fallback
+ ExpectRuleValue("rule2-*-*-value",
+ "rule2", AutocompleteInput::OTHER); // global fallback
+
+ // Tests for rule 3.
+ ExpectRuleValue("rule3-*-*-value",
+ "rule3", AutocompleteInput::HOMEPAGE); // global fallback
+ ExpectRuleValue("rule3-*-*-value",
+ "rule3", AutocompleteInput::OTHER); // global fallback
+
+ // Tests for rule 4.
+ ExpectRuleValue("",
+ "rule4", AutocompleteInput::BLANK); // no global fallback
+ ExpectRuleValue("",
+ "rule4", AutocompleteInput::HOMEPAGE); // no global fallback
+
+ // Tests for rule 5 (a missing rule).
+ ExpectRuleValue("",
+ "rule5", AutocompleteInput::OTHER); // no rule at all
+#endif // !defined(OS_IOS) && !defined(OS_ANDROID)
}
diff --git a/chrome/browser/pepper_flash_settings_manager.cc b/chrome/browser/pepper_flash_settings_manager.cc
index 243ea84..4061463 100644
--- a/chrome/browser/pepper_flash_settings_manager.cc
+++ b/chrome/browser/pepper_flash_settings_manager.cc
@@ -29,7 +29,6 @@
#include "ipc/ipc_listener.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "url/gurl.h"
-#include "webkit/plugins/plugin_constants.h"
using content::BrowserThread;
@@ -955,7 +954,7 @@
content::PluginService::GetInstance();
std::vector<content::WebPluginInfo> plugins;
plugin_service->GetPluginInfoArray(
- GURL(), kFlashPluginSwfMimeType, false, &plugins, NULL);
+ GURL(), content::kFlashPluginSwfMimeType, false, &plugins, NULL);
for (std::vector<content::WebPluginInfo>::iterator iter = plugins.begin();
iter != plugins.end(); ++iter) {
diff --git a/chrome/browser/plugins/plugin_installer.cc b/chrome/browser/plugins/plugin_installer.cc
index 69864ad..099711e 100644
--- a/chrome/browser/plugins/plugin_installer.cc
+++ b/chrome/browser/plugins/plugin_installer.cc
@@ -10,7 +10,7 @@
#include "base/strings/stringprintf.h"
#include "chrome/browser/download/download_service.h"
#include "chrome/browser/download/download_service_factory.h"
-#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/download_stats.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/plugins/plugin_installer_observer.h"
#include "chrome/browser/profiles/profile.h"
@@ -136,8 +136,7 @@
FOR_EACH_OBSERVER(PluginInstallerObserver, observers_, DownloadStarted());
Profile* profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext());
- download_util::RecordDownloadSource(
- download_util::INITIATED_BY_PLUGIN_INSTALLER);
+ RecordDownloadSource(DOWNLOAD_INITIATED_BY_PLUGIN_INSTALLER);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&BeginDownload,
diff --git a/chrome/browser/policy/browser_policy_connector.cc b/chrome/browser/policy/browser_policy_connector.cc
index 5d15e06..022c2e2 100644
--- a/chrome/browser/policy/browser_policy_connector.cc
+++ b/chrome/browser/policy/browser_policy_connector.cc
@@ -152,7 +152,7 @@
scoped_refptr<net::URLRequestContextGetter> request_context) {
// Initialization of some of the providers requires the FILE thread; make
// sure that threading is ready at this point.
- DCHECK(BrowserThread::IsWellKnownThread(BrowserThread::FILE));
+ DCHECK(BrowserThread::IsThreadInitialized(BrowserThread::FILE));
DCHECK(!is_initialized()) << "BrowserPolicyConnector::Init() called twice.";
local_state_ = local_state;
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index c45b476..65bb42f 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -94,6 +94,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_constants.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/page_transition_types.h"
#include "content/public/common/process_type.h"
@@ -120,7 +121,6 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "url/gurl.h"
-#include "webkit/plugins/plugin_constants.h"
#if defined(OS_CHROMEOS)
#include "ash/accelerators/accelerator_controller.h"
@@ -358,7 +358,7 @@
const std::vector<content::WebPluginInfo>& plugins) {
const content::WebPluginInfo* flash = NULL;
for (size_t i = 0; i < plugins.size(); ++i) {
- if (plugins[i].name == ASCIIToUTF16(kFlashPluginName)) {
+ if (plugins[i].name == ASCIIToUTF16(content::kFlashPluginName)) {
flash = &plugins[i];
break;
}
@@ -564,7 +564,7 @@
base::FilePath extension_path(ui_test_utils::GetTestFilePath(
base::FilePath(kTestExtensionsDir), base::FilePath(name)));
scoped_refptr<extensions::CrxInstaller> installer =
- extensions::CrxInstaller::Create(extension_service(), NULL);
+ extensions::CrxInstaller::CreateSilent(extension_service());
installer->set_allow_silent_install(true);
installer->set_install_cause(extension_misc::INSTALL_CAUSE_UPDATE);
installer->set_creation_flags(extensions::Extension::FROM_WEBSTORE);
@@ -1143,7 +1143,7 @@
EXPECT_TRUE(SetPluginEnabled(plugin_prefs, flash, false));
EXPECT_FALSE(plugin_prefs->IsPluginEnabled(*flash));
base::ListValue plugin_list;
- plugin_list.Append(base::Value::CreateStringValue(kFlashPluginName));
+ plugin_list.Append(base::Value::CreateStringValue(content::kFlashPluginName));
PolicyMap policies;
policies.Set(key::kEnabledPlugins, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, plugin_list.DeepCopy(), NULL);
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index f954807..948ba02 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -71,8 +71,6 @@
#include "chrome/browser/translate/translate_prefs.h"
#include "chrome/browser/ui/alternate_error_tab_observer.h"
#include "chrome/browser/ui/app_list/app_list_service.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h"
-#include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h"
#include "chrome/browser/ui/browser_ui_prefs.h"
#include "chrome/browser/ui/network_profile_bubble.h"
#include "chrome/browser/ui/prefs/prefs_tab_helper.h"
@@ -95,6 +93,10 @@
#include "components/user_prefs/pref_registry_syncable.h"
#include "content/public/browser/render_process_host.h"
+#if defined(ENABLE_AUTOFILL_DIALOG)
+#include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
+#endif
+
#if defined(ENABLE_CONFIGURATION_POLICY)
#include "chrome/browser/policy/browser_policy_connector.h"
#include "chrome/browser/policy/policy_statistics_collector.h"
@@ -153,6 +155,8 @@
#if defined(OS_ANDROID)
#include "chrome/browser/ui/webui/ntp/android/promo_handler.h"
+#else
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
#endif
#if defined(ENABLE_PLUGIN_INSTALLATION)
@@ -287,9 +291,10 @@
// User prefs. Please keep this list alphabetized.
AlternateErrorPageTabObserver::RegisterProfilePrefs(registry);
apps::RegisterProfilePrefs(registry);
- autofill::AutofillCreditCardBubbleController::RegisterUserPrefs(registry);
- autofill::AutofillDialogControllerImpl::RegisterProfilePrefs(registry);
autofill::AutofillManager::RegisterProfilePrefs(registry);
+#if !defined(OS_ANDROID)
+ autofill::GeneratedCreditCardBubbleController::RegisterUserPrefs(registry);
+#endif
BookmarkPromptPrefs::RegisterProfilePrefs(registry);
bookmark_utils::RegisterProfilePrefs(registry);
browser_sync::SyncPrefs::RegisterProfilePrefs(registry);
@@ -321,6 +326,10 @@
TemplateURLPrepopulateData::RegisterProfilePrefs(registry);
TranslatePrefs::RegisterProfilePrefs(registry);
+#if defined(ENABLE_AUTOFILL_DIALOG)
+ autofill::AutofillDialogController::RegisterProfilePrefs(registry);
+#endif
+
#if defined(ENABLE_CONFIGURATION_POLICY)
policy::URLBlacklistManager::RegisterProfilePrefs(registry);
#endif
diff --git a/chrome/browser/prefs/pref_metrics_service.cc b/chrome/browser/prefs/pref_metrics_service.cc
index bcac818..a437c8c 100644
--- a/chrome/browser/prefs/pref_metrics_service.cc
+++ b/chrome/browser/prefs/pref_metrics_service.cc
@@ -4,17 +4,39 @@
#include "chrome/browser/prefs/pref_metrics_service.h"
+#include "base/bind.h"
#include "base/metrics/histogram.h"
#include "base/prefs/pref_service.h"
+#include "chrome/browser/prefs/pref_service_syncable.h"
#include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/prefs/synced_pref_change_registrar.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+
+namespace {
+
+// Converts a host name into a domain name for easier matching.
+std::string GetDomainFromHost(const std::string& host) {
+ return net::registry_controlled_domains::GetDomainAndRegistry(
+ host,
+ net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
+}
+
+const int kSessionStartupPrefValueMax = SessionStartupPref::kPrefValueMax;
+
+} // namespace
PrefMetricsService::PrefMetricsService(Profile* profile)
: profile_(profile) {
RecordLaunchPrefs();
+
+ PrefServiceSyncable* prefs = PrefServiceSyncable::FromProfile(profile_);
+ synced_pref_change_registrar_.reset(new SyncedPrefChangeRegistrar(prefs));
+
+ RegisterSyncedPrefObservers();
}
PrefMetricsService::~PrefMetricsService() {
@@ -31,7 +53,7 @@
}
int restore_on_startup = prefs->GetInteger(prefs::kRestoreOnStartup);
UMA_HISTOGRAM_ENUMERATION("Settings.StartupPageLoadSettings",
- restore_on_startup, SessionStartupPref::kPrefValueMax);
+ restore_on_startup, kSessionStartupPrefValueMax);
if (restore_on_startup == SessionStartupPref::kPrefValueURLs) {
const int url_list_size = prefs->GetList(
prefs::kURLsToRestoreOnStartup)->GetSize();
@@ -40,6 +62,83 @@
}
}
+void PrefMetricsService::RegisterSyncedPrefObservers() {
+ LogHistogramValueCallback booleanHandler = base::Bind(
+ &PrefMetricsService::LogBooleanPrefChange, base::Unretained(this));
+
+ AddPrefObserver(prefs::kShowHomeButton, "ShowHomeButton", booleanHandler);
+ AddPrefObserver(prefs::kHomePageIsNewTabPage, "HomePageIsNewTabPage",
+ booleanHandler);
+
+ AddPrefObserver(prefs::kRestoreOnStartup, "StartupPageLoadSettings",
+ base::Bind(&PrefMetricsService::LogIntegerPrefChange,
+ base::Unretained(this),
+ kSessionStartupPrefValueMax));
+}
+
+void PrefMetricsService::AddPrefObserver(
+ const std::string& path,
+ const std::string& histogram_name_prefix,
+ const LogHistogramValueCallback& callback) {
+ synced_pref_change_registrar_->Add(path.c_str(),
+ base::Bind(&PrefMetricsService::OnPrefChanged,
+ base::Unretained(this),
+ histogram_name_prefix, callback));
+}
+
+void PrefMetricsService::OnPrefChanged(
+ const std::string& histogram_name_prefix,
+ const LogHistogramValueCallback& callback,
+ const std::string& path,
+ bool from_sync) {
+ PrefServiceSyncable* prefs = PrefServiceSyncable::FromProfile(profile_);
+ const PrefService::Preference* pref = prefs->FindPreference(path.c_str());
+ DCHECK(pref);
+ std::string source_name(
+ from_sync ? ".PulledFromSync" : ".PushedToSync");
+ std::string histogram_name("Settings." + histogram_name_prefix + source_name);
+ callback.Run(histogram_name, pref->GetValue());
+};
+
+void PrefMetricsService::LogBooleanPrefChange(const std::string& histogram_name,
+ const Value* value) {
+ bool boolean_value = false;
+ if (!value->GetAsBoolean(&boolean_value))
+ return;
+ base::HistogramBase* histogram = base::BooleanHistogram::FactoryGet(
+ histogram_name, base::HistogramBase::kUmaTargetedHistogramFlag);
+ histogram->Add(boolean_value);
+}
+
+void PrefMetricsService::LogIntegerPrefChange(int boundary_value,
+ const std::string& histogram_name,
+ const Value* value) {
+ int integer_value = 0;
+ if (!value->GetAsInteger(&integer_value))
+ return;
+ base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
+ histogram_name,
+ 1,
+ boundary_value,
+ boundary_value + 1,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ histogram->Add(integer_value);
+}
+
+void PrefMetricsService::LogListPrefChange(
+ const LogHistogramValueCallback& item_callback,
+ const std::string& histogram_name,
+ const Value* value) {
+ const ListValue* items = NULL;
+ if (!value->GetAsList(&items))
+ return;
+ for (size_t i = 0; i < items->GetSize(); ++i) {
+ const Value *item_value = NULL;
+ if (items->Get(i, &item_value))
+ item_callback.Run(histogram_name, item_value);
+ }
+}
+
// static
PrefMetricsService::Factory* PrefMetricsService::Factory::GetInstance() {
return Singleton<PrefMetricsService::Factory>::get();
diff --git a/chrome/browser/prefs/pref_metrics_service.h b/chrome/browser/prefs/pref_metrics_service.h
index 647cd94..fc48935 100644
--- a/chrome/browser/prefs/pref_metrics_service.h
+++ b/chrome/browser/prefs/pref_metrics_service.h
@@ -5,7 +5,12 @@
#ifndef CHROME_BROWSER_PREFS_PREF_METRICS_SERVICE_H_
#define CHROME_BROWSER_PREFS_PREF_METRICS_SERVICE_H_
+#include <map>
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
+#include "chrome/browser/prefs/synced_pref_change_registrar.h"
#include "chrome/browser/profiles/profile.h"
#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
@@ -34,11 +39,51 @@
virtual content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* context) const OVERRIDE;
};
+
private:
+ // Use a map to convert domains to their histogram identifiers. Ids are
+ // defined in tools/metrics/histograms/histograms.xml and (usually) also in
+ // chrome/browser/search_engines/prepopulated_engines.json.
+ typedef std::map<std::string, int> DomainIdMap;
+
+ // Function to log a Value to a histogram
+ typedef base::Callback<void(const std::string&, const Value*)>
+ LogHistogramValueCallback;
+
// Record prefs state on browser context creation.
void RecordLaunchPrefs();
+ // Register callbacks for synced pref changes.
+ void RegisterSyncedPrefObservers();
+
+ // Registers a histogram logging callback for a synced pref change.
+ void AddPrefObserver(const std::string& path,
+ const std::string& histogram_name_prefix,
+ const LogHistogramValueCallback& callback);
+
+ // Generic callback to observe a synced pref change.
+ void OnPrefChanged(const std::string& histogram_name_prefix,
+ const LogHistogramValueCallback& callback,
+ const std::string& path,
+ bool from_sync);
+
+ // Callback for a boolean pref change histogram.
+ void LogBooleanPrefChange(const std::string& histogram_name,
+ const Value* value);
+
+ // Callback for an integer pref change histogram.
+ void LogIntegerPrefChange(int boundary_value,
+ const std::string& histogram_name,
+ const Value* value);
+
+ // Callback for a list pref change. Each item in the list
+ // is logged using the given histogram callback.
+ void LogListPrefChange(const LogHistogramValueCallback& item_callback,
+ const std::string& histogram_name,
+ const Value* value);
+
Profile* profile_;
+ scoped_ptr<SyncedPrefChangeRegistrar> synced_pref_change_registrar_;
};
#endif // CHROME_BROWSER_PREFS_PREF_METRICS_SERVICE_H_
diff --git a/chrome/browser/prefs/pref_model_associator.cc b/chrome/browser/prefs/pref_model_associator.cc
index 42cd194..28759a1 100644
--- a/chrome/browser/prefs/pref_model_associator.cc
+++ b/chrome/browser/prefs/pref_model_associator.cc
@@ -10,6 +10,7 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/prefs/pref_service.h"
+#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
@@ -61,6 +62,10 @@
PrefModelAssociator::~PrefModelAssociator() {
DCHECK(CalledOnValidThread());
pref_service_ = NULL;
+
+ STLDeleteContainerPairSecondPointers(synced_pref_observers_.begin(),
+ synced_pref_observers_.end());
+ synced_pref_observers_.clear();
}
void PrefModelAssociator::InitPrefAndAssociate(
@@ -395,6 +400,8 @@
// policy controlled.
pref_service_->Set(pref_name, *value);
+ NotifySyncedPrefObservers(name, true /*from_sync*/);
+
// Keep track of any newly synced preferences.
if (iter->change_type() == syncer::SyncChange::ACTION_ADD) {
synced_preferences_.insert(name);
@@ -422,6 +429,26 @@
return synced_preferences_.find(name) != synced_preferences_.end();
}
+void PrefModelAssociator::AddSyncedPrefObserver(const std::string& name,
+ SyncedPrefObserver* observer) {
+ SyncedPrefObserverList* observers = synced_pref_observers_[name];
+ if (observers == NULL) {
+ observers = new SyncedPrefObserverList;
+ synced_pref_observers_[name] = observers;
+ }
+ observers->AddObserver(observer);
+}
+
+void PrefModelAssociator::RemoveSyncedPrefObserver(const std::string& name,
+ SyncedPrefObserver* observer) {
+ SyncedPrefObserverMap::iterator observer_iter =
+ synced_pref_observers_.find(name);
+ if (observer_iter == synced_pref_observers_.end())
+ return;
+ SyncedPrefObserverList* observers = observer_iter->second;
+ observers->RemoveObserver(observer);
+}
+
std::set<std::string> PrefModelAssociator::registered_preferences() const {
return registered_preferences_;
}
@@ -463,6 +490,8 @@
base::AutoReset<bool> processing_changes(&processing_syncer_changes_, true);
+ NotifySyncedPrefObservers(name, false /*from_sync*/);
+
if (synced_preferences_.count(name) == 0) {
// Not in synced_preferences_ means no synced data. InitPrefAndAssociate(..)
// will determine if we care about its data (e.g. if it has a default value
@@ -489,3 +518,14 @@
DCHECK(pref_service_ == NULL);
pref_service_ = pref_service;
}
+
+void PrefModelAssociator::NotifySyncedPrefObservers(const std::string& path,
+ bool from_sync) const {
+ SyncedPrefObserverMap::const_iterator observer_iter =
+ synced_pref_observers_.find(path);
+ if (observer_iter == synced_pref_observers_.end())
+ return;
+ SyncedPrefObserverList* observers = observer_iter->second;
+ FOR_EACH_OBSERVER(SyncedPrefObserver, *observers,
+ OnSyncedPrefChanged(path, from_sync));
+}
diff --git a/chrome/browser/prefs/pref_model_associator.h b/chrome/browser/prefs/pref_model_associator.h
index 584e271..539d38a 100644
--- a/chrome/browser/prefs/pref_model_associator.h
+++ b/chrome/browser/prefs/pref_model_associator.h
@@ -11,7 +11,10 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "base/containers/hash_tables.h"
+#include "base/observer_list.h"
#include "base/threading/non_thread_safe.h"
+#include "chrome/browser/prefs/synced_pref_observer.h"
#include "sync/api/sync_data.h"
#include "sync/api/syncable_service.h"
@@ -97,6 +100,14 @@
// Note this does not refer to SYNCABLE_PREF.
bool IsPrefSynced(const std::string& name) const;
+ // Adds a SyncedPrefObserver to watch for changes to a specific pref.
+ void AddSyncedPrefObserver(const std::string& name,
+ SyncedPrefObserver* observer);
+
+ // Removes a SyncedPrefObserver from a pref's list of observers.
+ void RemoveSyncedPrefObserver(const std::string& name,
+ SyncedPrefObserver* observer);
+
protected:
friend class ProfileSyncServicePreferenceTest;
@@ -157,6 +168,18 @@
// PRIORITY_PREFERENCES.
syncer::ModelType type_;
+ private:
+ // Map prefs to lists of observers. Observers will receive notification when
+ // a pref changes, including the detail of whether or not the change came
+ // from sync.
+ typedef ObserverList<SyncedPrefObserver> SyncedPrefObserverList;
+ typedef base::hash_map<std::string, SyncedPrefObserverList*>
+ SyncedPrefObserverMap;
+
+ void NotifySyncedPrefObservers(const std::string& path, bool from_sync) const;
+
+ SyncedPrefObserverMap synced_pref_observers_;
+
DISALLOW_COPY_AND_ASSIGN(PrefModelAssociator);
};
diff --git a/chrome/browser/prefs/pref_service_syncable.cc b/chrome/browser/prefs/pref_service_syncable.cc
index 0a4a455..58d040b 100644
--- a/chrome/browser/prefs/pref_service_syncable.cc
+++ b/chrome/browser/prefs/pref_service_syncable.cc
@@ -147,6 +147,20 @@
PrefService::UpdateCommandLinePrefStore(cmd_line_store);
}
+void PrefServiceSyncable::AddSyncedPrefObserver(
+ const std::string& name,
+ SyncedPrefObserver* observer) {
+ pref_sync_associator_.AddSyncedPrefObserver(name, observer);
+ priority_pref_sync_associator_.AddSyncedPrefObserver(name, observer);
+}
+
+void PrefServiceSyncable::RemoveSyncedPrefObserver(
+ const std::string& name,
+ SyncedPrefObserver* observer) {
+ pref_sync_associator_.RemoveSyncedPrefObserver(name, observer);
+ priority_pref_sync_associator_.RemoveSyncedPrefObserver(name, observer);
+}
+
void PrefServiceSyncable::AddRegisteredSyncablePreference(
const char* path,
const user_prefs::PrefRegistrySyncable::PrefSyncStatus sync_status) {
diff --git a/chrome/browser/prefs/pref_service_syncable.h b/chrome/browser/prefs/pref_service_syncable.h
index 4f4715e..b8390f1 100644
--- a/chrome/browser/prefs/pref_service_syncable.h
+++ b/chrome/browser/prefs/pref_service_syncable.h
@@ -7,6 +7,7 @@
#include "base/prefs/pref_service.h"
#include "chrome/browser/prefs/pref_model_associator.h"
+#include "chrome/browser/prefs/synced_pref_observer.h"
#include "components/user_prefs/pref_registry_syncable.h"
class PrefServiceSyncableObserver;
@@ -80,6 +81,11 @@
// Do not call this after having derived an incognito or per tab pref service.
virtual void UpdateCommandLinePrefStore(PrefStore* cmd_line_store) OVERRIDE;
+ void AddSyncedPrefObserver(const std::string& name,
+ SyncedPrefObserver* observer);
+ void RemoveSyncedPrefObserver(const std::string& name,
+ SyncedPrefObserver* observer);
+
private:
friend class PrefModelAssociator;
diff --git a/chrome/browser/prefs/synced_pref_change_registrar.cc b/chrome/browser/prefs/synced_pref_change_registrar.cc
new file mode 100644
index 0000000..1438d21
--- /dev/null
+++ b/chrome/browser/prefs/synced_pref_change_registrar.cc
@@ -0,0 +1,66 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/synced_pref_change_registrar.h"
+
+#include "base/bind.h"
+
+namespace {
+
+void InvokeUnnamedCallback(
+ const SyncedPrefChangeRegistrar::ChangeCallback& callback,
+ const std::string& path,
+ bool from_sync) {
+ callback.Run(from_sync);
+}
+
+} // namespace
+
+SyncedPrefChangeRegistrar::SyncedPrefChangeRegistrar(
+ PrefServiceSyncable* pref_service) {
+ pref_service_ = pref_service;
+}
+
+SyncedPrefChangeRegistrar::~SyncedPrefChangeRegistrar() {
+ RemoveAll();
+}
+
+void SyncedPrefChangeRegistrar::Add(const char *path,
+ const ChangeCallback& callback) {
+ Add(path, base::Bind(InvokeUnnamedCallback, callback));
+}
+
+void SyncedPrefChangeRegistrar::Add(const char *path,
+ const NamedChangeCallback& callback) {
+ DCHECK(!IsObserved(path));
+ observers_[path] = callback;
+ pref_service_->AddSyncedPrefObserver(path, this);
+}
+
+void SyncedPrefChangeRegistrar::Remove(const char *path) {
+ observers_.erase(path);
+ pref_service_->RemoveSyncedPrefObserver(path, this);
+}
+
+void SyncedPrefChangeRegistrar::RemoveAll() {
+ for (ObserverMap::iterator iter = observers_.begin();
+ iter != observers_.end(); ++iter) {
+ pref_service_->RemoveSyncedPrefObserver(iter->first, this);
+ }
+ observers_.clear();
+}
+
+bool SyncedPrefChangeRegistrar::IsObserved(const char* path) const {
+ return observers_.find(path) != observers_.end();
+}
+
+void SyncedPrefChangeRegistrar::OnSyncedPrefChanged(const std::string& path,
+ bool from_sync) {
+ if (pref_service_->IsManagedPreference(path.c_str()))
+ return;
+ ObserverMap::const_iterator iter = observers_.find(path);
+ if (iter == observers_.end())
+ return;
+ iter->second.Run(path, from_sync);
+}
diff --git a/chrome/browser/prefs/synced_pref_change_registrar.h b/chrome/browser/prefs/synced_pref_change_registrar.h
new file mode 100644
index 0000000..7cadd0a
--- /dev/null
+++ b/chrome/browser/prefs/synced_pref_change_registrar.h
@@ -0,0 +1,57 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_SYNCED_PREF_CHANGE_REGISTRAR_H_
+#define CHROME_BROWSER_PREFS_SYNCED_PREF_CHANGE_REGISTRAR_H_
+
+#include <map>
+#include <string>
+
+#include "base/callback.h"
+#include "chrome/browser/prefs/pref_service_syncable.h"
+#include "chrome/browser/prefs/synced_pref_observer.h"
+
+// Manages the registration of one or more SyncedPrefObservers on a
+// PrefServiceSyncable. This is modeled after base::PrefChangeRegistrar, and
+// it should be used whenever it's necessary to determine whether a pref change
+// has come from sync or from some other mechanism (managed, UI, external, etc.)
+class SyncedPrefChangeRegistrar : public SyncedPrefObserver {
+ public:
+ // Registered callbacks may optionally take a path argument.
+ // The boolean argument indicates whether (true) or not (false)
+ // the change was a result of syncing.
+ typedef base::Callback<void(bool)> ChangeCallback;
+ typedef base::Callback<void(const std::string&, bool)> NamedChangeCallback;
+
+ explicit SyncedPrefChangeRegistrar(PrefServiceSyncable* pref_service);
+ virtual ~SyncedPrefChangeRegistrar();
+
+ // Register an observer callback for sync change events on the pref at
+ // |path|. Only one callback may be registered per pref.
+ void Add(const char* path, const ChangeCallback& callback);
+ void Add(const char* path, const NamedChangeCallback& callback);
+
+ // Remove the registered observer for |path|.
+ void Remove(const char* path);
+
+ // Remove all registered observers.
+ void RemoveAll();
+
+ // Indicates whether or not an observer is already registered for |path|.
+ bool IsObserved(const char* path) const;
+
+ private:
+ // SyncedPrefObserver implementation
+ virtual void OnSyncedPrefChanged(const std::string& path, bool from_sync)
+ OVERRIDE;
+
+ typedef std::map<std::string, NamedChangeCallback> ObserverMap;
+
+ PrefServiceSyncable* pref_service_;
+ ObserverMap observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyncedPrefChangeRegistrar);
+};
+
+#endif // CHROME_BROWSER_PREFS_SYNCED_PREF_CHANGE_REGISTRAR_H_
diff --git a/chrome/browser/prefs/synced_pref_change_registrar_browsertest.cc b/chrome/browser/prefs/synced_pref_change_registrar_browsertest.cc
new file mode 100644
index 0000000..1dde6a8
--- /dev/null
+++ b/chrome/browser/prefs/synced_pref_change_registrar_browsertest.cc
@@ -0,0 +1,216 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/json/json_string_value_serializer.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
+#include "chrome/browser/policy/mock_configuration_policy_provider.h"
+#include "chrome/browser/policy/policy_map.h"
+#include "chrome/browser/prefs/synced_pref_change_registrar.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/testing_pref_service_syncable.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_utils.h"
+#include "policy/policy_constants.h"
+#include "sync/api/sync_change.h"
+#include "sync/api/sync_error_factory.h"
+#include "sync/api/sync_error_factory_mock.h"
+#include "sync/api/syncable_service.h"
+#include "sync/protocol/sync.pb.h"
+
+namespace {
+
+using testing::AnyNumber;
+using testing::Return;
+using testing::_;
+
+class TestSyncProcessorStub : public syncer::SyncChangeProcessor {
+ virtual syncer::SyncError ProcessSyncChanges(
+ const tracked_objects::Location& from_here,
+ const syncer::SyncChangeList& change_list) OVERRIDE {
+ return syncer::SyncError();
+ }
+};
+
+class SyncedPrefChangeRegistrarTest : public InProcessBrowserTest {
+ public:
+ SyncedPrefChangeRegistrarTest() : next_sync_data_id_(0) {}
+ virtual ~SyncedPrefChangeRegistrarTest() {}
+
+ void UpdateChromePolicy(const policy::PolicyMap& policies) {
+ policy_provider_.UpdateChromePolicy(policies);
+ DCHECK(base::MessageLoop::current());
+ base::RunLoop loop;
+ loop.RunUntilIdle();
+ }
+
+ void SetBooleanPrefValueFromSync(const std::string& name, bool value) {
+ std::string serialized_value;
+ JSONStringValueSerializer json(&serialized_value);
+ json.Serialize(base::FundamentalValue(value));
+
+ sync_pb::EntitySpecifics specifics;
+ sync_pb::PreferenceSpecifics* pref_specifics =
+ specifics.mutable_preference();
+ pref_specifics->set_name(name);
+ pref_specifics->set_value(serialized_value);
+
+ syncer::SyncData change_data = syncer::SyncData::CreateRemoteData(
+ ++next_sync_data_id_, specifics, base::Time());
+ syncer::SyncChange change(
+ FROM_HERE, syncer::SyncChange::ACTION_UPDATE, change_data);
+
+ syncer::SyncChangeList change_list;
+ change_list.push_back(change);
+
+ syncer_->ProcessSyncChanges(FROM_HERE, change_list);
+ }
+
+ void SetBooleanPrefValueFromLocal(const std::string& name, bool value) {
+ prefs_->SetBoolean(name.c_str(), value);
+ }
+
+ bool GetBooleanPrefValue(const std::string& name) {
+ return prefs_->GetBoolean(name.c_str());
+ }
+
+ PrefServiceSyncable* prefs() const {
+ return prefs_;
+ }
+
+ SyncedPrefChangeRegistrar* registrar() const {
+ return registrar_.get();
+ }
+
+ private:
+ virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+ EXPECT_CALL(policy_provider_, IsInitializationComplete(_))
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(policy_provider_, RegisterPolicyDomain(_)).Times(AnyNumber());
+ policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
+ &policy_provider_);
+ }
+
+ virtual void SetUpOnMainThread() OVERRIDE {
+ prefs_ = PrefServiceSyncable::FromProfile(browser()->profile());
+ syncer_ = prefs_->GetSyncableService(syncer::PREFERENCES);
+ syncer_->MergeDataAndStartSyncing(
+ syncer::PREFERENCES,
+ syncer::SyncDataList(),
+ scoped_ptr<syncer::SyncChangeProcessor>(new TestSyncProcessorStub),
+ scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock));
+ registrar_.reset(new SyncedPrefChangeRegistrar(prefs_));
+ }
+
+ virtual void CleanUpOnMainThread() OVERRIDE {
+ registrar_.reset();
+ }
+
+ PrefServiceSyncable* prefs_;
+ syncer::SyncableService* syncer_;
+ int next_sync_data_id_;
+
+ scoped_ptr<SyncedPrefChangeRegistrar> registrar_;
+ policy::MockConfigurationPolicyProvider policy_provider_;
+};
+
+struct TestSyncedPrefObserver {
+ bool last_seen_value;
+ bool last_update_is_from_sync;
+ bool has_been_notified;
+};
+
+void TestPrefChangeCallback(PrefService* prefs,
+ TestSyncedPrefObserver* observer,
+ const std::string& path,
+ bool from_sync) {
+ observer->last_seen_value = prefs->GetBoolean(path.c_str());
+ observer->last_update_is_from_sync = from_sync;
+ observer->has_been_notified = true;
+}
+
+} // namespace
+
+IN_PROC_BROWSER_TEST_F(SyncedPrefChangeRegistrarTest,
+ DifferentiateRemoteAndLocalChanges) {
+ TestSyncedPrefObserver observer = {};
+ registrar()->Add(prefs::kShowHomeButton,
+ base::Bind(&TestPrefChangeCallback, prefs(), &observer));
+
+ EXPECT_FALSE(observer.has_been_notified);
+
+ SetBooleanPrefValueFromSync(prefs::kShowHomeButton, true);
+ EXPECT_TRUE(observer.has_been_notified);
+ EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton));
+ EXPECT_TRUE(observer.last_update_is_from_sync);
+ EXPECT_TRUE(observer.last_seen_value);
+
+ observer.has_been_notified = false;
+ SetBooleanPrefValueFromLocal(prefs::kShowHomeButton, false);
+ EXPECT_TRUE(observer.has_been_notified);
+ EXPECT_FALSE(GetBooleanPrefValue(prefs::kShowHomeButton));
+ EXPECT_FALSE(observer.last_update_is_from_sync);
+ EXPECT_FALSE(observer.last_seen_value);
+
+ observer.has_been_notified = false;
+ SetBooleanPrefValueFromLocal(prefs::kShowHomeButton, true);
+ EXPECT_TRUE(observer.has_been_notified);
+ EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton));
+ EXPECT_FALSE(observer.last_update_is_from_sync);
+ EXPECT_TRUE(observer.last_seen_value);
+
+ observer.has_been_notified = false;
+ SetBooleanPrefValueFromSync(prefs::kShowHomeButton, false);
+ EXPECT_TRUE(observer.has_been_notified);
+ EXPECT_FALSE(GetBooleanPrefValue(prefs::kShowHomeButton));
+ EXPECT_TRUE(observer.last_update_is_from_sync);
+ EXPECT_FALSE(observer.last_seen_value);
+}
+
+IN_PROC_BROWSER_TEST_F(SyncedPrefChangeRegistrarTest,
+ IgnoreLocalChangesToManagedPrefs) {
+ TestSyncedPrefObserver observer = {};
+ registrar()->Add(prefs::kShowHomeButton,
+ base::Bind(&TestPrefChangeCallback, prefs(), &observer));
+
+ policy::PolicyMap policies;
+ policies.Set(policy::key::kShowHomeButton,
+ policy::POLICY_LEVEL_MANDATORY,
+ policy::POLICY_SCOPE_USER,
+ base::Value::CreateBooleanValue(true),
+ NULL);
+ UpdateChromePolicy(policies);
+
+ EXPECT_TRUE(prefs()->IsManagedPreference(prefs::kShowHomeButton));
+
+ SetBooleanPrefValueFromLocal(prefs::kShowHomeButton, false);
+ EXPECT_FALSE(observer.has_been_notified);
+ EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton));
+}
+
+IN_PROC_BROWSER_TEST_F(SyncedPrefChangeRegistrarTest,
+ IgnoreSyncChangesToManagedPrefs) {
+ TestSyncedPrefObserver observer = {};
+ registrar()->Add(prefs::kShowHomeButton,
+ base::Bind(&TestPrefChangeCallback, prefs(), &observer));
+
+ policy::PolicyMap policies;
+ policies.Set(policy::key::kShowHomeButton,
+ policy::POLICY_LEVEL_MANDATORY,
+ policy::POLICY_SCOPE_USER,
+ base::Value::CreateBooleanValue(true),
+ NULL);
+ UpdateChromePolicy(policies);
+
+ EXPECT_TRUE(prefs()->IsManagedPreference(prefs::kShowHomeButton));
+ SetBooleanPrefValueFromSync(prefs::kShowHomeButton, false);
+ EXPECT_FALSE(observer.has_been_notified);
+ EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton));
+}
diff --git a/chrome/browser/prefs/synced_pref_observer.h b/chrome/browser/prefs/synced_pref_observer.h
new file mode 100644
index 0000000..332e588
--- /dev/null
+++ b/chrome/browser/prefs/synced_pref_observer.h
@@ -0,0 +1,15 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_SYNCED_PREF_OBSERVER_H_
+#define CHROME_BROWSER_PREFS_SYNCED_PREF_OBSERVER_H_
+
+#include <string>
+
+class SyncedPrefObserver {
+ public:
+ virtual void OnSyncedPrefChanged(const std::string& path, bool from_sync) = 0;
+};
+
+#endif // CHROME_BROWSER_PREFS_SYNCED_PREF_OBSERVER_H_
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index e075cc1..7405e51 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -2475,7 +2475,8 @@
// Checks that when the cache is cleared, prerenders are cancelled but
// prerendering history is not cleared.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClearCache) {
+// Flaky/times out on linux_aura, win, mac - http://crbug.com/270948
+IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DISABLED_PrerenderClearCache) {
PrerenderTestURL("files/prerender/prerender_page.html",
FINAL_STATUS_CACHE_OR_HISTORY_CLEARED,
1);
diff --git a/chrome/browser/profile_resetter/profile_resetter_unittest.cc b/chrome/browser/profile_resetter/profile_resetter_unittest.cc
index 8a4993e..62cd06b 100644
--- a/chrome/browser/profile_resetter/profile_resetter_unittest.cc
+++ b/chrome/browser/profile_resetter/profile_resetter_unittest.cc
@@ -26,6 +26,7 @@
#include "chrome/common/pref_names.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/test/test_browser_thread.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/test_url_fetcher_factory.h"
@@ -695,39 +696,46 @@
ResettableSettingsSnapshot empty_snap(profile());
EXPECT_EQ(0, empty_snap.FindDifferentFields(empty_snap));
+ scoped_refptr<Extension> ext = CreateExtension(
+ "example",
+ base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
+ Manifest::INVALID_LOCATION,
+ extensions::Manifest::TYPE_EXTENSION,
+ false);
+ ASSERT_TRUE(ext);
+ service_->AddExtension(ext.get());
+
+ std::string master_prefs(kDistributionConfig);
+ std::string ext_id = ext->id();
+ ReplaceString(&master_prefs, "placeholder_for_id", ext_id);
+
// Reset to non organic defaults.
ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
ProfileResetter::HOMEPAGE |
- ProfileResetter::STARTUP_PAGES, kDistributionConfig);
+ ProfileResetter::STARTUP_PAGES, master_prefs);
ResettableSettingsSnapshot nonorganic_snap(profile());
- EXPECT_EQ(ResettableSettingsSnapshot::STARTUP_URLS |
- ResettableSettingsSnapshot::STARTUP_TYPE |
- ResettableSettingsSnapshot::HOMEPAGE |
- ResettableSettingsSnapshot::HOMEPAGE_IS_NTP |
- ResettableSettingsSnapshot::DSE_URL,
+ EXPECT_EQ(ResettableSettingsSnapshot::ALL_FIELDS,
empty_snap.FindDifferentFields(nonorganic_snap));
- empty_snap.SubtractStartupURLs(nonorganic_snap);
+ empty_snap.Subtract(nonorganic_snap);
EXPECT_TRUE(empty_snap.startup_urls().empty());
EXPECT_EQ(SessionStartupPref::GetDefaultStartupType(),
empty_snap.startup_type());
EXPECT_TRUE(empty_snap.homepage().empty());
EXPECT_TRUE(empty_snap.homepage_is_ntp());
EXPECT_NE(std::string::npos, empty_snap.dse_url().find("{google:baseURL}"));
+ EXPECT_EQ(std::vector<std::string>(), empty_snap.enabled_extensions());
// Reset to organic defaults.
ResetAndWait(ProfileResetter::DEFAULT_SEARCH_ENGINE |
ProfileResetter::HOMEPAGE |
- ProfileResetter::STARTUP_PAGES);
+ ProfileResetter::STARTUP_PAGES |
+ ProfileResetter::EXTENSIONS);
ResettableSettingsSnapshot organic_snap(profile());
- EXPECT_EQ(ResettableSettingsSnapshot::STARTUP_URLS |
- ResettableSettingsSnapshot::STARTUP_TYPE |
- ResettableSettingsSnapshot::HOMEPAGE |
- ResettableSettingsSnapshot::HOMEPAGE_IS_NTP |
- ResettableSettingsSnapshot::DSE_URL,
+ EXPECT_EQ(ResettableSettingsSnapshot::ALL_FIELDS,
nonorganic_snap.FindDifferentFields(organic_snap));
- nonorganic_snap.SubtractStartupURLs(organic_snap);
+ nonorganic_snap.Subtract(organic_snap);
const GURL urls[] = {GURL("http://foo.de"), GURL("http://goo.gl")};
EXPECT_EQ(std::vector<GURL>(urls, urls + arraysize(urls)),
nonorganic_snap.startup_urls());
@@ -735,6 +743,8 @@
EXPECT_EQ("http://www.foo.com", nonorganic_snap.homepage());
EXPECT_FALSE(nonorganic_snap.homepage_is_ntp());
EXPECT_EQ("http://www.foo.com/s?q={searchTerms}", nonorganic_snap.dse_url());
+ EXPECT_EQ(std::vector<std::string>(1, ext_id),
+ nonorganic_snap.enabled_extensions());
}
TEST_F(ProfileResetterTest, FeedbackSerializtionTest) {
@@ -743,9 +753,18 @@
ProfileResetter::HOMEPAGE |
ProfileResetter::STARTUP_PAGES, kDistributionConfig);
+ scoped_refptr<Extension> ext = CreateExtension(
+ "example",
+ base::FilePath(FILE_PATH_LITERAL("//nonexistent")),
+ Manifest::INVALID_LOCATION,
+ extensions::Manifest::TYPE_EXTENSION,
+ false);
+ ASSERT_TRUE(ext);
+ service_->AddExtension(ext.get());
+
const ResettableSettingsSnapshot nonorganic_snap(profile());
- COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 31,
+ COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 63,
expand_this_test);
for (int field_mask = 0; field_mask <= ResettableSettingsSnapshot::ALL_FIELDS;
++field_mask) {
@@ -764,6 +783,7 @@
std::string homepage;
bool homepage_is_ntp = true;
std::string default_search_engine;
+ ListValue* extensions;
EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::STARTUP_URLS),
dict->GetList("startup_urls", &startup_urls));
@@ -775,6 +795,8 @@
dict->GetBoolean("homepage_is_ntp", &homepage_is_ntp));
EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::DSE_URL),
dict->GetString("default_search_engine", &default_search_engine));
+ EXPECT_EQ(!!(field_mask & ResettableSettingsSnapshot::EXTENSIONS),
+ dict->GetList("enabled_extensions", &extensions));
}
}
diff --git a/chrome/browser/profile_resetter/resettable_settings_snapshot.cc b/chrome/browser/profile_resetter/resettable_settings_snapshot.cc
index f6892ba..0542727 100644
--- a/chrome/browser/profile_resetter/resettable_settings_snapshot.cc
+++ b/chrome/browser/profile_resetter/resettable_settings_snapshot.cc
@@ -6,6 +6,7 @@
#include "base/json/json_writer.h"
#include "base/prefs/pref_service.h"
+#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/feedback/feedback_data.h"
#include "chrome/browser/feedback/feedback_util.h"
#include "chrome/browser/profiles/profile.h"
@@ -20,6 +21,7 @@
// Dictionary keys for feedback report.
const char kDefaultSearchEnginePath[] = "default_search_engine";
+const char kEnabledExtensions[] = "enabled_extensions";
const char kHomepageIsNewTabPage[] = "homepage_is_ntp";
const char kHomepagePath[] = "homepage";
const char kStartupTypePath[] = "startup_type";
@@ -43,11 +45,23 @@
TemplateURL* dse = service->GetDefaultSearchProvider();
if (dse)
dse_url_ = dse->url();
+
+ ExtensionService* extension_service = profile->GetExtensionService();
+ DCHECK(extension_service);
+ const ExtensionSet* enabled_ext = extension_service->extensions();
+ enabled_extensions_.reserve(enabled_ext->size());
+
+ for (ExtensionSet::const_iterator it = enabled_ext->begin();
+ it != enabled_ext->end(); ++it)
+ enabled_extensions_.push_back((*it)->id());
+
+ // ExtensionSet is sorted but it seems to be an implementation detail.
+ std::sort(enabled_extensions_.begin(), enabled_extensions_.end());
}
ResettableSettingsSnapshot::~ResettableSettingsSnapshot() {}
-void ResettableSettingsSnapshot::SubtractStartupURLs(
+void ResettableSettingsSnapshot::Subtract(
const ResettableSettingsSnapshot& snapshot) {
std::vector<GURL> urls;
std::set_difference(startup_.urls.begin(), startup_.urls.end(),
@@ -55,6 +69,13 @@
snapshot.startup_.urls.end(),
std::back_inserter(urls));
startup_.urls.swap(urls);
+
+ std::vector<std::string> extensions;
+ std::set_difference(enabled_extensions_.begin(), enabled_extensions_.end(),
+ snapshot.enabled_extensions_.begin(),
+ snapshot.enabled_extensions_.end(),
+ std::back_inserter(extensions));
+ enabled_extensions_.swap(extensions);
}
int ResettableSettingsSnapshot::FindDifferentFields(
@@ -77,7 +98,10 @@
if (dse_url_ != snapshot.dse_url_)
bit_mask |= DSE_URL;
- COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 31,
+ if (enabled_extensions_ != snapshot.enabled_extensions_)
+ bit_mask |= EXTENSIONS;
+
+ COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 63,
add_new_field_here);
return bit_mask;
@@ -108,7 +132,16 @@
if (field_mask & ResettableSettingsSnapshot::DSE_URL)
dict.SetString(kDefaultSearchEnginePath, snapshot.dse_url());
- COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 31,
+ if (field_mask & ResettableSettingsSnapshot::EXTENSIONS) {
+ ListValue* list = new ListValue;
+ const std::vector<std::string>& extensions = snapshot.enabled_extensions();
+ for (std::vector<std::string>::const_iterator i = extensions.begin();
+ i != extensions.end(); ++i)
+ list->AppendString(*i);
+ dict.Set(kEnabledExtensions, list);
+ }
+
+ COMPILE_ASSERT(ResettableSettingsSnapshot::ALL_FIELDS == 63,
serialize_new_field_here);
std::string json;
diff --git a/chrome/browser/profile_resetter/resettable_settings_snapshot.h b/chrome/browser/profile_resetter/resettable_settings_snapshot.h
index 93aaf48..9fcf1cb 100644
--- a/chrome/browser/profile_resetter/resettable_settings_snapshot.h
+++ b/chrome/browser/profile_resetter/resettable_settings_snapshot.h
@@ -19,9 +19,10 @@
HOMEPAGE = 1 << 2,
HOMEPAGE_IS_NTP = 1 << 3,
DSE_URL = 1 << 4,
+ EXTENSIONS = 1 << 5,
ALL_FIELDS = STARTUP_URLS | STARTUP_TYPE | HOMEPAGE |
- HOMEPAGE_IS_NTP | DSE_URL,
+ HOMEPAGE_IS_NTP | DSE_URL | EXTENSIONS,
};
explicit ResettableSettingsSnapshot(Profile* profile);
@@ -38,8 +39,14 @@
const std::string& dse_url() const { return dse_url_; }
+ const std::vector<std::string>& enabled_extensions() const {
+ return enabled_extensions_;
+ }
+
// Substitutes |startup_.urls| with |startup_.urls|\|snapshot.startup_.urls|.
- void SubtractStartupURLs(const ResettableSettingsSnapshot& snapshot);
+ // Substitutes |enabled_extensions_| with
+ // |enabled_extensions_|\|snapshot.enabled_extensions_|.
+ void Subtract(const ResettableSettingsSnapshot& snapshot);
// For each member 'm' compares |this->m| with |snapshot.m| and sets the
// corresponding |ResetableSettingsSnapshot::Field| bit to 1 in case of
@@ -58,6 +65,9 @@
// Default search engine.
std::string dse_url_;
+ // Enabled extension ids. Always sorted.
+ std::vector<std::string> enabled_extensions_;
+
DISALLOW_COPY_AND_ASSIGN(ResettableSettingsSnapshot);
};
diff --git a/chrome/browser/profiles/profile_shortcut_manager_win.cc b/chrome/browser/profiles/profile_shortcut_manager_win.cc
index 9a0d9ed..48e862b 100644
--- a/chrome/browser/profiles/profile_shortcut_manager_win.cc
+++ b/chrome/browser/profiles/profile_shortcut_manager_win.cc
@@ -765,8 +765,8 @@
CreateOrUpdateMode create_mode,
NonProfileShortcutAction action,
const base::Closure& callback) {
- DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
- BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
+ BrowserThread::CurrentlyOn(BrowserThread::UI));
CreateOrUpdateShortcutsParams params(profile_path, create_mode, action);
ProfileInfoCache* cache = &profile_manager_->GetProfileInfoCache();
diff --git a/chrome/browser/resources/chromeos/connectivity_diagnostics/OWNERS b/chrome/browser/resources/chromeos/connectivity_diagnostics/OWNERS
new file mode 100644
index 0000000..b03ccb6
--- /dev/null
+++ b/chrome/browser/resources/chromeos/connectivity_diagnostics/OWNERS
@@ -0,0 +1,4 @@
+dpolukhin@chromium.org
+ebeach@chromium.org
+xiaowenx@chromium.org
+zork@chromium.org
diff --git a/chrome/browser/resources/chromeos/connectivity_diagnostics/manifest.json b/chrome/browser/resources/chromeos/connectivity_diagnostics/manifest.json
index f1368d8..38a5d74 100644
--- a/chrome/browser/resources/chromeos/connectivity_diagnostics/manifest.json
+++ b/chrome/browser/resources/chromeos/connectivity_diagnostics/manifest.json
@@ -1,8 +1,8 @@
{
"key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGJWLUb83WKoDeODlrPIZu60M8bzbvrkg3Jf/5aO3ux2FL+G+/BO4Vyt/J0t8lXBtnTOvHo6KPpA042PyE9xMdlufFnJqEkvPXNzRlBWeVQqFHbMWE6o/x8diG69dNmHyFYcUjjFFDk2X2GOLQXNUGJQ6MIikbdzoWdLGttmhAIwIDAQAB",
"manifest_version": 2,
- "name": "Chrome Connectivity Debugger (Dev)",
- "version": "0.2.8",
+ "name": "Connectivity Diagnostics",
+ "version": "0.5.2",
"minimum_chrome_version": "27",
"offline_enabled": true,
"default_locale": "en",
@@ -21,12 +21,15 @@
]},
"clipboardWrite",
"experimental",
+ "networkingPrivate",
"http://*.google.com/*",
- "http://www.yahoo.com/*"
+ "https://*.google.com/*"
],
"app": {
"background": {
"scripts": ["background.js"]
}
- }
+ },
+ "display_in_launcher": false,
+ "display_in_new_tab_page": false
}
diff --git a/chrome/browser/resources/chromeos/drive_internals.html b/chrome/browser/resources/chromeos/drive_internals.html
index b704782..6b25ee5 100644
--- a/chrome/browser/resources/chromeos/drive_internals.html
+++ b/chrome/browser/resources/chromeos/drive_internals.html
@@ -11,14 +11,6 @@
<h1>Drive Internals</h1>
<ul id='toc'></ul>
- <h2 id='drive-related-flags-section'>Drive related Flags</h2>
- <ul id='drive-related-flags'>
- </ul>
-
- <h2 id='drive-related-preferences-section'>Drive related Preferences</h2>
- <ul id='drive-related-preferences'>
- </ul>
-
<h2 id='authentication-status-section'>Authentication Status</h2>
<ul>
<li>
@@ -33,33 +25,21 @@
<h2 id='account-information-section'>Account Information</h2>
<ul>
- <li>Quota Information: <span id='account-quota-info'></span></li>
- <li>Largest Changestamp (remote):
+ <li>Remote Changestamp:
<span id='account-largest-changestamp-remote'></span>
</li>
+ <li>Quota Information: <span id='account-quota-info'></span></li>
<li>Root Resource Id: <span id='root-resource-id'></span></li>
</ul>
- <h2 id='app-list-section'>Application List</h2>
- <ul>
- <li>ETag: <span id='app-list-etag'></span></li>
- </ul>
- <table>
- <tbody id='app-list-items'>
- <tr>
- <th>App Name</th>
- <th>App ID</th>
- <th>Object Type</th>
- <th>Support Create</th>
- </tr>
- </tbody>
- </table>
-
<h2 id='local-metadata-section'>Local Metadata</h2>
<ul>
- <li>Largest Changestamp (local):
+ <li>Local Changestamp:
<span id='account-largest-changestamp-local'></span>
</li>
+ <li>Local Free Space:
+ <span id='local-storage-freespace'></span> MB
+ </li>
</ul>
<h2 id='delta-update-status-section'>Delta Update Status</h2>
@@ -85,6 +65,10 @@
</tbody>
</table>
+ <h2 id='file-system-contents-section'>File System Contents</h2>
+ <button id='button-show-file-entries'>Show</button>
+ <div id='file-system-contents'></div>
+
<h2 id='gcache-contents-section'>GCache Contents</h2>
<table>
<tbody id='gcache-contents'>
@@ -100,14 +84,10 @@
<ul>
<li>
Total Size:
- <span id='gcache-summary-total-size'>(calculating...)</span> bytes.
+ <span id='gcache-summary-total-size'>(calculating...)</span> MB.
</li>
</ul>
- <h2 id='file-system-contents-section'>File System Contents</h2>
- <button id='button-show-file-entries'>Show</button>
- <div id='file-system-contents'></div>
-
<h2 id='cache-contents-section'>Cache Contents</h2>
<table>
<tbody id='cache-contents'>
@@ -117,14 +97,32 @@
<th>Present</th>
<th>Pinned</th>
<th>Dirty</th>
- <th>Mounted</th>
- <th>Persistent</th>
</tr>
</tbody>
</table>
- <h2 id='local-storage-usage-section'>Local Storage Usage</h2>
- <div>Free space: <span id='local-storage-freespace'></span> MB</div>
+ <h2 id='drive-related-flags-section'>Drive related Flags</h2>
+ <ul id='drive-related-flags'>
+ </ul>
+
+ <h2 id='drive-related-preferences-section'>Drive related Preferences</h2>
+ <ul id='drive-related-preferences'>
+ </ul>
+
+ <h2 id='app-list-section'>Application List</h2>
+ <ul>
+ <li>ETag: <span id='app-list-etag'></span></li>
+ </ul>
+ <table>
+ <tbody id='app-list-items'>
+ <tr>
+ <th>App Name</th>
+ <th>App ID</th>
+ <th>Object Type</th>
+ <th>Support Create</th>
+ </tr>
+ </tbody>
+ </table>
<h2 id='event-log-section'>Event Log</h2>
<ul id='event-log'>
diff --git a/chrome/browser/resources/chromeos/drive_internals.js b/chrome/browser/resources/chromeos/drive_internals.js
index bb5b9e9..46c2fee 100644
--- a/chrome/browser/resources/chromeos/drive_internals.js
+++ b/chrome/browser/resources/chromeos/drive_internals.js
@@ -3,6 +3,20 @@
// found in the LICENSE file.
/**
+ * Converts a number in bytes to a string in megabytes split by comma into
+ * three digit block.
+ * @param {number} bytes The number in bytes.
+ * @return {string} Formatted string in megabytes.
+ */
+function ToMegaByteString(bytes) {
+ var mb = Math.floor(bytes / (1 << 20));
+ return mb.toString().replace(
+ /\d+?(?=(\d{3})+$)/g, // Digit sequence (\d+) followed (?=) by 3n digits.
+ function(three_digit_block) { return three_digit_block + ','; }
+ );
+}
+
+/**
* Updates the Drive related Flags section.
* @param {Array} flags List of dictionaries describing flags.
*/
@@ -55,7 +69,8 @@
tbody.appendChild(tr);
}
- $('gcache-summary-total-size').textContent = gcacheSummary['total_size'];
+ $('gcache-summary-total-size').textContent =
+ ToMegaByteString(gcacheSummary['total_size']);
}
/**
@@ -91,7 +106,7 @@
* stogage.
*/
function updateLocalStorageUsage(localStorageSummary) {
- var freeSpaceInMB = localStorageSummary.free_space / (1 << 20);
+ var freeSpaceInMB = ToMegaByteString(localStorageSummary.free_space);
$('local-storage-freespace').innerText = freeSpaceInMB;
}
@@ -123,8 +138,8 @@
tr.appendChild(createElementFromText('td', operation.state));
var progress = operation.progress_current + '/' + operation.progress_total;
if (operation.progress_total > 0) {
- progress += ' (' +
- (operation.progress_current / operation.progress_total * 100) + '%)';
+ var percent = operation.progress_current / operation.progress_total * 100;
+ progress += ' (' + Math.round(percent) + '%)';
}
tr.appendChild(createElementFromText('td', progress));
@@ -137,8 +152,8 @@
* @param {Object} aboutResource Dictionary describing about resource.
*/
function updateAboutResource(aboutResource) {
- var quotaTotalInMb = aboutResource['account-quota-total'] / (1 << 20);
- var quotaUsedInMb = aboutResource['account-quota-used'] / (1 << 20);
+ var quotaTotalInMb = ToMegaByteString(aboutResource['account-quota-total']);
+ var quotaUsedInMb = ToMegaByteString(aboutResource['account-quota-used']);
$('account-quota-info').textContent =
quotaUsedInMb + ' / ' + quotaTotalInMb + ' (MB)';
diff --git a/chrome/browser/resources/chromeos/login/demo_user_login.js b/chrome/browser/resources/chromeos/login/demo_user_login.js
index 22ce544..1fefc23 100644
--- a/chrome/browser/resources/chromeos/login/demo_user_login.js
+++ b/chrome/browser/resources/chromeos/login/demo_user_login.js
@@ -24,7 +24,6 @@
initialize = function() {
$('page').style.opacity = 1;
document.addEventListener('click', onClick);
- chrome.send('demoWebuiReady');
// Report back sign in UI being painted.
window.webkitRequestAnimationFrame(function() {
chrome.send('loginVisible', ['demo']);
diff --git a/chrome/browser/resources/chromeos/login/display_manager.js b/chrome/browser/resources/chromeos/login/display_manager.js
index 9ddeee2..85c97b1 100644
--- a/chrome/browser/resources/chromeos/login/display_manager.js
+++ b/chrome/browser/resources/chromeos/login/display_manager.js
@@ -57,6 +57,36 @@
var Bubble = cr.ui.Bubble;
/**
+ * Maximum time in milliseconds to wait for step transition to finish.
+ * The value is used as the duration for ensureTransitionEndEvent below.
+ * It needs to be inline with the step screen transition duration time
+ * defined in css file. The current value in css is 200ms. To avoid emulated
+ * webkitTransitionEnd fired before real one, 250ms is used.
+ * @const
+ */
+ var MAX_SCREEN_TRANSITION_DURATION = 250;
+
+ /**
+ * webkitTransitionEnd does not always fire (e.g. when animation is aborted
+ * or when no paint happens during the animation). This function sets up
+ * a timer and emulate the event if it is not fired when the timer expires.
+ * @param {!HTMLElement} el The element to watch for webkitTransitionEnd.
+ * @param {number} timeOut The maximum wait time in milliseconds for the
+ * webkitTransitionEnd to happen.
+ */
+ function ensureTransitionEndEvent(el, timeOut) {
+ var fired = false;
+ el.addEventListener('webkitTransitionEnd', function f(e) {
+ el.removeEventListener('webkitTransitionEnd', f);
+ fired = true;
+ });
+ window.setTimeout(function() {
+ if (!fired)
+ cr.dispatchSimpleEvent(el, 'webkitTransitionEnd');
+ }, timeOut);
+ }
+
+ /**
* Groups of screens (screen IDs) that should have the same dimensions.
* @type Array.<Array.<string>>
* @const
@@ -310,6 +340,7 @@
if (defaultControl)
defaultControl.focus();
});
+ ensureTransitionEndEvent(oldStep, MAX_SCREEN_TRANSITION_DURATION);
} else {
oldStep.classList.add('hidden');
if (defaultControl)
@@ -330,6 +361,8 @@
if (defaultControl)
defaultControl.focus();
});
+ ensureTransitionEndEvent(innerContainer,
+ MAX_SCREEN_TRANSITION_DURATION);
} else {
if (defaultControl)
defaultControl.focus();
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_enable_kiosk.js b/chrome/browser/resources/chromeos/login/oobe_screen_enable_kiosk.js
index e9ad0b8..8bb2bb4 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_enable_kiosk.js
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_enable_kiosk.js
@@ -80,7 +80,7 @@
* Cancels the reset and drops the user back to the login screen.
*/
cancel: function() {
- chrome.send('kioskOnCancel');
+ chrome.send('kioskOnClose');
},
/**
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.css b/chrome/browser/resources/chromeos/login/screen_gaia_signin.css
index dc90711..af26cc3 100644
--- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.css
+++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.css
@@ -115,6 +115,7 @@
margin-top: 16px;
}
-#createManagedUserLinkPlaceholder {
+#createManagedUserLinkPlaceholder,
+#createManagedUserNoManagerText {
margin-top: 10px;
}
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.css b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.css
index 2aa3962..2d5bcde 100644
--- a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.css
+++ b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.css
@@ -45,7 +45,7 @@
line-height: 24px;
}
-#managed-user-creation strong {
+#managed-user-creation-created-1 strong {
color: #000;
font-weight: normal;
}
@@ -85,7 +85,16 @@
}
#managed-user-creation-intro .below-marketing {
- margin: 40px 40px 0;
+ margin: 20px 40px 0;
+}
+
+#managed-user-creation-intro-alternate-text {
+ margin-bottom: 12px;
+ margin-top: 12px;
+}
+
+#managed-user-creation-intro-text-3 {
+ margin-top: 12px;
}
#managed-user-creation-created-1 .below-marketing {
diff --git a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.html b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.html
index b912d46..5887325 100644
--- a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.html
+++ b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.html
@@ -6,16 +6,12 @@
<img src="chrome://theme/IDR_SUPERVISED_ILLUSTRATION_START">
</div>
<div class="below-marketing">
- <div i18n-content="createManagedUserIntroText1"></div>
- <div>
- <ul>
- <li i18n-content="createManagedUserIntroManagerItem1"></li>
- <li i18n-content="createManagedUserIntroManagerItem2"></li>
- <li i18n-content="createManagedUserIntroManagerItem3"></li>
- </ul>
+ <div class="page-title" i18n-content="createManagedUserIntroTextTitle">
</div>
+ <div id="managed-user-creation-intro-alternate-text"></div>
<div i18n-content="createManagedUserIntroText2"></div>
- <div id="managed-user-creation-intro-text-3"></div>
+ <div id="managed-user-creation-intro-text-3"
+ i18n-content="createManagedUserIntroText3"></div>
</div>
</div>
<div id="managed-user-creation-manager" class="page-no-marketing" hidden>
diff --git a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.js b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.js
index e8c3928..b685ed0 100644
--- a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.js
+++ b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.js
@@ -488,12 +488,14 @@
return;
var managerId = selectedPod.user.username;
+ var managerDisplayId = selectedPod.user.emailAddress;
var managerPassword = selectedPod.passwordElement.value;
if (managerPassword.empty)
return;
this.disabled = true;
this.context_.managerId = managerId;
+ this.context_.managerDisplayId = managerDisplayId;
this.context_.managerName = selectedPod.user.displayName;
chrome.send('authenticateManagerInLocallyManagedUserCreationFlow',
[managerId, managerPassword]);
@@ -855,19 +857,22 @@
},
updateText_: function() {
- var managerId = this.context_.managerId;
+ var managerDisplayId = this.context_.managerDisplayId;
+ this.updateElementText_('intro-alternate-text',
+ 'createManagedUserIntroAlternateText');
this.updateElementText_('created-1-text-1',
- 'createManagedUserCreated1Text1',
- this.context_.managedName);
+ 'createManagedUserCreated1Text1',
+ this.context_.managedName);
this.updateElementText_('created-1-text-2',
- 'createManagedUserCreated1Text2',
- loadTimeData.getString('managementURL'), this.context_.managedName);
+ 'createManagedUserCreated1Text2',
+ loadTimeData.getString('managementURL'),
+ this.context_.managedName);
this.updateElementText_('created-1-text-3',
- 'createManagedUserCreated1Text3',
- managerId);
+ 'createManagedUserCreated1Text3',
+ managerDisplayId);
this.updateElementText_('name-explanation',
- 'createManagedUserNameExplanation',
- managerId);
+ 'createManagedUserNameExplanation',
+ managerDisplayId);
},
updateElementText_: function(localId, templateName) {
diff --git a/chrome/browser/resources/chromeos/login/user_pod_row.js b/chrome/browser/resources/chromeos/login/user_pod_row.js
index cb91bd8..85502c1 100644
--- a/chrome/browser/resources/chromeos/login/user_pod_row.js
+++ b/chrome/browser/resources/chromeos/login/user_pod_row.js
@@ -1537,7 +1537,6 @@
this.podsWithPendingImages_.splice(index, 1);
if (this.podsWithPendingImages_.length == 0) {
this.classList.remove('images-loading');
- chrome.send('userImagesLoaded');
}
}
};
diff --git a/chrome/browser/resources/chromeos/slow.css b/chrome/browser/resources/chromeos/slow.css
new file mode 100644
index 0000000..fec2369
--- /dev/null
+++ b/chrome/browser/resources/chromeos/slow.css
@@ -0,0 +1,48 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+body {
+ background-color: #E6E6E6;
+ font-family: Helvetica, Arial, sans-serif;
+ font-size: 12pt;
+ margin: 50px 40px 20px 40px;
+ text-align: center;
+}
+
+#container {
+ background-color: #fbfbfb;
+ border: 1px solid #AAA;
+ border-bottom: 1px solid #888;
+ border-radius: 3px;
+ box-shadow: 0 2px 2px #AAA;
+ color: #666;
+ margin: auto;
+ max-width: 540px;
+ min-height: 29px;
+ min-width: 200px;
+ padding: 20px 60px;
+ text-align: start;
+}
+
+#container-inner {
+ background-color: #fbfbfb;
+ margin-top: 25px;
+ text-align: center;
+}
+
+button {
+ -webkit-user-select: none;
+ background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);
+ border: 1px solid rgba(0, 0, 0, 0.25);
+ border-radius: 2px;
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08),
+ inset 0 1px 2px rgba(255, 255, 255, 0.75);
+ margin-top: 10px;
+ min-height: 29px;
+ min-width: 65px;
+ padding: 8px 13px;
+ text-shadow: 0 1px 0 rgb(240, 240, 240);
+}
+
diff --git a/chrome/browser/resources/chromeos/slow.html b/chrome/browser/resources/chromeos/slow.html
new file mode 100644
index 0000000..4a1eebb
--- /dev/null
+++ b/chrome/browser/resources/chromeos/slow.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html i18n-values="dir:textdirection">
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1.0,
+ maximum-scale=1.0, user-scalable=no">
+<link rel="stylesheet" href="chrome://resources/css/widgets.css">
+<link rel="stylesheet" href="slow.css">
+<script src="chrome://resources/js/load_time_data.js"></script>
+<script src="chrome://resources/js/cr.js"></script>
+<script src="chrome://resources/js/cr/event_target.js"></script>
+<script src="chrome://resources/js/util.js"></script>
+<script src="chrome://slow/slow.js"></script>
+<script src="chrome://slow/strings.js"></script>
+</head>
+<body i18n-values=".style.fontFamily:fontfamily;">
+ <div id="container" class="container">
+ <div i18n-content="slowDescription"></div>
+ <br>
+ <div i18n-values=".innerHTML:slowWarning"></div>
+ <div id="container-inner" width=100% class="container-inner">
+ <button id="slow-disable" i18n-content="slowDisable" hidden></button>
+ <button id="slow-enable" i18n-content="slowEnable" hidden></button>
+ </div>
+ </div>
+<script src="chrome://resources/js/i18n_template2.js"></script>
+<script src="chrome://resources/js/jstemplate_compiled.js"></script>
+</body>
+</html>
diff --git a/chrome/browser/resources/chromeos/slow.js b/chrome/browser/resources/chromeos/slow.js
new file mode 100644
index 0000000..14a5e82
--- /dev/null
+++ b/chrome/browser/resources/chromeos/slow.js
@@ -0,0 +1,48 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('options', function() {
+ function Slow() {
+ }
+ cr.addSingletonGetter(Slow);
+
+ Slow.prototype = {
+ initialized_: false
+ };
+
+ Slow.initialize = function() {
+ $('slow-disable').addEventListener('click', function(event) {
+ Slow.disableTracing();
+ });
+ $('slow-enable').addEventListener('click', function(event) {
+ Slow.enableTracing();
+ });
+ this.initialized_ = true;
+ };
+
+ Slow.disableTracing = function() {
+ chrome.send('disableTracing');
+ };
+
+ Slow.enableTracing = function() {
+ chrome.send('enableTracing');
+ };
+
+ Slow.tracingPrefChanged = function(enabled) {
+ $('slow-disable').hidden = !enabled;
+ $('slow-enable').hidden = enabled;
+ };
+
+ // Export
+ return {
+ Slow: Slow
+ };
+});
+
+function load() {
+ options.Slow.initialize();
+ chrome.send('loadComplete');
+}
+
+document.addEventListener('DOMContentLoaded', load);
diff --git a/chrome/browser/resources/downloads/downloads.js b/chrome/browser/resources/downloads/downloads.js
index c6a6253..d50f5eb 100644
--- a/chrome/browser/resources/downloads/downloads.js
+++ b/chrome/browser/resources/downloads/downloads.js
@@ -423,6 +423,7 @@
this.state_ = download.state;
this.fileExternallyRemoved_ = download.file_externally_removed;
this.dangerType_ = download.danger_type;
+ this.finchString_ = download.finch_string;
this.lastReasonDescription_ = download.last_reason_text;
this.byExtensionId_ = download.by_ext_id;
this.byExtensionName_ = download.by_ext_name;
@@ -452,6 +453,10 @@
this.dangerDesc_.textContent = loadTimeData.getStringF(
'danger_potentially_unwanted_desc', this.fileName_);
}
+ if (this.finchString_) {
+ // Finch trial overrides the normal display string.
+ this.dangerDesc_.textContent = this.finchString_;
+ }
this.danger_.style.display = 'block';
this.safe_.style.display = 'none';
} else {
@@ -753,7 +758,19 @@
function setSearch(searchText) {
fifoResults.length = 0;
downloads.setSearchText(searchText);
- chrome.send('getDownloads', [searchText.toString()]);
+ searchText = searchText.toString().match(/(?:[^\s"]+|"[^"]*")+/g);
+ if (searchText) {
+ searchText = searchText.map(function(term) {
+ // strip quotes
+ return (term.match(/\s/) &&
+ term[0].match(/["']/) &&
+ term[term.length - 1] == term[0]) ?
+ term.substr(1, term.length - 2) : term;
+ });
+ } else {
+ searchText = [];
+ }
+ chrome.send('getDownloads', searchText);
}
function clearAll() {
diff --git a/chrome/browser/resources/extensions/extensions.html b/chrome/browser/resources/extensions/extensions.html
index c6418d8..b6ff0f0 100644
--- a/chrome/browser/resources/extensions/extensions.html
+++ b/chrome/browser/resources/extensions/extensions.html
@@ -101,10 +101,10 @@
</span>
</div>
<div id="footer-section">
- <a target="blank_" class="more-extensions-link"
+ <a target="_blank" class="more-extensions-link"
i18n-values="href:extensionSettingsGetMoreExtensionsUrl"
i18n-content="extensionSettingsGetMoreExtensions"></a>
- <a target="blank_" hidden
+ <a target="_blank" hidden
class="extension-commands-config"
i18n-content="extensionSettingsCommandsLink"
href="#"></a>
diff --git a/chrome/browser/resources/feedback.html b/chrome/browser/resources/feedback.html
index ba0c501..d548824 100644
--- a/chrome/browser/resources/feedback.html
+++ b/chrome/browser/resources/feedback.html
@@ -73,6 +73,15 @@
</span>
</label>
</div>
+
+ <!-- Performance Feedback -->
+ <div class="checkbox" id="performance-info-area" hidden>
+ <label>
+ <input id="performance-info-checkbox" type="checkbox">
+ <span id="performance-info-label" i18n-content="performance-trace">
+ </span>
+ </label>
+ </div>
</if>
<!-- Screenshot -->
<div id="screenshot-row" hidden>
diff --git a/chrome/browser/resources/feedback.js b/chrome/browser/resources/feedback.js
index c5e183e..34e9645 100644
--- a/chrome/browser/resources/feedback.js
+++ b/chrome/browser/resources/feedback.js
@@ -18,6 +18,7 @@
var categoryTag = '';
var filePath = '';
var forceDisableScreenshots = false;
+var traceId = 0;
// Globals to manage reading data from the attach a file option.
var attachFileBinaryData = '';
@@ -184,6 +185,10 @@
// Add chromeos data if it exists.
if ($('sys-info-checkbox')) {
reportArray = reportArray.concat([String($('sys-info-checkbox').checked)]);
+ if (!$('performance-info-checkbox').checked) {
+ traceId = 0;
+ }
+ reportArray = reportArray.concat([String(traceId)]);
}
if ($('attach-file-checkbox') &&
@@ -274,6 +279,24 @@
currentSelected();
}
+<if expr="pp_ifdef('chromeos')">
+/**
+ * Update the page when performance feedback state is changed.
+ */
+function performanceFeedbackChanged() {
+ if ($('performance-info-checkbox').checked) {
+ $('attach-file-checkbox').disabled = true;
+ $('attach-file-checkbox').checked = false;
+
+ $('screenshot-checkbox').disabled = true;
+ $('screenshot-checkbox').checked = false;
+ } else {
+ $('attach-file-checkbox').disabled = false;
+ $('screenshot-checkbox').disabled = false;
+ }
+}
+</if>
+
///////////////////////////////////////////////////////////////////////////////
// Document Functions:
/**
@@ -293,6 +316,9 @@
<if expr="pp_ifdef('chromeos')">
$('screenshot-link-tosaved').onclick = changeToSaved;
$('screenshot-link-tocurrent').onclick = changeToCurrent;
+
+ $('performance-info-checkbox').addEventListener(
+ 'change', performanceFeedbackChanged);
</if>
$('send-report-button').onclick = sendReport;
$('cancel-button').onclick = cancel;
@@ -304,6 +330,7 @@
'categoryTag': '',
'customPageUrl': '',
'filePath': '',
+ 'traceId': 0,
};
var loc = window.location;
@@ -357,6 +384,13 @@
}
}
+ traceId = parameters['traceId'];
+ if (traceId != 0 && ($('performance-info-area'))) {
+ $('performance-info-area').hidden = false;
+ $('performance-info-checkbox').checked = true;
+ performanceFeedbackChanged();
+ }
+
chrome.send('getDialogDefaults');
chrome.send('refreshCurrentScreenshot');
}
diff --git a/chrome/browser/resources/file_manager/css/file_manager.css b/chrome/browser/resources/file_manager/css/file_manager.css
index ae84a63..a8da017 100644
--- a/chrome/browser/resources/file_manager/css/file_manager.css
+++ b/chrome/browser/resources/file_manager/css/file_manager.css
@@ -792,6 +792,8 @@
min-width: 22px;
opacity: 0.6;
padding-left: 26px;
+ position: relative;
+ z-index: 10;
}
.downloads-warning {
diff --git a/chrome/browser/resources/file_manager/js/directory_model.js b/chrome/browser/resources/file_manager/js/directory_model.js
index 77dda39..f1c5f97 100644
--- a/chrome/browser/resources/file_manager/js/directory_model.js
+++ b/chrome/browser/resources/file_manager/js/directory_model.js
@@ -226,7 +226,7 @@
this.taskQueue_.run(this.updateRoots_.bind(this));
if (!enabled && (this.getCurrentRootType() == RootType.DRIVE ||
this.getCurrentRootType() == RootType.DRIVE_OFFLINE))
- this.changeDirectory(this.getDefaultDirectory());
+ this.changeDirectory(PathUtil.DEFAULT_DIRECTORY);
};
/**
@@ -1077,7 +1077,7 @@
var EXISTS = true;
var changeToDefault = function(leafName) {
- var def = self.getDefaultDirectory();
+ var def = PathUtil.DEFAULT_DIRECTORY;
self.resolveDirectory(def, function(directoryEntry) {
resolveCallback(def, leafName, !EXISTS);
changeDirectoryEntry(directoryEntry, INITIAL);
@@ -1130,20 +1130,6 @@
};
/**
- * Sets up the default path.
- */
-DirectoryModel.prototype.setupDefaultPath = function() {
- this.setupPath(this.getDefaultDirectory());
-};
-
-/**
- * @return {string} The default directory.
- */
-DirectoryModel.prototype.getDefaultDirectory = function() {
- return RootDirectory.DOWNLOADS;
-};
-
-/**
* @param {string} name Filename.
*/
DirectoryModel.prototype.selectEntry = function(name) {
@@ -1223,7 +1209,7 @@
if ((rootType == RootType.ARCHIVE || rootType == RootType.REMOVABLE) &&
!this.volumeManager_.isMounted(this.getCurrentRootPath())) {
- this.changeDirectory(this.getDefaultDirectory());
+ this.changeDirectory(PathUtil.DEFAULT_DIRECTORY);
}
callback();
@@ -1413,7 +1399,7 @@
} else {
// Unknown path.
- this.changeDirectory(this.getDefaultDirectory());
+ this.changeDirectory(PathUtil.DEFAULT_DIRECTORY);
return;
}
diff --git a/chrome/browser/resources/file_manager/js/directory_tree.js b/chrome/browser/resources/file_manager/js/directory_tree.js
index 9214d23..981089e 100644
--- a/chrome/browser/resources/file_manager/js/directory_tree.js
+++ b/chrome/browser/resources/file_manager/js/directory_tree.js
@@ -108,39 +108,22 @@
};
/**
- * Modifies a list of the directory entries to match the new UI sepc.
- *
- * TODO(yoshiki): remove this after the old UI is removed.
- *
- * @param {Array.<DirectoryEntry>} entries The list of entty.
- * @return {Array.<DirectoryEntries>} Modified entries.
+ * Generate a list of the directory entries for the top level on the tree.
+ * @return {Array.<DirectoryEntry>} Entries for the top level on the tree.
*/
-DirectoryTreeUtil.addAndRemoveDriveSpecialDirs = function(entries) {
- var modifiedEntries = [];
+DirectoryTreeUtil.generateTopLevelEntries = function() {
+ var entries = [
+ DirectoryModel.fakeDriveEntry_,
+ DirectoryModel.fakeDriveOfflineEntry_,
+ DirectoryModel.fakeDriveSharedWithMeEntry_,
+ DirectoryModel.fakeDriveRecentEntry_,
+ ];
+
for (var i in entries) {
- // Removes '/drive/other'.
- var entry = entries[i];
- if (entry.fullPath ==
- (RootDirectory.DRIVE + '/' + DriveSubRootDirectory.OTHER)) {
- continue;
- }
-
- // Changes the label of '/drive/root' to 'My Drive'.
- if (entry.fullPath == DirectoryModel.fakeDriveEntry_.fullPath) {
- entry.label = str('DRIVE_MY_DRIVE_LABEL');
- }
-
- modifiedEntries.push(entry);
+ entries[i]['label'] = PathUtil.getRootLabel(entries[i].fullPath);
}
- // Adds the special directories.
- var specialDirs = DirectoryModel.FAKE_DRIVE_SPECIAL_SEARCH_ENTRIES;
- for (var i in specialDirs) {
- var dir = specialDirs[i];
- dir['label'] = PathUtil.getRootLabel(dir.fullPath);
- modifiedEntries.push(dir);
- }
- return modifiedEntries;
+ return entries;
};
/**
@@ -180,12 +163,8 @@
var readEntry = function() {
reader.readEntries(function(results) {
if (!results.length) {
- if (item.entry.fullPath == RootDirectory.DRIVE)
- successCallback(
- DirectoryTreeUtil.addAndRemoveDriveSpecialDirs(entries));
- else
- successCallback(
- DirectoryTreeUtil.sortEntries(item.fileFilter_, entries));
+ successCallback(
+ DirectoryTreeUtil.sortEntries(item.fileFilter_, entries));
return;
}
@@ -215,14 +194,14 @@
};
/**
- * Checks if tre tree should be hidden on the given directory.
+ * Checks if the given directory can be on the tree or not.
*
* @param {string} path Path to be checked.
- * @return {boolean} True if the tree should NOT be visible on the given
- * directory. Otherwise, false.
+ * @return {boolean} True if the path is eligible for the directory tree.
+ * Otherwise, false.
*/
-DirectoryTreeUtil.shouldHideTree = function(path) {
- return !PathUtil.isDriveBasedPath(path);
+DirectoryTreeUtil.isEligiblePathForDirectoryTree = function(path) {
+ return PathUtil.isDriveBasedPath(path);
};
////////////////////////////////////////////////////////////////////////////////
@@ -492,16 +471,6 @@
*/
set expanded(value) {},
- /**
- * The DirectoryEntry corresponding to this DirectoryItem. This may be
- * a dummy DirectoryEntry.
- * @type {DirectoryEntry|Object}
- * @override
- **/
- get entry() {
- return this.dirEntry_;
- },
-
get directoryModel() {
return this.directoryModel_;
}
@@ -517,24 +486,11 @@
cr.ui.Tree.prototype.decorate.call(this);
this.directoryModel_ = directoryModel;
- this.entries_ = [];
+ this.entries_ = DirectoryTreeUtil.generateTopLevelEntries();
this.fileFilter_ = this.directoryModel_.getFileFilter();
this.fileFilter_.addEventListener('changed',
this.onFilterChanged_.bind(this));
- /**
- * The path of the root directory.
- * @type {string}
- */
- this.fullPath = '/';
- this.dirEntry_ = null;
-
- /**
- * The currently selected entry.
- * For special search entries, this could be a fake DirectoryEntry.
- * @type {DirectoryEntry|Object}
- */
- this.currentEntry_ = null;
this.directoryModel_.addEventListener('directory-changed',
this.onCurrentDirectoryChanged_.bind(this));
@@ -557,6 +513,8 @@
this.scrollBar_ = MainPanelScrollBar();
this.scrollBar_.initialize(this.parentNode, this);
+
+ this.redraw(false /* recursive */);
};
/**
@@ -565,53 +523,10 @@
* be a fake.
*/
DirectoryTree.prototype.selectByEntry = function(entry) {
- if ((this.entry && util.isSameEntry(this.entry, entry)) ||
- (this.currentEntry_ && util.isSameEntry(this.currentEntry_, entry)))
+ // If the target directory is not in the tree, do nothing.
+ if (!DirectoryTreeUtil.isEligiblePathForDirectoryTree(entry.fullPath))
return;
- this.currentEntry_ = entry;
- if (DirectoryTreeUtil.shouldHideTree(entry.fullPath))
- return;
-
- this.selectByEntryInternal_(entry);
-};
-
-/**
- * Select the item corresponding to the given entry. This method is used
- * internally.
- * @param {DirectoryEntry|Object} entry The directory entry to be selected.
- * @private
- */
-DirectoryTree.prototype.selectByEntryInternal_ = function(entry) {
- var rootDirPath = PathUtil.getRootPath(entry.fullPath);
-
- if (PathUtil.isSpecialSearchRoot(rootDirPath) ||
- PathUtil.getRootType(rootDirPath) == RootType.DRIVE) {
- rootDirPath = RootDirectory.DRIVE;
- }
-
- var onError = function() {
- this.clearTree_(true);
- }.bind(this);
-
- if (this.fullPath != rootDirPath || !this.dirEntry_) {
- // The old root is not the one for the new entry. So, first we try to set
- // the root, then retry.
- this.fullPath = rootDirPath;
-
- this.directoryModel_.resolveDirectory(
- rootDirPath,
- function(rootDirEntry) {
- if (this.fullPath != rootDirPath)
- return;
-
- this.dirEntry_ = rootDirEntry;
- this.selectByEntryInternal_(entry);
- }.bind(this),
- onError);
- return;
- }
-
if (this.selectedItem && util.isSameEntry(entry, this.selectedItem.entry))
return;
@@ -621,13 +536,11 @@
this.selectedItem = null;
this.updateSubDirectories(
false /* recursive */,
+ // Success callback, failure is not handled.
function() {
- if (!DirectoryTreeUtil.searchAndSelectByEntry(
- this.items, this.currentEntry_))
+ if (!DirectoryTreeUtil.searchAndSelectByEntry(this.items, entry))
this.selectedItem = null;
- cr.dispatchSimpleEvent(this, 'content-updated');
- }.bind(this),
- onError);
+ }.bind(this));
};
/**
@@ -638,11 +551,9 @@
*/
DirectoryTree.prototype.updateSubDirectories = function(
recursive, opt_successCallback, opt_errorCallback) {
- if (!this.currentEntry_)
- return;
-
+ var myDriveItem = this.items[0];
DirectoryTreeUtil.updateSubDirectories(
- this,
+ myDriveItem,
this.directoryModel_,
function(entries) {
this.entries_ = entries;
@@ -672,12 +583,10 @@
*/
DirectoryTree.prototype.onFilterChanged_ = function() {
// Returns immediately, if the tree is hidden.
- if (!this.currentEntry_ ||
- DirectoryTreeUtil.shouldHideTree(this.currentEntry_.fullPath))
+ if (this.hidden)
return;
this.redraw(true /* recursive */);
- cr.dispatchSimpleEvent(this, 'content-updated');
};
/**
@@ -686,14 +595,13 @@
* @private
*/
DirectoryTree.prototype.onDirectoryContentChanged_ = function(event) {
- // Returns immediately, if the tree is hidden.
- if (!this.currentEntry_ ||
- DirectoryTreeUtil.shouldHideTree(this.currentEntry_.fullPath))
- return;
-
if (event.eventType == 'changed') {
var path = util.extractFilePath(event.directoryUrl);
- DirectoryTreeUtil.updateChangedDirectoryItem(path, this);
+ if (!DirectoryTreeUtil.isEligiblePathForDirectoryTree(path))
+ return;
+
+ var myDriveItem = this.items[0];
+ DirectoryTreeUtil.updateChangedDirectoryItem(path, myDriveItem);
}
};
@@ -707,31 +615,6 @@
};
/**
- * Returns the path of the selected item.
- * @return {string} The current path.
- */
-DirectoryTree.prototype.getCurrentPath = function() {
- return this.selectedItem ? this.selectedItem.fullPath : null;
-};
-
-/**
- * Clears the tree.
- * @param {boolean} redraw Redraw the tree if true.
- * @private
- */
-DirectoryTree.prototype.clearTree_ = function(redraw) {
- this.dirEntry_ = null;
- this.fullPath = '';
- this.selectedItem = null;
- this.entries_ = [];
-
- if (redraw) {
- this.redraw(false);
- cr.dispatchSimpleEvent(this, 'content-updated');
- }
-};
-
-/**
* Sets the margin height for the transparent preview panel at the bottom.
* @param {number} margin Margin to be set in px.
*/
diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js
index 657a7f2..9ef23dc 100644
--- a/chrome/browser/resources/file_manager/js/file_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_manager.js
@@ -1181,35 +1181,35 @@
FileManager.prototype.initSidebar_ = function() {
this.directoryTree_ = this.dialogDom_.querySelector('#directory-tree');
DirectoryTree.decorate(this.directoryTree_, this.directoryModel_);
- this.directoryTree_.addEventListener('content-updated', function() {
- this.updateMiddleBarVisibility_(true);
- }.bind(this));
this.navigationList_ = this.dialogDom_.querySelector('#volume-list');
- NavigationList.decorate(this.navigationList_,
- this.directoryModel_,
- this.folderShortcutsModel_);
+ NavigationList.decorate(this.navigationList_, this.directoryModel_);
+ this.navigationList_.fileManager = this;
+ this.navigationList_.dataModel =
+ new NavigationListModel(this.directoryModel_.getRootsList(),
+ this.folderShortcutsModel_);
+
+ this.navigationList_.addEventListener(
+ 'shortcut-target-not-found',
+ function(e) {
+ var path = e.path;
+ var label = e.label;
+ this.confirm.showWithTitle(
+ label,
+ str('SHORTCUT_TARGET_UNAVAILABLE'),
+ // 'Yes' is clicked.
+ function() {
+ this.removeFolderShortcut(path);
+ }.bind(this));
+ }.bind(this));
};
/**
- * @param {boolean=} opt_delayed If true, updating is delayed by 500ms.
* @private
*/
- FileManager.prototype.updateMiddleBarVisibility_ = function(opt_delayed) {
- if (this.updateMiddleBarVisibilityTimer_) {
- clearTimeout(this.updateMiddleBarVisibilityTimer_);
- this.updateMiddleBarVisibilityTimer_ = null;
- }
-
- if (opt_delayed) {
- this.updateMiddleBarVisibilityTimer_ =
- setTimeout(this.updateMiddleBarVisibility_.bind(this, false), 500);
- return;
- }
+ FileManager.prototype.updateMiddleBarVisibility_ = function() {
var currentPath = this.directoryModel_.getCurrentDirPath();
- var visible =
- (this.directoryTree_.items.length > 0) &&
- (!DirectoryTreeUtil.shouldHideTree(currentPath));
+ var visible = DirectoryTreeUtil.isEligiblePathForDirectoryTree(currentPath);
this.dialogDom_.
querySelector('.dialog-middlebar-contents').hidden = !visible;
this.dialogDom_.querySelector('#middlebar-splitter').hidden = !visible;
@@ -1591,10 +1591,10 @@
return;
if (!path) {
- path = this.directoryModel_.getDefaultDirectory();
+ path = PathUtil.DEFAULT_DIRECTORY;
} else if (path.indexOf('/') == -1) {
// Path is a file name.
- path = this.directoryModel_.getDefaultDirectory() + '/' + path;
+ path = PathUtil.DEFAULT_DIRECTORY + '/' + path;
}
// In the FULL_PAGE mode if the hash path points to a file we might have
@@ -2015,10 +2015,8 @@
FileManager.prototype.isDriveEnabled = function() {
// Auto resolving to local path does not work for folders (e.g., dialog for
- // loading unpacked extensions) and saving.
- // TODO(kinaba): make it work for the save dialog http://crbug.com/140425
+ // loading unpacked extensions).
var noLocalPathResolution =
- this.params_.type == DialogType.SELECT_SAVEAS_FILE ||
this.params_.type == DialogType.SELECT_FOLDER ||
this.params_.type == DialogType.SELECT_UPLOAD_FOLDER;
if (noLocalPathResolution && this.params_.shouldReturnLocalPath)
@@ -2685,9 +2683,8 @@
this.scanUpdatedTimer_ = null;
}
- if (!this.spinner_.hidden) {
+ if (this.spinner_.hidden) {
this.cancelSpinnerTimeout_();
- this.showSpinner_(false);
this.showSpinnerTimeout_ =
setTimeout(this.showSpinner_.bind(this, true), 500);
}
diff --git a/chrome/browser/resources/file_manager/js/folder_shortcuts_data_model.js b/chrome/browser/resources/file_manager/js/folder_shortcuts_data_model.js
index 113a5f2..25895f9 100644
--- a/chrome/browser/resources/file_manager/js/folder_shortcuts_data_model.js
+++ b/chrome/browser/resources/file_manager/js/folder_shortcuts_data_model.js
@@ -56,6 +56,7 @@
if (this.array_.length == list.length) {
var changed = false;
for (var i = 0; i < this.array_.length; i++) {
+ // Same item check: must be exact match.
if (this.array_[i] != list[i]) {
changed = true;
break;
@@ -103,7 +104,8 @@
*/
getIndex: function(value) {
for (var i = 0; i < this.length; i++) {
- if (this.array_[i].localeCompare(value) == 0) {
+ // Same item check: must be exact match.
+ if (this.array_[i] == value) {
return i;
}
}
@@ -111,6 +113,21 @@
},
/**
+ * Compares 2 strings and returns a number indicating one string comes before
+ * or after or is the same as the other string in sort order.
+ *
+ * @param {string} a String1.
+ * @param {string} b String2.
+ * @return {boolean} Return -1, if String1 < String2. Return 0, if String1 ==
+ * String2. Otherwise, return 1.
+ */
+ compare: function(a, b) {
+ return a.localeCompare(b,
+ undefined, // locale parameter, use default locale.
+ {usage: 'sort', numeric: true});
+ },
+
+ /**
* Adds the given item to the array. If there were already same item in the
* list, return the index of the existing item without adding a duplicate
* item.
@@ -122,11 +139,13 @@
var oldArray = this.array_.slice(0); // Shallow copy.
var addedIndex = -1;
for (var i = 0; i < this.length; i++) {
- // Since the array is sorted, new item will be added just before the first
- // larger item. If the same item exists, do nothing.
- if (this.array_[i].localeCompare(value) == 0) {
+ // Same item check: must be exact match.
+ if (this.array_[i] == value)
return i;
- } else if (this.array_[i].localeCompare(value) >= 0) {
+
+ // Since the array is sorted, new item will be added just before the first
+ // larger item.
+ if (this.compare(this.array_[i], value) >= 0) {
this.array_.splice(i, 0, value);
addedIndex = i;
break;
@@ -153,6 +172,7 @@
var removedIndex = -1;
var oldArray = this.array_.slice(0); // Shallow copy.
for (var i = 0; i < this.length; i++) {
+ // Same item check: must be exact match.
if (this.array_[i] == value) {
this.array_.splice(i, 1);
removedIndex = i;
@@ -214,20 +234,23 @@
}
while (newIndex < newArray.length) {
+ // Unchanged item, which exists in both new and old array. But the
+ // index may be changed.
if (oldArray[oldIndex] == newArray[newIndex]) {
- // Unchanged item, which exists in both new and old array. But the
- // index may be changed.
permutation[oldIndex] = newIndex;
newIndex++;
break;
- } else if (oldArray[oldIndex] < newArray[newIndex]) {
- // oldArray[oldIndex] is deleted, which is not in the new array.
+ }
+
+ // oldArray[oldIndex] is deleted, which is not in the new array.
+ if (this.compare(oldArray[oldIndex], newArray[newIndex]) < 0) {
permutation[oldIndex] = -1;
break;
- } else { // oldArray[oldIndex] > newArray[newIndex]
- // newArray[newIndex] is added, which is not in the old array.
- newIndex++;
}
+
+ // In the case of this.compare(oldArray[oldIndex]) > 0:
+ // newArray[newIndex] is added, which is not in the old array.
+ newIndex++;
}
}
return permutation;
diff --git a/chrome/browser/resources/file_manager/js/navigation_list.js b/chrome/browser/resources/file_manager/js/navigation_list.js
index 476fe6d..16bd17b 100644
--- a/chrome/browser/resources/file_manager/js/navigation_list.js
+++ b/chrome/browser/resources/file_manager/js/navigation_list.js
@@ -66,7 +66,8 @@
*/
NavigationListModel.prototype = {
__proto__: cr.EventTarget.prototype,
- get length() { return this.length_(); }
+ get length() { return this.length_(); },
+ get folderShortcutList() { return this.pinnedList_; }
};
/**
@@ -213,29 +214,50 @@
/**
* NavigationList inherits cr.ui.List.
*/
-NavigationList.prototype.__proto__ = cr.ui.List.prototype;
+NavigationList.prototype = {
+ __proto__: cr.ui.List.prototype,
+
+ set dataModel(dataModel) {
+ if (!this.boundHandleListChanged_)
+ this.boundHandleListChanged_ = this.onListContentChanged_.bind(this);
+
+ if (this.dataModel_) {
+ dataModel.removeEventListener('change', this.boundHandleListChanged_);
+ dataModel.removeEventListener('permuted', this.boundHandleListChanged_);
+ }
+
+ dataModel.addEventListener('change', this.boundHandleListChanged_);
+ dataModel.addEventListener('permuted', this.boundHandleListChanged_);
+
+ var parentSetter = cr.ui.List.prototype.__lookupSetter__('dataModel');
+ return parentSetter.call(this, dataModel);
+ },
+
+ get dataModel() {
+ return this.dataModel_;
+ },
+
+ // TODO(yoshiki): Add a setter of 'directoryModel'.
+};
/**
* @param {HTMLElement} el Element to be DirectoryItem.
* @param {DirectoryModel} directoryModel Current DirectoryModel.
- * @param {cr.ui.ArrayDataModel} pinnedFolderModel Current model of the pinned
* folders.
*/
-NavigationList.decorate = function(el, directoryModel, pinnedFolderModel) {
+NavigationList.decorate = function(el, directoryModel) {
el.__proto__ = NavigationList.prototype;
- el.decorate(directoryModel, pinnedFolderModel);
+ el.decorate(directoryModel);
};
/**
* @param {DirectoryModel} directoryModel Current DirectoryModel.
- * @param {cr.ui.ArrayDataModel} pinnedFolderModel Current model of the pinned
- * folders.
*/
-NavigationList.prototype.decorate =
- function(directoryModel, pinnedFolderModel) {
+NavigationList.prototype.decorate = function(directoryModel) {
cr.ui.List.decorate(this);
this.__proto__ = NavigationList.prototype;
+ this.fileManager_ = null;
this.directoryModel_ = directoryModel;
this.volumeManager_ = VolumeManager.getInstance();
this.selectionModel = new cr.ui.ListSingleSelectionModel();
@@ -258,16 +280,6 @@
this.itemConstructor = function(path) {
return self.renderRoot_(path);
};
-
- this.pinnedItemList_ = pinnedFolderModel;
-
- this.dataModel =
- new NavigationListModel(this.directoryModel_.getRootsList(),
- this.pinnedItemList_);
- this.dataModel.addEventListener(
- 'change', this.onDataModelChanged_.bind(this));
- this.dataModel.addEventListener(
- 'permuted', this.onDataModelChanged_.bind(this));
};
/**
@@ -282,9 +294,8 @@
item.setPath(path);
var handleClick = function() {
- if (item.selected && path !== this.directoryModel_.getCurrentDirPath()) {
- this.directoryModel_.changeDirectory(path);
- }
+ if (item.selected && path !== this.directoryModel_.getCurrentDirPath())
+ this.changeDirectory_(path);
}.bind(this);
item.addEventListener('click', handleClick);
@@ -304,6 +315,25 @@
};
/**
+ * Changes the current directory to the given path.
+ * If the given path is not found, a 'shortcut-target-not-found' event is
+ * fired.
+ *
+ * @param {string} path Path of the directory to be chagned to.
+ * @private
+ */
+NavigationList.prototype.changeDirectory_ = function(path) {
+ var onErrorCallback = function() {
+ var e = new Event('shortcut-target-not-found');
+ e.path = path;
+ e.label = PathUtil.getFolderLabel(path);
+ this.dispatchEvent(e);
+ }.bind(this);
+
+ this.directoryModel_.changeDirectory(path, onErrorCallback);
+};
+
+/**
* Sets a context menu. Context menu is enabled only on archive and removable
* volumes as of now.
*
@@ -334,7 +364,7 @@
if (this.directoryModel_.getCurrentDirEntry().fullPath == newPath)
return false;
- this.directoryModel_.changeDirectory(newPath);
+ this.changeDirectory_(newPath);
return true;
};
@@ -376,7 +406,7 @@
* @param {Event} event The event.
* @private
*/
-NavigationList.prototype.onDataModelChanged_ = function(event) {
+NavigationList.prototype.onListContentChanged_ = function(event) {
this.selectBestMatchItem_();
};
diff --git a/chrome/browser/resources/file_manager/js/path_util.js b/chrome/browser/resources/file_manager/js/path_util.js
index 774cb13..1517377 100644
--- a/chrome/browser/resources/file_manager/js/path_util.js
+++ b/chrome/browser/resources/file_manager/js/path_util.js
@@ -45,6 +45,13 @@
var PathUtil = {};
/**
+ * The path to the default directory.
+ * @type {string}
+ * @const
+ */
+PathUtil.DEFAULT_DIRECTORY = RootDirectory.DOWNLOADS;
+
+/**
* Checks if the given path represents a special search. Fake entries in
* RootDirectory correspond to special searches.
* @param {string} path Path to check.
diff --git a/chrome/browser/resources/google_now/background.js b/chrome/browser/resources/google_now/background.js
index 188545b..893bfef 100644
--- a/chrome/browser/resources/google_now/background.js
+++ b/chrome/browser/resources/google_now/background.js
@@ -114,33 +114,29 @@
return false;
}
-var googleGeolocationAccessEnabledPref =
- chrome.preferencesPrivate.googleGeolocationAccessEnabled;
-
var tasks = buildTaskManager(areTasksConflicting);
// Add error processing to API calls.
-tasks.instrumentApiFunction(chrome.location.onLocationUpdate, 'addListener', 0);
-tasks.instrumentApiFunction(chrome.notifications, 'create', 2);
-tasks.instrumentApiFunction(chrome.notifications, 'update', 2);
-tasks.instrumentApiFunction(chrome.notifications, 'getAll', 0);
-tasks.instrumentApiFunction(
- chrome.notifications.onButtonClicked, 'addListener', 0);
-tasks.instrumentApiFunction(chrome.notifications.onClicked, 'addListener', 0);
-tasks.instrumentApiFunction(chrome.notifications.onClosed, 'addListener', 0);
-tasks.instrumentApiFunction(chrome.omnibox.onInputEntered, 'addListener', 0);
-tasks.instrumentApiFunction(
- googleGeolocationAccessEnabledPref,
- 'get',
+tasks.instrumentChromeApiFunction('location.onLocationUpdate.addListener', 0);
+tasks.instrumentChromeApiFunction('metricsPrivate.getVariationParams', 1);
+tasks.instrumentChromeApiFunction('notifications.create', 2);
+tasks.instrumentChromeApiFunction('notifications.update', 2);
+tasks.instrumentChromeApiFunction('notifications.getAll', 0);
+tasks.instrumentChromeApiFunction(
+ 'notifications.onButtonClicked.addListener', 0);
+tasks.instrumentChromeApiFunction('notifications.onClicked.addListener', 0);
+tasks.instrumentChromeApiFunction('notifications.onClosed.addListener', 0);
+tasks.instrumentChromeApiFunction('omnibox.onInputEntered.addListener', 0);
+tasks.instrumentChromeApiFunction(
+ 'preferencesPrivate.googleGeolocationAccessEnabled.get',
1);
-tasks.instrumentApiFunction(
- googleGeolocationAccessEnabledPref.onChange,
- 'addListener',
+tasks.instrumentChromeApiFunction(
+ 'preferencesPrivate.googleGeolocationAccessEnabled.onChange.addListener',
0);
-tasks.instrumentApiFunction(chrome.runtime.onInstalled, 'addListener', 0);
-tasks.instrumentApiFunction(chrome.runtime.onStartup, 'addListener', 0);
-tasks.instrumentApiFunction(chrome.tabs, 'create', 1);
-tasks.instrumentApiFunction(storage, 'get', 1);
+tasks.instrumentChromeApiFunction('runtime.onInstalled.addListener', 0);
+tasks.instrumentChromeApiFunction('runtime.onStartup.addListener', 0);
+tasks.instrumentChromeApiFunction('tabs.create', 1);
+tasks.instrumentChromeApiFunction('storage.local.get', 1);
var updateCardsAttempts = buildAttemptManager(
'cards-update',
@@ -255,80 +251,84 @@
}
tasks.debugSetStepName('parseAndShowNotificationCards-storage-get');
- storage.get(['notificationsData', 'recentDismissals'], function(items) {
- console.log('parseAndShowNotificationCards-get ' + JSON.stringify(items));
- items.notificationsData = items.notificationsData || {};
- items.recentDismissals = items.recentDismissals || {};
+ instrumented.storage.local.get(['notificationsData', 'recentDismissals'],
+ function(items) {
+ console.log('parseAndShowNotificationCards-get ' +
+ JSON.stringify(items));
+ items.notificationsData = items.notificationsData || {};
+ items.recentDismissals = items.recentDismissals || {};
- tasks.debugSetStepName(
- 'parseAndShowNotificationCards-notifications-getAll');
- chrome.notifications.getAll(function(notifications) {
- console.log('parseAndShowNotificationCards-getAll ' +
- JSON.stringify(notifications));
- // TODO(vadimt): Figure out what to do when notifications are disabled for
- // our extension.
- notifications = notifications || {};
+ tasks.debugSetStepName(
+ 'parseAndShowNotificationCards-notifications-getAll');
+ instrumented.notifications.getAll(function(notifications) {
+ console.log('parseAndShowNotificationCards-getAll ' +
+ JSON.stringify(notifications));
+ // TODO(vadimt): Figure out what to do when notifications are
+ // disabled for our extension.
+ notifications = notifications || {};
- // Build a set of non-expired recent dismissals. It will be used for
- // client-side filtering of cards.
- var updatedRecentDismissals = {};
- var currentTimeMs = Date.now();
- for (var notificationId in items.recentDismissals) {
- if (currentTimeMs - items.recentDismissals[notificationId] <
- DISMISS_RETENTION_TIME_MS) {
- updatedRecentDismissals[notificationId] =
- items.recentDismissals[notificationId];
- }
- }
+ // Build a set of non-expired recent dismissals. It will be used for
+ // client-side filtering of cards.
+ var updatedRecentDismissals = {};
+ var currentTimeMs = Date.now();
+ for (var notificationId in items.recentDismissals) {
+ if (currentTimeMs - items.recentDismissals[notificationId] <
+ DISMISS_RETENTION_TIME_MS) {
+ updatedRecentDismissals[notificationId] =
+ items.recentDismissals[notificationId];
+ }
+ }
- // Mark existing notifications that received an update in this server
- // response.
- var updatedNotifications = {};
+ // Mark existing notifications that received an update in this server
+ // response.
+ var updatedNotifications = {};
- for (var i = 0; i < cards.length; ++i) {
- var notificationId = cards[i].notificationId;
- if (!(notificationId in updatedRecentDismissals) &&
- notificationId in notifications) {
- updatedNotifications[notificationId] = true;
- }
- }
+ for (var i = 0; i < cards.length; ++i) {
+ var notificationId = cards[i].notificationId;
+ if (!(notificationId in updatedRecentDismissals) &&
+ notificationId in notifications) {
+ updatedNotifications[notificationId] = true;
+ }
+ }
- // Delete notifications that didn't receive an update.
- for (var notificationId in notifications) {
- console.log('parseAndShowNotificationCards-delete-check ' +
- notificationId);
- if (!(notificationId in updatedNotifications)) {
- console.log('parseAndShowNotificationCards-delete ' + notificationId);
- cardSet.clear(notificationId);
- }
- }
+ // Delete notifications that didn't receive an update.
+ for (var notificationId in notifications) {
+ console.log('parseAndShowNotificationCards-delete-check ' +
+ notificationId);
+ if (!(notificationId in updatedNotifications)) {
+ console.log('parseAndShowNotificationCards-delete ' +
+ notificationId);
+ cardSet.clear(notificationId);
+ }
+ }
- recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS);
+ recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS);
- // Create/update notifications and store their new properties.
- var newNotificationsData = {};
- for (var i = 0; i < cards.length; ++i) {
- var card = cards[i];
- if (!(card.notificationId in updatedRecentDismissals)) {
- var notificationData = items.notificationsData[card.notificationId];
- var previousVersion = notifications[card.notificationId] &&
- notificationData &&
- notificationData.cardCreateInfo &&
- notificationData.cardCreateInfo.version;
- newNotificationsData[card.notificationId] =
- cardSet.update(card, previousVersion);
- }
- }
+ // Create/update notifications and store their new properties.
+ var newNotificationsData = {};
+ for (var i = 0; i < cards.length; ++i) {
+ var card = cards[i];
+ if (!(card.notificationId in updatedRecentDismissals)) {
+ var notificationData =
+ items.notificationsData[card.notificationId];
+ var previousVersion = notifications[card.notificationId] &&
+ notificationData &&
+ notificationData.cardCreateInfo &&
+ notificationData.cardCreateInfo.version;
+ newNotificationsData[card.notificationId] =
+ cardSet.update(card, previousVersion);
+ }
+ }
- updateCardsAttempts.start(parsedResponse.next_poll_seconds);
+ updateCardsAttempts.start(parsedResponse.next_poll_seconds);
- storage.set({
- notificationsData: newNotificationsData,
- recentDismissals: updatedRecentDismissals
+ chrome.storage.local.set({
+ notificationsData: newNotificationsData,
+ recentDismissals: updatedRecentDismissals
+ });
+ callback();
+ });
});
- callback();
- });
- });
}
/**
@@ -342,11 +342,11 @@
// TODO(robliao): Once Google Now clears its own checkbox in the
// notifications center and bug 260376 is fixed, the below clearing
// code is no longer necessary.
- chrome.notifications.getAll(function(notifications) {
+ instrumented.notifications.getAll(function(notifications) {
for (var notificationId in notifications) {
chrome.notifications.clear(notificationId, function() {});
}
- storage.set({notificationsData: {}});
+ chrome.storage.local.set({notificationsData: {}});
});
}
@@ -401,11 +401,19 @@
function requestLocation() {
console.log('requestLocation');
recordEvent(GoogleNowEvent.LOCATION_REQUEST);
- // TODO(vadimt): Figure out location request options. Use experiments
- // framework to enable setting these parameters remotely.
- chrome.location.watchLocation(LOCATION_WATCH_NAME, {
- minDistanceInMeters: 100,
- minTimeInMilliseconds: 180000 // 3 minutes.
+ // TODO(vadimt): Figure out location request options.
+ chrome.metricsPrivate.getVariationParams('GoogleNow', function(params) {
+ var minDistanceInMeters =
+ parseInt(params && params.minDistanceInMeters, 10) ||
+ 100;
+ var minTimeInMilliseconds =
+ parseInt(params && params.minTimeInMilliseconds, 10) ||
+ 180000; // 3 minutes.
+
+ chrome.location.watchLocation(LOCATION_WATCH_NAME, {
+ minDistanceInMeters: minDistanceInMeters,
+ minTimeInMilliseconds: minTimeInMilliseconds
+ });
});
}
@@ -503,52 +511,53 @@
*/
function processPendingDismissals(callbackBoolean) {
tasks.debugSetStepName('processPendingDismissals-storage-get');
- storage.get(['pendingDismissals', 'recentDismissals'], function(items) {
- console.log('processPendingDismissals-storage-get ' +
- JSON.stringify(items));
- items.pendingDismissals = items.pendingDismissals || [];
- items.recentDismissals = items.recentDismissals || {};
+ instrumented.storage.local.get(['pendingDismissals', 'recentDismissals'],
+ function(items) {
+ console.log('processPendingDismissals-storage-get ' +
+ JSON.stringify(items));
+ items.pendingDismissals = items.pendingDismissals || [];
+ items.recentDismissals = items.recentDismissals || {};
- var dismissalsChanged = false;
+ var dismissalsChanged = false;
- function onFinish(success) {
- if (dismissalsChanged) {
- storage.set({
- pendingDismissals: items.pendingDismissals,
- recentDismissals: items.recentDismissals
- });
- }
- callbackBoolean(success);
- }
+ function onFinish(success) {
+ if (dismissalsChanged) {
+ chrome.storage.local.set({
+ pendingDismissals: items.pendingDismissals,
+ recentDismissals: items.recentDismissals
+ });
+ }
+ callbackBoolean(success);
+ }
- function doProcessDismissals() {
- if (items.pendingDismissals.length == 0) {
- dismissalAttempts.stop();
- onFinish(true);
- return;
- }
+ function doProcessDismissals() {
+ if (items.pendingDismissals.length == 0) {
+ dismissalAttempts.stop();
+ onFinish(true);
+ return;
+ }
- // Send dismissal for the first card, and if successful, repeat
- // recursively with the rest.
- var dismissal = items.pendingDismissals[0];
- requestCardDismissal(
- dismissal.notificationId,
- dismissal.time,
- dismissal.parameters,
- function(done) {
- if (done) {
- dismissalsChanged = true;
- items.pendingDismissals.splice(0, 1);
- items.recentDismissals[dismissal.notificationId] = Date.now();
- doProcessDismissals();
- } else {
- onFinish(false);
- }
- });
- }
+ // Send dismissal for the first card, and if successful, repeat
+ // recursively with the rest.
+ var dismissal = items.pendingDismissals[0];
+ requestCardDismissal(
+ dismissal.notificationId,
+ dismissal.time,
+ dismissal.parameters,
+ function(done) {
+ if (done) {
+ dismissalsChanged = true;
+ items.pendingDismissals.splice(0, 1);
+ items.recentDismissals[dismissal.notificationId] = Date.now();
+ doProcessDismissals();
+ } else {
+ onFinish(false);
+ }
+ });
+ }
- doProcessDismissals();
- });
+ doProcessDismissals();
+ });
}
/**
@@ -569,7 +578,7 @@
* the clicked area from the button action URLs info.
*/
function onNotificationClicked(notificationId, selector) {
- storage.get('notificationsData', function(items) {
+ instrumented.storage.local.get('notificationsData', function(items) {
items.notificationsData = items.notificationsData || {};
var notificationData = items.notificationsData[notificationId];
@@ -590,7 +599,7 @@
if (typeof url != 'string')
return;
- chrome.tabs.create({url: url}, function(tab) {
+ instrumented.tabs.create({url: url}, function(tab) {
if (!tab)
chrome.windows.create({url: url});
});
@@ -602,11 +611,11 @@
* @param {number} buttonIndex The index of the button which was clicked.
*/
function onToastNotificationClicked(buttonIndex) {
- storage.set({userRespondedToToast: true});
+ chrome.storage.local.set({userRespondedToToast: true});
if (buttonIndex == ToastButtonIndex.YES) {
chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastClickedYes');
- googleGeolocationAccessEnabledPref.set({value: true});
+ chrome.preferencesPrivate.googleGeolocationAccessEnabled.set({value: true});
// The googlegeolocationaccessenabled preference change callback
// will take care of starting the poll for cards.
} else {
@@ -628,7 +637,7 @@
// Even though they only closed the notification without clicking no, treat
// it as though they clicked No anwyay, and don't show the toast again.
chrome.metricsPrivate.recordUserAction('GoogleNow.WelcomeToastDismissed');
- storage.set({userRespondedToToast: true});
+ chrome.storage.local.set({userRespondedToToast: true});
return;
}
@@ -643,21 +652,23 @@
cardSet.clear(notificationId);
tasks.debugSetStepName('onNotificationClosed-storage-get');
- storage.get(['pendingDismissals', 'notificationsData'], function(items) {
- items.pendingDismissals = items.pendingDismissals || [];
- items.notificationsData = items.notificationsData || {};
+ instrumented.storage.local.get(['pendingDismissals', 'notificationsData'],
+ function(items) {
+ items.pendingDismissals = items.pendingDismissals || [];
+ items.notificationsData = items.notificationsData || {};
- var notificationData = items.notificationsData[notificationId];
+ var notificationData = items.notificationsData[notificationId];
- var dismissal = {
- notificationId: notificationId,
- time: Date.now(),
- parameters: notificationData && notificationData.dismissalParameters
- };
- items.pendingDismissals.push(dismissal);
- storage.set({pendingDismissals: items.pendingDismissals});
- processPendingDismissals(function(success) { callback(); });
- });
+ var dismissal = {
+ notificationId: notificationId,
+ time: Date.now(),
+ parameters: notificationData && notificationData.dismissalParameters
+ };
+ items.pendingDismissals.push(dismissal);
+ chrome.storage.local.set(
+ {pendingDismissals: items.pendingDismissals});
+ processPendingDismissals(function(success) { callback(); });
+ });
});
}
@@ -714,6 +725,9 @@
startPollingCards();
else
stopPollingCards();
+ } else {
+ console.log(
+ 'Action Ignored setShouldPollCards=' + shouldPollCardsRequest);
}
callback();
});
@@ -728,7 +742,7 @@
function setToastVisible(visibleRequest, callback) {
tasks.debugSetStepName(
'setToastVisible-shouldSetToastVisible-getAllNotifications');
- chrome.notifications.getAll(function(notifications) {
+ instrumented.notifications.getAll(function(notifications) {
// TODO(vadimt): Figure out what to do when notifications are disabled for
// our extension.
notifications = notifications || {};
@@ -739,6 +753,8 @@
showWelcomeToast();
else
hideWelcomeToast();
+ } else {
+ console.log('Action Ignored setToastVisible=' + visibleRequest);
}
callback();
@@ -775,7 +791,7 @@
// If the user enabled geolocation independently of Google Now,
// the user has implicitly responded to the toast.
// We do not want to show it again.
- storage.set({userRespondedToToast: true});
+ chrome.storage.local.set({userRespondedToToast: true});
}
shouldPollCards = true;
@@ -810,19 +826,24 @@
var signedIn = !!token && !!NOTIFICATION_CARDS_URL;
tasks.debugSetStepName(
'onStateChange-get-googleGeolocationAccessEnabledPref');
- googleGeolocationAccessEnabledPref.get({}, function(prefValue) {
- var geolocationEnabled = !!prefValue.value;
- tasks.debugSetStepName(
- 'onStateChange-get-userRespondedToToast');
- storage.get('userRespondedToToast', function(items) {
- var userRespondedToToast = !!items.userRespondedToToast;
- updateRunningState(
- signedIn,
- geolocationEnabled,
- userRespondedToToast,
- callback);
- });
- });
+ instrumented.
+ preferencesPrivate.
+ googleGeolocationAccessEnabled.
+ get({}, function(prefValue) {
+ var geolocationEnabled = !!prefValue.value;
+ tasks.debugSetStepName(
+ 'onStateChange-get-userRespondedToToast');
+ instrumented.storage.local.get(
+ 'userRespondedToToast',
+ function(items) {
+ var userRespondedToToast = !!items.userRespondedToToast;
+ updateRunningState(
+ signedIn,
+ geolocationEnabled,
+ userRespondedToToast,
+ callback);
+ });
+ });
});
});
}
@@ -845,7 +866,7 @@
priority: 2,
buttons: buttons
};
- chrome.notifications.create(WELCOME_TOAST_NOTIFICATION_ID, options,
+ instrumented.notifications.create(WELCOME_TOAST_NOTIFICATION_ID, options,
function(notificationId) {});
}
@@ -858,21 +879,26 @@
function() {});
}
-chrome.runtime.onInstalled.addListener(function(details) {
+instrumented.runtime.onInstalled.addListener(function(details) {
console.log('onInstalled ' + JSON.stringify(details));
if (details.reason != 'chrome_update') {
initialize();
}
});
-chrome.runtime.onStartup.addListener(function() {
+instrumented.runtime.onStartup.addListener(function() {
console.log('onStartup');
initialize();
});
-googleGeolocationAccessEnabledPref.onChange.addListener(function(prefValue) {
- console.log('googleGeolocationAccessEnabledPref onChange ' + prefValue.value);
- onStateChange();
+instrumented.
+ preferencesPrivate.
+ googleGeolocationAccessEnabled.
+ onChange.
+ addListener(function(prefValue) {
+ console.log('googleGeolocationAccessEnabled Pref onChange ' +
+ prefValue.value);
+ onStateChange();
});
authenticationManager.addListener(function() {
@@ -880,7 +906,7 @@
onStateChange();
});
-chrome.notifications.onClicked.addListener(
+instrumented.notifications.onClicked.addListener(
function(notificationId) {
chrome.metricsPrivate.recordUserAction('GoogleNow.MessageClicked');
onNotificationClicked(notificationId, function(actionUrls) {
@@ -888,7 +914,7 @@
});
});
-chrome.notifications.onButtonClicked.addListener(
+instrumented.notifications.onButtonClicked.addListener(
function(notificationId, buttonIndex) {
if (notificationId == WELCOME_TOAST_NOTIFICATION_ID) {
onToastNotificationClicked(buttonIndex);
@@ -904,14 +930,14 @@
}
});
-chrome.notifications.onClosed.addListener(onNotificationClosed);
+instrumented.notifications.onClosed.addListener(onNotificationClosed);
-chrome.location.onLocationUpdate.addListener(function(position) {
+instrumented.location.onLocationUpdate.addListener(function(position) {
recordEvent(GoogleNowEvent.LOCATION_UPDATE);
updateNotificationsCards(position);
});
-chrome.omnibox.onInputEntered.addListener(function(text) {
+instrumented.omnibox.onInputEntered.addListener(function(text) {
localStorage['server_url'] = NOTIFICATION_CARDS_URL = text;
initialize();
});
diff --git a/chrome/browser/resources/google_now/background_test_util.js b/chrome/browser/resources/google_now/background_test_util.js
index 3e52dd7..3d59e0f 100644
--- a/chrome/browser/resources/google_now/background_test_util.js
+++ b/chrome/browser/resources/google_now/background_test_util.js
@@ -9,7 +9,7 @@
function buildTaskManager() {
return {
debugSetStepName: emptyMock,
- instrumentApiFunction: emptyMock,
+ instrumentChromeApiFunction: emptyMock,
};
}
@@ -23,21 +23,21 @@
var buildAttemptManager = emptyMock;
var buildCardSet = emptyMock;
var emptyListener = {addListener: emptyMock};
-chrome['location'] = {onLocationUpdate: emptyListener};
-chrome['notifications'] = {
+var instrumented = {};
+instrumented['location'] = {onLocationUpdate: emptyListener};
+instrumented['notifications'] = {
onButtonClicked: emptyListener,
onClicked: emptyListener,
onClosed: emptyListener
};
-chrome['omnibox'] = {onInputEntered: emptyListener};
-chrome['preferencesPrivate'] = {
+instrumented['omnibox'] = {onInputEntered: emptyListener};
+instrumented['preferencesPrivate'] = {
googleGeolocationAccessEnabled: {
onChange: emptyListener
}
};
-chrome['runtime'] = {
+instrumented['runtime'] = {
onInstalled: emptyListener,
onStartup: emptyListener
};
-var storage = {};
diff --git a/chrome/browser/resources/google_now/background_unittest.gtestjs b/chrome/browser/resources/google_now/background_unittest.gtestjs
index 5ad7050..a99ff5f 100644
--- a/chrome/browser/resources/google_now/background_unittest.gtestjs
+++ b/chrome/browser/resources/google_now/background_unittest.gtestjs
@@ -61,10 +61,10 @@
fixture.makeAndRegisterMockApis([
'authenticationManager.isSignedIn',
'chrome.location.clearWatch',
- 'chrome.notifications.getAll',
- 'chrome.preferencesPrivate.googleGeolocationAccessEnabled.get',
- 'storage.get',
- 'storage.set',
+ 'chrome.storage.local.set',
+ 'instrumented.notifications.getAll',
+ 'instrumented.preferencesPrivate.googleGeolocationAccessEnabled.get',
+ 'instrumented.storage.local.get',
'tasks.add',
'updateCardsAttempts.isRunning',
'updateCardsAttempts.stop'
@@ -99,7 +99,7 @@
var googleGeolocationPrefGetSavedArgs = new SaveMockArguments();
mockApisObj.expects(once()).
- chrome_preferencesPrivate_googleGeolocationAccessEnabled_get(
+ instrumented_preferencesPrivate_googleGeolocationAccessEnabled_get(
googleGeolocationPrefGetSavedArgs.match(eqJSON({})),
googleGeolocationPrefGetSavedArgs.match(ANYTHING)).
will(invokeCallback(
@@ -107,7 +107,7 @@
var storageGetSavedArgs = new SaveMockArguments();
mockApisObj.expects(once()).
- storage_get(
+ instrumented_storage_local_get(
storageGetSavedArgs.match(eq('userRespondedToToast')),
storageGetSavedArgs.match(ANYTHING)).
will(invokeCallback(storageGetSavedArgs, 1, testUserRespondedToToast));
@@ -126,7 +126,7 @@
mockApisObj.expects(once()).
updateCardsAttempts_stop();
mockApisObj.expects(once()).
- storage_set(eqJSON({notificationsData: {}}));
+ chrome_storage_local_set(eqJSON({notificationsData: {}}));
var tasksAddSavedArgs = new SaveMockArguments();
mockApisObj.expects(once()).
tasks_add(
@@ -174,7 +174,7 @@
var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
this.mockApis.expects(exactly(2)).
- chrome_notifications_getAll(
+ instrumented_notifications_getAll(
chromeNotificationGetAllSavedArgs.match(ANYTHING)).
will(
invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
@@ -218,7 +218,7 @@
var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
this.mockApis.expects(exactly(2)).
- chrome_notifications_getAll(
+ instrumented_notifications_getAll(
chromeNotificationGetAllSavedArgs.match(ANYTHING)).
will(
invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
@@ -257,7 +257,7 @@
var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
this.mockApis.expects(exactly(2)).
- chrome_notifications_getAll(
+ instrumented_notifications_getAll(
chromeNotificationGetAllSavedArgs.match(ANYTHING)).
will(
invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
@@ -294,7 +294,7 @@
var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
this.mockApis.expects(exactly(2)).
- chrome_notifications_getAll(
+ instrumented_notifications_getAll(
chromeNotificationGetAllSavedArgs.match(ANYTHING)).
will(
invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
@@ -334,7 +334,7 @@
var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
this.mockApis.expects(exactly(2)).
- chrome_notifications_getAll(
+ instrumented_notifications_getAll(
chromeNotificationGetAllSavedArgs.match(ANYTHING)).
will(
invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
@@ -350,9 +350,9 @@
*/
function mockOnNotificationClickedDependencies(fixture) {
fixture.makeAndRegisterMockApis([
- 'storage.get',
- 'chrome.tabs.create',
- 'chrome.windows.create']);
+ 'chrome.windows.create',
+ 'instrumented.storage.local.get',
+ 'instrumented.tabs.create']);
}
TEST_F(
@@ -371,7 +371,7 @@
var storageGetSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- storage_get(
+ instrumented_storage_local_get(
storageGetSavedArgs.match(eq('notificationsData')),
storageGetSavedArgs.match(ANYTHING)).
will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
@@ -401,7 +401,7 @@
var storageGetSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- storage_get(
+ instrumented_storage_local_get(
storageGetSavedArgs.match(eq('notificationsData')),
storageGetSavedArgs.match(ANYTHING)).
will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
@@ -432,7 +432,7 @@
var storageGetSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- storage_get(
+ instrumented_storage_local_get(
storageGetSavedArgs.match(eq('notificationsData')),
storageGetSavedArgs.match(ANYTHING)).
will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
@@ -464,7 +464,7 @@
var storageGetSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- storage_get(
+ instrumented_storage_local_get(
storageGetSavedArgs.match(eq('notificationsData')),
storageGetSavedArgs.match(ANYTHING)).
will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
@@ -472,7 +472,7 @@
returnValue(testActionUrl));
var chromeTabsCreateSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- chrome_tabs_create(
+ instrumented_tabs_create(
chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
chromeTabsCreateSavedArgs.match(ANYTHING)).
will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
@@ -504,7 +504,7 @@
var storageGetSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- storage_get(
+ instrumented_storage_local_get(
storageGetSavedArgs.match(eq('notificationsData')),
storageGetSavedArgs.match(ANYTHING)).
will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
@@ -512,7 +512,7 @@
returnValue(testActionUrl));
var chromeTabsCreateSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- chrome_tabs_create(
+ instrumented_tabs_create(
chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
chromeTabsCreateSavedArgs.match(ANYTHING)).
will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
diff --git a/chrome/browser/resources/google_now/cards.js b/chrome/browser/resources/google_now/cards.js
index 09ca6e1..5e24819 100644
--- a/chrome/browser/resources/google_now/cards.js
+++ b/chrome/browser/resources/google_now/cards.js
@@ -43,7 +43,7 @@
try {
// Delete a notification with the specified id if it already exists, and
// then create a notification.
- chrome.notifications.create(
+ instrumented.notifications.create(
cardId,
cardCreateInfo.notification,
function(newNotificationId) {
@@ -63,7 +63,7 @@
} else {
try {
// Update existing notification.
- chrome.notifications.update(
+ instrumented.notifications.update(
cardId,
cardCreateInfo.notification,
function(wasUpdated) {
@@ -147,13 +147,13 @@
chrome.alarms.clear(cardHidePrefix + cardId);
}
- chrome.alarms.onAlarm.addListener(function(alarm) {
+ instrumented.alarms.onAlarm.addListener(function(alarm) {
console.log('cardManager.onAlarm ' + JSON.stringify(alarm));
if (alarm.name.indexOf(cardShowPrefix) == 0) {
// Alarm to show the card.
var cardId = alarm.name.substring(cardShowPrefix.length);
- storage.get('notificationsData', function(items) {
+ instrumented.storage.local.get('notificationsData', function(items) {
items.notificationsData = items.notificationsData || {};
console.log('cardManager.onAlarm.get ' + JSON.stringify(items));
var notificationData = items.notificationsData[cardId];
diff --git a/chrome/browser/resources/google_now/cards_unittest.gtestjs b/chrome/browser/resources/google_now/cards_unittest.gtestjs
index 01cb789..50375c4 100644
--- a/chrome/browser/resources/google_now/cards_unittest.gtestjs
+++ b/chrome/browser/resources/google_now/cards_unittest.gtestjs
@@ -29,20 +29,20 @@
function setUpCardManagerTest(fixture) {
fixture.makeAndRegisterMockApis([
- 'chrome.alarms.onAlarm.addListener',
'chrome.alarms.clear',
'chrome.alarms.create',
'chrome.notifications.clear',
- 'chrome.notifications.create',
- 'chrome.notifications.update',
- 'storage.get'
+ 'instrumented.alarms.onAlarm.addListener',
+ 'instrumented.notifications.create',
+ 'instrumented.notifications.update',
+ 'instrumented.storage.local.get'
]);
chrome.runtime = {}; // No error.
var onAlarmSavedArgs = new SaveMockArguments();
fixture.mockApis.expects(once()).
- chrome_alarms_onAlarm_addListener(
+ instrumented_alarms_onAlarm_addListener(
onAlarmSavedArgs.match(ANYTHING));
var cardSet = buildCardSet();
@@ -78,7 +78,7 @@
chrome_alarms_clear(expectedShowAlarmId);
var chromeNotificationsCreateSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- chrome_notifications_create(
+ instrumented_notifications_create(
chromeNotificationsCreateSavedArgs.match(eq(testCardId)),
chromeNotificationsCreateSavedArgs.match(eqJSON(testNotification)),
chromeNotificationsCreateSavedArgs.match(ANYTHING)).
@@ -101,7 +101,7 @@
timeHide: undefined,
version: 0
},
- dismissalParameters: testDismissal
+ dismissalParameters: testDismissal
}),
JSON.stringify(notificationData));
});
@@ -116,7 +116,7 @@
this.mockApis.expects(once()).
chrome_alarms_clear(expectedShowAlarmId);
this.mockApis.expects(once()).
- chrome_notifications_create(
+ instrumented_notifications_create(
testCardId, eqJSON(testNotification), ANYTHING);
// Call tested method.
@@ -153,7 +153,7 @@
chrome_alarms_clear(expectedShowAlarmId);
var chromeNotificationsCreateSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- chrome_notifications_create(
+ instrumented_notifications_create(
chromeNotificationsCreateSavedArgs.match(eq(testCardId)),
chromeNotificationsCreateSavedArgs.match(eqJSON(testNotification)),
chromeNotificationsCreateSavedArgs.match(ANYTHING)).
@@ -195,7 +195,7 @@
chrome_alarms_clear(expectedShowAlarmId);
var chromeNotificationsCreateSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- chrome_notifications_update(
+ instrumented_notifications_update(
chromeNotificationsCreateSavedArgs.match(eq(testCardId)),
chromeNotificationsCreateSavedArgs.match(eqJSON(testNotification)),
chromeNotificationsCreateSavedArgs.match(ANYTHING)).
@@ -236,7 +236,7 @@
chrome_alarms_clear(expectedShowAlarmId);
var chromeNotificationsCreateSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- chrome_notifications_update(
+ instrumented_notifications_update(
chromeNotificationsCreateSavedArgs.match(eq(testCardId)),
chromeNotificationsCreateSavedArgs.match(eqJSON(testNotification)),
chromeNotificationsCreateSavedArgs.match(ANYTHING)).
@@ -265,7 +265,7 @@
this.mockApis.expects(once()).
chrome_alarms_clear(expectedShowAlarmId);
this.mockApis.expects(once()).
- chrome_notifications_create(
+ instrumented_notifications_create(
testCardId, eqJSON(testNotification), ANYTHING);
// Call tested method.
@@ -288,7 +288,7 @@
this.mockApis.expects(once()).
chrome_alarms_clear(expectedShowAlarmId);
this.mockApis.expects(once()).
- chrome_notifications_create(
+ instrumented_notifications_create(
testCardId, eqJSON(testNotification), ANYTHING);
// Call tested method.
@@ -351,7 +351,7 @@
var test = setUpCardManagerTest(this);
var storageGetSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- storage_get(
+ instrumented_storage_local_get(
storageGetSavedArgs.match(eq('notificationsData')),
storageGetSavedArgs.match(ANYTHING)).
will(invokeCallback(storageGetSavedArgs, 1, {}));
@@ -366,7 +366,7 @@
var test = setUpCardManagerTest(this);
var storageGetSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- storage_get(
+ instrumented_storage_local_get(
storageGetSavedArgs.match(eq('notificationsData')),
storageGetSavedArgs.match(ANYTHING)).
will(invokeCallback(
@@ -382,7 +382,7 @@
version: 0}}}}));
var chromeNotificationsCreateSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- chrome_notifications_create(
+ instrumented_notifications_create(
chromeNotificationsCreateSavedArgs.match(eq(testCardId)),
chromeNotificationsCreateSavedArgs.match(eqJSON(testNotification)),
chromeNotificationsCreateSavedArgs.match(ANYTHING)).
@@ -400,7 +400,7 @@
var test = setUpCardManagerTest(this);
var storageGetSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- storage_get(
+ instrumented_storage_local_get(
storageGetSavedArgs.match(eq('notificationsData')),
storageGetSavedArgs.match(ANYTHING)).
will(invokeCallback(
@@ -417,7 +417,7 @@
previousVersion:0}}}}));
var chromeNotificationsCreateSavedArgs = new SaveMockArguments();
this.mockApis.expects(once()).
- chrome_notifications_update(
+ instrumented_notifications_update(
testCardId, eqJSON(testNotification), ANYTHING);
// Call tested method.
diff --git a/chrome/browser/resources/google_now/utility.js b/chrome/browser/resources/google_now/utility.js
index 0ab7c4b..12e9f93 100644
--- a/chrome/browser/resources/google_now/utility.js
+++ b/chrome/browser/resources/google_now/utility.js
@@ -55,6 +55,9 @@
return request;
}
+// Partial mirror of chrome.* for all instrumented functions.
+var instrumented = {};
+
/**
* Builds the object to manage tasks (mutually exclusive chains of events).
* @param {function(string, string): boolean} areConflicting Function that
@@ -296,37 +299,75 @@
}
/**
- * Instruments an API function to add error processing to its user
- * code-provided callback.
- * @param {Object} namespace Namespace of the API function.
- * @param {string} functionName Name of the API function.
+ * Returns an instrumented function.
+ * @param {array} functionIdentifierParts Path to the chrome.* function.
+ * @param {string} functionName Name of the chrome API function.
* @param {number} callbackParameter Index of the callback parameter to this
* API function.
+ * @return {function} An instrumented function.
*/
- function instrumentApiFunction(namespace, functionName, callbackParameter) {
- var originalFunction = namespace[functionName];
-
- if (!originalFunction)
- debugAlert('Cannot instrument ' + functionName);
-
- namespace[functionName] = function() {
+ function createInstrumentedFunction(
+ functionIdentifierParts,
+ functionName,
+ callbackParameter) {
+ return function() {
// This is the wrapper for the API function. Pass the wrapped callback to
// the original function.
var callback = arguments[callbackParameter];
if (typeof callback != 'function') {
- debugAlert('Argument ' + callbackParameter + ' of ' + functionName +
- ' is not a function');
+ debugAlert('Argument ' + callbackParameter + ' of ' +
+ functionIdentifierParts.join('.') + '.' + functionName +
+ ' is not a function');
}
arguments[callbackParameter] = wrapCallback(
callback, functionName == 'addListener');
- return originalFunction.apply(namespace, arguments);
+
+ var chromeContainer = chrome;
+ functionIdentifierParts.map(function(fragment) {
+ chromeContainer = chromeContainer[fragment];
+ });
+ return chromeContainer[functionName].
+ apply(chromeContainer, arguments);
};
}
- instrumentApiFunction(chrome.alarms, 'get', 1);
- instrumentApiFunction(chrome.alarms.onAlarm, 'addListener', 0);
- instrumentApiFunction(chrome.identity, 'getAuthToken', 1);
- instrumentApiFunction(chrome.runtime.onSuspend, 'addListener', 0);
+ /**
+ * Instruments an API function to add error processing to its user
+ * code-provided callback.
+ * @param {string} functionIdentifier Full identifier of the function without
+ * the 'chrome.' portion.
+ * @param {number} callbackParameter Index of the callback parameter to this
+ * API function.
+ */
+ function instrumentChromeApiFunction(functionIdentifier, callbackParameter) {
+ var functionIdentifierParts = functionIdentifier.split('.');
+ var functionName = functionIdentifierParts.pop();
+ var chromeContainer = chrome;
+ var instrumentedContainer = instrumented;
+ functionIdentifierParts.map(function(fragment) {
+ chromeContainer = chromeContainer[fragment];
+ if (!(fragment in instrumentedContainer))
+ instrumentedContainer[fragment] = {};
+
+ instrumentedContainer = instrumentedContainer[fragment];
+ });
+
+ var targetFunction = chromeContainer[functionName];
+
+ if (!targetFunction)
+ debugAlert('Cannot instrument ' + functionName);
+
+ instrumentedContainer[functionName] = createInstrumentedFunction(
+ functionIdentifierParts,
+ functionName,
+ callbackParameter);
+ }
+
+ instrumentChromeApiFunction('alarms.get', 1);
+ instrumentChromeApiFunction('alarms.onAlarm.addListener', 0);
+ instrumentChromeApiFunction('identity.getAuthToken', 1);
+ instrumentChromeApiFunction('identity.removeCachedAuthToken', 1);
+ instrumentChromeApiFunction('runtime.onSuspend.addListener', 0);
chrome.runtime.onSuspend.addListener(function() {
var stringifiedPendingCallbacks = JSON.stringify(pendingCallbacks);
@@ -340,13 +381,11 @@
return {
add: add,
debugSetStepName: function() {}, // TODO(vadimt): remove
- instrumentApiFunction: instrumentApiFunction,
+ instrumentChromeApiFunction: instrumentChromeApiFunction,
wrapCallback: wrapCallback
};
}
-var storage = chrome.storage.local;
-
/**
* Builds an object to manage retrying activities with exponential backoff.
* @param {string} name Name of this attempt manager.
@@ -380,7 +419,7 @@
* true if the attempt manager has started, false otherwise.
*/
function isRunning(callback) {
- chrome.alarms.get(alarmName, function(alarmInfo) {
+ instrumented.alarms.get(alarmName, function(alarmInfo) {
callback(!!alarmInfo);
});
}
@@ -401,7 +440,7 @@
var items = {};
items[currentDelayStorageKey] = newRetryDelaySeconds;
- storage.set(items);
+ chrome.storage.local.set(items);
}
/**
@@ -413,7 +452,7 @@
function start(opt_firstDelaySeconds) {
if (opt_firstDelaySeconds) {
createAlarm(opt_firstDelaySeconds);
- storage.remove(currentDelayStorageKey);
+ chrome.storage.local.remove(currentDelayStorageKey);
} else {
scheduleNextAttempt();
}
@@ -424,7 +463,7 @@
*/
function stop() {
chrome.alarms.clear(alarmName);
- storage.remove(currentDelayStorageKey);
+ chrome.storage.local.remove(currentDelayStorageKey);
}
/**
@@ -433,14 +472,14 @@
* the planning is done.
*/
function planForNext(callback) {
- storage.get(currentDelayStorageKey, function(items) {
+ instrumented.storage.local.get(currentDelayStorageKey, function(items) {
console.log('planForNext-get-storage ' + JSON.stringify(items));
scheduleNextAttempt(items[currentDelayStorageKey]);
callback();
});
}
- chrome.alarms.onAlarm.addListener(function(alarm) {
+ instrumented.alarms.onAlarm.addListener(function(alarm) {
if (alarm.name == alarmName)
isRunning(function(running) {
if (running)
@@ -474,7 +513,7 @@
* If the user is signed in, the string contains the token.
*/
function isSignedIn(callback) {
- chrome.identity.getAuthToken({interactive: false}, function(token) {
+ instrumented.identity.getAuthToken({interactive: false}, function(token) {
token = chrome.runtime.lastError ? undefined : token;
callback(token);
checkAndNotifyListeners(!!token);
@@ -487,7 +526,7 @@
* @param {function} onSuccess Called on completion.
*/
function removeToken(token, onSuccess) {
- chrome.identity.removeCachedAuthToken({token: token}, function() {
+ instrumented.identity.removeCachedAuthToken({token: token}, function() {
// Removing the token from the cache will change the sign in state.
// Repoll now to check the state and notify listeners.
// This also lets Chrome now about a possible problem with the token.
@@ -522,7 +561,7 @@
lastReturnedSignedInState = currentSignedInState;
}
- chrome.alarms.onAlarm.addListener(function(alarm) {
+ instrumented.alarms.onAlarm.addListener(function(alarm) {
if (alarm.name == alarmName)
isSignedIn(function() {});
});
diff --git a/chrome/browser/resources/history/history.css b/chrome/browser/resources/history/history.css
index c929298..61bddb3 100644
--- a/chrome/browser/resources/history/history.css
+++ b/chrome/browser/resources/history/history.css
@@ -352,6 +352,7 @@
text-align: right;
text-overflow: ellipsis;
white-space: nowrap;
+ width: 60px;
}
html[dir='rtl'] .entry .time {
diff --git a/chrome/browser/resources/history/history.js b/chrome/browser/resources/history/history.js
index 1f688e5..1227c99 100644
--- a/chrome/browser/resources/history/history.js
+++ b/chrome/browser/resources/history/history.js
@@ -17,6 +17,9 @@
// with IDs greater than this will be included in this bucket.
/** @const */ var UMA_MAX_BUCKET_VALUE = 1000;
+// The largest bucket value for a UMA histogram that is a subset of above.
+/** @const */ var UMA_MAX_SUBSET_BUCKET_VALUE = 100;
+
// TODO(glen): Get rid of these global references, replace with a controller
// or just make the classes own more of the page.
var historyModel;
@@ -62,14 +65,15 @@
* Record a histogram value in UMA. If specified value is larger than the max
* bucket value, record the value in the largest bucket.
* @param {string} histogram The name of the histogram to be recorded in.
+ * @param {integer} maxBucketValue The max value for the last histogram bucket.
* @param {integer} value The value to record in the histogram.
*/
-function recordUmaHistogram(histogram, value) {
+function recordUmaHistogram(histogram, maxBucketValue, value) {
chrome.send('metricsHandler:recordInHistogram',
[histogram,
- ((value > UMA_MAX_BUCKET_VALUE) ? UMA_MAX_BUCKET_VALUE : value),
- UMA_MAX_BUCKET_VALUE]);
+ ((value > maxBucketValue) ? maxBucketValue : value),
+ maxBucketValue]);
}
///////////////////////////////////////////////////////////////////////////////
@@ -343,7 +347,14 @@
recordUmaAction('HistoryPage_EntryLinkClick');
// Record the ID of the entry to signify how many entries are above this
// link on the page.
- recordUmaHistogram('HistoryPage.ClickPosition', integerId);
+ recordUmaHistogram('HistoryPage.ClickPosition',
+ UMA_MAX_BUCKET_VALUE,
+ integerId);
+ if (integerId <= UMA_MAX_SUBSET_BUCKET_VALUE) {
+ recordUmaHistogram('HistoryPage.ClickPositionSubset',
+ UMA_MAX_SUBSET_BUCKET_VALUE,
+ integerId);
+ }
});
link.addEventListener('contextmenu', function() {
recordUmaAction('HistoryPage_EntryLinkRightClick');
@@ -1508,6 +1519,9 @@
});
}
+ if (!loadTimeData.getBoolean('showDeleteVisitUI'))
+ $('remove-visit').hidden = true;
+
searchField.addEventListener('search', doSearch);
$('search-button').addEventListener('click', doSearch);
@@ -1658,7 +1672,14 @@
var integerId = parseInt(entry.visit.id_, 10);
// Record the ID of the entry to signify how many entries are above this
// link on the page.
- recordUmaHistogram('HistoryPage.RemoveEntryPosition', integerId);
+ recordUmaHistogram('HistoryPage.RemoveEntryPosition',
+ UMA_MAX_BUCKET_VALUE,
+ integerId);
+ if (integerId <= UMA_MAX_SUBSET_BUCKET_VALUE) {
+ recordUmaHistogram('HistoryPage.RemoveEntryPositionSubset',
+ UMA_MAX_SUBSET_BUCKET_VALUE,
+ integerId);
+ }
if (entry.parentNode.className == 'search-results')
recordUmaAction('HistoryPage_SearchResultRemove');
}
diff --git a/chrome/browser/resources/history/history_focus_manager.js b/chrome/browser/resources/history/history_focus_manager.js
index 540f331..2d01f5c 100644
--- a/chrome/browser/resources/history/history_focus_manager.js
+++ b/chrome/browser/resources/history/history_focus_manager.js
@@ -20,6 +20,8 @@
/** @override */
getFocusParent: function() {
- return document.querySelector('#overlay .showing') || $('history-page');
+ return document.querySelector('#overlay .showing') ||
+ document.querySelector('menu:not([hidden])') ||
+ $('history-page');
},
};
diff --git a/chrome/browser/resources/history/history_mobile.css b/chrome/browser/resources/history/history_mobile.css
index dc7681f..41268f5 100644
--- a/chrome/browser/resources/history/history_mobile.css
+++ b/chrome/browser/resources/history/history_mobile.css
@@ -52,7 +52,7 @@
-webkit-padding-start: 64px;
background-image:
url('../../../../ui/webui/resources/images/2x/search.png');
- background-position: left 16px center;
+ background-position: 16px center;
background-repeat: no-repeat;
background-size: 32px;
border: 0;
@@ -242,6 +242,13 @@
display: none;
}
+.entry .time {
+ line-height: 60px;
+ min-width: 90px;
+ text-align: inherit;
+ width: 90px;
+}
+
@media only screen and (max-width:600px) {
/* Omit the time on very small screens. */
diff --git a/chrome/browser/resources/local_ntp/local_ntp.css b/chrome/browser/resources/local_ntp/local_ntp.css
index 8c1dec4..14d5275 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.css
+++ b/chrome/browser/resources/local_ntp/local_ntp.css
@@ -108,6 +108,11 @@
opacity: 0;
}
}
+
+body.fakebox-drag-focused #cursor {
+ visibility: inherit;
+}
+
body.fakebox-focused #cursor {
-webkit-animation: blink 1.3s step-end infinite;
visibility: inherit;
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js
index ab514df..b387819 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -28,6 +28,8 @@
DELAYED_HIDE_NOTIFICATION: 'mv-notice-delayed-hide',
FAKEBOX_DISABLE: 'fakebox-disable', // Makes fakebox non-interactive
FAKEBOX_FOCUS: 'fakebox-focused', // Applies focus styles to the fakebox
+ // Applies drag focus style to the fakebox
+ FAKEBOX_DRAG_FOCUS: 'fakebox-drag-focused',
FAVICON: 'mv-favicon',
HIDE_BLACKLIST_BUTTON: 'mv-x-hide', // hides blacklist button during animation
HIDE_FAKEBOX_AND_LOGO: 'hide-fakebox-logo',
@@ -55,6 +57,7 @@
ATTRIBUTION_TEXT: 'attribution-text',
CUSTOM_THEME_STYLE: 'ct-style',
FAKEBOX: 'fakebox',
+ FAKEBOX_INPUT: 'fakebox-input',
LOGO: 'logo',
NOTIFICATION: 'mv-notice',
NOTIFICATION_CLOSE_BUTTON: 'mv-notice-x',
@@ -770,6 +773,7 @@
function onInputStart() {
if (fakebox && isFakeboxFocused()) {
setFakeboxFocus(false);
+ setFakeboxDragFocus(false);
disposeNtp(true);
} else if (!isFakeboxFocused()) {
disposeNtp(false);
@@ -806,12 +810,19 @@
document.body.classList.toggle(CLASSES.FAKEBOX_FOCUS, focus);
}
+/**
+ * @param {boolean} focus True to show a dragging focus to the fakebox.
+ */
+function setFakeboxDragFocus(focus) {
+ document.body.classList.toggle(CLASSES.FAKEBOX_DRAG_FOCUS, focus);
+}
/**
* @return {boolean} True if the fakebox has focus.
*/
function isFakeboxFocused() {
- return document.body.classList.contains(CLASSES.FAKEBOX_FOCUS);
+ return document.body.classList.contains(CLASSES.FAKEBOX_FOCUS) ||
+ document.body.classList.contains(CLASSES.FAKEBOX_DRAG_FOCUS);
}
@@ -947,7 +958,8 @@
fakebox = document.createElement('div');
fakebox.id = IDS.FAKEBOX;
fakebox.innerHTML =
- '<input autocomplete="off" tabindex="-1" aria-hidden="true">' +
+ '<input id="' + IDS.FAKEBOX_INPUT +
+ '" autocomplete="off" tabindex="-1" aria-hidden="true">' +
'<div id=cursor></div>';
ntpContents.insertBefore(fakebox, ntpContents.firstChild);
@@ -1011,7 +1023,7 @@
if (fakebox) {
// Listener for updating the key capture state.
- document.body.onclick = function(event) {
+ document.body.onmousedown = function(event) {
if (isFakeboxClick(event))
searchboxApiHandle.startCapturingKeyStrokes();
else if (isFakeboxFocused())
@@ -1020,6 +1032,26 @@
searchboxApiHandle.onkeycapturechange = function() {
setFakeboxFocus(searchboxApiHandle.isKeyCaptureEnabled);
};
+ var inputbox = $(IDS.FAKEBOX_INPUT);
+ if (inputbox) {
+ inputbox.onpaste = function(event) {
+ event.preventDefault();
+ searchboxApiHandle.paste();
+ };
+ inputbox.ondrop = function(event) {
+ event.preventDefault();
+ var text = event.dataTransfer.getData('text/plain');
+ if (text) {
+ searchboxApiHandle.paste(text);
+ }
+ };
+ inputbox.ondragenter = function() {
+ setFakeboxDragFocus(true);
+ };
+ inputbox.ondragleave = function() {
+ setFakeboxDragFocus(false);
+ };
+ }
}
if (searchboxApiHandle.rtl) {
diff --git a/chrome/browser/resources/managed_mode_block_interstitial.js b/chrome/browser/resources/managed_mode_block_interstitial.js
index f6d1049..313ba6e 100644
--- a/chrome/browser/resources/managed_mode_block_interstitial.js
+++ b/chrome/browser/resources/managed_mode_block_interstitial.js
@@ -8,10 +8,14 @@
}
function initialize() {
- $('request-access-button').onclick = function(event) {
- updateAfterRequestSent();
- sendCommand('request');
- };
+ if (loadTimeData.getBoolean('allowAccessRequests')) {
+ $('request-access-button').onclick = function(event) {
+ updateAfterRequestSent();
+ sendCommand('request');
+ };
+ } else {
+ $('request-access-button').hidden = true;
+ }
$('back-button').onclick = function(event) {
sendCommand('back');
};
diff --git a/chrome/browser/resources/net_internals/quic_view.html b/chrome/browser/resources/net_internals/quic_view.html
index 3f4a4b8..b40cedd 100644
--- a/chrome/browser/resources/net_internals/quic_view.html
+++ b/chrome/browser/resources/net_internals/quic_view.html
@@ -15,6 +15,7 @@
<thead>
<tr>
<th>Host</th>
+ <th>Version</th>
<th>Peer address</th>
<th>GUID</th>
<th>Active streams</th>
@@ -26,6 +27,7 @@
<td><span jscontent="host_port_pair"></span>
<span jscontent="$this.aliases ? $this.aliases.join(' ') : ''"></span>
</td>
+ <td jscontent="version"></td>
<td jscontent="peer_address"></td>
<td jscontent="guid"></td>
<td jscontent="open_streams"></td>
diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js
index 70830b0..e2e80fd 100644
--- a/chrome/browser/resources/options/browser_options.js
+++ b/chrome/browser/resources/options/browser_options.js
@@ -178,7 +178,9 @@
options.browser_options.ProfileList.decorate(profilesList);
profilesList.autoExpands = true;
+ // The profiles info data in |loadTimeData| might be stale.
this.setProfilesInfo_(loadTimeData.getValue('profilesInfo'));
+ chrome.send('requestProfilesInfo');
profilesList.addEventListener('change',
this.setProfileViewButtonsStatus_);
diff --git a/chrome/browser/resources/options/chromeos/internet_detail.js b/chrome/browser/resources/options/chromeos/internet_detail.js
index 45cc551..c3a8f36 100644
--- a/chrome/browser/resources/options/chromeos/internet_detail.js
+++ b/chrome/browser/resources/options/chromeos/internet_detail.js
@@ -820,7 +820,9 @@
if (data.type != Constants.TYPE_ETHERNET)
$('details-internet-disconnect').hidden = !data.connected;
- if (data.type == Constants.TYPE_WIMAX)
+ if (data.type == Constants.TYPE_WIMAX ||
+ data.type == Constants.TYPE_WIFI ||
+ data.type == Constants.TYPE_VPN)
$('details-internet-configure').hidden = false;
else
$('details-internet-configure').hidden = true;
@@ -879,7 +881,9 @@
$('details-internet-disconnect').hidden = true;
else
$('details-internet-disconnect').hidden = !data.connected;
- if (data.type == Constants.TYPE_WIMAX)
+ if (data.type == Constants.TYPE_WIMAX ||
+ data.type == Constants.TYPE_WIFI ||
+ data.type == Constants.TYPE_VPN)
$('details-internet-configure').hidden = false;
else
$('details-internet-configure').hidden = true;
diff --git a/chrome/browser/resources/options/clear_browser_data_overlay.html b/chrome/browser/resources/options/clear_browser_data_overlay.html
index 1c386d4..cde999e 100644
--- a/chrome/browser/resources/options/clear_browser_data_overlay.html
+++ b/chrome/browser/resources/options/clear_browser_data_overlay.html
@@ -12,21 +12,21 @@
data-type="number">
</select>
<div id="clear-data-checkboxes">
- <div class="checkbox">
+ <div id="delete-browsing-history-container" class="checkbox">
<label>
<input id="delete-browsing-history-checkbox"
pref="browser.clear_data.browsing_history" type="checkbox">
<span i18n-content="deleteBrowsingHistoryCheckbox"></span>
</label>
</div>
- <div class="checkbox">
+ <div id="delete-download-history-container" class="checkbox">
<label>
<input id="delete-download-history-checkbox"
pref="browser.clear_data.download_history" type="checkbox">
<span i18n-content="deleteDownloadHistoryCheckbox"></span>
</label>
</div>
- <div class="checkbox">
+ <div id="delete-cookies-container" class="checkbox">
<label>
<input id="delete-cookies-checkbox"
pref="browser.clear_data.cookies" type="checkbox">
@@ -36,35 +36,36 @@
class="clear-plugin-lso-data-disabled"></span>
</label>
</div>
- <div class="checkbox">
+ <div id="delete-cache-container" class="checkbox">
<label>
<input id="delete-cache-checkbox"
pref="browser.clear_data.cache" type="checkbox">
<span i18n-content="deleteCacheCheckbox"></span>
</label>
</div>
- <div class="checkbox">
+ <div id="delete-passwords-container" class="checkbox">
<label>
<input id="delete-passwords-checkbox"
pref="browser.clear_data.passwords" type="checkbox">
<span i18n-content="deletePasswordsCheckbox"></span>
</label>
</div>
- <div class="checkbox">
+ <div id="delete-form-data-container" class="checkbox">
<label>
<input id="delete-form-data-checkbox"
pref="browser.clear_data.form_data" type="checkbox">
<span i18n-content="deleteFormDataCheckbox"></span>
</label>
</div>
- <div class="checkbox">
+ <div id="delete-hosted-apps-data-container" class="checkbox">
<label>
<input id="delete-hosted-apps-data-checkbox"
pref="browser.clear_data.hosted_apps_data" type="checkbox">
<span i18n-content="deleteHostedAppsDataCheckbox"></span>
</label>
</div>
- <div class="checkbox pepper-flash-settings">
+ <div id="deauthorize-content-licenses-container"
+ class="checkbox pepper-flash-settings">
<label>
<input id="deauthorize-content-licenses-checkbox"
pref="browser.clear_data.content_licenses" type="checkbox">
diff --git a/chrome/browser/resources/options/clear_browser_data_overlay.js b/chrome/browser/resources/options/clear_browser_data_overlay.js
index c12315d..5fb745b 100644
--- a/chrome/browser/resources/options/clear_browser_data_overlay.js
+++ b/chrome/browser/resources/options/clear_browser_data_overlay.js
@@ -59,6 +59,9 @@
ClearBrowserDataOverlay.setClearingState(true);
chrome.send('performClearBrowserData');
};
+
+ var show = loadTimeData.getBoolean('showDeleteBrowsingHistoryCheckboxes');
+ this.showDeleteHistoryCheckboxes_(show);
},
// Set the enabled state of the commit button.
@@ -79,6 +82,13 @@
this.allowDeletingHistory_ = allowed;
},
+ showDeleteHistoryCheckboxes_: function(show) {
+ if (!show) {
+ $('delete-browsing-history-container').hidden = true;
+ $('delete-download-history-container').hidden = true;
+ }
+ },
+
/** @override */
didShowPage: function() {
var allowed = ClearBrowserDataOverlay.getInstance().allowDeletingHistory_;
diff --git a/chrome/browser/resources/options/import_data_overlay.css b/chrome/browser/resources/options/import_data_overlay.css
index 7bea409..d7c076d 100644
--- a/chrome/browser/resources/options/import_data_overlay.css
+++ b/chrome/browser/resources/options/import_data_overlay.css
@@ -2,6 +2,10 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
+#import-data-overlay {
+ width: 400px;
+}
+
#import-from-div {
margin-bottom: 20px;
}
diff --git a/chrome/browser/resources/options/import_data_overlay.html b/chrome/browser/resources/options/import_data_overlay.html
index 2b78735..5721508 100644
--- a/chrome/browser/resources/options/import_data_overlay.html
+++ b/chrome/browser/resources/options/import_data_overlay.html
@@ -98,6 +98,8 @@
<div id="import-throbber" class="throbber"></div>
<div class="button-strip">
<button id="import-data-cancel" i18n-content="cancel"></button>
+ <button id="import-choose-file" i18n-content="importChooseFile">
+ </button>
<button id="import-data-commit" class="default-button"
i18n-content="importCommit">
</button>
@@ -114,4 +116,7 @@
</div>
</div>
</div>
+ <div id="mac-password-keychain" class="gray-bottom-bar">
+ <span i18n-content="macPasswordKeychain"></span>
+ </div>
</div>
diff --git a/chrome/browser/resources/options/import_data_overlay.js b/chrome/browser/resources/options/import_data_overlay.js
index 8841b73..36bc866 100644
--- a/chrome/browser/resources/options/import_data_overlay.js
+++ b/chrome/browser/resources/options/import_data_overlay.js
@@ -42,6 +42,7 @@
$('import-browsers').onchange = function() {
self.updateCheckboxes_();
self.validateCommitButton_();
+ self.updateBottomBar_();
};
$('import-data-commit').onclick = function() {
@@ -57,6 +58,10 @@
ImportDataOverlay.dismiss();
};
+ $('import-choose-file').onclick = function() {
+ chrome.send('chooseBookmarksFile');
+ };
+
$('import-data-show-bookmarks-bar').onchange = function() {
// Note: The callback 'toggleShowBookmarksBar' is handled within the
// browser options handler -- rather than the import data handler --
@@ -93,6 +98,7 @@
for (var i = 0; i < checkboxes.length; i++)
this.setUpCheckboxState_(checkboxes[i], enabled);
$('import-data-commit').disabled = !enabled;
+ $('mac-password-keychain').hidden = !enabled;
},
/**
@@ -115,6 +121,10 @@
*/
updateCheckboxes_: function() {
var index = $('import-browsers').selectedIndex;
+ var bookmarksFileSelected = index == this.browserProfiles.length - 1;
+ $('import-choose-file').hidden = !bookmarksFileSelected;
+ $('import-data-commit').hidden = bookmarksFileSelected;
+
var browserProfile;
if (this.browserProfiles.length > index)
browserProfile = this.browserProfiles[index];
@@ -122,6 +132,7 @@
for (var i = 0; i < importOptions.length; i++) {
var checkbox = $('import-' + importOptions[i]);
var enable = browserProfile && browserProfile[importOptions[i]];
+ checkbox.checked = enable;
this.setUpCheckboxState_(checkbox, enable);
var checkboxWithLabel = $('import-' + importOptions[i] + '-with-label');
checkboxWithLabel.style.display = enable ? '' : 'none';
@@ -129,6 +140,19 @@
},
/**
+ * Show or hide gray message at the bottom.
+ * @private
+ */
+ updateBottomBar_: function() {
+ var index = $('import-browsers').selectedIndex;
+ var browserProfile;
+ if (this.browserProfiles.length > index)
+ browserProfile = this.browserProfiles[index];
+ var enable = browserProfile && browserProfile['show_bottom_bar'];
+ $('mac-password-keychain').hidden = !enable;
+ },
+
+ /**
* Update the supported browsers popup with given entries.
* @param {array} browsers List of supported browsers name.
* @private
@@ -155,6 +179,7 @@
this.updateCheckboxes_();
this.validateCommitButton_();
+ this.updateBottomBar_();
}
},
diff --git a/chrome/browser/resources/options/manage_profile_overlay.css b/chrome/browser/resources/options/manage_profile_overlay.css
index 5b5f093..4bbdb02 100644
--- a/chrome/browser/resources/options/manage_profile_overlay.css
+++ b/chrome/browser/resources/options/manage_profile_overlay.css
@@ -120,7 +120,8 @@
color: #999;
}
-#create-profile-managed-not-signed-in-label {
+#create-profile-managed-not-signed-in-label,
+#create-profile-managed-account-details-out-of-date-label {
white-space: pre-wrap;
word-wrap: break-word;
}
diff --git a/chrome/browser/resources/options/manage_profile_overlay.html b/chrome/browser/resources/options/manage_profile_overlay.html
index 2982a65..c81d543 100644
--- a/chrome/browser/resources/options/manage_profile_overlay.html
+++ b/chrome/browser/resources/options/manage_profile_overlay.html
@@ -79,9 +79,16 @@
<input id="create-profile-managed" type="checkbox">
<span id="create-profile-managed-signed-in">
<span id="create-profile-managed-signed-in-label"></span>
- <button id="create-profile-managed-signed-in-link"
+ <span id="create-profile-managed-account-details-out-of-date-label"
+ hidden>
+ </span>
+ <button id="create-profile-managed-signed-in-learn-more-link"
class="link-button" i18n-content="learnMore">
</button>
+ <button id="create-profile-managed-sign-in-again-link"
+ class="link-button"
+ i18n-content="manageProfilesManagedSignInAgainLink" hidden>
+ </button>
</span>
<span id="create-profile-managed-not-signed-in" hidden>
<span id="create-profile-managed-not-signed-in-label"
diff --git a/chrome/browser/resources/options/manage_profile_overlay.js b/chrome/browser/resources/options/manage_profile_overlay.js
index 497ca1e..533d029 100644
--- a/chrome/browser/resources/options/manage_profile_overlay.js
+++ b/chrome/browser/resources/options/manage_profile_overlay.js
@@ -82,7 +82,8 @@
chrome.send('removeProfileShortcut', [self.profileInfo_.filePath]);
};
- $('create-profile-managed-signed-in-link').onclick = function(event) {
+ $('create-profile-managed-signed-in-learn-more-link').onclick =
+ function(event) {
OptionsPage.navigateToPage('managedUserLearnMore');
return false;
};
@@ -97,6 +98,11 @@
SyncSetupOverlay.startSignIn();
};
+ $('create-profile-managed-sign-in-again-link').onclick = function(event) {
+ OptionsPage.closeOverlay();
+ SyncSetupOverlay.showSetupUI();
+ };
+
$('create-profile-managed').onchange = function(event) {
var createManagedProfile = $('create-profile-managed').checked;
$('select-existing-managed-profile-checkbox').disabled =
@@ -601,10 +607,13 @@
* will update additional UI elements.
* @param {string} email The email address of the currently signed-in user.
* An empty string indicates that the user is not signed in.
+ * @param {boolean} hasError Whether the user's sign-in credentials are
+ * still valid.
* @private
*/
- updateSignedInStatus_: function(email) {
+ updateSignedInStatus_: function(email, hasError) {
this.signedInEmail_ = email;
+ this.hasError_ = hasError;
var isSignedIn = email !== '';
$('create-profile-managed-signed-in').hidden = !isSignedIn;
$('create-profile-managed-not-signed-in').hidden = isSignedIn;
@@ -612,9 +621,19 @@
$('choose-existing-managed-profile').hidden = !isSignedIn;
if (isSignedIn) {
+ var accountDetailsOutOfDate =
+ $('create-profile-managed-account-details-out-of-date-label');
+ accountDetailsOutOfDate.textContent = loadTimeData.getStringF(
+ 'manageProfilesManagedAccountDetailsOutOfDate', email);
+ accountDetailsOutOfDate.hidden = !hasError;
+
$('create-profile-managed-signed-in-label').textContent =
loadTimeData.getStringF(
'manageProfilesManagedSignedInLabel', email);
+ $('create-profile-managed-signed-in-label').hidden = hasError;
+
+ $('create-profile-managed-sign-in-again-link').hidden = !hasError;
+ $('create-profile-managed-signed-in-learn-more-link').hidden = hasError;
}
},
@@ -629,7 +648,8 @@
*/
updateManagedUsersAllowed_: function(allowed) {
var isSignedIn = this.signedInEmail_ !== '';
- $('create-profile-managed').disabled = !isSignedIn || !allowed;
+ $('create-profile-managed').disabled =
+ !isSignedIn || !allowed || this.hasError_;
$('create-profile-managed-not-signed-in-link').hidden = !allowed;
if (!allowed) {
diff --git a/chrome/browser/resources/options/options_page.js b/chrome/browser/resources/options/options_page.js
index 67fbe2f..a9b7c84 100644
--- a/chrome/browser/resources/options/options_page.js
+++ b/chrome/browser/resources/options/options_page.js
@@ -3,6 +3,8 @@
// found in the LICENSE file.
cr.define('options', function() {
+ /** @const */ var FocusOutlineManager = cr.ui.FocusOutlineManager;
+
/////////////////////////////////////////////////////////////////////////////
// OptionsPage class:
@@ -279,8 +281,7 @@
// Change focus to the overlay if any other control was focused by keyboard
// before. Otherwise, no one should have focus.
if (document.activeElement != document.body) {
- if (document.documentElement.classList.contains(
- cr.ui.FocusOutlineManager.CLASS_NAME)) {
+ if (FocusOutlineManager.forDocument(document).visible) {
overlay.focus();
} else {
document.activeElement.blur();
@@ -648,7 +649,7 @@
OptionsPage.initialize = function() {
chrome.send('coreOptionsInitialize');
uber.onContentFrameLoaded();
- cr.ui.FocusOutlineManager.forDocument(document);
+ FocusOutlineManager.forDocument(document);
document.addEventListener('scroll', this.handleScroll_.bind(this));
// Trigger the scroll handler manually to set the initial state.
diff --git a/chrome/browser/resources/options/reset_profile_settings_overlay.css b/chrome/browser/resources/options/reset_profile_settings_overlay.css
index f8b838c..9fa3b8e 100644
--- a/chrome/browser/resources/options/reset_profile_settings_overlay.css
+++ b/chrome/browser/resources/options/reset_profile_settings_overlay.css
@@ -11,13 +11,3 @@
vertical-align: middle;
visibility: hidden;
}
-
-.feedback-area {
- background-color: #f5f5f5;
- border-color: #e7e7e7;
- border-top-style: solid;
- border-width: 1px;
- color: #888;
- display: -webkit-box;
- padding: 14px 17px;
-}
diff --git a/chrome/browser/resources/options/reset_profile_settings_overlay.html b/chrome/browser/resources/options/reset_profile_settings_overlay.html
index b2fa0bc..5c96eaa 100644
--- a/chrome/browser/resources/options/reset_profile_settings_overlay.html
+++ b/chrome/browser/resources/options/reset_profile_settings_overlay.html
@@ -21,7 +21,7 @@
</div>
</div>
</div>
- <div class="feedback-area checkbox">
+ <div class="gray-bottom-bar checkbox">
<input id="send-settings" type="checkbox" checked=true>
<label for="send-settings" i18n-content="resetProfileSettingsFeedback">
</label>
diff --git a/chrome/browser/resources/performance_monitor/chart.html b/chrome/browser/resources/performance_monitor/chart.html
index 2f2faed..38f1f6a 100644
--- a/chrome/browser/resources/performance_monitor/chart.html
+++ b/chrome/browser/resources/performance_monitor/chart.html
@@ -20,7 +20,7 @@
<div id="warnings-text">
<span id="flag-not-enabled-warning" class="warning">
<span i18n-content="flagNotEnabledWarning"></span>
- <a target="blank_" i18n-content="enableFlag"
+ <a target="_blank" i18n-content="enableFlag"
i18n-values="href:enableFlagsURL">
</a>
</span>
diff --git a/chrome/browser/resources/user_chooser/control_bar.css b/chrome/browser/resources/user_manager/control_bar.css
similarity index 100%
rename from chrome/browser/resources/user_chooser/control_bar.css
rename to chrome/browser/resources/user_manager/control_bar.css
diff --git a/chrome/browser/resources/user_chooser/control_bar.html b/chrome/browser/resources/user_manager/control_bar.html
similarity index 100%
rename from chrome/browser/resources/user_chooser/control_bar.html
rename to chrome/browser/resources/user_manager/control_bar.html
diff --git a/chrome/browser/resources/user_chooser/control_bar.js b/chrome/browser/resources/user_manager/control_bar.js
similarity index 100%
rename from chrome/browser/resources/user_chooser/control_bar.js
rename to chrome/browser/resources/user_manager/control_bar.js
diff --git a/chrome/browser/resources/user_chooser/user_chooser.html b/chrome/browser/resources/user_manager/user_manager.html
similarity index 93%
rename from chrome/browser/resources/user_chooser/user_chooser.html
rename to chrome/browser/resources/user_manager/user_manager.html
index 024693a..bb656f7 100644
--- a/chrome/browser/resources/user_chooser/user_chooser.html
+++ b/chrome/browser/resources/user_manager/user_manager.html
@@ -8,7 +8,7 @@
<link rel="stylesheet" href="../chromeos/login/screen_container.css">
<link rel="stylesheet" href="../chromeos/login/oobe.css">
<link rel="stylesheet" href="../chromeos/login/user_pod_row.css">
-<!-- desktop user chooser specific overrides -->
+<!-- desktop user manager specific overrides -->
<link rel="stylesheet" href="control_bar.css">
<!-- framework imports -->
<!-- as per chrome/browser/resources/chromeos/login/login_resources.html -->
@@ -28,8 +28,8 @@
<script src="chrome://resources/js/cr/ui/menu_button.js"></script>
<script src="chrome://resources/js/load_time_data.js"></script>
<script src="chrome://resources/js/util.js"></script>
-<script src="user_chooser.js"></script>
-<script src="chrome://user-chooser/strings.js"></script>
+<script src="user_manager.js"></script>
+<script src="chrome://user-manager/strings.js"></script>
</head>
<body class="login-display" i18n-values=".style.fontFamily:fontfamily;">
<div id="outer-container">
diff --git a/chrome/browser/resources/user_chooser/user_chooser.js b/chrome/browser/resources/user_manager/user_manager.js
similarity index 93%
rename from chrome/browser/resources/user_chooser/user_chooser.js
rename to chrome/browser/resources/user_manager/user_manager.js
index a98e703..c1da909 100644
--- a/chrome/browser/resources/user_chooser/user_chooser.js
+++ b/chrome/browser/resources/user_manager/user_manager.js
@@ -31,7 +31,7 @@
* Shows the given screen.
* @param {Object} screen Screen params dict, e.g. {id: screenId, data: data}
*/
- Oobe.showUserChooserScreen = function() {
+ Oobe.showUserManagerScreen = function() {
Oobe.getInstance().showScreen({id: 'account-picker',
data: {disableAddUser: false}});
// The ChromeOS account-picker will hide the AddUser button if a user is
@@ -89,14 +89,14 @@
};
});
-cr.define('UserChooser', function() {
+cr.define('UserManager', function() {
'use strict';
function initialize() {
login.AccountPickerScreen.register();
cr.ui.Bubble.decorate($('bubble'));
login.HeaderBar.decorate($('login-header-bar'));
- chrome.send('userChooserInitialize');
+ chrome.send('userManagerInitialize');
}
// Return an object with all of the exports.
@@ -116,4 +116,4 @@
/text|password|search/.test(src.type);
});
-document.addEventListener('DOMContentLoaded', UserChooser.initialize);
+document.addEventListener('DOMContentLoaded', UserManager.initialize);
diff --git a/chrome/browser/rlz/rlz.cc b/chrome/browser/rlz/rlz.cc
index dd153fd..4aa8b5f 100644
--- a/chrome/browser/rlz/rlz.cc
+++ b/chrome/browser/rlz/rlz.cc
@@ -337,10 +337,11 @@
}
void RLZTracker::ScheduleFinancialPing() {
- BrowserThread::GetBlockingPool()->PostSequencedWorkerTask(
+ BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
worker_pool_token_,
FROM_HERE,
- base::Bind(&RLZTracker::PingNowImpl, base::Unretained(this)));
+ base::Bind(&RLZTracker::PingNowImpl, base::Unretained(this)),
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
}
void RLZTracker::PingNowImpl() {
@@ -436,11 +437,12 @@
if (!BrowserThread::CurrentlyOn(BrowserThread::UI))
return false;
- BrowserThread::GetBlockingPool()->PostSequencedWorkerTask(
+ BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
worker_pool_token_,
FROM_HERE,
base::Bind(base::IgnoreResult(&RLZTracker::RecordProductEvent),
- product, point, event_id));
+ product, point, event_id),
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
return true;
}
@@ -465,11 +467,12 @@
bool RLZTracker::ScheduleRecordFirstSearch(rlz_lib::AccessPoint point) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI))
return false;
- BrowserThread::GetBlockingPool()->PostSequencedWorkerTask(
+ BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
worker_pool_token_,
FROM_HERE,
base::Bind(&RLZTracker::RecordFirstSearch,
- base::Unretained(this), point));
+ base::Unretained(this), point),
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
return true;
}
@@ -534,11 +537,12 @@
return false;
string16* not_used = NULL;
- BrowserThread::GetBlockingPool()->PostSequencedWorkerTask(
+ BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
worker_pool_token_,
FROM_HERE,
base::Bind(base::IgnoreResult(&RLZTracker::GetAccessPointRlz), point,
- not_used));
+ not_used),
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
return true;
}
@@ -558,11 +562,12 @@
if (!BrowserThread::CurrentlyOn(BrowserThread::UI))
return false;
- BrowserThread::GetBlockingPool()->PostSequencedWorkerTask(
+ BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
worker_pool_token_,
FROM_HERE,
base::Bind(&RLZTracker::ClearRlzStateImpl,
- base::Unretained(this)));
+ base::Unretained(this)),
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
return true;
}
#endif
diff --git a/chrome/browser/safe_browsing/malware_details_unittest.cc b/chrome/browser/safe_browsing/malware_details_unittest.cc
index 7389893..251ce98 100644
--- a/chrome/browser/safe_browsing/malware_details_unittest.cc
+++ b/chrome/browser/safe_browsing/malware_details_unittest.cc
@@ -117,7 +117,6 @@
GetCache()->GetBackend(&cache, cb.callback());
ASSERT_EQ(net::OK, cb.GetResult(rv));
- std::string empty;
WriteToEntry(cache, kMalwareURL, kMalwareHeaders, kMalwareData);
WriteToEntry(cache, kLandingURL, kLandingHeaders, kLandingData);
}
diff --git a/chrome/browser/search/search.cc b/chrome/browser/search/search.cc
index dca93cd..1328ffe 100644
--- a/chrome/browser/search/search.cc
+++ b/chrome/browser/search/search.cc
@@ -11,6 +11,7 @@
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
+#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/profiles/profile.h"
@@ -73,6 +74,34 @@
// Remember if we reported metrics about opt-in/out state.
bool instant_extended_opt_in_state_gate = false;
+// Used to set the Instant support state of the Navigation entry.
+const char kInstantSupportStateKey[] = "instant_support_state";
+
+const char kInstantSupportEnabled[] = "Instant support enabled";
+const char kInstantSupportDisabled[] = "Instant support disabled";
+const char kInstantSupportUnknown[] = "Instant support unknown";
+
+InstantSupportState StringToInstantSupportState(const string16& value) {
+ if (value == ASCIIToUTF16(kInstantSupportEnabled))
+ return INSTANT_SUPPORT_YES;
+ else if (value == ASCIIToUTF16(kInstantSupportDisabled))
+ return INSTANT_SUPPORT_NO;
+ else
+ return INSTANT_SUPPORT_UNKNOWN;
+}
+
+string16 InstantSupportStateToString(InstantSupportState state) {
+ switch (state) {
+ case INSTANT_SUPPORT_NO:
+ return ASCIIToUTF16(kInstantSupportDisabled);
+ case INSTANT_SUPPORT_YES:
+ return ASCIIToUTF16(kInstantSupportEnabled);
+ case INSTANT_SUPPORT_UNKNOWN:
+ return ASCIIToUTF16(kInstantSupportUnknown);
+ }
+ return ASCIIToUTF16(kInstantSupportUnknown);
+}
+
TemplateURL* GetDefaultSearchProviderTemplateURL(Profile* profile) {
TemplateURLService* template_url_service =
TemplateURLServiceFactory::GetForProfile(profile);
@@ -197,7 +226,7 @@
string16 GetSearchTermsImpl(const content::WebContents* contents,
const content::NavigationEntry* entry) {
- if (!IsQueryExtractionEnabled())
+ if (!contents || !IsQueryExtractionEnabled())
return string16();
// For security reasons, don't extract search terms if the page is not being
@@ -299,6 +328,14 @@
if (!entry)
return string16();
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+ // iOS and Android doesn't use the Instant framework, disable this check for
+ // the two platforms.
+ InstantSupportState state = GetInstantSupportStateFromNavigationEntry(*entry);
+ if (state == INSTANT_SUPPORT_NO)
+ return string16();
+#endif // !defined(OS_IOS) && !defined(OS_ANDROID)
+
return GetSearchTermsImpl(contents, entry);
}
@@ -556,6 +593,23 @@
return true;
}
+void SetInstantSupportStateInNavigationEntry(InstantSupportState state,
+ content::NavigationEntry* entry) {
+ if (!entry)
+ return;
+
+ entry->SetExtraData(kInstantSupportStateKey,
+ InstantSupportStateToString(state));
+}
+
+InstantSupportState GetInstantSupportStateFromNavigationEntry(
+ const content::NavigationEntry& entry) {
+ string16 value;
+ if (!entry.GetExtraData(kInstantSupportStateKey, &value))
+ return INSTANT_SUPPORT_UNKNOWN;
+
+ return StringToInstantSupportState(value);
+}
void EnableInstantExtendedAPIForTesting() {
CommandLine* cl = CommandLine::ForCurrentProcess();
diff --git a/chrome/browser/search/search.h b/chrome/browser/search/search.h
index 83e660a..094f660 100644
--- a/chrome/browser/search/search.h
+++ b/chrome/browser/search/search.h
@@ -11,6 +11,7 @@
#include "base/basictypes.h"
#include "base/strings/string16.h"
+#include "chrome/browser/ui/search/search_model.h"
class GURL;
class Profile;
@@ -59,21 +60,25 @@
// Extracts and returns search terms from |url|. Returns empty string if the URL
// is not secure or doesn't have a search term replacement key. Does not
-// consider IsQueryExtractionEnabled() and does not check for a privileged
-// process, so most callers should use GetSearchTerms() below instead.
+// consider IsQueryExtractionEnabled() and Instant support state of the page and
+// does not check for a privileged process, so most callers should use
+// GetSearchTerms() below instead.
string16 GetSearchTermsFromURL(Profile* profile, const GURL& url);
// Returns the search terms attached to a specific NavigationEntry, or empty
-// string otherwise. Does not consider IsQueryExtractionEnabled(), so most
-// callers should use GetSearchTerms() below instead.
+// string otherwise. Does not consider IsQueryExtractionEnabled() and does not
+// check Instant support, so most callers should use GetSearchTerms() below
+// instead.
string16 GetSearchTermsFromNavigationEntry(
const content::NavigationEntry* entry);
// Returns search terms if this WebContents is a search results page. It looks
// in the visible NavigationEntry first, to see if search terms have already
// been extracted. Failing that, it tries to extract search terms from the URL.
+//
// Returns a blank string if search terms were not found, or if search terms
-// extraction is disabled for this WebContents or profile.
+// extraction is disabled for this WebContents or profile, or if |contents|
+// does not support Instant.
string16 GetSearchTerms(const content::WebContents* contents);
// Returns true if |url| should be rendered in the Instant renderer process.
@@ -168,6 +173,15 @@
bool HandleNewTabURLReverseRewrite(GURL* url,
content::BrowserContext* browser_context);
+// Sets the Instant support |state| in the navigation |entry|.
+void SetInstantSupportStateInNavigationEntry(InstantSupportState state,
+ content::NavigationEntry* entry);
+
+// Returns the Instant support state attached to the NavigationEntry, or
+// INSTANT_SUPPORT_UNKNOWN otherwise.
+InstantSupportState GetInstantSupportStateFromNavigationEntry(
+ const content::NavigationEntry& entry);
+
// -----------------------------------------------------
// The following APIs are exposed for use in tests only.
// -----------------------------------------------------
diff --git a/chrome/browser/search_engines/prepopulated_engines.json b/chrome/browser/search_engines/prepopulated_engines.json
index a4e7c94..c0fce8b 100644
--- a/chrome/browser/search_engines/prepopulated_engines.json
+++ b/chrome/browser/search_engines/prepopulated_engines.json
@@ -9,8 +9,8 @@
// definitions.
// The following unique IDs are available:
-// 53, 56, 58, 60, 61, 64, 65, 66, 70, 74, 78, 79, 80, 81, 84, 86, 88, 91,
-// 92, 93, 94, 95, 96, 97, 98, 99, 102+
+// 11, 12, 14, 18, 19, 20, 22, 24, 26, 28, 29, 30, 32, 33, 34, 39, 37, 38,
+// 40, 41, 42, 46, 47, 48, 49, 51, 52, 59, 71, 72, 82, 84, 86, 88, 89, 91+
//
// IDs > 1000 are reserved for distribution custom engines.
//
@@ -22,114 +22,42 @@
"int_variables": {
// The following id is for UMA stats only. Please update it if you add new
// engines outside the current range or it will not be counted in stats.
- "kMaxPrepopulatedEngineID": 101,
+ "kMaxPrepopulatedEngineID": 90,
// Increment this if you change the data in ways that mean users with
// existing data should get a new version.
- "kCurrentDataVersion": 58
+ "kCurrentDataVersion": 60
},
// The following engines are included in country lists and are added to the
// list of search engines on the first run depending on user's country.
"elements": {
- "abcsok": {
- "name": "ABC S\u00f8k",
- "keyword": "abcsok.no",
- "favicon_url": "http://abcsok.no/favicon.ico",
- "search_url": "http://abcsok.no/index.html?q={searchTerms}",
- "type": "SEARCH_ENGINE_ABCSOK",
- "id": 72
- },
-
- "altavista": {
- "name": "AltaVista",
- "keyword": "altavista.com",
- "favicon_url": "http://www.altavista.com/favicon.ico",
- "search_url": "http://www.altavista.com/web/results?q={searchTerms}",
- "type": "SEARCH_ENGINE_ALTAVISTA",
- "id": 89
- },
-
- "altavista_ar": {
- "name": "AltaVista",
- "keyword": "ar.altavista.com",
- "favicon_url": "http://ar.altavista.com/favicon.ico",
- "search_url": "http://ar.altavista.com/web/results?q={searchTerms}",
- "type": "SEARCH_ENGINE_ALTAVISTA",
- "id": 89
- },
-
- "altavista_se": {
- "name": "AltaVista",
- "keyword": "se.altavista.com",
- "favicon_url": "http://se.altavista.com/favicon.ico",
- "search_url": "http://se.altavista.com/web/results?q={searchTerms}",
- "type": "SEARCH_ENGINE_ALTAVISTA",
- "id": 89
- },
-
"aol": {
"name": "AOL",
"keyword": "aol.com",
"favicon_url": "http://search.aol.com/favicon.ico",
"search_url": "http://search.aol.com/aol/search?query={searchTerms}",
+ "suggest_url": "http://autocomplete.search.aol.com/autocomplete/get?output=json&it=&q={searchTerms}",
+ "type": "SEARCH_ENGINE_AOL",
"id": 35
},
- "araby": {
- "name": "\u0639\u0631\u0628\u064a",
- "keyword": "araby.com",
- "favicon_url": "http://araby.com/favicon.ico",
- "search_url": "http://araby.com/?q={searchTerms}",
- "id": 12
- },
-
"ask": {
"name": "Ask",
"keyword": "ask.com",
- "favicon_url": "http://www.ask.com/favicon.ico",
+ "favicon_url": "http://sp.ask.com/sh/i/a16/favicon/favicon.ico",
"search_url": "http://www.ask.com/web?q={searchTerms}",
"suggest_url": "http://ss.ask.com/query?q={searchTerms}&li=ff",
"type": "SEARCH_ENGINE_ASK",
"id": 4
},
- "ask_de": {
- "name": "Ask.com Deutschland",
- "keyword": "de.ask.com",
- "favicon_url": "http://de.ask.com/favicon.ico",
- "search_url": "http://de.ask.com/web?q={searchTerms}",
- "suggest_url": "http://ss.de.ask.com/query?q={searchTerms}&li=ff",
- "type": "SEARCH_ENGINE_ASK",
- "id": 4
- },
-
- "ask_es": {
- "name": "Ask.com Espa\u00f1a",
- "keyword": "es.ask.com",
- "favicon_url": "http://es.ask.com/favicon.ico",
- "search_url": "http://es.ask.com/web?q={searchTerms}",
- "suggest_url": "http://ss.es.ask.com/query?q={searchTerms}&li=ff",
- "type": "SEARCH_ENGINE_ASK",
- "id": 4
- },
-
- "ask_it": {
- "name": "Ask.com Italia",
- "keyword": "it.ask.com",
- "favicon_url": "http://it.ask.com/favicon.ico",
- "search_url": "http://it.ask.com/web?q={searchTerms}",
- "suggest_url": "http://ss.it.ask.com/query?q={searchTerms}&li=ff",
- "type": "SEARCH_ENGINE_ASK",
- "id": 4
- },
-
- "ask_nl": {
- "name": "Ask.com Nederland",
- "keyword": "nl.ask.com",
- "favicon_url": "http://nl.ask.com/favicon.ico",
- "search_url": "http://nl.ask.com/web?q={searchTerms}",
- "suggest_url": "http://ss.nl.ask.com/query?q={searchTerms}&li=ff",
+ "ask_br": {
+ "name": "Ask Brasil",
+ "keyword": "br.ask.com",
+ "favicon_url": "http://sp.br.ask.com/sh/i/a14/favicon/favicon.ico",
+ "search_url": "http://br.ask.com/web?q={searchTerms}",
+ "suggest_url": "http://ss.ask.com/query?q={searchTerms}&li=ff",
"type": "SEARCH_ENGINE_ASK",
"id": 4
},
@@ -137,36 +65,18 @@
"ask_uk": {
"name": "Ask Jeeves",
"keyword": "uk.ask.com",
- "favicon_url": "http://uk.ask.com/favicon.ico",
+ "favicon_url": "http://sp.uk.ask.com/sh/i/a16/favicon/favicon.ico",
"search_url": "http://uk.ask.com/web?q={searchTerms}",
"suggest_url": "http://ss.uk.ask.com/query?q={searchTerms}&li=ff",
"type": "SEARCH_ENGINE_ASK",
"id": 4
},
- "atlas_cz": {
- "name": "Atlas",
- "keyword": "atlas.cz",
- "favicon_url": "http://img.atlas.cz/favicon.ico",
- "search_url": "http://search.atlas.cz/?q={searchTerms}",
- "encoding": "windows-1250",
- "id": 27
- },
-
- "atlas_sk": {
- "name": "ATLAS.SK",
- "keyword": "atlas.sk",
- "favicon_url": "http://www.atlas.sk/images/favicon.ico",
- "search_url": "http://hladaj.atlas.sk/fulltext/?phrase={searchTerms}",
- "id": 27
- },
-
"baidu": {
"name": "\u767e\u5ea6",
"keyword": "baidu.com",
"favicon_url": "http://www.baidu.com/favicon.ico",
- "search_url": "http://www.baidu.com/s?wd={searchTerms}",
- "encoding": "GB2312",
+ "search_url": "http://www.baidu.com/s?ie={inputEncoding}&wd={searchTerms}",
"type": "SEARCH_ENGINE_BAIDU",
"id": 21
},
@@ -182,7 +92,7 @@
},
"bing_ar_XA": {
- "name": "Bing",
+ "name": "Bing (\u0627\u0644\u0639\u0631\u0628\u064a\u0629)",
"keyword": "bing.com_", // bing.com is taken by bing_en_XA.
"favicon_url": "http://www.bing.com/s/wlflag.ico",
"search_url": "http://www.bing.com/search?setmkt=ar-XA&q={searchTerms}",
@@ -192,26 +102,6 @@
// lists alongside bing_en_XA.
},
- "bing_bg_BG": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=bg-BG&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
- "bing_cs_CZ": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=cs-CZ&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
"bing_da_DK": {
"name": "Bing",
"keyword": "bing.com",
@@ -233,7 +123,7 @@
},
"bing_de_CH": {
- "name": "Bing",
+ "name": "Bing (Deutsch)",
"keyword": "bing.com",
"favicon_url": "http://www.bing.com/s/wlflag.ico",
"search_url": "http://www.bing.com/search?setmkt=de-CH&q={searchTerms}",
@@ -252,16 +142,6 @@
"id": 3
},
- "bing_el_GR": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=el-GR&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
"bing_en_AU": {
"name": "Bing",
"keyword": "bing.com",
@@ -273,7 +153,7 @@
},
"bing_en_CA": {
- "name": "Bing",
+ "name": "Bing (English)",
"keyword": "bing.com",
"favicon_url": "http://www.bing.com/s/wlflag.ico",
"search_url": "http://www.bing.com/search?setmkt=en-CA&q={searchTerms}",
@@ -292,16 +172,6 @@
"id": 3
},
- "bing_en_ID": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=en-ID&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
"bing_en_IE": {
"name": "Bing",
"keyword": "bing.com",
@@ -322,16 +192,6 @@
"id": 3
},
- "bing_en_MY": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=en-MY&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
"bing_en_NZ": {
"name": "Bing",
"keyword": "bing.com",
@@ -373,7 +233,7 @@
},
"bing_en_XA": {
- "name": "Bing",
+ "name": "Bing (English)",
"keyword": "bing.com",
"favicon_url": "http://www.bing.com/s/wlflag.ico",
"search_url": "http://www.bing.com/search?setmkt=en-XA&q={searchTerms}",
@@ -382,16 +242,6 @@
"id": 3
},
- "bing_en_ZA": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=en-ZA&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
"bing_es_AR": {
"name": "Bing",
"keyword": "bing.com",
@@ -442,16 +292,6 @@
"id": 3
},
- "bing_et_EE": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=et-EE&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
"bing_fi_FI": {
"name": "Bing",
"keyword": "bing.com",
@@ -463,7 +303,7 @@
},
"bing_fr_BE": {
- "name": "Bing",
+ "name": "Bing (Fran\u00e7ais)",
"keyword": "bing.com_", // bing.com is taken by bing_nl_BE.
"favicon_url": "http://www.bing.com/s/wlflag.ico",
"search_url": "http://www.bing.com/search?setmkt=fr-BE&q={searchTerms}",
@@ -473,7 +313,7 @@
},
"bing_fr_CA": {
- "name": "Bing",
+ "name": "Bing (Fran\u00e7ais)",
"keyword": "bing.com_", // bing.com is taken by bing_en_CA.
"favicon_url": "http://www.bing.com/s/wlflag.ico",
"search_url": "http://www.bing.com/search?setmkt=fr-CA&q={searchTerms}",
@@ -483,7 +323,7 @@
},
"bing_fr_CH": {
- "name": "Bing",
+ "name": "Bing (Fran\u00e7ais)",
"keyword": "bing.com_", // bing.com is taken by bing_de_CH.
"favicon_url": "http://www.bing.com/s/wlflag.ico",
"search_url": "http://www.bing.com/search?setmkt=fr-CH&q={searchTerms}",
@@ -502,36 +342,6 @@
"id": 3
},
- "bing_he_IL": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=he-IL&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
- "bing_hr_HR": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=hr-HR&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
- "bing_hu_HU": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=hu-HU&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
"bing_it_IT": {
"name": "Bing",
"keyword": "bing.com",
@@ -552,26 +362,6 @@
"id": 3
},
- "bing_ko_KR": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=ko-KR&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
- "bing_lt_LT": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=lt-LT&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
"bing_lv_LV": {
"name": "Bing",
"keyword": "bing.com",
@@ -593,7 +383,7 @@
},
"bing_nl_BE": {
- "name": "Bing",
+ "name": "Bing (Nederlandstalige)",
"keyword": "bing.com",
"favicon_url": "http://www.bing.com/s/wlflag.ico",
"search_url": "http://www.bing.com/search?setmkt=nl-BE&q={searchTerms}",
@@ -602,16 +392,6 @@
"id": 3
},
- "bing_nl_NL": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=nl-NL&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
"bing_pl_PL": {
"name": "Bing",
"keyword": "bing.com",
@@ -642,16 +422,6 @@
"id": 3
},
- "bing_ro_RO": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=ro-RO&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
"bing_ru_RU": {
"name": "Bing",
"keyword": "bing.com",
@@ -662,26 +432,6 @@
"id": 3
},
- "bing_sl_SI": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=sl-SI&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
- "bing_sk_SK": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=sk-SK&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
"bing_sv_SE": {
"name": "Bing",
"keyword": "bing.com",
@@ -692,16 +442,6 @@
"id": 3
},
- "bing_th_TH": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=th-TH&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
"bing_tr_TR": {
"name": "Bing",
"keyword": "bing.com",
@@ -712,26 +452,6 @@
"id": 3
},
- "bing_uk_UA": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=uk-UA&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
- "bing_zh_CN": {
- "name": "Bing",
- "keyword": "bing.com",
- "favicon_url": "http://www.bing.com/s/wlflag.ico",
- "search_url": "http://www.bing.com/search?setmkt=zh-CN&q={searchTerms}",
- "suggest_url": "http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
- "type": "SEARCH_ENGINE_BING",
- "id": 3
- },
-
"bing_zh_HK": {
"name": "Bing",
"keyword": "bing.com",
@@ -752,106 +472,25 @@
"id": 3
},
- "centrum_cz": {
- "name": "Centrum.cz",
- "keyword": "centrum.cz",
- "favicon_url": "http://img.centrum.cz/6/vy2/o/favicon.ico",
- "search_url": "http://search.centrum.cz/index.php?charset={inputEncoding}&q={searchTerms}",
- "type": "SEARCH_ENGINE_CENTRUM",
- "id": 26
- },
-
- "centrum_sk": {
- "name": "Centrum.sk",
- "keyword": "centrum.sk",
- "favicon_url": "http://img.centrum.sk/4/favicon.ico",
- "search_url": "http://search.centrum.sk/index.php?charset={inputEncoding}&q={searchTerms}",
- "type": "SEARCH_ENGINE_CENTRUM",
- "id": 26
- },
-
"daum": {
"name": "Daum",
"keyword": "daum.net",
- "favicon_url": "http://icon.daum-img.net/favicon.ico",
- "search_url": "http://search.daum.net/search?q={searchTerms}",
- "suggest_url": "http://sug.search.daum.net/search_nsuggest?mod=fxjson&code=utf_in_out&q={searchTerms}",
+ "favicon_url": "http://search.daum.net/favicon.ico",
+ "search_url": "http://search.daum.net/search?ie={inputEncoding}&q={searchTerms}",
+ "suggest_url": "http://sug.search.daum.net/search_nsuggest?mod=fxjson&ie={inputEncoding}&code=utf_in_out&q={searchTerms}",
"type": "SEARCH_ENGINE_DAUM",
"id": 68
},
- "delfi_lt": {
- "name": "DELFI",
- "keyword": "delfi.lt",
- "favicon_url": "http://search.delfi.lt/img/favicon.png",
- "search_url": "http://search.delfi.lt/search.php?q={searchTerms}",
- "type": "SEARCH_ENGINE_DELFI",
- "id": 45
- },
-
- "delfi_lv": {
- "name": "DELFI",
- "keyword": "delfi.lv",
- "favicon_url": "http://smart.delfi.lv/img/smart_search.png",
- "search_url": "http://smart.delfi.lv/i.php?enc={inputEncoding}&q={searchTerms}",
- "type": "SEARCH_ENGINE_DELFI",
- "id": 45
- },
-
- "diri": {
- "name": "diri",
- "keyword": "diri.bg",
- "favicon_url": "http://i.dir.bg/diri/images/favicon.ico",
- "search_url": "http://diri.bg/search.php?textfield={searchTerms}",
- "encoding": "windows-1251",
- "type": "SEARCH_ENGINE_DIRI",
- "id": 32
- },
-
- "eniro_fi": {
- "name": "Eniro",
- "keyword": "eniro.fi",
- "favicon_url": "http://eniro.fi/favicon.ico",
- "search_url": "http://eniro.fi/query?search_word={searchTerms}&what=web_local",
- "encoding": "ISO-8859-1",
- "id": 29
- },
-
- "eniro_se": {
- "name": "Eniro",
- "keyword": "eniro.se",
- "favicon_url": "http://eniro.se/favicon.ico",
- "search_url": "http://eniro.se/query?search_word={searchTerms}&what=web_local",
- "encoding": "ISO-8859-1",
- "id": 29
- },
-
- "fonecta_02_fi": {
- "name": "Fonecta 02.fi",
- "keyword": "www.fi",
- "favicon_url": "http://www.02.fi/img/favicon.ico",
- "search_url": "http://www.02.fi/haku/{searchTerms}",
- "id": 46
- },
-
- "goo": {
- "name": "goo",
- "keyword": "search.goo.ne.jp",
- "favicon_url": "http://goo.ne.jp/favicon.ico",
- "search_url": "http://search.goo.ne.jp/web.jsp?MT={searchTerms}&IE={inputEncoding}",
- "type": "SEARCH_ENGINE_GOO",
- "id": 23
- },
-
"google": {
"name": "Google",
"keyword": "google.com",
"favicon_url": "http://www.google.com/favicon.ico",
"search_url": "{google:baseURL}search?q={searchTerms}&{google:RLZ}{google:originalQueryForSuggestion}{google:assistedQueryStats}{google:searchFieldtrialParameter}{google:searchClient}{google:sourceId}{google:instantExtendedEnabledParameter}{google:omniboxStartMarginParameter}ie={inputEncoding}",
- "suggest_url": "{google:baseSuggestURL}search?{google:searchFieldtrialParameter}client={google:suggestClient}&q={searchTerms}&{google:cursorPosition}{google:zeroPrefixUrl}sugkey={google:suggestAPIKeyParameter}",
+ "suggest_url": "{google:baseSuggestURL}search?{google:searchFieldtrialParameter}client={google:suggestClient}&q={searchTerms}&{google:cursorPosition}{google:zeroPrefixUrl}{google:pageClassification}sugkey={google:suggestAPIKeyParameter}",
"instant_url": "{google:baseURL}webhp?sourceid=chrome-instant&{google:RLZ}{google:instantEnabledParameter}{google:instantExtendedEnabledParameter}{google:ntpIsThemedParameter}{google:omniboxStartMarginParameter}ie={inputEncoding}",
"image_url": "{google:baseURL}searchbyimage/upload",
- "image_url_post_params": "encoded_image={google:imageThumbnail},image_url={google:imageURL},sbisrc={google:imageSearchSource}",
+ "image_url_post_params": "image_content={google:imageThumbnail},image_url={google:imageURL},sbisrc={google:imageSearchSource}",
"alternate_urls": [
"{google:baseURL}#q={searchTerms}",
"{google:baseURL}search#q={searchTerms}",
@@ -862,85 +501,15 @@
"id": 1
},
- "guruji": {
- "name": "guruji",
- "keyword": "guruji.com",
- "favicon_url": "http://guruji.com/favicon.ico",
- "search_url": "http://guruji.com/search?q={searchTerms}",
- "id": 38
- },
-
- "hispavista": {
- "name": "hispavista",
- "keyword": "hispavista.com",
- "favicon_url": "http://buscar.hispavista.com/favicon.ico",
- "search_url": "http://buscar.hispavista.com/?cadena={searchTerms}",
- "encoding": "iso-8859-1",
- "id": 18
- },
-
- "in": {
- "name": "in.gr",
- "keyword": "in.gr",
- "favicon_url": "http://www.in.gr/favicon.ico",
- "search_url": "http://find.in.gr/?qs={searchTerms}",
- "encoding": "ISO-8859-7",
- "type": "SEARCH_ENGINE_IN",
- "id": 54
- },
-
- "jabse": {
- "name": "Jabse",
- "keyword": "jabse.com",
- "favicon_url": "http://www.jabse.com/favicon.ico",
- "search_url": "http://www.jabse.com/searchmachine.php?query={searchTerms}",
- "id": 19
- },
-
- "jubii": {
- "name": "Jubii",
- "keyword": "jubii.dk",
- "favicon_url": "http://search.jubii.dk/favicon_jubii.ico",
- "search_url": "http://search.jubii.dk/cgi-bin/pursuit?query={searchTerms}",
- "encoding": "ISO-8859-1",
- "id": 28
- },
-
"kvasir": {
"name": "Kvasir",
"keyword": "kvasir.no",
- "favicon_url": "http://www.kvasir.no/img/favicon.ico",
- "search_url": "http://www.kvasir.no/nettsok/searchResult.html?searchExpr={searchTerms}",
- "encoding": "ISO-8859-1",
+ "favicon_url": "http://www.kvasir.no/grafikk/favicon.ico",
+ "search_url": "http://www.kvasir.no/alle?q={searchTerms}",
+ "type": "SEARCH_ENGINE_KVASIR",
"id": 73
},
- "latne": {
- "name": "LATNE",
- "keyword": "latne.lv",
- "favicon_url": "http://latne.lv/favicon.ico",
- "search_url": "http://latne.lv/siets.php?q={searchTerms}",
- "id": 71
- },
-
- "leit": {
- "name": "leit.is",
- "keyword": "leit.is",
- "favicon_url": "http://leit.is/leit.ico",
- "search_url": "http://leit.is/query.aspx?qt={searchTerms}",
- "encoding": "ISO-8859-1",
- "id": 59
- },
-
- "libero": {
- "name": "Libero",
- "keyword": "libero.it",
- "favicon_url": "http://arianna.libero.it/favicon.ico",
- "search_url": "http://arianna.libero.it/search/abin/integrata.cgi?query={searchTerms}",
- "encoding": "ISO-8859-1",
- "id": 63
- },
-
"mail_ru": {
"name": "@MAIL.RU",
"keyword": "mail.ru",
@@ -952,177 +521,44 @@
"id": 83
},
- "maktoob": {
- "name": "\u0645\u0643\u062a\u0648\u0628",
- "keyword": "maktoob.com",
- "favicon_url": "http://www.maktoob.com/favicon.ico",
- "search_url": "http://www.maktoob.com/searchResult.php?q={searchTerms}",
- "id": 13
- },
-
- "masrawy": {
- "name": "\u0645\u0635\u0631\u0627\u0648\u064a",
- "keyword": "masrawy.com",
- "favicon_url": "http://www.masrawy.com/new/images/masrawy.ico",
- "search_url": "http://masrawy.com/new/search.aspx?sr={searchTerms}",
- "encoding": "windows-1256",
- "id": 14
- },
-
- "mynet": {
- "name": "MYNET",
- "keyword": "mynet.com",
- "favicon_url": "http://img.mynet.com/mynetfavori.ico",
- "search_url": "http://arama.mynet.com/search.aspx?q={searchTerms}&pg=q",
- "encoding": "windows-1254",
- "id": 101
- },
-
"najdi": {
"name": "Najdi.si",
"keyword": "najdi.si",
- "favicon_url": "http://www.najdi.si/master/favicon.ico",
+ "favicon_url": "http://nsi2.sdn.si/master/v2/favicon.ico",
"search_url": "http://www.najdi.si/search.jsp?q={searchTerms}",
"type": "SEARCH_ENGINE_NAJDI",
"id": 87
},
"nate": {
- "name": "\ub124\uc774\ud2b8\ub2f7\ucef4",
+ "name": "\ub124\uc774\ud2b8",
"keyword": "nate.com",
- "favicon_url": "http://nate.search.empas.com/favicon.ico",
- "search_url": "http://nate.search.empas.com/search/all.html?q={searchTerms}",
+ "favicon_url": "http://search.nate.com/favicon.ico",
+ "search_url": "http://search.nate.com/search/all.html?q={searchTerms}",
"encoding": "EUC-KR",
+ "type": "SEARCH_ENGINE_NATE",
"id": 69
},
"naver": {
"name": "\ub124\uc774\ubc84",
"keyword": "naver.com",
- "favicon_url": "http://search.naver.com/favicon.ico",
+ "favicon_url": "http://static.naver.net/www/favicon.ico",
"search_url": "http://search.naver.com/search.naver?ie={inputEncoding}&query={searchTerms}",
- "suggest_url": "http://ac.search.naver.com/autocompl?m=s&ie={inputEncoding}&oe=utf-8&q={searchTerms}",
+ "suggest_url": "http://ac.search.naver.com/autocompl?m=s&ie={inputEncoding}&oe={outputEncoding}&q={searchTerms}",
"type": "SEARCH_ENGINE_NAVER",
"id": 67
},
- "neti": {
- "name": "NETI",
- "keyword": "neti.ee",
- "favicon_url": "http://www.neti.ee/favicon.ico",
- "search_url": "http://www.neti.ee/cgi-bin/otsing?query={searchTerms}",
- "encoding": "ISO-8859-1",
- "type": "SEARCH_ENGINE_NETI",
- "id": 44
- },
-
- "netsprint": {
- "name": "NetSprint",
- "keyword": "netsprint.pl",
- "favicon_url": "http://netsprint.pl/favicon.ico",
- "search_url": "http://www.netsprint.pl/serwis/search?q={searchTerms}",
- "type": "SEARCH_ENGINE_NETSPRINT",
- "id": 30
- },
-
- "nur_kz": {
- "name": "NUR.KZ",
- "keyword": "nur.kz",
- "favicon_url": "http://www.nur.kz/favicon_kz.ico",
- "search_url": "http://search.nur.kz/?encoding={inputEncoding}&query={searchTerms}",
- "id": 20
- },
-
- "ok": {
- "name": "OK.hu",
- "keyword": "ok.hu",
- "favicon_url": "http://ok.hu/gfx/favicon.ico",
- "search_url": "http://ok.hu/katalogus?q={searchTerms}",
- "encoding": "ISO-8859-2",
- "type": "SEARCH_ENGINE_OK",
- "id": 6
- },
-
"onet": {
"name": "Onet.pl",
"keyword": "onet.pl",
"favicon_url": "http://szukaj.onet.pl/favicon.ico",
- "search_url": "http://szukaj.onet.pl/query.html?qt={searchTerms}",
- "encoding": "ISO-8859-2",
+ "search_url": "http://szukaj.onet.pl/wyniki.html?qt={searchTerms}",
+ "type": "SEARCH_ENGINE_ONET",
"id": 75
},
- "pogodak_rs": {
- "name": "Pogodak!",
- "keyword": "pogodak.rs",
- "favicon_url": "http://www.pogodak.rs/favicon.ico",
- "search_url": "http://www.pogodak.rs/search.jsp?q={searchTerms}",
- "type": "SEARCH_ENGINE_POGODAK",
- "id": 24
- },
-
- "rambler": {
- "name": "Rambler",
- "keyword": "rambler.ru",
- "favicon_url": "http://www.rambler.ru/favicon.ico",
- "search_url": "http://www.rambler.ru/srch?words={searchTerms}",
- "encoding": "windows-1251",
- "type": "SEARCH_ENGINE_RAMBLER",
- "id": 16
- },
-
- "rediff": {
- "name": "Rediff",
- "keyword": "rediff.com",
- "favicon_url": "http://search1.rediff.com/favicon.ico",
- "search_url": "http://search1.rediff.com/dirsrch/default.asp?MT={searchTerms}",
- "id": 37
- },
-
- "rednano": {
- "name": "Rednano",
- "keyword": "rednano.sg",
- "favicon_url": "http://rednano.sg/favicon.ico",
- "search_url": "http://rednano.sg/sfe/lwi.action?querystring={searchTerms}",
- "id": 41
- },
-
- "sanook": {
- "name": "\u0e2a\u0e19\u0e38\u0e01!",
- "keyword": "sanook.com",
- "favicon_url": "http://search.sanook.com/favicon.ico",
- "search_url": "http://search.sanook.com/search.php?q={searchTerms}",
- "type": "SEARCH_ENGINE_SANOOK",
- "id": 100
- },
-
- "sapo": {
- "name": "SAPO",
- "keyword": "sapo.pt",
- "favicon_url": "http://imgs.sapo.pt/images/sapo.ico",
- "search_url": "http://pesquisa.sapo.pt/?q={searchTerms}",
- "suggest_url": "http://pesquisa.sapo.pt/livesapo?q={searchTerms}",
- "type": "SEARCH_ENGINE_SAPO",
- "id": 77
- },
-
- "search_de_CH": {
- "name": "search.ch",
- "keyword": "search.ch",
- "favicon_url": "http://www.search.ch/favicon.ico",
- "search_url": "http://www.search.ch/index.de.html?q={searchTerms}",
- "encoding": "ISO-8859-1",
- "id": 51
- },
-
- "search_fr_CH": {
- "name": "search.ch",
- "keyword": "search.ch_", // search.ch is taken by search_de_CH.
- "favicon_url": "http://www.search.ch/favicon.ico",
- "search_url": "http://www.search.ch/index.fr.html?q={searchTerms}",
- "id": 22
- },
-
"seznam": {
"name": "Seznam",
"keyword": "seznam.cz",
@@ -1133,72 +569,43 @@
"id": 25
},
- "terra_ar": {
- "name": "Terra Argentina",
- "keyword": "terra.com.ar",
- "favicon_url": "http://buscar.terra.com.ar/favicon.ico",
- "search_url": "http://buscar.terra.com.ar/Default.aspx?query={searchTerms}&source=Search",
- "encoding": "ISO-8859-1",
- "id": 90
+ "sogou": {
+ "name": "\u641c\u72d7",
+ "keyword": "sogou.com",
+ "favicon_url": "http://www.sogou.com/favicon.ico",
+ "search_url": "http://www.sogou.com/web?ie={inputEncoding}&query={searchTerms}",
+ "type": "SEARCH_ENGINE_SOGOU",
+ "id": 56
},
- "terra_es": {
- "name": "Terra",
- "keyword": "terra.es",
- "favicon_url": "http://buscador.terra.es/favicon.ico",
- "search_url": "http://buscador.terra.es/Default.aspx?query={searchTerms}&source=Search",
- "encoding": "ISO-8859-1",
- "id": 90
+ "soso": {
+ "name": "\u641c\u641c",
+ "keyword": "soso.com",
+ "favicon_url": "http://www.soso.com/favicon.ico",
+ "search_url": "http://www.soso.com/q?ie={inputEncoding}&w={searchTerms}",
+ "type": "SEARCH_ENGINE_SOSO",
+ "id": 58
},
- "tut": {
- "name": "TUT.BY",
- "keyword": "tut.by",
- "favicon_url": "http://www.tut.by/favicon.ico",
- "search_url": "http://search.tut.by/?query={searchTerms}",
- "encoding": "windows-1251",
- "type": "SEARCH_ENGINE_TUT",
- "id": 17
- },
-
- "uol": {
- "name": "UOL Busca",
- "keyword": "busca.uol.com.br",
- "favicon_url": "http://busca.uol.com.br/favicon.ico",
- "search_url": "http://busca.uol.com.br/www/index.html?q={searchTerms}",
- "encoding": "ISO-8859-1",
- "id": 82
+ "vinden": {
+ "name": "Vinden.nl",
+ "keyword": "vinden.nl",
+ "favicon_url": "http://www.vinden.nl/favicon.ico",
+ "search_url": "http://www.vinden.nl/?q={searchTerms}",
+ "type": "SEARCH_ENGINE_VINDEN",
+ "id": 53
},
"virgilio": {
"name": "Virgilio",
"keyword": "virgilio.it",
- "favicon_url": "http://ricerca.alice.it/favicon.ico",
- "search_url": "http://ricerca.alice.it/ricerca?qs={searchTerms}",
+ "favicon_url": "http://ricerca.virgilio.it/common/favicon.ico",
+ "search_url": "http://ricerca.virgilio.it/ricerca?qs={searchTerms}",
"encoding": "ISO-8859-1",
"type": "SEARCH_ENGINE_VIRGILIO",
"id": 62
},
- "walla": {
- "name": "\u05d5\u05d5\u05d0\u05dc\u05d4!",
- "keyword": "walla.co.il",
- "favicon_url": "http://www.walla.co.il/favicon.ico",
- "search_url": "http://search.walla.co.il/?e=hew&q={searchTerms}",
- "encoding": "windows-1255",
- "type": "SEARCH_ENGINE_WALLA",
- "id": 55
- },
-
- "wp": {
- "name": "Wirtualna Polska",
- "keyword": "wp.pl",
- "favicon_url": "http://szukaj.wp.pl/favicon.ico",
- "search_url": "http://szukaj.wp.pl/szukaj.html?szukaj={searchTerms}",
- "encoding": "ISO-8859-2",
- "id": 76
- },
-
"yahoo": {
"name": "Yahoo!",
"keyword": "yahoo.com",
@@ -1209,9 +616,6 @@
"id": 2
},
- // For regional Yahoo variants without region-specific suggestion service,
- // suggestion is disabled. For some of them, we might consider
- // using a fallback (e.g. de for at/ch, ca or fr for qc, en for nl, no, hk).
"yahoo_ar": {
"name": "Yahoo! Argentina",
"keyword": "ar.yahoo.com",
@@ -1223,10 +627,11 @@
},
"yahoo_at": {
- "name": "Yahoo! Suche",
+ "name": "Yahoo! \u00d6sterreich",
"keyword": "at.yahoo.com",
"favicon_url": "http://at.search.yahoo.com/favicon.ico",
"search_url": "http://at.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+ "suggest_url": "http://de-sayt.ff.search.yahoo.com/gossip-de-sayt?output=fxjson&command={searchTerms}",
"type": "SEARCH_ENGINE_YAHOO",
"id": 2
},
@@ -1241,6 +646,18 @@
"id": 2
},
+ // For regional Yahoo variants without a region-specific suggestion service,
+ // suggestion is disabled. For some of them, we might consider using one of
+ // the other language/country URLs as a fallback.
+ "yahoo_be": {
+ "name": "Yahoo! Belgi\u00eb",
+ "keyword": "be.yahoo.com",
+ "favicon_url": "http://be.search.yahoo.com/favicon.ico",
+ "search_url": "http://be.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+ "type": "SEARCH_ENGINE_YAHOO",
+ "id": 2
+ },
+
"yahoo_br": {
"name": "Yahoo! Brasil",
"keyword": "br.yahoo.com",
@@ -1262,10 +679,11 @@
},
"yahoo_ch": {
- "name": "Yahoo! Suche",
+ "name": "Yahoo! Schweiz",
"keyword": "ch.yahoo.com",
"favicon_url": "http://ch.search.yahoo.com/favicon.ico",
"search_url": "http://ch.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+ "suggest_url": "http://de-sayt.ff.search.yahoo.com/gossip-de-sayt?output=fxjson&command={searchTerms}",
"type": "SEARCH_ENGINE_YAHOO",
"id": 2
},
@@ -1280,16 +698,6 @@
"id": 2
},
- "yahoo_cn": {
- "name": "\u4e2d\u56fd\u96c5\u864e",
- "keyword": "cn.yahoo.com",
- "favicon_url": "http://search.cn.yahoo.com/favicon.ico",
- "search_url": "http://search.cn.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
- "encoding": "GB2312",
- "type": "SEARCH_ENGINE_YAHOO",
- "id": 2
- },
-
"yahoo_co": {
"name": "Yahoo! Colombia",
"keyword": "co.yahoo.com",
@@ -1330,7 +738,7 @@
},
"yahoo_fi": {
- "name": "Yahoo!-haku",
+ "name": "Yahoo! Suomi",
"keyword": "fi.yahoo.com",
"favicon_url": "http://fi.search.yahoo.com/favicon.ico",
"search_url": "http://fi.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
@@ -1348,11 +756,32 @@
"id": 2
},
+ "yahoo_fr_be": {
+ "name": "Yahoo! Belgique",
+ "keyword": "fr-be.yahoo.com",
+ "favicon_url": "http://fr.search.yahoo.com/favicon.ico",
+ "search_url": "http://fr.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+ "suggest_url": "http://fr-sayt.ff.search.yahoo.com/gossip-fr-sayt?output=fxjson&command={searchTerms}",
+ "type": "SEARCH_ENGINE_YAHOO",
+ "id": 5 // Can't be 2 as this has to appear in the Belgium list alongside
+ // yahoo_be.
+ },
+
+ "yahoo_gr": {
+ "name": "Yahoo! \u0395\u03bb\u03bb\u03ac\u03b4\u03b1\u03c2",
+ "keyword": "gr.yahoo.com",
+ "favicon_url": "http://gr.search.yahoo.com/favicon.ico",
+ "search_url": "http://gr.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+ "type": "SEARCH_ENGINE_YAHOO",
+ "id": 2
+ },
+
"yahoo_hk": {
"name": "Yahoo! Hong Kong",
"keyword": "hk.yahoo.com",
"favicon_url": "http://hk.search.yahoo.com/favicon.ico",
"search_url": "http://hk.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+ "suggest_url": "http://hk-sayt.ff.search.yahoo.com/gossip-hk-sayt?output=fxjson&command={searchTerms}",
"type": "SEARCH_ENGINE_YAHOO",
"id": 2
},
@@ -1377,43 +806,23 @@
"id": 2
},
- "yahoo_it": {
- "name": "Yahoo! Italia",
- "keyword": "it.yahoo.com",
- "favicon_url": "http://it.search.yahoo.com/favicon.ico",
- "search_url": "http://it.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
- "suggest_url": "http://it-sayt.ff.search.yahoo.com/gossip-it-sayt?output=fxjson&command={searchTerms}",
- "type": "SEARCH_ENGINE_YAHOO",
- "id": 2
- },
-
"yahoo_jp": {
"name": "Yahoo! JAPAN",
"keyword": "yahoo.co.jp",
"favicon_url": "http://search.yahoo.co.jp/favicon.ico",
"search_url": "http://search.yahoo.co.jp/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
- "type": "SEARCH_ENGINE_YAHOOJP",
- "id": 2
- },
-
- "yahoo_kr": {
- "name": "\uc57c\ud6c4! \ucf54\ub9ac\uc544",
- "keyword": "kr.yahoo.com",
- "favicon_url": "http://kr.search.yahoo.com/favicon.ico",
- "search_url": "http://kr.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
- "suggest_url": "http://kr.atc.search.yahoo.com/atcx.php?property=main&ot=fxjson&ei=utf8&eo=utf8&command={searchTerms}",
+ "suggest_url": "http://search.yahooapis.jp/AssistSearchService/V2/webassistSearch?p={searchTerms}&appid=oQsoxcyxg66enp0TYoirkKoryq6rF8bK76mW0KYxZ0v0WPLtn.Lix6wy8F_LwGWHUII-&output=fxjson&fr=crmas",
"type": "SEARCH_ENGINE_YAHOO",
"id": 2
},
- "yahoo_malaysia": {
- "name": "Yahoo! Malaysia",
- "keyword": "malaysia.yahoo.com",
- "favicon_url": "http://malaysia.search.yahoo.com/favicon.ico",
- "search_url": "http://malaysia.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
- "suggest_url": "http://my-sayt.ff.search.yahoo.com/gossip-my-sayt?output=fxjson&command={searchTerms}",
+ "yahoo_maktoob": {
+ "name": "Yahoo!\u200e \u0645\u0643\u062a\u0648\u0628",
+ "keyword": "maktoob.yahoo.com",
+ "favicon_url": "http://maktoob.yahoo.com/favicon.ico",
+ "search_url": "http://maktoob.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
"type": "SEARCH_ENGINE_YAHOO",
- "id": 2
+ "id": 13 // Should be 2, but is 13 due to historical reasons.
},
"yahoo_mx": {
@@ -1426,26 +835,28 @@
"id": 2
},
+ "yahoo_my": {
+ "name": "Yahoo! Malaysia",
+ "keyword": "malaysia.yahoo.com",
+ "favicon_url": "http://malaysia.search.yahoo.com/favicon.ico",
+ "search_url": "http://malaysia.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+ "suggest_url": "http://my-sayt.ff.search.yahoo.com/gossip-my-sayt?output=fxjson&command={searchTerms}",
+ "type": "SEARCH_ENGINE_YAHOO",
+ "id": 2
+ },
+
"yahoo_nl": {
"name": "Yahoo! Nederland",
"keyword": "nl.yahoo.com",
"favicon_url": "http://nl.search.yahoo.com/favicon.ico",
"search_url": "http://nl.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
- "type": "SEARCH_ENGINE_YAHOO",
- "id": 2
- },
-
- "yahoo_no": {
- "name": "Yahoo! Norge",
- "keyword": "no.yahoo.com",
- "favicon_url": "http://no.search.yahoo.com/favicon.ico",
- "search_url": "http://no.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+ "suggest_url": "http://ff.search.yahoo.com/gossip?output=fxjson&command={searchTerms}",
"type": "SEARCH_ENGINE_YAHOO",
"id": 2
},
"yahoo_nz": {
- "name": "Yahoo!Xtra",
+ "name": "Yahoo! New Zealand",
"keyword": "nz.yahoo.com",
"favicon_url": "http://nz.search.yahoo.com/favicon.ico",
"search_url": "http://nz.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
@@ -1479,11 +890,21 @@
"keyword": "qc.yahoo.com",
"favicon_url": "http://qc.search.yahoo.com/favicon.ico",
"search_url": "http://qc.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
- "type": "SEARCH_ENGINE_YAHOOQC",
+ "suggest_url": "http://gossip.ca.yahoo.com/gossip-ca-sayt?output=fxjsonp&command={searchTerms}",
+ "type": "SEARCH_ENGINE_YAHOO",
"id": 5 // Can't be 2 as this has to appear in the Canada list alongside
// yahoo_ca.
},
+ "yahoo_ro": {
+ "name": "Yahoo! Rom\u00e2nia",
+ "keyword": "ro.yahoo.com",
+ "favicon_url": "http://ro.search.yahoo.com/favicon.ico",
+ "search_url": "http://ro.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+ "type": "SEARCH_ENGINE_YAHOO",
+ "id": 2
+ },
+
"yahoo_ru": {
"name": "Yahoo! \u043f\u043e-\u0440\u0443\u0441\u0441\u043a\u0438",
"keyword": "ru.yahoo.com",
@@ -1522,11 +943,21 @@
"id": 2
},
+ "yahoo_tr": {
+ "name": "Yahoo! T\u00fcrkiye",
+ "keyword": "tr.yahoo.com",
+ "favicon_url": "http://tr.search.yahoo.com/favicon.ico",
+ "search_url": "http://tr.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+ "type": "SEARCH_ENGINE_YAHOO",
+ "id": 2
+ },
+
"yahoo_tw": {
"name": "Yahoo!\u5947\u6469",
"keyword": "tw.yahoo.com",
"favicon_url": "http://tw.search.yahoo.com/favicon.ico",
"search_url": "http://tw.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+ "suggest_url": "http://hk-sayt.ff.search.yahoo.com/gossip-hk-sayt?output=fxjson&command={searchTerms}",
"type": "SEARCH_ENGINE_YAHOO",
"id": 2
},
@@ -1561,12 +992,13 @@
"id": 2
},
- "yamli": {
- "name": "Yamli",
- "keyword": "yamli.com",
- "favicon_url": "http://www.yamli.com/favicon.ico",
- "search_url": "http://www.yamli.com/#q={searchTerms}",
- "id": 11
+ "yahoo_za": {
+ "name": "Yahoo! South Africa",
+ "keyword": "sa.yahoo.com",
+ "favicon_url": "http://sa.search.yahoo.com/favicon.ico",
+ "search_url": "http://sa.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+ "type": "SEARCH_ENGINE_YAHOO",
+ "id": 2
},
"yandex_ru": {
@@ -1589,16 +1021,6 @@
"id": 15
},
- "zoznam": {
- "name": "Zoznam",
- "keyword": "zoznam.sk",
- "favicon_url": "http://zoznam.sk/favicon.ico",
- "search_url": "http://zoznam.sk/hladaj.fcgi?s={searchTerms}",
- "encoding": "windows-1250",
- "type": "SEARCH_ENGINE_ZOZNAM",
- "id": 85
- },
-
// UMA-only engines ////////////////////////////////////////////////////////
@@ -1606,122 +1028,369 @@
// are listed in |kAllEngines|, however, so that GetEngineType can find them
// for UMA reporting purposes.
- "all_by": {
- "name": "ALL.BY",
- "keyword": "all.by",
- "favicon_url": "http://all.by/favicon.ico",
- "search_url": "http://www.all.by/cgi-bin/search.cgi?mode=by&query={searchTerms}",
- "type": "SEARCH_ENGINE_ALL_BY",
- "id": 33
+ "atlas_cz": {
+ "name": "Atlas.cz",
+ "keyword": "atlas.cz",
+ "favicon_url": "http://searchatlas.centrum.cz/favicon.ico",
+ "search_url": "http://searchatlas.centrum.cz/?q={searchTerms}",
+ "suggest_url": "http://radce.centrum.cz/?q={searchTerms}&of=1",
+ "type": "SEARCH_ENGINE_ATLAS",
+ "id": 27
},
- "aport": {
- "name": "Aport",
- "keyword": "aport.ru",
- "favicon_url": "http://www.aport.ru/favicon.png",
- "search_url": "http://www.aport.ru/search/?r={searchTerms}",
- "type": "SEARCH_ENGINE_APORT",
- "id": 34
+ "atlas_sk": {
+ "name": "ATLAS.SK",
+ "keyword": "atlas.sk",
+ "favicon_url": "http://static.mediacentrum.sk/katalog/atlas.sk/images/favicon.ico",
+ "search_url": "http://hladaj.atlas.sk/fulltext/?phrase={searchTerms}",
+ "id": 27
},
"avg": {
- "name": "AVG Secure Search",
+ "name": "AVG",
"keyword": "search.avg.com",
"favicon_url": "http://search.avg.com/favicon.ico",
- "search_url": "http://search.avg.com/route/?q={searchTerms}&lng={language}",
+ "search_url": "http://search.avg.com/search?q={searchTerms}",
+ "alternate_urls": [
+ "http://isearch.avg.com/search?q={searchTerms}",
+ "http://search.avg.com/route/?q={searchTerms}&lng={language}"
+ ],
"type": "SEARCH_ENGINE_AVG",
"id": 50
},
- "avg_i": {
- "name": "AVG Secure Search",
- "keyword": "isearch.avg.com",
- "favicon_url": "http://isearch.avg.com/favicon.ico",
- "search_url": "http://isearch.avg.com/search?q={searchTerms}&lng={language}",
- "type": "SEARCH_ENGINE_AVG",
- "id": 52
+ "babylon": {
+ "name": "Babylon",
+ "keyword": "search.babylon.com",
+ "favicon_url": "http://search.babylon.com/favicon.ico",
+ "search_url": "http://search.babylon.com/home?q={searchTerms}",
+ "alternate_urls": [
+ "http://search.babylon.com/?q={searchTerms}"
+ ],
+ "type": "SEARCH_ENGINE_BABYLON",
+ "id": 64
},
"conduit": {
"name": "Conduit",
"keyword": "conduit.com",
- "favicon_url": "http://search.conduit.com/favicon.ico",
- "search_url": "http://search.conduit.com/Results.aspx?q={searchTerms}",
+ "favicon_url": "http://www.conduit.com/favicon.ico",
+ "search_url": "http://www.conduit.com/search?q={searchTerms}&ie={inputEncoding}&cx=010301873083402539744%3Anxaq5wgrtuo&cof=forid%3A11",
+ "alternate_urls": [
+ "http://search.conduit.com/Results.aspx?q={searchTerms}"
+ ],
"type": "SEARCH_ENGINE_CONDUIT",
"id": 36
},
- "icq": {
- "name": "ICQ",
- "keyword": "icq.com",
- "favicon_url": "http://www.icq.com/favicon.ico",
- "search_url": "http://search.icq.com/search/results.php?q={searchTerms}",
- "type": "SEARCH_ENGINE_ICQ",
- "id": 39
+ "delfi_lt": {
+ "name": "DELFI",
+ "keyword": "delfi.lt",
+ "favicon_url": "http://www.delfi.lt/favicon.ico",
+ "search_url": "http://www.delfi.lt/paieska/?q={searchTerms}",
+ "type": "SEARCH_ENGINE_DELFI",
+ "id": 45
},
- "meta_ua": {
- "name": "Meta-Ukraine",
- "keyword": "meta.ua",
- "favicon_url": "http://meta.ua/favicon.ico",
- "search_url": "http://meta.ua/search.asp?q={searchTerms}",
- "type": "SEARCH_ENGINE_META_UA",
- "id": 40
+ "delfi_lv": {
+ "name": "DELFI",
+ "keyword": "delfi.lv",
+ "favicon_url": "http://g1.delphi.lv/favicon.ico",
+ "search_url": "http://www.delfi.lv/search_all/?ie={inputEncoding}&q={searchTerms}&lang={language}&cx=partner-pub-7754285690273419%3A1507605038&cof=FORID%3A10",
+ "type": "SEARCH_ENGINE_DELFI",
+ "id": 45
},
- "metabot_ru": {
- "name": "Metabot",
- "keyword": "metabot.ru",
- "favicon_url": "http://www.metabot.ru/favicon.ico",
- "search_url": "http://results.metabot.ru/?st={searchTerms}",
- "type": "SEARCH_ENGINE_METABOT_RU",
- "id": 42
+ "delta": {
+ "name": "Delta",
+ "keyword": "delta-search.com",
+ "favicon_url": "http://www.delta-search.com/favicon.ico",
+ "search_url": "http://www.delta-search.com/home?q={searchTerms}",
+ "alternate_urls": [
+ "http://www.delta-search.com/?q={searchTerms}",
+ "http://www1.delta-search.com/home?q={searchTerms}",
+ "http://www1.delta-search.com/?q={searchTerms}",
+ "http://www2.delta-search.com/home?q={searchTerms}",
+ "http://www2.delta-search.com/?q={searchTerms}",
+ "http://www.search.delta-search.com/home?q={searchTerms}",
+ "http://www.search.delta-search.com/?q={searchTerms}",
+ "http://www.yhs.delta-search.com/home?q={searchTerms}",
+ "http://www.yhs.delta-search.com/?q={searchTerms}",
+ "http://mixidj.delta-search.com/home?q={searchTerms}",
+ "http://mixidj.delta-search.com/?q={searchTerms}",
+ "http://www.search.delta-search.com/home?q={searchTerms}",
+ "http://www.search.delta-search.com/?q={searchTerms}"
+ ],
+ "type": "SEARCH_ENGINE_DELTA",
+ "id": 66
+ },
+
+ "funmoods": {
+ "name": "Funmoods",
+ "keyword": "searchfunmoods.com",
+ "favicon_url": "http://searchfunmoods.com/favicon.ico",
+ "search_url": "http://searchfunmoods.com/results.php?q={searchTerms}",
+ "type": "SEARCH_ENGINE_FUNMOODS",
+ "id": 60
+ },
+
+ "goo": {
+ "name": "goo",
+ "keyword": "search.goo.ne.jp",
+ "favicon_url": "http://goo.ne.jp/favicon.ico",
+ "search_url": "http://search.goo.ne.jp/web.jsp?MT={searchTerms}&IE={inputEncoding}",
+ "suggest_url": "http://search.goo.ne.jp/sgt.jsp?MT={searchTerms}&CL=plugin&FM=json&IE={inputEncoding}",
+ "encoding": "EUC-JP",
+ "type": "SEARCH_ENGINE_GOO",
+ "id": 23
+ },
+
+ "imesh": {
+ "name": "IMesh",
+ "keyword": "search.imesh.net",
+ "favicon_url": "http://search.imesh.net/favicon.ico",
+ "search_url": "http://search.imesh.net/music?hl={language}&si={searchTerms}",
+ "type": "SEARCH_ENGINE_IMESH",
+ "id": 81
+ },
+
+ "iminent": {
+ "name": "SearchTheWeb",
+ "keyword": "iminent.com",
+ "favicon_url": "http://search.iminent.com/Shared/Images/favicon_gl.ico",
+ "search_url": "http://search.iminent.com/?q={searchTerms}",
+ "alternate_urls": [
+ "http://search.iminent.com/SearchTheWeb/v6/1033/homepage/Default.aspx#q={searchTerms}",
+ "http://search.iminent.com/SearchTheWeb/v6/1033/homepage/Result.aspx#q={searchTerms}",
+ "http://start.iminent.com/?q={searchTerms}",
+ "http://start.iminent.com/StartWeb/1033/homepage/#q={searchTerms}"
+ ],
+ "type": "SEARCH_ENGINE_IMINENT",
+ "id": 79
+ },
+
+ "in": {
+ "name": "in.gr",
+ "keyword": "in.gr",
+ "favicon_url": "http://find.in.gr/Themes/1/Default/Media/Layout/icon_in.png",
+ "search_url": "http://find.in.gr/?q={searchTerms}&ie={inputEncoding}&cx=partner-pub-3451081775397713%3Aklnvxp4nycj&cof=FORID%3A9",
+ "type": "SEARCH_ENGINE_IN",
+ "id": 54
+ },
+
+ "incredibar": {
+ "name": "MyStart",
+ "keyword": "mystart.incredibar.com",
+ "favicon_url": "http://search.incredibar.com/favicon.ico",
+ "search_url": "http://search.incredibar.com/search.php?q={searchTerms}",
+ "alternate_urls": [
+ "http://search.incredibar.com/?q={searchTerms}",
+ "http://mystart.incredibar.com/?search={searchTerms}"
+ ],
+ "type": "SEARCH_ENGINE_INCREDIBAR",
+ "id": 74
+ },
+
+ "libero": {
+ "name": "Libero",
+ "keyword": "libero.it",
+ "favicon_url": "http://ms1.iol.it/graph_hf/v.8.3.04/themes/default/img/favicon.ico",
+ "search_url": "http://arianna.libero.it/search/abin/integrata.cgi?query={searchTerms}",
+ "encoding": "ISO-8859-1",
+ "type": "SEARCH_ENGINE_LIBERO",
+ "id": 63
+ },
+
+ "neti": {
+ "name": "NETI",
+ "keyword": "neti.ee",
+ "favicon_url": "http://www.neti.ee/favicon.ico",
+ "search_url": "http://www.neti.ee/cgi-bin/otsing?query={searchTerms}",
+ "suggest_url": "http://www.neti.ee/api/suggestOS?suggestQuery={searchTerms}",
+ "encoding": "ISO-8859-1",
+ "type": "SEARCH_ENGINE_NETI",
+ "id": 44
},
"nigma": {
- "name": "Nigma",
+ "name": "\u041d\u0438\u0433\u043c\u0430",
"keyword": "nigma.ru",
- "favicon_url": "http://nigma.ru/favicon.ico",
- "search_url": "http://www.nigma.ru/?s={searchTerms}",
+ "favicon_url": "http://nigma.ru/themes/nigma/img/favicon.ico",
+ "search_url": "http://nigma.ru/?s={searchTerms}",
+ "suggest_url": "http://autocomplete.nigma.ru/complete/query_help.php?suggest=true&q={searchTerms}",
"type": "SEARCH_ENGINE_NIGMA",
"id": 43
},
- "qip": {
- "name": "QIP",
- "keyword": "qip.ru",
- "favicon_url": "http://search.qip.ru/favicon.ico",
- "search_url": "http://search.qip.ru/?query={searchTerms}",
- "type": "SEARCH_ENGINE_QIP",
- "id": 47
+ "ok": {
+ "name": "OK.hu",
+ "keyword": "ok.hu",
+ "favicon_url": "http://ok.hu/gfx/favicon.ico",
+ "search_url": "http://ok.hu/katalogus?q={searchTerms}",
+ "encoding": "ISO-8859-2",
+ "type": "SEARCH_ENGINE_OK",
+ "id": 6
},
- "ukr_net": {
- "name": "Ukr.net",
- "keyword": "ukr.net",
- "favicon_url": "http://search.ukr.net/i/favicon.ico",
- "search_url": "http://search.ukr.net/google/search.php?q={searchTerms}",
- "type": "SEARCH_ENGINE_UKR_NET",
- "id": 48
+ "rambler": {
+ "name": "\u0420\u0430\u043c\u0431\u043b\u0435\u0440",
+ "keyword": "rambler.ru",
+ "favicon_url": "http://nova.rambler.ru/static/blocks/images/favicon.ico",
+ "search_url": "http://nova.rambler.ru/search?query={searchTerms}",
+ "suggest_url": "http://nova.rambler.ru/suggest?v=3&query={searchTerms}",
+ "type": "SEARCH_ENGINE_RAMBLER",
+ "id": 16
},
- "webalta": {
- "name": "Webalta",
- "keyword": "webalta.ru",
- "favicon_url": "http://webalta.ru/favicon.ico",
- "search_url": "http://webalta.ru/search?q={searchTerms}",
- "type": "SEARCH_ENGINE_WEBALTA",
- "id": 49
+ "sapo": {
+ "name": "SAPO",
+ "keyword": "sapo.pt",
+ "favicon_url": "http://imgs.sapo.pt/images/sapo.ico",
+ "search_url": "http://pesquisa.sapo.pt/?q={searchTerms}",
+ "suggest_url": "http://pesquisa.sapo.pt/livesapo?q={searchTerms}",
+ "type": "SEARCH_ENGINE_SAPO",
+ "id": 77
+ },
+
+ "searchnu": {
+ "name": "searchnu",
+ "keyword": "searchnu.com",
+ "favicon_url": "http://www.searchnu.com/favicon.ico",
+ "search_url": "http://www.searchnu.com/web?hl={language}&si={searchTerms}",
+ "type": "SEARCH_ENGINE_SEARCHNU",
+ "id": 61
+ },
+
+ "search_results": {
+ "name": "Search-results",
+ "keyword": "search-results.com",
+ "favicon_url": "http://ak.apnstatic.com/media/images/favicon_search-results.ico",
+ "search_url": "http://dts.search-results.com/sr?lng={language}&src=hmp&q={searchTerms}",
+ "alternate_urls": [
+ "http://www.search-results.com/web?q={searchTerms}"
+ ],
+ "type": "SEARCH_ENGINE_SEARCH_RESULTS",
+ "id": 78
+ },
+
+ "snapdo": {
+ "name": "SnapDo",
+ "keyword": "search.snapdo.com",
+ "favicon_url": "http://linkurystoragenorthus.blob.core.windows.net/static/favicon.ico",
+ "search_url": "http://search.snapdo.com/?q={searchTerms}",
+ "alternate_urls": [
+ "http://search.snap.do/?q={searchTerms}",
+ "http://feed.snapdo.com/?q={searchTerms}",
+ "http://feed.snap.do/?q={searchTerms}"
+ ],
+ "type": "SEARCH_ENGINE_SNAPDO",
+ "id": 70
+ },
+
+ "softonic": {
+ "name": "softonic",
+ "keyword": "search.softonic.com",
+ "favicon_url": "http://search.softonic.com/img/favicon.ico",
+ "search_url": "http://search.softonic.com/?q={searchTerms}",
+ "alternate_urls": [
+ "http://en.softonic.com/s/{searchTerms}",
+ "http://www.softonic.com/s/{searchTerms}",
+ "http://www.softonic.com.br/s/{searchTerms}",
+ "http://buscador.softonic.com/?q={searchTerms}",
+ "http://nl.softonic.com/s/{searchTerms}"
+ ],
+ "type": "SEARCH_ENGINE_SOFTONIC",
+ "id": 80
+ },
+
+ "sweetim": {
+ "name": "SweetIM",
+ "keyword": "home.sweetim.com",
+ "favicon_url": "http://search.sweetim.com/favicon.ico",
+ "search_url": "http://search.sweetim.com/search.asp?q={searchTerms}&ln={language}",
+ "type": "SEARCH_ENGINE_SWEETPACKS",
+ "id": 65
+ },
+
+ "sweetpacks": {
+ "name": "Sweetpacks",
+ "keyword": "start.sweetpacks.com",
+ "favicon_url": "http://start.sweetpacks.com/favicon.ico",
+ "search_url": "http://start.sweetpacks.com/search.asp?q={searchTerms}&ln={language}",
+ "alternate_urls": [
+ "http://start.sweetpacks.com/?q={searchTerms}",
+ "http://mysearch.sweetpacks.com/?q={searchTerms}"
+ ],
+ "type": "SEARCH_ENGINE_SWEETPACKS",
+ "id": 65
+ },
+
+ "terra_ar": {
+ "name": "Terra Argentina",
+ "keyword": "terra.com.ar",
+ "favicon_url": "http://buscar.terra.com.ar/favicon.ico",
+ "search_url": "http://buscar.terra.com.ar/Default.aspx?source=Search&ca=s&query={searchTerms}",
+ "encoding": "ISO-8859-1",
+ "type": "SEARCH_ENGINE_TERRA",
+ "id": 90
+ },
+
+ "terra_es": {
+ "name": "Terra",
+ "keyword": "terra.es",
+ "favicon_url": "http://buscador.terra.es/favicon.ico",
+ "search_url": "http://buscador.terra.es/Default.aspx?source=Search&ca=s&query={searchTerms}",
+ "encoding": "ISO-8859-1",
+ "type": "SEARCH_ENGINE_TERRA",
+ "id": 90
+ },
+
+ "tut": {
+ "name": "TUT.BY",
+ "keyword": "tut.by",
+ "favicon_url": "http://search.tut.by/favicon.ico",
+ "search_url": "http://search.tut.by/?ru=1&query={searchTerms}",
+ "suggest_url": "http://suggest.yandex.ru/suggest-ff.cgi?part={searchTerms}&limit=10",
+ "type": "SEARCH_ENGINE_TUT",
+ "id": 17
+ },
+
+ "walla": {
+ "name": "\u05d5\u05d5\u05d0\u05dc\u05d4!",
+ "keyword": "walla.co.il",
+ "favicon_url": "http://www.walla.co.il/favicon.ico",
+ "search_url": "http://search.walla.co.il/?q={searchTerms}",
+ "type": "SEARCH_ENGINE_WALLA",
+ "id": 55
+ },
+
+ "wp": {
+ "name": "Wirtualna Polska",
+ "keyword": "wp.pl",
+ "favicon_url": "http://i.wp.pl/a/i/stg/500/favicon.ico",
+ "search_url": "http://szukaj.wp.pl/szukaj.html?q={searchTerms}",
+ "type": "SEARCH_ENGINE_WP",
+ "id": 76
},
"yandex_tr": {
"name": "Yandex",
"keyword": "yandex.com.tr",
- "favicon_url": "http://yandex.com.tr/favicon.ico",
- "search_url": "http://yandex.com.tr/yandsearch?text={searchTerms}",
- "suggest_url": "http://suggest.yandex.net/suggest-ff.cgi?part={searchTerms}",
+ "favicon_url": "http://yandex.st/islands-icons/_/6jyHGXR8-HAc8oJ1bU8qMUQQz_g.ico",
+ "search_url": "http://www.yandex.com.tr/yandsearch?text={searchTerms}",
+ "suggest_url": "http://suggest.yandex.com.tr/suggest-ff.cgi?part={searchTerms}",
"type": "SEARCH_ENGINE_YANDEX",
"id": 15
+ },
+
+ "zoznam": {
+ "name": "Zoznam",
+ "keyword": "zoznam.sk",
+ "favicon_url": "http://www.zoznam.sk/favicon.ico",
+ "search_url": "http://www.zoznam.sk/hladaj.fcgi?s={searchTerms}",
+ "encoding": "windows-1250",
+ "type": "SEARCH_ENGINE_ZOZNAM",
+ "id": 85
}
}
}
diff --git a/chrome/browser/search_engines/search_engine_type.h b/chrome/browser/search_engines/search_engine_type.h
index 6aea298..1541848 100644
--- a/chrome/browser/search_engines/search_engine_type.h
+++ b/chrome/browser/search_engines/search_engine_type.h
@@ -9,52 +9,56 @@
// search engines at the bottom and do not delete from this list, so as not
// to disrupt UMA data already recorded.
enum SearchEngineType {
- SEARCH_ENGINE_OTHER = 0, // At the top in case of future list changes.
- SEARCH_ENGINE_GOOGLE,
- SEARCH_ENGINE_YAHOO,
- SEARCH_ENGINE_YAHOOJP,
- SEARCH_ENGINE_BING,
+ // Prepopulated engines.
+ SEARCH_ENGINE_OTHER = 0, // At the top in case of future list changes.
+ SEARCH_ENGINE_AOL,
SEARCH_ENGINE_ASK,
- SEARCH_ENGINE_YANDEX,
- SEARCH_ENGINE_SEZNAM,
- SEARCH_ENGINE_CENTRUM,
- SEARCH_ENGINE_NETSPRINT,
- SEARCH_ENGINE_VIRGILIO,
- SEARCH_ENGINE_MAILRU,
- SEARCH_ENGINE_ABCSOK,
- SEARCH_ENGINE_ALTAVISTA,
+ SEARCH_ENGINE_ATLAS,
+ SEARCH_ENGINE_AVG,
SEARCH_ENGINE_BAIDU,
+ SEARCH_ENGINE_BABYLON,
+ SEARCH_ENGINE_BING,
+ SEARCH_ENGINE_CONDUIT,
SEARCH_ENGINE_DAUM,
SEARCH_ENGINE_DELFI,
- SEARCH_ENGINE_DIRI,
+ SEARCH_ENGINE_DELTA,
+ SEARCH_ENGINE_FUNMOODS,
SEARCH_ENGINE_GOO,
+ SEARCH_ENGINE_GOOGLE,
+ SEARCH_ENGINE_IMINENT,
+ SEARCH_ENGINE_IMESH,
SEARCH_ENGINE_IN,
+ SEARCH_ENGINE_INCREDIBAR,
+ SEARCH_ENGINE_KVASIR,
+ SEARCH_ENGINE_LIBERO,
+ SEARCH_ENGINE_MAILRU,
SEARCH_ENGINE_NAJDI,
+ SEARCH_ENGINE_NATE,
SEARCH_ENGINE_NAVER,
SEARCH_ENGINE_NETI,
- SEARCH_ENGINE_OK,
- SEARCH_ENGINE_POGODAK,
- SEARCH_ENGINE_POGODOK_MK, // Defunct. Deletion would corrupt UMA stats.
- SEARCH_ENGINE_RAMBLER,
- SEARCH_ENGINE_SANOOK,
- SEARCH_ENGINE_SAPO,
- SEARCH_ENGINE_TUT,
- SEARCH_ENGINE_WALLA,
- SEARCH_ENGINE_ZOZNAM,
- SEARCH_ENGINE_YAHOOQC,
- SEARCH_ENGINE_NONE, // Defunct. Deletion would corrupt UMA stats.
- SEARCH_ENGINE_CONDUIT,
- SEARCH_ENGINE_ALL_BY,
- SEARCH_ENGINE_APORT,
- SEARCH_ENGINE_ICQ,
- SEARCH_ENGINE_METABOT_RU,
- SEARCH_ENGINE_META_UA,
SEARCH_ENGINE_NIGMA,
- SEARCH_ENGINE_QIP,
- SEARCH_ENGINE_UKR_NET,
- SEARCH_ENGINE_WEBALTA,
- SEARCH_ENGINE_AVG,
- SEARCH_ENGINE_MAX // Bounding max value needed for UMA histogram macro.
+ SEARCH_ENGINE_OK,
+ SEARCH_ENGINE_ONET,
+ SEARCH_ENGINE_RAMBLER,
+ SEARCH_ENGINE_SAPO,
+ SEARCH_ENGINE_SEARCHNU,
+ SEARCH_ENGINE_SEARCH_RESULTS,
+ SEARCH_ENGINE_SEZNAM,
+ SEARCH_ENGINE_SNAPDO,
+ SEARCH_ENGINE_SOFTONIC,
+ SEARCH_ENGINE_SOGOU,
+ SEARCH_ENGINE_SOSO,
+ SEARCH_ENGINE_SWEETPACKS,
+ SEARCH_ENGINE_TERRA,
+ SEARCH_ENGINE_TUT,
+ SEARCH_ENGINE_VINDEN,
+ SEARCH_ENGINE_VIRGILIO,
+ SEARCH_ENGINE_WALLA,
+ SEARCH_ENGINE_WP,
+ SEARCH_ENGINE_YAHOO,
+ SEARCH_ENGINE_YANDEX,
+ SEARCH_ENGINE_ZOZNAM,
+ SEARCH_ENGINE_MAX // Bounding value needed for UMA histogram macro.
};
#endif // CHROME_BROWSER_SEARCH_ENGINES_SEARCH_ENGINE_TYPE_H_
diff --git a/chrome/browser/search_engines/search_terms_data.cc b/chrome/browser/search_engines/search_terms_data.cc
index 32b6100..29d10f6 100644
--- a/chrome/browser/search_engines/search_terms_data.cc
+++ b/chrome/browser/search_engines/search_terms_data.cc
@@ -90,12 +90,12 @@
UIThreadSearchTermsData::UIThreadSearchTermsData(Profile* profile)
: profile_(profile) {
- DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+ DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
}
std::string UIThreadSearchTermsData::GoogleBaseURLValue() const {
- DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+ DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
if (google_base_url_)
return *google_base_url_;
@@ -108,7 +108,7 @@
}
std::string UIThreadSearchTermsData::GetApplicationLocale() const {
- DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+ DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
return g_browser_process->GetApplicationLocale();
}
@@ -116,7 +116,7 @@
// Android implementations are located in search_terms_data_android.cc.
#if !defined(OS_ANDROID)
string16 UIThreadSearchTermsData::GetRlzParameterValue() const {
- DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+ DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
string16 rlz_string;
#if defined(ENABLE_RLZ)
@@ -138,26 +138,26 @@
// search client string. There is already a unit test in place for Android
// called TemplateURLTest::SearchClient.
std::string UIThreadSearchTermsData::GetSearchClient() const {
- DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+ DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
return std::string();
}
#endif
std::string UIThreadSearchTermsData::GetSuggestClient() const {
- DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+ DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
return chrome::IsInstantExtendedAPIEnabled() ? "chrome-omni" : "chrome";
}
std::string UIThreadSearchTermsData::InstantEnabledParam() const {
- DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+ DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
return chrome::IsInstantExtendedAPIEnabled() ? std::string() : "ion=1&";
}
std::string UIThreadSearchTermsData::InstantExtendedEnabledParam() const {
- DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+ DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
uint64 instant_extended_api_version = chrome::EmbeddedSearchPageVersion();
if (instant_extended_api_version) {
@@ -168,7 +168,7 @@
}
std::string UIThreadSearchTermsData::NTPIsThemedParam() const {
- DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+ DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
#if defined(ENABLE_THEMES)
if (!chrome::IsInstantExtendedAPIEnabled())
diff --git a/chrome/browser/search_engines/search_terms_data_android.cc b/chrome/browser/search_engines/search_terms_data_android.cc
index 0eb9047..521aaeb 100644
--- a/chrome/browser/search_engines/search_terms_data_android.cc
+++ b/chrome/browser/search_engines/search_terms_data_android.cc
@@ -13,17 +13,17 @@
SearchTermsDataAndroid::search_client_ = LAZY_INSTANCE_INITIALIZER;
string16 UIThreadSearchTermsData::GetRlzParameterValue() const {
- DCHECK(
- !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
- content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK(!content::BrowserThread::IsThreadInitialized(
+ content::BrowserThread::UI) ||
+ content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
// Android doesn't use the rlz library. Instead, it manages the rlz string
// on its own.
return SearchTermsDataAndroid::rlz_parameter_value_.Get();
}
std::string UIThreadSearchTermsData::GetSearchClient() const {
- DCHECK(
- !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
- content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK(!content::BrowserThread::IsThreadInitialized(
+ content::BrowserThread::UI) ||
+ content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
return SearchTermsDataAndroid::search_client_.Get();
}
diff --git a/chrome/browser/search_engines/template_url.cc b/chrome/browser/search_engines/template_url.cc
index 1991d2c..3d0bea9 100644
--- a/chrome/browser/search_engines/template_url.cc
+++ b/chrome/browser/search_engines/template_url.cc
@@ -73,6 +73,7 @@
"google:omniboxStartMarginParameter";
const char kGoogleOriginalQueryForSuggestionParameter[] =
"google:originalQueryForSuggestion";
+const char kGooglePageClassificationParameter[] = "google:pageClassification";
const char kGoogleRLZParameter[] = "google:RLZ";
const char kGoogleSearchClient[] = "google:searchClient";
const char kGoogleSearchFieldtrialParameter[] =
@@ -192,6 +193,7 @@
accepted_suggestion(NO_SUGGESTIONS_AVAILABLE),
cursor_position(string16::npos),
omnibox_start_margin(-1),
+ page_classification(AutocompleteInput::INVALID_SPEC),
append_extra_query_params(false) {
}
@@ -561,6 +563,8 @@
} else if (parameter == kGoogleOriginalQueryForSuggestionParameter) {
replacements->push_back(Replacement(GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION,
start));
+ } else if (parameter == kGooglePageClassificationParameter) {
+ replacements->push_back(Replacement(GOOGLE_PAGE_CLASSIFICATION, start));
} else if (parameter == kGoogleRLZParameter) {
replacements->push_back(Replacement(GOOGLE_RLZ, start));
} else if (parameter == kGoogleSearchClient) {
@@ -866,6 +870,15 @@
}
break;
+ case GOOGLE_PAGE_CLASSIFICATION:
+ if (search_terms_args.page_classification !=
+ AutocompleteInput::INVALID_SPEC) {
+ HandleReplacement(
+ "pgcl", base::IntToString(search_terms_args.page_classification),
+ *i, &url);
+ }
+ break;
+
case GOOGLE_RLZ: {
DCHECK(!i->is_post_param);
// On platforms that don't have RLZ, we still want this branch
diff --git a/chrome/browser/search_engines/template_url.h b/chrome/browser/search_engines/template_url.h
index c192e04..1d874bb 100644
--- a/chrome/browser/search_engines/template_url.h
+++ b/chrome/browser/search_engines/template_url.h
@@ -11,6 +11,7 @@
#include "base/gtest_prod_util.h"
#include "base/time/time.h"
+#include "chrome/browser/autocomplete/autocomplete_input.h"
#include "chrome/browser/search_engines/template_url_id.h"
#include "url/gurl.h"
#include "url/url_parse.h"
@@ -95,6 +96,9 @@
// suggestions.
std::string zero_prefix_url;
+ // Which omnibox the user used to type the prefix.
+ AutocompleteInput::PageClassification page_classification;
+
// If set, ReplaceSearchTerms() will automatically append any extra query
// params specified via the --extra-search-query-params command-line
// argument. Generally, this should be set when dealing with the search or
@@ -238,6 +242,7 @@
GOOGLE_NTP_IS_THEMED,
GOOGLE_OMNIBOX_START_MARGIN,
GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION,
+ GOOGLE_PAGE_CLASSIFICATION,
GOOGLE_RLZ,
GOOGLE_SEARCH_CLIENT,
GOOGLE_SEARCH_FIELDTRIAL_GROUP,
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data.cc b/chrome/browser/search_engines/template_url_prepopulate_data.cc
index 31c7505..064b65e 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data.cc
+++ b/chrome/browser/search_engines/template_url_prepopulate_data.cc
@@ -20,7 +20,6 @@
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/prepopulated_engines.h"
-#include "chrome/browser/search_engines/search_engine_type.h"
#include "chrome/browser/search_engines/search_terms_data.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_service.h"
@@ -30,6 +29,7 @@
#include "content/public/browser/browser_thread.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"
@@ -41,34 +41,37 @@
namespace TemplateURLPrepopulateData {
+
+// Helpers --------------------------------------------------------------------
+
+namespace {
+
// NOTE: You should probably not change the data in this file without changing
// |kCurrentDataVersion| in prepopulated_engines.json. See comments in
// GetDataVersion() below!
-// Lists of engines per country ////////////////////////////////////////////////
-
-// Put these in order with most interesting/important first. The default will
-// be the first engine.
+// Put the engines within each country in order with most interesting/important
+// first. The default will be the first engine.
// Default (for countries with no better engine set)
const PrepopulatedEngine* engines_default[] =
- { &google, &yahoo, &bing, };
+ { &google, &bing, &yahoo, };
// United Arab Emirates
const PrepopulatedEngine* engines_AE[] =
- { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &araby, &maktoob, };
+ { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
// Albania
const PrepopulatedEngine* engines_AL[] =
- { &google, &yahoo, &bing_en_XA, };
+ { &google, &yahoo, &bing_en_XA, &bing_ar_XA, };
// Argentina
const PrepopulatedEngine* engines_AR[] =
- { &google, &yahoo_ar, &bing_es_AR, &terra_ar, &altavista_ar, };
+ { &google, &bing_es_AR, &yahoo_ar, };
// Austria
const PrepopulatedEngine* engines_AT[] =
- { &google, &yahoo_at, &bing_de_AT, };
+ { &google, &bing_de_AT, &yahoo_at, };
// Australia
const PrepopulatedEngine* engines_AU[] =
@@ -80,15 +83,15 @@
// Belgium
const PrepopulatedEngine* engines_BE[] =
- { &google, &bing_nl_BE, &yahoo, &bing_fr_BE, };
+ { &google, &bing_nl_BE, &bing_fr_BE, &yahoo_be, &yahoo_fr_be, };
// Bulgaria
const PrepopulatedEngine* engines_BG[] =
- { &google, &bing_bg_BG, &yahoo, &diri, &jabse, };
+ { &google, &bing, &ask, };
// Bahrain
const PrepopulatedEngine* engines_BH[] =
- { &google, &yahoo, &bing_en_XA, &bing_ar_XA, };
+ { &google, &yahoo_maktoob, &bing_en_XA, &bing_ar_XA, };
// Burundi
const PrepopulatedEngine* engines_BI[] =
@@ -96,40 +99,39 @@
// Brunei
const PrepopulatedEngine* engines_BN[] =
- { &google, &yahoo_malaysia, &bing_en_MY, };
+ { &google, &yahoo_my, &bing, };
// Bolivia
const PrepopulatedEngine* engines_BO[] =
- { &google, &altavista, &bing_es_XL, &yahoo, };
+ { &google, &bing_es_XL, &yahoo, };
// Brazil
const PrepopulatedEngine* engines_BR[] =
- { &google, &bing_pt_BR, &yahoo_br, &uol, };
+ { &google, &ask_br, &bing_pt_BR, &yahoo_br, };
// Belarus
const PrepopulatedEngine* engines_BY[] =
- { &google, &tut, &yandex_ru, &rambler, &yahoo, };
+ { &google, &yahoo_ru, &bing_ru_RU, };
// Belize
const PrepopulatedEngine* engines_BZ[] =
- { &google, &yahoo, &bing, &aol, };
+ { &google, &yahoo, &bing, };
// Canada
const PrepopulatedEngine* engines_CA[] =
- { &google, &yahoo_ca, &yahoo_qc, &bing_en_CA, &bing_fr_CA, };
+ { &google, &bing_en_CA, &bing_fr_CA, &ask, &yahoo_ca, &yahoo_qc, };
// Switzerland
const PrepopulatedEngine* engines_CH[] =
- { &google, &yahoo_ch, &bing_de_CH, &bing_fr_CH, &search_de_CH,
- &search_fr_CH, };
+ { &google, &bing_de_CH, &bing_fr_CH, &yahoo_ch, };
// Chile
const PrepopulatedEngine* engines_CL[] =
- { &google, &yahoo_cl, &bing_es_CL, };
+ { &google, &bing_es_CL, &yahoo_cl, };
// China
const PrepopulatedEngine* engines_CN[] =
- { &google, &baidu, &yahoo_cn, &bing_zh_CN, };
+ { &google, &baidu, &sogou, &soso, };
// Colombia
const PrepopulatedEngine* engines_CO[] =
@@ -137,15 +139,15 @@
// Costa Rica
const PrepopulatedEngine* engines_CR[] =
- { &google, &bing_es_XL, &yahoo, };
+ { &google, &yahoo, &bing_es_XL, };
// Czech Republic
const PrepopulatedEngine* engines_CZ[] =
- { &google, &seznam, &bing_cs_CZ, ¢rum_cz, &atlas_cz, };
+ { &google, &seznam, &bing, };
// Germany
const PrepopulatedEngine* engines_DE[] =
- { &google, &ask_de, &bing_de_DE, &yahoo_de };
+ { &google, &bing_de_DE, &yahoo_de };
// Denmark
const PrepopulatedEngine* engines_DK[] =
@@ -153,11 +155,11 @@
// Dominican Republic
const PrepopulatedEngine* engines_DO[] =
- { &google, &bing_es_XL, &yahoo, };
+ { &google, &yahoo, &bing_es_XL, };
// Algeria
const PrepopulatedEngine* engines_DZ[] =
- { &google, &bing_en_XA, &yahoo, &bing_ar_XA, &maktoob, };
+ { &google, &bing_ar_XA, &bing_en_XA, &yahoo_maktoob, };
// Ecuador
const PrepopulatedEngine* engines_EC[] =
@@ -165,87 +167,87 @@
// Estonia
const PrepopulatedEngine* engines_EE[] =
- { &google, &bing_et_EE, &neti, &yahoo, };
+ { &google, &bing, &yahoo, };
// Egypt
const PrepopulatedEngine* engines_EG[] =
- { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &masrawy, };
+ { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
// Spain
const PrepopulatedEngine* engines_ES[] =
- { &google, &ask_es, &bing_es_ES, &yahoo_es, &terra_es, &hispavista, };
+ { &google, &bing_es_ES, &yahoo_es, };
// Faroe Islands
const PrepopulatedEngine* engines_FO[] =
- { &google, &bing_da_DK, &yahoo_dk, &jubii };
+ { &google, &bing_da_DK, &ask, };
// Finland
const PrepopulatedEngine* engines_FI[] =
- { &google, &bing_fi_FI, &yahoo_fi, &eniro_fi, &fonecta_02_fi, };
+ { &google, &bing_fi_FI, &yahoo_fi, };
// France
const PrepopulatedEngine* engines_FR[] =
- { &google, &yahoo_fr, &bing_fr_FR, };
+ { &google, &bing_fr_FR, &yahoo_fr, };
// United Kingdom
const PrepopulatedEngine* engines_GB[] =
- { &google, &ask_uk, &yahoo_uk, &bing_en_GB, };
+ { &google, &bing_en_GB, &yahoo_uk, &ask_uk, };
// Greece
const PrepopulatedEngine* engines_GR[] =
- { &google, &yahoo, &in, &bing_el_GR };
+ { &google, &bing, &yahoo_gr, };
// Guatemala
const PrepopulatedEngine* engines_GT[] =
- { &google, &bing_es_XL, &yahoo, &ask_es, };
+ { &google, &yahoo, &bing_es_XL, };
// Hong Kong
const PrepopulatedEngine* engines_HK[] =
- { &google, &yahoo_hk, &bing_zh_HK, &baidu, };
+ { &google, &yahoo_hk, &baidu, &bing_zh_HK, };
// Honduras
const PrepopulatedEngine* engines_HN[] =
- { &google, &bing_es_XL, &yahoo, &ask_es, };
+ { &google, &yahoo, &bing_es_XL, };
// Croatia
const PrepopulatedEngine* engines_HR[] =
- { &google, &yahoo, &bing_hr_HR, };
+ { &google, &bing, &yahoo, };
// Hungary
const PrepopulatedEngine* engines_HU[] =
- { &google, &ok, &bing_hu_HU, };
+ { &google, &bing, &yahoo, };
// Indonesia
const PrepopulatedEngine* engines_ID[] =
- { &google, &yahoo_id, &bing_en_ID, };
+ { &google, &yahoo_id, &bing, };
// Ireland
const PrepopulatedEngine* engines_IE[] =
- { &google, &yahoo_uk, &bing_en_IE, };
+ { &google, &bing_en_IE, &yahoo_uk, };
// Israel
const PrepopulatedEngine* engines_IL[] =
- { &google, &walla, &bing_he_IL, };
+ { &google, &yahoo, &bing, };
// India
const PrepopulatedEngine* engines_IN[] =
- { &google, &yahoo_in, &bing_en_IN, &rediff, &guruji, };
+ { &google, &bing_en_IN, &yahoo_in, };
// Iraq
const PrepopulatedEngine* engines_IQ[] =
- { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &maktoob, &ask, };
+ { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
// Iran
const PrepopulatedEngine* engines_IR[] =
- { &google, &yahoo, };
+ { &google, &yahoo, &bing, };
// Iceland
const PrepopulatedEngine* engines_IS[] =
- { &google, &yahoo, &bing, &leit, };
+ { &google, &bing, &yahoo, };
// Italy
const PrepopulatedEngine* engines_IT[] =
- { &google, &ask_it, &virgilio, &bing_it_IT, &yahoo_it, &libero, };
+ { &google, &virgilio, &bing_it_IT, };
// Jamaica
const PrepopulatedEngine* engines_JM[] =
@@ -253,11 +255,11 @@
// Jordan
const PrepopulatedEngine* engines_JO[] =
- { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &maktoob, &araby, };
+ { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
// Japan
const PrepopulatedEngine* engines_JP[] =
- { &google, &yahoo_jp, &bing_ja_JP, &goo, };
+ { &google, &yahoo_jp, &bing_ja_JP, };
// Kenya
const PrepopulatedEngine* engines_KE[] =
@@ -265,19 +267,19 @@
// Kuwait
const PrepopulatedEngine* engines_KW[] =
- { &google, &bing_en_XA, &yahoo, &bing_ar_XA, &maktoob, &araby, };
+ { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
// South Korea
const PrepopulatedEngine* engines_KR[] =
- { &google, &naver, &daum, &yahoo_kr, &nate, };
+ { &google, &naver, &daum, &nate, };
// Kazakhstan
const PrepopulatedEngine* engines_KZ[] =
- { &google, &rambler, &yandex_ru, &nur_kz, };
+ { &google, &bing, &yahoo, };
// Lebanon
const PrepopulatedEngine* engines_LB[] =
- { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &maktoob, &araby, };
+ { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
// Liechtenstein
const PrepopulatedEngine* engines_LI[] =
@@ -285,7 +287,7 @@
// Lithuania
const PrepopulatedEngine* engines_LT[] =
- { &google, &delfi_lt, &yahoo, &bing_lt_LT, };
+ { &google, &bing, &yandex_ru, };
// Luxembourg
const PrepopulatedEngine* engines_LU[] =
@@ -293,27 +295,27 @@
// Latvia
const PrepopulatedEngine* engines_LV[] =
- { &google, &bing, &yandex_ru, &yahoo, &latne, };
+ { &google, &yandex_ru, &bing, };
// Libya
const PrepopulatedEngine* engines_LY[] =
- { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &maktoob, &ask, };
+ { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
// Morocco
const PrepopulatedEngine* engines_MA[] =
- { &google, &bing_en_XA, &yahoo, &bing_ar_XA, };
+ { &google, &bing_ar_XA, &bing_en_XA, &yahoo_maktoob, };
// Monaco
const PrepopulatedEngine* engines_MC[] =
- { &google, &bing_fr_FR, &yahoo_fr, };
+ { &google, &yahoo_fr, &bing_fr_FR, };
// Moldova
const PrepopulatedEngine* engines_MD[] =
- { &google, &yandex_ru, &yahoo, &bing, };
+ { &google, &bing, &yahoo, };
// Montenegro
const PrepopulatedEngine* engines_ME[] =
- { &google, &yahoo, &bing };
+ { &google, &bing, &yahoo, };
// Macedonia
const PrepopulatedEngine* engines_MK[] =
@@ -325,31 +327,31 @@
// Malaysia
const PrepopulatedEngine* engines_MY[] =
- { &google, &yahoo_malaysia, &bing_en_MY, };
+ { &google, &yahoo_my, &bing, };
// Nicaragua
const PrepopulatedEngine* engines_NI[] =
- { &google, &bing_es_XL, &yahoo, &ask_es, };
+ { &google, &yahoo, &bing_es_XL, };
// Netherlands
const PrepopulatedEngine* engines_NL[] =
- { &google, &bing_nl_NL, &yahoo_nl, &ask_nl, };
+ { &google, &yahoo_nl, &vinden, };
// Norway
const PrepopulatedEngine* engines_NO[] =
- { &google, &bing_nb_NO, &abcsok, &yahoo_no, &kvasir, };
+ { &google, &bing_nb_NO, &kvasir, };
// New Zealand
const PrepopulatedEngine* engines_NZ[] =
- { &google, &yahoo_nz, &bing_en_NZ, };
+ { &google, &bing_en_NZ, &yahoo_nz, };
// Oman
const PrepopulatedEngine* engines_OM[] =
- { &google, &yahoo, &bing_en_XA, &bing_ar_XA, };
+ { &google, &bing_ar_XA, &yahoo_maktoob, &bing_en_XA, };
// Panama
const PrepopulatedEngine* engines_PA[] =
- { &google, &bing_es_XL, &yahoo, &ask_es, };
+ { &google, &yahoo, &bing_es_XL, };
// Peru
const PrepopulatedEngine* engines_PE[] =
@@ -365,15 +367,15 @@
// Puerto Rico
const PrepopulatedEngine* engines_PR[] =
- { &google, &bing_es_XL, &yahoo, &ask_es, };
+ { &google, &yahoo, &bing_es_XL, };
// Poland
const PrepopulatedEngine* engines_PL[] =
- { &google, &bing_pl_PL, &netsprint, &yahoo_uk, &onet, &wp, };
+ { &google, &onet, &bing_pl_PL, };
// Portugal
const PrepopulatedEngine* engines_PT[] =
- { &google, &sapo, &bing_pt_PT, &yahoo, };
+ { &google, &bing_pt_PT, &yahoo, };
// Paraguay
const PrepopulatedEngine* engines_PY[] =
@@ -381,67 +383,67 @@
// Qatar
const PrepopulatedEngine* engines_QA[] =
- { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &maktoob, &araby };
+ { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
// Romania
const PrepopulatedEngine* engines_RO[] =
- { &google, &yahoo_uk, &bing_ro_RO, };
+ { &google, &yahoo_ro, &bing, };
// Serbia
const PrepopulatedEngine* engines_RS[] =
- { &google, &pogodak_rs, &bing, };
+ { &google, &bing, &yahoo, };
// Russia
const PrepopulatedEngine* engines_RU[] =
- { &google, &yandex_ru, &mail_ru, &tut, &rambler, &bing_ru_RU, };
+ { &google, &yandex_ru, &mail_ru, };
// Rwanda
const PrepopulatedEngine* engines_RW[] =
- { &google, &yahoo, &bing, };
+ { &google, &bing, &yahoo, };
// Saudi Arabia
const PrepopulatedEngine* engines_SA[] =
- { &google, &yahoo, &bing_en_XA, &bing_ar_XA, };
+ { &google, &yahoo_maktoob, &bing_ar_XA, &bing_en_XA, };
// Sweden
const PrepopulatedEngine* engines_SE[] =
- { &google, &bing_sv_SE, &yahoo_se, &altavista_se, &eniro_se };
+ { &google, &bing_sv_SE, &yahoo_se, };
// Singapore
const PrepopulatedEngine* engines_SG[] =
- { &google, &yahoo_sg, &bing_en_SG, &rednano, };
+ { &google, &yahoo_sg, &bing_en_SG, };
// Slovenia
const PrepopulatedEngine* engines_SI[] =
- { &google, &najdi, &yahoo, &bing_sl_SI, };
+ { &google, &najdi, &ask, };
// Slovakia
const PrepopulatedEngine* engines_SK[] =
- { &google, &zoznam, &bing_sk_SK, &atlas_sk, ¢rum_sk };
+ { &google, &bing, &yahoo, };
// El Salvador
const PrepopulatedEngine* engines_SV[] =
- { &google, &bing_es_XL, &yahoo, };
+ { &google, &yahoo, &bing_es_XL, };
// Syria
const PrepopulatedEngine* engines_SY[] =
- { &google, &bing_en_XA, &yahoo, &bing_ar_XA, &maktoob, &yamli, };
+ { &google, &bing_ar_XA, &bing_en_XA, &yahoo_maktoob, };
// Thailand
const PrepopulatedEngine* engines_TH[] =
- { &google, &sanook, &yahoo_th, &bing_th_TH, };
+ { &google, &yahoo_th, &bing, };
// Tunisia
const PrepopulatedEngine* engines_TN[] =
- { &google, &bing_en_XA, &yahoo, &bing_ar_XA, &maktoob, &yamli };
+ { &google, &bing_ar_XA, &bing_en_XA, &yahoo_maktoob, };
// Turkey
const PrepopulatedEngine* engines_TR[] =
- { &google, &bing_tr_TR, &yahoo, &mynet, };
+ { &google, &bing_tr_TR, &yahoo_tr, };
// Trinidad and Tobago
const PrepopulatedEngine* engines_TT[] =
- { &google, &bing, &yahoo, &aol, };
+ { &google, &bing, &yahoo, };
// Taiwan
const PrepopulatedEngine* engines_TW[] =
@@ -453,11 +455,11 @@
// Ukraine
const PrepopulatedEngine* engines_UA[] =
- { &google, &yandex_ua, &mail_ru, &rambler, };
+ { &google, &yandex_ua, &bing_ru_RU, };
// United States
const PrepopulatedEngine* engines_US[] =
- { &google, &yahoo, &bing_en_US, };
+ { &google, &bing_en_US, &yahoo, &aol, &ask, };
// Uruguay
const PrepopulatedEngine* engines_UY[] =
@@ -469,57 +471,61 @@
// Vietnam
const PrepopulatedEngine* engines_VN[] =
- { &google, &yahoo_vn, };
+ { &google, &yahoo_vn, &bing, };
// Yemen
const PrepopulatedEngine* engines_YE[] =
- { &google, &yahoo, &bing_en_XA, &bing_ar_XA, &maktoob, &araby, };
+ { &google, &bing_ar_XA, &bing_en_XA, &yahoo_maktoob, };
// South Africa
const PrepopulatedEngine* engines_ZA[] =
- { &google, &yahoo, &bing_en_ZA, };
+ { &google, &bing, &yahoo_za, };
// Zimbabwe
const PrepopulatedEngine* engines_ZW[] =
- { &google, &yahoo, &bing, };
-
+ { &google, &bing, &yahoo, &ask, };
// A list of all the engines that we know about.
-const PrepopulatedEngine* kAllEngines[] =
- { // Prepopulated engines:
- &abcsok, &altavista, &altavista_ar, &altavista_se, &aol, &araby, &ask,
- &ask_de, &ask_es, &ask_it, &ask_nl, &ask_uk, &atlas_cz, &atlas_sk, &baidu,
- &bing, &bing_ar_XA, &bing_bg_BG, &bing_cs_CZ, &bing_da_DK, &bing_de_AT,
- &bing_de_CH, &bing_de_DE, &bing_el_GR, &bing_en_AU, &bing_en_CA,
- &bing_en_GB, &bing_en_ID, &bing_en_IE, &bing_en_IN, &bing_en_MY,
- &bing_en_NZ, &bing_en_PH, &bing_en_SG, &bing_en_US, &bing_en_XA,
- &bing_en_ZA, &bing_es_AR, &bing_es_CL, &bing_es_ES, &bing_es_MX,
- &bing_es_XL, &bing_et_EE, &bing_fi_FI, &bing_fr_BE, &bing_fr_CA,
- &bing_fr_CH, &bing_fr_FR, &bing_he_IL, &bing_hr_HR, &bing_hu_HU,
- &bing_it_IT, &bing_ja_JP, &bing_ko_KR, &bing_lt_LT, &bing_lv_LV,
- &bing_nb_NO, &bing_nl_BE, &bing_nl_NL, &bing_pl_PL, &bing_pt_BR,
- &bing_pt_PT, &bing_ro_RO, &bing_ru_RU, &bing_sl_SI, &bing_sk_SK,
- &bing_sv_SE, &bing_th_TH, &bing_tr_TR, &bing_uk_UA, &bing_zh_CN,
- &bing_zh_HK, &bing_zh_TW, ¢rum_cz, ¢rum_sk, &daum, &delfi_lt,
- &delfi_lv, &diri, &eniro_fi, &eniro_se, &fonecta_02_fi, &goo, &google,
- &guruji, &hispavista, &in, &jabse, &jubii, &kvasir, &latne, &leit,
- &libero, &mail_ru, &maktoob, &masrawy, &mynet, &najdi, &nate, &naver,
- &neti, &netsprint, &nur_kz, &ok, &onet, &pogodak_rs, &rambler, &rediff,
- &rednano, &sanook, &sapo, &search_de_CH, &search_fr_CH, &seznam,
- &terra_ar, &terra_es, &tut, &uol, &virgilio, &walla, &wp, &yahoo,
- &yahoo_ar, &yahoo_at, &yahoo_au, &yahoo_br, &yahoo_ca, &yahoo_ch,
- &yahoo_cl, &yahoo_cn, &yahoo_co, &yahoo_de, &yahoo_dk, &yahoo_es,
- &yahoo_fi, &yahoo_fr, &yahoo_hk, &yahoo_id, &yahoo_in, &yahoo_it,
- &yahoo_jp, &yahoo_kr, &yahoo_malaysia, &yahoo_mx, &yahoo_nl, &yahoo_no,
- &yahoo_nz, &yahoo_pe, &yahoo_ph, &yahoo_qc, &yahoo_ru, &yahoo_se,
- &yahoo_sg, &yahoo_th, &yahoo_tw, &yahoo_uk, &yahoo_ve, &yahoo_vn, &yamli,
- &yandex_ru, &yandex_ua, &zoznam,
- // UMA-only engines:
- &all_by, &aport, &avg, &avg_i, &conduit, &icq, &meta_ua, &metabot_ru,
- &nigma, &qip, &ukr_net, &webalta, &yandex_tr };
+const PrepopulatedEngine* kAllEngines[] = {
+ // Prepopulated engines:
+ &aol, &ask, &ask_br, &ask_uk, &baidu,
+ &bing, &bing_ar_XA, &bing_da_DK, &bing_de_AT, &bing_de_CH,
+ &bing_de_DE, &bing_en_AU, &bing_en_CA, &bing_en_GB, &bing_en_IE,
+ &bing_en_IN, &bing_en_NZ, &bing_en_PH, &bing_en_SG, &bing_en_US,
+ &bing_en_XA, &bing_es_AR, &bing_es_CL, &bing_es_ES, &bing_es_MX,
+ &bing_es_XL, &bing_fi_FI, &bing_fr_BE, &bing_fr_CA, &bing_fr_CH,
+ &bing_fr_FR, &bing_it_IT, &bing_ja_JP, &bing_lv_LV, &bing_nb_NO,
+ &bing_nl_BE, &bing_pl_PL, &bing_pt_BR, &bing_pt_PT, &bing_ru_RU,
+ &bing_sv_SE, &bing_tr_TR, &bing_zh_HK, &bing_zh_TW, &daum,
+ &google, &kvasir, &mail_ru, &najdi, &nate,
+ &naver, &onet, &seznam, &sogou, &soso,
+ &vinden, &virgilio, &yahoo, &yahoo_ar, &yahoo_at,
+ &yahoo_au, &yahoo_be, &yahoo_br, &yahoo_ca, &yahoo_ch,
+ &yahoo_cl, &yahoo_co, &yahoo_de, &yahoo_dk, &yahoo_es,
+ &yahoo_fi, &yahoo_fr, &yahoo_fr_be, &yahoo_gr, &yahoo_hk,
+ &yahoo_id, &yahoo_in, &yahoo_jp, &yahoo_maktoob, &yahoo_mx,
+ &yahoo_my, &yahoo_nl, &yahoo_nz, &yahoo_pe, &yahoo_ph,
+ &yahoo_qc, &yahoo_ro, &yahoo_ru, &yahoo_se, &yahoo_sg,
+ &yahoo_th, &yahoo_tr, &yahoo_tw, &yahoo_uk, &yahoo_ve,
+ &yahoo_vn, &yahoo_za, &yandex_ru, &yandex_ua,
+ // UMA-only engines:
+ &atlas_cz, &atlas_sk, &avg, &babylon, &conduit,
+ &delfi_lt, &delfi_lv, &delta, &funmoods, &goo,
+ &imesh, &iminent, &in, &incredibar, &libero,
+ &neti, &nigma, &ok, &rambler, &sapo,
+ &search_results, &searchnu, &snapdo, &softonic, &sweetim,
+ &terra_ar, &terra_es, &tut, &walla, &wp,
+ &yandex_tr, &zoznam,
+};
-// Geographic mappings /////////////////////////////////////////////////////////
+const struct LogoURLs {
+ const char* const logo_100_percent_url;
+ const char* const logo_200_percent_url;
+} google_logos = {
+ "https://www.google.com/images/chrome_search/google_logo.png",
+ "https://www.google.com/images/chrome_search/google_logo_2x.png",
+};
// Please refer to ISO 3166-1 for information about the two-character country
// codes; http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 is useful. In the
@@ -641,16 +647,6 @@
return g_country_code_at_install;
}
-void InitCountryCode(const std::string& country_code) {
- if (country_code.size() != 2) {
- DLOG(ERROR) << "Invalid country code: " << country_code;
- g_country_code_at_install = kCountryIDUnknown;
- } else {
- g_country_code_at_install =
- CountryCharsToCountryIDWithUpdate(country_code[0], country_code[1]);
- }
-}
-
#elif defined(OS_POSIX)
int GetCurrentCountryID() {
@@ -1073,47 +1069,6 @@
}
}
-
-// Logo URLs ///////////////////////////////////////////////////////////////////
-
-struct LogoURLs {
- const char* const logo_100_percent_url;
- const char* const logo_200_percent_url;
-};
-
-const LogoURLs google_logos = {
- "https://www.google.com/images/chrome_search/google_logo.png",
- "https://www.google.com/images/chrome_search/google_logo_2x.png",
-};
-
-
-////////////////////////////////////////////////////////////////////////////////
-
-void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
- registry->RegisterIntegerPref(
- prefs::kCountryIDAtInstall,
- kCountryIDUnknown,
- user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
- registry->RegisterListPref(prefs::kSearchProviderOverrides,
- user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
- registry->RegisterIntegerPref(
- prefs::kSearchProviderOverridesVersion,
- -1,
- user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
- // Obsolete pref, for migration.
- registry->RegisterIntegerPref(
- prefs::kGeoIDAtInstall,
- -1,
- user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-}
-
-int GetDataVersion(PrefService* prefs) {
- // Allow tests to override the local version.
- return (prefs && prefs->HasPrefPath(prefs::kSearchProviderOverridesVersion)) ?
- prefs->GetInteger(prefs::kSearchProviderOverridesVersion) :
- kCurrentDataVersion;
-}
-
TemplateURL* MakePrepopulatedTemplateURL(
Profile* profile,
const string16& name,
@@ -1220,16 +1175,6 @@
}
}
-void ClearPrepopulatedEnginesInPrefs(Profile* profile) {
- if (!profile)
- return;
-
- PrefService* prefs = profile->GetPrefs();
- DCHECK(prefs);
- prefs->ClearPref(prefs::kSearchProviderOverrides);
- prefs->ClearPref(prefs::kSearchProviderOverridesVersion);
-}
-
// The caller owns the returned TemplateURL.
TemplateURL* MakePrepopulatedTemplateURLFromPrepopulateEngine(
Profile* profile,
@@ -1249,6 +1194,55 @@
alternate_urls, engine.search_terms_replacement_key, engine.id);
}
+bool SameDomain(const GURL& given_url, const GURL& prepopulated_url) {
+ return prepopulated_url.is_valid() &&
+ net::registry_controlled_domains::SameDomainOrHost(
+ given_url, prepopulated_url,
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+}
+
+} // namespace
+
+
+// Global functions -----------------------------------------------------------
+
+#if defined(OS_ANDROID)
+void InitCountryCode(const std::string& country_code) {
+ if (country_code.size() != 2) {
+ DLOG(ERROR) << "Invalid country code: " << country_code;
+ g_country_code_at_install = kCountryIDUnknown;
+ } else {
+ g_country_code_at_install =
+ CountryCharsToCountryIDWithUpdate(country_code[0], country_code[1]);
+ }
+}
+#endif
+
+void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterIntegerPref(
+ prefs::kCountryIDAtInstall,
+ kCountryIDUnknown,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterListPref(prefs::kSearchProviderOverrides,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ registry->RegisterIntegerPref(
+ prefs::kSearchProviderOverridesVersion,
+ -1,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ // Obsolete pref, for migration.
+ registry->RegisterIntegerPref(
+ prefs::kGeoIDAtInstall,
+ -1,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+}
+
+int GetDataVersion(PrefService* prefs) {
+ // Allow tests to override the local version.
+ return (prefs && prefs->HasPrefPath(prefs::kSearchProviderOverridesVersion)) ?
+ prefs->GetInteger(prefs::kSearchProviderOverridesVersion) :
+ kCurrentDataVersion;
+}
+
void GetPrepopulatedEngines(Profile* profile,
std::vector<TemplateURL*>* t_urls,
size_t* default_search_provider_index) {
@@ -1269,6 +1263,16 @@
}
}
+void ClearPrepopulatedEnginesInPrefs(Profile* profile) {
+ if (!profile)
+ return;
+
+ PrefService* prefs = profile->GetPrefs();
+ DCHECK(prefs);
+ prefs->ClearPref(prefs::kSearchProviderOverrides);
+ prefs->ClearPref(prefs::kSearchProviderOverridesVersion);
+}
+
TemplateURL* GetPrepopulatedDefaultSearch(Profile* profile) {
TemplateURL* default_search_provider = NULL;
ScopedVector<TemplateURL> loaded_urls;
@@ -1286,7 +1290,7 @@
SearchEngineType GetEngineType(const std::string& url) {
// Restricted to UI thread because ReplaceSearchTerms() is so restricted.
using content::BrowserThread;
- DCHECK(!BrowserThread::IsWellKnownThread(BrowserThread::UI) ||
+ DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
// We may get a valid URL, or we may get the Google prepopulate URL which
@@ -1302,8 +1306,8 @@
if (!as_gurl.is_valid())
return SEARCH_ENGINE_OTHER;
- // Check using origins, in order to more aggressively match search engine
- // types for data imported from other browsers.
+ // Check using TLD+1s, in order to more aggressively match search engine types
+ // for data imported from other browsers.
//
// First special-case Google, because the prepopulate URL for it will not
// convert to a GURL and thus won't have an origin. Instead see if the
@@ -1313,11 +1317,16 @@
return google.type;
// Now check the rest of the prepopulate data.
- GURL origin(as_gurl.GetOrigin());
for (size_t i = 0; i < arraysize(kAllEngines); ++i) {
- GURL engine_url(kAllEngines[i]->search_url);
- if (engine_url.is_valid() && (origin == engine_url.GetOrigin()))
+ // First check the main search URL.
+ if (SameDomain(as_gurl, GURL(kAllEngines[i]->search_url)))
return kAllEngines[i]->type;
+
+ // Then check the alternate URLs.
+ for (size_t j = 0; j < kAllEngines[i]->alternate_urls_size; ++j) {
+ if (SameDomain(as_gurl, GURL(kAllEngines[i]->alternate_urls[j])))
+ return kAllEngines[i]->type;
+ }
}
return SEARCH_ENGINE_OTHER;
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data.h b/chrome/browser/search_engines/template_url_prepopulate_data.h
index cfd614b..ef07dd0 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data.h
+++ b/chrome/browser/search_engines/template_url_prepopulate_data.h
@@ -32,11 +32,9 @@
};
#if defined(OS_ANDROID)
-
// This must be called early only once. |country_code| is the country code at
// install following the ISO-3166 specification.
void InitCountryCode(const std::string& country_code);
-
#endif
void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc b/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc
index 140d700..d1f69fd 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc
+++ b/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc
@@ -226,7 +226,8 @@
EXPECT_FALSE(t_urls[default_index]->instant_url().empty());
EXPECT_FALSE(t_urls[default_index]->image_url().empty());
EXPECT_FALSE(t_urls[default_index]->image_url_post_params().empty());
- EXPECT_EQ(SEARCH_ENGINE_GOOGLE,
+ EXPECT_EQ(
+ SEARCH_ENGINE_GOOGLE,
TemplateURLPrepopulateData::GetEngineType(t_urls[default_index]->url()));
}
@@ -263,7 +264,8 @@
EXPECT_GT(t_urls[default_index]->alternate_urls().size(), 1u);
for (size_t i = 0; i < t_urls[default_index]->alternate_urls().size(); ++i)
EXPECT_FALSE(t_urls[default_index]->alternate_urls()[i].empty());
- EXPECT_EQ(SEARCH_ENGINE_GOOGLE,
+ EXPECT_EQ(
+ SEARCH_ENGINE_GOOGLE,
TemplateURLPrepopulateData::GetEngineType(t_urls[default_index]->url()));
EXPECT_FALSE(t_urls[default_index]->search_terms_replacement_key().empty());
}
@@ -297,20 +299,29 @@
EXPECT_EQ(SEARCH_ENGINE_GOOGLE,
TemplateURLPrepopulateData::GetEngineType(kGoogleURLs[i]));
}
+
// Non-Google URLs.
const char* kYahooURLs[] = {
"http://search.yahoo.com/search?"
"ei={inputEncoding}&fr=crmas&p={searchTerms}",
- "http://search.yahoo.com/search?p={searchTerms}"
+ "http://search.yahoo.com/search?p={searchTerms}",
+ // Aggressively match types by checking just TLD+1.
+ "http://someothersite.yahoo.com/",
};
for (size_t i = 0; i < arraysize(kYahooURLs); ++i) {
EXPECT_EQ(SEARCH_ENGINE_YAHOO,
TemplateURLPrepopulateData::GetEngineType(kYahooURLs[i]));
}
+
// URLs for engines not present in country-specific lists.
EXPECT_EQ(SEARCH_ENGINE_NIGMA,
TemplateURLPrepopulateData::GetEngineType(
- "http://www.nigma.ru/?s={searchTerms}&arg1=value1"));
+ "http://nigma.ru/?s={searchTerms}&arg1=value1"));
+ // Also test matching against alternate URLs (and TLD+1 matching).
+ EXPECT_EQ(SEARCH_ENGINE_SOFTONIC,
+ TemplateURLPrepopulateData::GetEngineType(
+ "http://test.softonic.com.br/?{searchTerms}"));
+
// Search URL for which no prepopulated search provider exists.
EXPECT_EQ(SEARCH_ENGINE_OTHER,
TemplateURLPrepopulateData::GetEngineType(
diff --git a/chrome/browser/search_engines/template_url_service.cc b/chrome/browser/search_engines/template_url_service.cc
index 8ae629a..34a3b8e 100644
--- a/chrome/browser/search_engines/template_url_service.cc
+++ b/chrome/browser/search_engines/template_url_service.cc
@@ -690,6 +690,12 @@
return initial_default_search_provider_.get();
}
+bool TemplateURLService::IsSearchResultsPageFromDefaultSearchProvider(
+ const GURL& url) {
+ TemplateURL* default_provider = GetDefaultSearchProvider();
+ return default_provider && default_provider->IsSearchURL(url);
+}
+
TemplateURL* TemplateURLService::FindNewDefaultSearchProvider() {
// See if the prepopulated default still exists.
scoped_ptr<TemplateURL> prepopulated_default(
diff --git a/chrome/browser/search_engines/template_url_service.h b/chrome/browser/search_engines/template_url_service.h
index a7e3e24..7da1932 100644
--- a/chrome/browser/search_engines/template_url_service.h
+++ b/chrome/browser/search_engines/template_url_service.h
@@ -228,6 +228,10 @@
// NOTE: At least in unittest mode, this may return NULL.
TemplateURL* GetDefaultSearchProvider();
+ // Returns true if the |url| is a search results page from the default search
+ // provider.
+ bool IsSearchResultsPageFromDefaultSearchProvider(const GURL& url);
+
// Returns true if the default search is managed through group policy.
bool is_default_search_managed() const { return is_default_search_managed_; }
diff --git a/chrome/browser/search_engines/template_url_unittest.cc b/chrome/browser/search_engines/template_url_unittest.cc
index a4d38a5..708da7e 100644
--- a/chrome/browser/search_engines/template_url_unittest.cc
+++ b/chrome/browser/search_engines/template_url_unittest.cc
@@ -1168,3 +1168,58 @@
EXPECT_EQ("http://www.google.com/search?q=abc#oq=def&x",
url.url_ref().ReplaceSearchTerms(search_terms));
}
+
+// Tests replacing pageClassification.
+TEST_F(TemplateURLTest, ReplacePageClassification) {
+ TemplateURLData data;
+ data.input_encodings.push_back("UTF-8");
+ data.SetURL("{google:baseURL}?{google:pageClassification}q={searchTerms}");
+ TemplateURL url(NULL, data);
+ EXPECT_TRUE(url.url_ref().IsValid());
+ ASSERT_TRUE(url.url_ref().SupportsReplacement());
+ TemplateURLRef::SearchTermsArgs search_terms_args(ASCIIToUTF16("foo"));
+
+ std::string result = url.url_ref().ReplaceSearchTerms(search_terms_args);
+ EXPECT_EQ("http://www.google.com/?q=foo", result);
+
+ search_terms_args.page_classification = AutocompleteInput::NEW_TAB_PAGE;
+ result = url.url_ref().ReplaceSearchTerms(search_terms_args);
+ EXPECT_EQ("http://www.google.com/?pgcl=1&q=foo", result);
+
+ search_terms_args.page_classification =
+ AutocompleteInput::HOMEPAGE;
+ result = url.url_ref().ReplaceSearchTerms(search_terms_args);
+ EXPECT_EQ("http://www.google.com/?pgcl=3&q=foo", result);
+}
+
+// Test the IsSearchResults function.
+TEST_F(TemplateURLTest, IsSearchResults) {
+ TemplateURLData data;
+ data.SetURL("http://bar/search?q={searchTerms}");
+ data.instant_url = "http://bar/instant#q={searchTerms}";
+ data.alternate_urls.push_back("http://bar/?q={searchTerms}");
+ data.alternate_urls.push_back("http://bar/#q={searchTerms}");
+ data.alternate_urls.push_back("http://bar/search#q{searchTerms}");
+ data.alternate_urls.push_back("http://bar/webhp#q={searchTerms}");
+ TemplateURL search_provider(NULL, data);
+
+ const struct {
+ const char* const url;
+ bool result;
+ } url_data[] = {
+ { "http://bar/search?q=foo&oq=foo", true, },
+ { "http://bar/?q=foo&oq=foo", true, },
+ { "http://bar/#output=search&q=foo&oq=foo", true, },
+ { "http://bar/webhp#q=foo&oq=foo", true, },
+ { "http://bar/#q=foo&oq=foo", true, },
+ { "http://bar/?ext=foo&q=foo#ref=bar", true, },
+ { "http://bar/url?url=http://www.foo.com/&q=foo#ref=bar", false, },
+ { "http://bar/", false, },
+ { "http://foo/", false, },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(url_data); ++i) {
+ EXPECT_EQ(url_data[i].result,
+ search_provider.IsSearchURL(GURL(url_data[i].url)));
+ }
+}
diff --git a/chrome/browser/signin/signin_browsertest.cc b/chrome/browser/signin/signin_browsertest.cc
index aef931c..1aa32ce 100644
--- a/chrome/browser/signin/signin_browsertest.cc
+++ b/chrome/browser/signin/signin_browsertest.cc
@@ -207,8 +207,13 @@
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
- // Simulate clicking on the Skip for now link by navigating to the URL.
- ui_test_utils::NavigateToURL(browser(), skip_url);
+ // Simulate clicking on the Skip for now link. It's important to have a
+ // link transition so that OneClickSigninHelper removes the blank page
+ // from the history.
+ chrome::NavigateParams navigate_params(browser(),
+ skip_url,
+ content::PAGE_TRANSITION_LINK);
+ ui_test_utils::NavigateToURL(&navigate_params);
// Register an observer that will navigate back immediately on the commit of
// the NTP. This will allow us to hit the race condition of navigating back
diff --git a/chrome/browser/speech/extension_api/tts_engine_extension_api.cc b/chrome/browser/speech/extension_api/tts_engine_extension_api.cc
index ae3fa1d..ba5e65b 100644
--- a/chrome/browser/speech/extension_api/tts_engine_extension_api.cc
+++ b/chrome/browser/speech/extension_api/tts_engine_extension_api.cc
@@ -188,7 +188,6 @@
bool ExtensionTtsEngineSendTtsEventFunction::RunImpl() {
int utterance_id;
- std::string error_message;
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &utterance_id));
DictionaryValue* event;
diff --git a/chrome/browser/ssl/ssl_blocking_page.cc b/chrome/browser/ssl/ssl_blocking_page.cc
index 33ef570..1e8ab90 100644
--- a/chrome/browser/ssl/ssl_blocking_page.cc
+++ b/chrome/browser/ssl/ssl_blocking_page.cc
@@ -10,6 +10,7 @@
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/renderer_preferences_util.h"
#include "chrome/browser/ssl/ssl_error_info.h"
@@ -70,6 +71,8 @@
SHOW_UNDERSTAND,
SHOW_INTERNAL_HOSTNAME,
PROCEED_INTERNAL_HOSTNAME,
+ SHOW_NEW_SITE,
+ PROCEED_NEW_SITE,
UNUSED_BLOCKING_PAGE_EVENT,
};
@@ -84,7 +87,8 @@
int cert_error,
bool overridable,
bool internal,
- const base::TimeTicks& start_time) {
+ const base::TimeTicks& start_time,
+ int num_visits) {
UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type",
SSLErrorInfo::NetErrorToErrorType(cert_error), SSLErrorInfo::END_OF_ENUM);
if (start_time.is_null() || !overridable) {
@@ -93,10 +97,14 @@
// back. In either case, we don't want to record some of our metrics.
return;
}
+ if (num_visits == 0)
+ RecordSSLBlockingPageEventStats(SHOW_NEW_SITE);
if (proceed) {
RecordSSLBlockingPageEventStats(PROCEED_OVERRIDABLE);
if (internal)
RecordSSLBlockingPageEventStats(PROCEED_INTERNAL_HOSTNAME);
+ if (num_visits == 0)
+ RecordSSLBlockingPageEventStats(PROCEED_NEW_SITE);
} else if (!proceed) {
RecordSSLBlockingPageEventStats(DONT_PROCEED_OVERRIDABLE);
}
@@ -158,17 +166,28 @@
request_url_(request_url),
overridable_(overridable),
strict_enforcement_(strict_enforcement),
- internal_(false) {
+ internal_(false),
+ num_visits_(-1) {
trialCondition_ = base::FieldTrialList::FindFullName(kStudyName);
+ // For UMA stats.
if (net::IsHostnameNonUnique(request_url_.HostNoBrackets()))
internal_ = true;
-
RecordSSLBlockingPageEventStats(SHOW_ALL);
if (overridable_ && !strict_enforcement_) {
RecordSSLBlockingPageEventStats(SHOW_OVERRIDABLE);
if (internal_)
RecordSSLBlockingPageEventStats(SHOW_INTERNAL_HOSTNAME);
+ HistoryService* history_service = HistoryServiceFactory::GetForProfile(
+ Profile::FromBrowserContext(web_contents->GetBrowserContext()),
+ Profile::EXPLICIT_ACCESS);
+ if (history_service) {
+ history_service->GetVisibleVisitCountToHost(
+ request_url_,
+ &request_consumer_,
+ base::Bind(&SSLBlockingPage::OnGotHistoryCount,
+ base::Unretained(this)));
+ }
}
interstitial_page_ = InterstitialPage::Create(
@@ -183,7 +202,8 @@
cert_error_,
overridable_ && !strict_enforcement_,
internal_,
- display_start_time_);
+ display_start_time_,
+ num_visits_);
// The page is closed without the user having chosen what to do, default to
// deny.
NotifyDenyCertificate();
@@ -310,7 +330,8 @@
cert_error_,
overridable_ && !strict_enforcement_,
internal_,
- display_start_time_);
+ display_start_time_,
+ num_visits_);
// Accepting the certificate resumes the loading of the page.
NotifyAllowCertificate();
}
@@ -320,7 +341,8 @@
cert_error_,
overridable_ && !strict_enforcement_,
internal_,
- display_start_time_);
+ display_start_time_,
+ num_visits_);
NotifyDenyCertificate();
}
@@ -358,3 +380,10 @@
strings->SetString(keys[i], std::string());
}
}
+
+void SSLBlockingPage::OnGotHistoryCount(HistoryService::Handle handle,
+ bool success,
+ int num_visits,
+ base::Time first_visit) {
+ num_visits_ = num_visits;
+}
diff --git a/chrome/browser/ssl/ssl_blocking_page.h b/chrome/browser/ssl/ssl_blocking_page.h
index af24412..d4703f4 100644
--- a/chrome/browser/ssl/ssl_blocking_page.h
+++ b/chrome/browser/ssl/ssl_blocking_page.h
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
+#include "chrome/browser/history/history_service.h"
#include "content/public/browser/interstitial_page_delegate.h"
#include "net/ssl/ssl_info.h"
#include "url/gurl.h"
@@ -60,6 +61,12 @@
void NotifyDenyCertificate();
void NotifyAllowCertificate();
+ // Used to query the HistoryService to see if the URL is in history. For UMA.
+ void OnGotHistoryCount(HistoryService::Handle handle,
+ bool success,
+ int num_visits,
+ base::Time first_visit);
+
base::Callback<void(bool)> callback_;
content::WebContents* web_contents_;
@@ -74,6 +81,10 @@
content::InterstitialPage* interstitial_page_; // Owns us.
// Is the hostname for an internal network?
bool internal_;
+ // How many times is this same URL in history?
+ int num_visits_;
+ // Used for getting num_visits_.
+ CancelableRequestConsumer request_consumer_;
// For the FieldTrial: this contains the name of the condition.
std::string trialCondition_;
diff --git a/chrome/browser/storage_monitor/storage_monitor.h b/chrome/browser/storage_monitor/storage_monitor.h
index cf9767e..f008dca 100644
--- a/chrome/browser/storage_monitor/storage_monitor.h
+++ b/chrome/browser/storage_monitor/storage_monitor.h
@@ -29,10 +29,6 @@
class MediaTransferProtocolManager;
}
-namespace extensions {
-class StorageInfoProviderTest;
-}
-
namespace chrome {
class MediaFileSystemRegistryTest;
@@ -145,7 +141,6 @@
friend class MediaFileSystemRegistryTest;
friend class ::SystemStorageApiTest;
friend class ::SystemStorageEjectApiTest;
- friend class extensions::StorageInfoProviderTest;
StorageMonitor();
diff --git a/chrome/browser/sxs_linux.cc b/chrome/browser/sxs_linux.cc
new file mode 100644
index 0000000..daf6f93
--- /dev/null
+++ b/chrome/browser/sxs_linux.cc
@@ -0,0 +1,97 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sxs_linux.h"
+
+#include <vector>
+
+#include "base/logging.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/important_file_writer.h"
+#include "base/path_service.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_version_info.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace {
+
+bool DoAddChannelMarkToUserDataDir(const base::FilePath& user_data_dir) {
+ std::string product_channel_name;
+ chrome::VersionInfo::Channel product_channel(
+ chrome::VersionInfo::GetChannel());
+ switch (product_channel) {
+ case chrome::VersionInfo::CHANNEL_UNKNOWN: {
+ // Add the channel mark even for Chromium builds (which do not have
+ // channel) to better handle possibility of users using Chromium builds
+ // with their Google Chrome profiles. Include version string modifier
+ // as additional piece of information for debugging (it can't make
+ // a meaningful difference for the code since unknown does not match any
+ // real channel name).
+ std::string version_string_modifier(
+ chrome::VersionInfo::GetVersionStringModifier());
+ product_channel_name = "unknown (" + version_string_modifier + ")";
+ break;
+ }
+ case chrome::VersionInfo::CHANNEL_CANARY:
+ product_channel_name = "canary";
+ break;
+ case chrome::VersionInfo::CHANNEL_DEV:
+ product_channel_name = "dev";
+ break;
+ case chrome::VersionInfo::CHANNEL_BETA:
+ product_channel_name = "beta";
+ break;
+ case chrome::VersionInfo::CHANNEL_STABLE:
+ product_channel_name = "stable";
+ break;
+ // Rely on -Wswitch compiler warning to detect unhandled enum values.
+ }
+
+ base::FilePath channels_path(user_data_dir.AppendASCII("Channels"));
+ std::vector<std::string> user_data_dir_channels;
+
+ // Note: failure to read the channels file is not fatal. It's possible
+ // and legitimate that it doesn't exist, e.g. for new profile or for profile
+ // existing before channel marks have been introduced.
+ std::string channels_contents;
+ if (file_util::ReadFileToString(channels_path, &channels_contents))
+ base::SplitString(channels_contents, '\n', &user_data_dir_channels);
+
+ if (std::find(user_data_dir_channels.begin(),
+ user_data_dir_channels.end(),
+ product_channel_name) != user_data_dir_channels.end()) {
+ // No need to do further disk writes if our channel mark is already present.
+ return true;
+ }
+
+ user_data_dir_channels.push_back(product_channel_name);
+ return base::ImportantFileWriter::WriteFileAtomically(
+ channels_path,
+ JoinString(user_data_dir_channels, "\n"));
+}
+
+} // namespace
+
+namespace sxs_linux {
+
+void AddChannelMarkToUserDataDir() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+ base::FilePath user_data_dir;
+ if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
+ LOG(ERROR) << "Failed to get user data dir path. The profile will not be "
+ << "automatically migrated for updated Linux packages.";
+ return;
+ }
+
+ if (!DoAddChannelMarkToUserDataDir(user_data_dir)) {
+ LOG(ERROR) << "Failed to add channel mark to the user data dir ("
+ << user_data_dir.value() << "). This profile will not be "
+ << "automatically migrated for updated Linux packages.";
+ }
+}
+
+} // namespace sxs_linux
diff --git a/chrome/browser/sxs_linux.h b/chrome/browser/sxs_linux.h
new file mode 100644
index 0000000..a6d7b42
--- /dev/null
+++ b/chrome/browser/sxs_linux.h
@@ -0,0 +1,24 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SXS_LINUX_H_
+#define CHROME_BROWSER_SXS_LINUX_H_
+
+#include "base/compiler_specific.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace sxs_linux {
+
+// Records channel of the running browser in user data dir. This is needed
+// to support a seamless and automatic upgrade from non-side-by-side
+// to side-by-side Linux packages (the latter use different default data dirs).
+// Must be run on FILE thread.
+void AddChannelMarkToUserDataDir();
+
+} // namespace sxs_linux
+
+#endif // CHROME_BROWSER_SXS_LINUX_H_
diff --git a/chrome/browser/sync/glue/session_model_associator.cc b/chrome/browser/sync/glue/session_model_associator.cc
index 916ccfb..0598340 100644
--- a/chrome/browser/sync/glue/session_model_associator.cc
+++ b/chrome/browser/sync/glue/session_model_associator.cc
@@ -285,8 +285,7 @@
}
}
- // Free old sync nodes.
- local_tab_pool_.FreeUnassociatedTabNodes();
+ local_tab_pool_.DeleteUnassociatedTabNodes();
// Free memory for closed windows and tabs.
synced_session_tracker_.CleanupSession(local_tag);
@@ -749,9 +748,7 @@
} else {
// This is a valid old tab node, add it to the pool so it can be
// reused for reassociation.
- SessionID tab_id;
- tab_id.set_id(specifics.tab().tab_id());
- local_tab_pool_.AddTabNode(specifics.tab_node_id(), tab_id);
+ local_tab_pool_.AddTabNode(specifics.tab_node_id());
}
}
}
diff --git a/chrome/browser/sync/glue/session_model_associator.h b/chrome/browser/sync/glue/session_model_associator.h
index 2b3aac4..5fd7ca5 100644
--- a/chrome/browser/sync/glue/session_model_associator.h
+++ b/chrome/browser/sync/glue/session_model_associator.h
@@ -224,6 +224,8 @@
FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest, MissingLocalTabNode);
FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest,
TabPoolFreeNodeLimits);
+ FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceSessionTest,
+ TabNodePoolDeleteUnassociatedNodes);
FRIEND_TEST_ALL_PREFIXES(SyncSessionModelAssociatorTest,
PopulateSessionHeader);
FRIEND_TEST_ALL_PREFIXES(SyncSessionModelAssociatorTest,
diff --git a/chrome/browser/sync/glue/synced_session_tracker.cc b/chrome/browser/sync/glue/synced_session_tracker.cc
index 402800c..083aac4 100644
--- a/chrome/browser/sync/glue/synced_session_tracker.cc
+++ b/chrome/browser/sync/glue/synced_session_tracker.cc
@@ -313,12 +313,6 @@
// node for this session before actually associating the tab itself, so
// the tab node id wasn't available at the time. Update it.
- // TODO(shashishekhar): Make sure the following constraint works.
- // All nodes either have unique tab_ids or have kInvalidTabID as their
- // tab_id. There can be multiple nodes associated with kInvalidTabID but
- // there is always one-to-one mapping between valid tab_ids and
- // tab_node_ids.
-
if (iter->second.tab_node_id != tab_node_id &&
iter->second.tab_node_id != TabNodePool::kInvalidTabNodeID) {
// We are updating tab_node_id for a valid tab_id, ideally this should
diff --git a/chrome/browser/sync/glue/tab_node_pool.cc b/chrome/browser/sync/glue/tab_node_pool.cc
index 4d981f3..a16bb57 100644
--- a/chrome/browser/sync/glue/tab_node_pool.cc
+++ b/chrome/browser/sync/glue/tab_node_pool.cc
@@ -39,10 +39,8 @@
return base::StringPrintf("%s %d", machine_tag.c_str(), tab_node_id);
}
-void TabNodePool::AddTabNode(int tab_node_id,
- const SessionID& tab_id) {
+void TabNodePool::AddTabNode(int tab_node_id) {
DCHECK_GT(tab_node_id, kInvalidTabNodeID);
- DCHECK_GT(tab_id.id(), kInvalidTabID);
DCHECK(nodeid_tabid_map_.find(tab_node_id) == nodeid_tabid_map_.end());
unassociated_nodes_.insert(tab_node_id);
if (max_used_tab_node_id_ < tab_node_id)
@@ -168,10 +166,18 @@
return kInvalidTabID;
}
-void TabNodePool::FreeUnassociatedTabNodes() {
+void TabNodePool::DeleteUnassociatedTabNodes() {
+ syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
for (std::set<int>::iterator it = unassociated_nodes_.begin();
it != unassociated_nodes_.end();) {
- FreeTabNodeInternal(*it);
+ syncer::WriteNode tab_node(&trans);
+ const std::string tab_node_tag = TabIdToTag(machine_tag_, *it);
+ if (tab_node.InitByClientTagLookup(syncer::SESSIONS, tab_node_tag) !=
+ syncer::BaseNode::INIT_OK) {
+ LOG(ERROR) << "Could not find sync node with tag: " << tab_node_tag;
+ } else {
+ tab_node.Tombstone();
+ }
unassociated_nodes_.erase(it++);
}
DCHECK(unassociated_nodes_.empty());
diff --git a/chrome/browser/sync/glue/tab_node_pool.h b/chrome/browser/sync/glue/tab_node_pool.h
index 6435175..64b34d2 100644
--- a/chrome/browser/sync/glue/tab_node_pool.h
+++ b/chrome/browser/sync/glue/tab_node_pool.h
@@ -32,7 +32,7 @@
// restart. Nodes are only unassociated temporarily while the
// model associator figures out which tabs belong to which
// nodes. Eventually any remaining unassociated nodes are
-// freed.
+// deleted.
// 3. Free : Sync node is unused.
class TabNodePool {
@@ -77,7 +77,7 @@
// Note: this should only be called when we discover tab sync nodes from
// previous sessions, not for freeing tab nodes we created through
// GetFreeTabNode (use FreeTabNode below for that).
- void AddTabNode(int tab_node_id, const SessionID& tab_id);
+ void AddTabNode(int tab_node_id);
// Returns the tab_id for |tab_node_id| if it is associated else returns
// kInvalidTabID.
@@ -90,8 +90,8 @@
// Returns true if |tab_node_id| is an unassociated tab node.
bool IsUnassociatedTabNode(int tab_node_id);
- // Returns any unassociated nodes to the free node pool.
- void FreeUnassociatedTabNodes();
+ // Deletes any unassociated nodes.
+ void DeleteUnassociatedTabNodes();
// Clear tab pool.
void Clear();
diff --git a/chrome/browser/sync/glue/tab_node_pool_unittest.cc b/chrome/browser/sync/glue/tab_node_pool_unittest.cc
index 093e520..f93de85 100644
--- a/chrome/browser/sync/glue/tab_node_pool_unittest.cc
+++ b/chrome/browser/sync/glue/tab_node_pool_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "chrome/browser/sync/glue/tab_node_pool.h"
+#include "base/logging.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -14,53 +15,57 @@
int GetMaxUsedTabNodeId() const { return pool_.max_used_tab_node_id_; }
+ void AddFreeTabNodes(size_t size, const int node_ids[]);
+
TabNodePool pool_;
};
+void SyncTabNodePoolTest::AddFreeTabNodes(size_t size, const int node_ids[]) {
+ for (size_t i = 0; i < size; ++i) {
+ pool_.free_nodes_pool_.insert(node_ids[i]);
+ }
+}
+
namespace {
TEST_F(SyncTabNodePoolTest, TabNodeIdIncreases) {
// max_used_tab_node_ always increases.
- SessionID session_id;
- session_id.set_id(1);
- pool_.AddTabNode(10, session_id);
+ pool_.AddTabNode(10);
EXPECT_EQ(10, GetMaxUsedTabNodeId());
- session_id.set_id(2);
- pool_.AddTabNode(1, session_id);
+ pool_.AddTabNode(5);
EXPECT_EQ(10, GetMaxUsedTabNodeId());
- session_id.set_id(3);
- pool_.AddTabNode(1000, session_id);
+ pool_.AddTabNode(1000);
EXPECT_EQ(1000, GetMaxUsedTabNodeId());
- pool_.ReassociateTabNode(1000, 500);
-
+ pool_.ReassociateTabNode(1000, 1);
+ pool_.ReassociateTabNode(5, 2);
+ pool_.ReassociateTabNode(10, 3);
// Freeing a tab node does not change max_used_tab_node_id_.
pool_.FreeTabNode(1000);
- pool_.FreeUnassociatedTabNodes();
- EXPECT_EQ(1000, GetMaxUsedTabNodeId());
+ pool_.FreeTabNode(5);
+ pool_.FreeTabNode(10);
for (int i = 0; i < 3; ++i) {
pool_.AssociateTabNode(pool_.GetFreeTabNode(), i + 1);
EXPECT_EQ(1000, GetMaxUsedTabNodeId());
}
EXPECT_EQ(1000, GetMaxUsedTabNodeId());
+ EXPECT_TRUE(pool_.Empty());
}
TEST_F(SyncTabNodePoolTest, OldTabNodesAddAndRemove) {
// VerifyOldTabNodes are added.
- // tab_node_id = 1, tab_id = 1
- SessionID session_id;
- session_id.set_id(1);
- pool_.AddTabNode(1, session_id);
- // tab_node_id = 2, tab_id = 2
- session_id.set_id(2);
- pool_.AddTabNode(2, session_id);
+ pool_.AddTabNode(1);
+ pool_.AddTabNode(2);
EXPECT_EQ(2u, pool_.Capacity());
EXPECT_TRUE(pool_.Empty());
EXPECT_TRUE(pool_.IsUnassociatedTabNode(1));
+ EXPECT_TRUE(pool_.IsUnassociatedTabNode(2));
pool_.ReassociateTabNode(1, 2);
EXPECT_TRUE(pool_.Empty());
- // Check FreeUnassociatedTabNodes returns the node to free node pool_.
- pool_.FreeUnassociatedTabNodes();
+ pool_.AssociateTabNode(2, 3);
+ EXPECT_FALSE(pool_.IsUnassociatedTabNode(1));
+ EXPECT_FALSE(pool_.IsUnassociatedTabNode(2));
+ pool_.FreeTabNode(2);
// 2 should be returned to free node pool_.
EXPECT_EQ(2u, pool_.Capacity());
// Should be able to free 1.
@@ -77,19 +82,18 @@
TEST_F(SyncTabNodePoolTest, OldTabNodesReassociation) {
// VerifyOldTabNodes are reassociated correctly.
- SessionID session_id;
- session_id.set_id(1);
- pool_.AddTabNode(4, session_id);
- session_id.set_id(2);
- pool_.AddTabNode(5, session_id);
- session_id.set_id(3);
- pool_.AddTabNode(6, session_id);
+ pool_.AddTabNode(4);
+ pool_.AddTabNode(5);
+ pool_.AddTabNode(6);
EXPECT_EQ(3u, pool_.Capacity());
EXPECT_TRUE(pool_.Empty());
EXPECT_TRUE(pool_.IsUnassociatedTabNode(4));
pool_.ReassociateTabNode(4, 5);
+ pool_.AssociateTabNode(5, 6);
+ pool_.AssociateTabNode(6, 7);
// Free 5 and 6.
- pool_.FreeUnassociatedTabNodes();
+ pool_.FreeTabNode(5);
+ pool_.FreeTabNode(6);
// 5 and 6 nodes should not be unassociated.
EXPECT_FALSE(pool_.IsUnassociatedTabNode(5));
EXPECT_FALSE(pool_.IsUnassociatedTabNode(6));
@@ -121,15 +125,10 @@
}
TEST_F(SyncTabNodePoolTest, AddGet) {
- SessionID session_id;
- session_id.set_id(1);
- pool_.AddTabNode(5, session_id);
- session_id.set_id(2);
- pool_.AddTabNode(10, session_id);
- pool_.FreeUnassociatedTabNodes();
+ int free_nodes[] = {5, 10};
+ AddFreeTabNodes(2, free_nodes);
EXPECT_FALSE(pool_.Empty());
EXPECT_TRUE(pool_.Full());
-
EXPECT_EQ(2U, pool_.Capacity());
EXPECT_EQ(5, pool_.GetFreeTabNode());
pool_.AssociateTabNode(5, 1);
@@ -144,13 +143,8 @@
EXPECT_TRUE(pool_.Empty());
EXPECT_TRUE(pool_.Full());
EXPECT_EQ(0U, pool_.Capacity());
- SessionID session_id;
- session_id.set_id(1);
- pool_.AddTabNode(5, session_id);
- session_id.set_id(2);
- pool_.AddTabNode(10, session_id);
- // Free added nodes.
- pool_.FreeUnassociatedTabNodes();
+ int free_nodes[] = {5, 10};
+ AddFreeTabNodes(2, free_nodes);
EXPECT_FALSE(pool_.Empty());
EXPECT_TRUE(pool_.Full());
EXPECT_EQ(2U, pool_.Capacity());
diff --git a/chrome/browser/sync/profile_sync_service_session_unittest.cc b/chrome/browser/sync/profile_sync_service_session_unittest.cc
index c7aa28f..592a826 100644
--- a/chrome/browser/sync/profile_sync_service_session_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_session_unittest.cc
@@ -792,13 +792,13 @@
ASSERT_TRUE(create_root.success());
const size_t num_starting_nodes = 3;
- SessionID session_id;
for (size_t i = 0; i < num_starting_nodes; ++i) {
- session_id.set_id(i + 1);
- model_associator_->local_tab_pool_.AddTabNode(i + 1, session_id);
+ size_t node_id = i + 1;
+ model_associator_->local_tab_pool_.AddTabNode(node_id);
+ model_associator_->local_tab_pool_.AssociateTabNode(node_id, i);
+ model_associator_->local_tab_pool_.FreeTabNode(node_id);
}
- model_associator_->local_tab_pool_.FreeUnassociatedTabNodes();
std::vector<int> node_ids;
ASSERT_EQ(num_starting_nodes, model_associator_->local_tab_pool_.Capacity());
ASSERT_FALSE(model_associator_->local_tab_pool_.Empty());
@@ -1372,4 +1372,33 @@
model_associator_->local_tab_pool_.Capacity());
}
+TEST_F(ProfileSyncServiceSessionTest, TabNodePoolDeleteUnassociatedNodes) {
+ CreateRootHelper create_root(this);
+ ASSERT_TRUE(StartSyncService(create_root.callback(), false));
+ std::string local_tag = model_associator_->GetCurrentMachineTag();
+ syncer::SyncError error;
+ // Create a free node and then dissassociate sessions so that it ends up
+ // unassociated.
+ int tab_node_id = model_associator_->local_tab_pool_.GetFreeTabNode();
+ // Update the tab_id of the node, so that it is considered a valid
+ // unassociated node otherwise it will be mistaken for a corrupted node and
+ // will be deleted before being added to the tab node pool.
+ {
+ std::string tab_tag = TabNodePool::TabIdToTag(local_tag, tab_node_id);
+ syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
+ syncer::WriteNode tab_node(&trans);
+ ASSERT_EQ(syncer::BaseNode::INIT_OK,
+ tab_node.InitByClientTagLookup(syncer::SESSIONS, tab_tag));
+ sync_pb::SessionSpecifics specifics = tab_node.GetSessionSpecifics();
+ sync_pb::SessionTab* tab = specifics.mutable_tab();
+ tab->set_tab_id(1);
+ tab_node.SetSessionSpecifics(specifics);
+ }
+
+ error = model_associator_->DisassociateModels();
+ ASSERT_FALSE(error.IsSet());
+ error = model_associator_->AssociateModels(NULL, NULL);
+ ASSERT_FALSE(error.IsSet());
+}
+
} // namespace browser_sync
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
index c0307d4..5219758 100644
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
@@ -78,6 +78,46 @@
return base::FilePath(result).NormalizePathSeparators();
}
+scoped_ptr<FileMetadata> CreateFileMetadataFromChangeResource(
+ const google_apis::ChangeResource& change) {
+ scoped_ptr<FileMetadata> file(new FileMetadata);
+ file->set_file_id(change.file_id());
+
+ FileDetails* details = file->mutable_details();
+ details->set_change_id(change.change_id());
+
+ if (change.is_deleted()) {
+ details->set_deleted(true);
+ return file.Pass();
+ }
+
+ const google_apis::FileResource& file_resource = *change.file();
+ for (ScopedVector<google_apis::ParentReference>::const_iterator itr =
+ file_resource.parents().begin();
+ itr != file_resource.parents().end();
+ ++itr) {
+ details->add_parent_folder_ids((*itr)->file_id());
+ }
+ details->set_title(file_resource.title());
+
+ google_apis::DriveEntryKind kind = file_resource.GetKind();
+ if (kind == google_apis::ENTRY_KIND_FILE)
+ details->set_file_kind(FILE_KIND_FILE);
+ else if (kind == google_apis::ENTRY_KIND_FOLDER)
+ details->set_file_kind(FILE_KIND_FOLDER);
+ else
+ details->set_file_kind(FILE_KIND_UNSUPPORTED);
+
+ details->set_md5(file_resource.md5_checksum());
+ details->set_etag(file_resource.etag());
+ details->set_creation_time(file_resource.created_date().ToInternalValue());
+ details->set_modification_time(
+ file_resource.modified_date().ToInternalValue());
+ details->set_deleted(false);
+
+ return file.Pass();
+}
+
void AdaptLevelDBStatusToSyncStatusCode(const SyncStatusCallback& callback,
const leveldb::Status& status) {
callback.Run(LevelDBStatusToSyncStatusCode(status));
@@ -115,6 +155,25 @@
batch->Delete(kFileTrackerKeyPrefix + base::Int64ToString(tracker_id));
}
+void PushChildTrackersToStack(
+ const TrackersByParentAndTitle& trackers_by_parent,
+ int64 parent_tracker_id,
+ std::stack<int64>* stack) {
+ TrackersByParentAndTitle::const_iterator found =
+ trackers_by_parent.find(parent_tracker_id);
+ if (found == trackers_by_parent.end())
+ return;
+
+ for (TrackersByTitle::const_iterator title_itr = found->second.begin();
+ title_itr != found->second.end(); ++title_itr) {
+ const TrackerSet& trackers = title_itr->second;
+ for (TrackerSet::const_iterator tracker_itr = trackers.begin();
+ tracker_itr != trackers.end(); ++tracker_itr) {
+ stack->push((*tracker_itr)->tracker_id());
+ }
+ }
+}
+
std::string GetTrackerTitle(const FileTracker& tracker) {
if (tracker.has_synced_details())
return tracker.synced_details().title();
@@ -391,6 +450,19 @@
return true;
}
+template <typename Container, typename Key>
+typename Container::mapped_type FindAndEraseItem(Container* container,
+ const Key& key) {
+ typedef typename Container::mapped_type Value;
+ typename Container::iterator found = container->find(key);
+ if (found == container->end())
+ return Value();
+
+ Value result = found->second;
+ container->erase(found);
+ return result;
+}
+
void RunSoon(const tracked_objects::Location& from_here,
const base::Closure& closure) {
base::MessageLoopProxy::current()->PostTask(from_here, closure);
@@ -430,28 +502,153 @@
void MetadataDatabase::RegisterApp(const std::string& app_id,
const std::string& folder_id,
const SyncStatusCallback& callback) {
- NOTIMPLEMENTED();
+ if (FindAppRootTracker(app_id, NULL)) {
+ RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
+ return;
+ }
+
+ TrackerSet trackers;
+ if (!FindTrackersByFileID(folder_id, &trackers) ||
+ trackers.has_active() ||
+ trackers.tracker_set().size() != 1) {
+ util::Log(logging::LOG_WARNING, FROM_HERE,
+ "Failed to register App for %s", app_id.c_str());
+ RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_HAS_CONFLICT));
+ return;
+ }
+
+ FileTracker* tracker = *trackers.tracker_set().begin();
+
+ scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
+ RegisterTrackerAsAppRoot(app_id, tracker->tracker_id(), batch.get());
+ WriteToDatabase(batch.Pass(), callback);
}
void MetadataDatabase::DisableApp(const std::string& app_id,
const SyncStatusCallback& callback) {
- NOTIMPLEMENTED();
+ FileTracker tracker;
+ if (!FindAppRootTracker(app_id, &tracker)) {
+ RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
+ return;
+ }
+
+ if (!tracker.active()) {
+ RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
+ return;
+ }
+
+ scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
+ MakeTrackerInactive(tracker.tracker_id(), batch.get());
+ WriteToDatabase(batch.Pass(), callback);
}
void MetadataDatabase::EnableApp(const std::string& app_id,
const SyncStatusCallback& callback) {
- NOTIMPLEMENTED();
+ FileTracker tracker;
+ if (!FindAppRootTracker(app_id, &tracker)) {
+ RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
+ return;
+ }
+
+ if (tracker.active()) {
+ RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
+ return;
+ }
+
+ scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
+ MakeTrackerActive(tracker.tracker_id(), batch.get());
+ WriteToDatabase(batch.Pass(), callback);
}
void MetadataDatabase::UnregisterApp(const std::string& app_id,
const SyncStatusCallback& callback) {
- NOTIMPLEMENTED();
+ FileTracker tracker;
+ if (!FindAppRootTracker(app_id, &tracker)) {
+ RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
+ return;
+ }
+
+ scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
+ UnregisterTrackerAsAppRoot(app_id, batch.get());
+ WriteToDatabase(batch.Pass(), callback);
+}
+
+bool MetadataDatabase::FindAppRootTracker(const std::string& app_id,
+ FileTracker* tracker) const {
+ return FindItem(app_root_by_app_id_, app_id, tracker);
+}
+
+bool MetadataDatabase::FindFileByFileID(const std::string& file_id,
+ FileMetadata* file) const {
+ return FindItem(file_by_id_, file_id, file);
+}
+
+bool MetadataDatabase::FindTrackersByFileID(const std::string& file_id,
+ TrackerSet* trackers) const {
+ TrackersByFileID::const_iterator found = trackers_by_file_id_.find(file_id);
+ if (found == trackers_by_file_id_.end())
+ return false;
+ if (trackers)
+ *trackers = found->second;
+ return true;
+}
+
+bool MetadataDatabase::FindTrackerByTrackerID(int64 tracker_id,
+ FileTracker* tracker) const {
+ return FindItem(tracker_by_id_, tracker_id, tracker);
+}
+
+bool MetadataDatabase::BuildPathForTracker(int64 tracker_id,
+ base::FilePath* path) const {
+ FileTracker current;
+ if (!FindTrackerByTrackerID(tracker_id, ¤t) || !current.active())
+ return false;
+
+ std::vector<base::FilePath> components;
+ while (!current.is_app_root()) {
+ std::string title = GetTrackerTitle(current);
+ if (title.empty())
+ return false;
+ components.push_back(base::FilePath::FromUTF8Unsafe(title));
+ if (!FindTrackerByTrackerID(current.parent_tracker_id(), ¤t) ||
+ !current.active())
+ return false;
+ }
+
+ if (path)
+ *path = ReverseConcatPathComponents(components);
+
+ return true;
}
void MetadataDatabase::UpdateByChangeList(
ScopedVector<google_apis::ChangeResource> changes,
const SyncStatusCallback& callback) {
- NOTIMPLEMENTED();
+ scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
+
+ for (ScopedVector<google_apis::ChangeResource>::const_iterator itr =
+ changes.begin();
+ itr != changes.end();
+ ++itr) {
+ const google_apis::ChangeResource& change = **itr;
+ scoped_ptr<FileMetadata> file(
+ CreateFileMetadataFromChangeResource(change));
+ std::string file_id = file->file_id();
+
+ MarkTrackersDirtyByFileID(file_id, batch.get());
+ if (!file->details().deleted())
+ MaybeAddTrackersForNewFile(*file, batch.get());
+
+ if (FindTrackersByFileID(file_id, NULL)) {
+ PutFileToBatch(*file, batch.get());
+
+ FileMetadata* file_ptr = file.release();
+ std::swap(file_ptr, file_by_id_[file_id]);
+ delete file_ptr;
+ }
+ }
+
+ WriteToDatabase(batch.Pass(), callback);
}
MetadataDatabase::MetadataDatabase(base::SequencedTaskRunner* task_runner)
@@ -572,6 +769,257 @@
contents->file_trackers.weak_clear();
}
+void MetadataDatabase::RegisterTrackerAsAppRoot(
+ const std::string& app_id,
+ int64 tracker_id,
+ leveldb::WriteBatch* batch) {
+ FileTracker* tracker = tracker_by_id_[tracker_id];
+ DCHECK(tracker);
+ tracker->set_app_id(app_id);
+ tracker->set_is_app_root(true);
+ app_root_by_app_id_[app_id] = tracker;
+
+ MakeTrackerActive(tracker->tracker_id(), batch);
+}
+
+void MetadataDatabase::UnregisterTrackerAsAppRoot(
+ const std::string& app_id,
+ leveldb::WriteBatch* batch) {
+ FileTracker* tracker = FindAndEraseItem(&app_root_by_app_id_, app_id);
+ tracker->set_app_id(std::string());
+ tracker->set_is_app_root(false);
+
+ // Inactivate the tracker to drop all descendant.
+ // (Note that we set is_app_root to false before calling this.)
+ MakeTrackerInactive(tracker->tracker_id(), batch);
+}
+
+void MetadataDatabase::MakeTrackerActive(int64 tracker_id,
+ leveldb::WriteBatch* batch) {
+ FileTracker* tracker = tracker_by_id_[tracker_id];
+ int64 parent_tracker_id = tracker->parent_tracker_id();
+ DCHECK(tracker->has_synced_details());
+ trackers_by_file_id_[tracker->file_id()].Activate(tracker);
+ if (parent_tracker_id) {
+ trackers_by_parent_and_title_[parent_tracker_id][
+ tracker->synced_details().title()].Activate(tracker);
+ }
+ tracker->set_active(true);
+ tracker->set_needs_folder_listing(
+ tracker->synced_details().file_kind() == FILE_KIND_FOLDER);
+ tracker->set_dirty(true);
+ dirty_trackers_.insert(tracker);
+
+ PutTrackerToBatch(*tracker, batch);
+}
+
+void MetadataDatabase::MakeTrackerInactive(int64 tracker_id,
+ leveldb::WriteBatch* batch) {
+ FileTracker* tracker = tracker_by_id_[tracker_id];
+ trackers_by_file_id_[tracker->file_id()].Inactivate(tracker);
+
+ std::string title = GetTrackerTitle(*tracker);
+ int64 parent_tracker_id = tracker->parent_tracker_id();
+ if (parent_tracker_id)
+ trackers_by_parent_and_title_[parent_tracker_id][title].Inactivate(tracker);
+ tracker->set_active(false);
+
+ // Keep the folder tree under an app-root, since we keep the local files of
+ // SyncFileSystem.
+ if (!tracker->is_app_root())
+ RemoveAllDescendantTrackers(tracker_id, batch);
+ MarkTrackersDirtyByFileID(tracker->file_id(), batch);
+ if (parent_tracker_id)
+ MarkTrackersDirtyByPath(parent_tracker_id, title, batch);
+ PutTrackerToBatch(*tracker, batch);
+}
+
+void MetadataDatabase::CreateTrackerForParentAndFileID(
+ const FileTracker& parent_tracker,
+ const std::string& file_id,
+ leveldb::WriteBatch* batch) {
+ int64 tracker_id = GetNextTrackerID(batch);
+ scoped_ptr<FileTracker> tracker(new FileTracker);
+ tracker->set_tracker_id(tracker_id);
+ tracker->set_parent_tracker_id(parent_tracker.tracker_id());
+ tracker->set_file_id(file_id);
+ tracker->set_app_id(parent_tracker.app_id());
+ tracker->set_is_app_root(false);
+ tracker->set_dirty(true);
+ tracker->set_active(false);
+ tracker->set_needs_folder_listing(false);
+ PutTrackerToBatch(*tracker, batch);
+
+ trackers_by_file_id_[file_id].Insert(tracker.get());
+ // Note: |trackers_by_parent_and_title_| does not map from
+ // FileMetadata::details but from FileTracker::synced_details, which is filled
+ // on tracker updated phase. Use empty string as the title since
+ // FileTracker::synced_details is empty here.
+ trackers_by_parent_and_title_[parent_tracker.tracker_id()][std::string()]
+ .Insert(tracker.get());
+ dirty_trackers_.insert(tracker.get());
+ tracker_by_id_[tracker_id] = tracker.release();
+}
+
+void MetadataDatabase::RemoveTrackerIgnoringSiblings(
+ int64 tracker_id,
+ leveldb::WriteBatch* batch) {
+ FileTracker* tracker = FindAndEraseItem(&tracker_by_id_, tracker_id);
+ if (!tracker)
+ return;
+
+ EraseTrackerFromFileIDIndex(tracker, batch);
+ if (tracker->is_app_root())
+ app_root_by_app_id_.erase(tracker->app_id());
+ EraseTrackerFromPathIndex(tracker);
+
+ MarkTrackersDirtyByFileID(tracker->file_id(), batch);
+ // Do not mark the same path trackers as dirty, since the caller is deleting
+ // all its siblings.
+ delete tracker;
+ PutTrackerDeletionToBatch(tracker_id, batch);
+}
+
+void MetadataDatabase::MaybeAddTrackersForNewFile(
+ const FileMetadata& file,
+ leveldb::WriteBatch* batch) {
+ std::set<int64> known_parents;
+ TrackersByFileID::iterator found = trackers_by_file_id_.find(file.file_id());
+ if (found != trackers_by_file_id_.end()) {
+ for (TrackerSet::const_iterator itr = found->second.begin();
+ itr != found->second.end(); ++itr) {
+ int64 parent_tracker_id = (*itr)->parent_tracker_id();
+ if (parent_tracker_id)
+ known_parents.insert(parent_tracker_id);
+ }
+ }
+
+ for (int i = 0; i < file.details().parent_folder_ids_size(); ++i) {
+ std::string parent_folder_id = file.details().parent_folder_ids(i);
+ TrackersByFileID::iterator found =
+ trackers_by_file_id_.find(parent_folder_id);
+ if (found == trackers_by_file_id_.end())
+ continue;
+
+ for (TrackerSet::const_iterator itr = found->second.begin();
+ itr != found->second.end(); ++itr) {
+ FileTracker* parent_tracker = *itr;
+ int64 parent_tracker_id = parent_tracker->tracker_id();
+ if (!parent_tracker->active() && !parent_tracker->is_app_root())
+ continue;
+
+ if (ContainsKey(known_parents, parent_tracker_id))
+ continue;
+
+ CreateTrackerForParentAndFileID(*parent_tracker, file.file_id(), batch);
+ }
+ }
+}
+
+void MetadataDatabase::RemoveAllDescendantTrackers(int64 root_tracker_id,
+ leveldb::WriteBatch* batch) {
+ std::stack<int64> pending_trackers;
+ PushChildTrackersToStack(trackers_by_parent_and_title_,
+ root_tracker_id, &pending_trackers);
+
+ while (!pending_trackers.empty()) {
+ int64 tracker_id = pending_trackers.top();
+ pending_trackers.pop();
+ PushChildTrackersToStack(trackers_by_parent_and_title_,
+ tracker_id, &pending_trackers);
+ RemoveTrackerIgnoringSiblings(tracker_id, batch);
+ }
+}
+
+void MetadataDatabase::EraseTrackerFromFileIDIndex(FileTracker* tracker,
+ leveldb::WriteBatch* batch) {
+ TrackersByFileID::iterator found =
+ trackers_by_file_id_.find(tracker->file_id());
+ if (found == trackers_by_file_id_.end())
+ return;
+
+ TrackerSet* trackers = &found->second;
+ trackers->Erase(tracker);
+ if (!trackers->tracker_set().empty())
+ return;
+ trackers_by_file_id_.erase(found);
+ EraseFileFromDatabase(tracker->file_id(), batch);
+}
+
+void MetadataDatabase::EraseFileFromDatabase(const std::string& file_id,
+ leveldb::WriteBatch* batch) {
+ FileMetadata* file = FindAndEraseItem(&file_by_id_, file_id);
+ if (!file)
+ return;
+ delete file;
+ PutFileDeletionToBatch(file_id, batch);
+}
+
+void MetadataDatabase::EraseTrackerFromPathIndex(FileTracker* tracker) {
+ TrackersByParentAndTitle::iterator found =
+ trackers_by_parent_and_title_.find(tracker->parent_tracker_id());
+ if (found == trackers_by_parent_and_title_.end())
+ return;
+
+ std::string title = GetTrackerTitle(*tracker);
+ TrackersByTitle* trackers_by_title = &found->second;
+ TrackersByTitle::iterator found_by_title = trackers_by_title->find(title);
+ TrackerSet* conflicting_trackers = &found_by_title->second;
+ conflicting_trackers->Erase(tracker);
+
+ if (conflicting_trackers->tracker_set().empty()) {
+ trackers_by_title->erase(found_by_title);
+ if (trackers_by_title->empty())
+ trackers_by_parent_and_title_.erase(found);
+ }
+}
+
+void MetadataDatabase::MarkTrackerSetDirty(
+ TrackerSet* trackers,
+ leveldb::WriteBatch* batch) {
+ for (TrackerSet::iterator itr = trackers->begin();
+ itr != trackers->end(); ++itr) {
+ FileTracker* tracker = *itr;
+ if (tracker->dirty())
+ continue;
+ tracker->set_dirty(true);
+ PutTrackerToBatch(*tracker, batch);
+ dirty_trackers_.insert(tracker);
+ }
+}
+
+void MetadataDatabase::MarkTrackersDirtyByFileID(
+ const std::string& file_id,
+ leveldb::WriteBatch* batch) {
+ TrackersByFileID::iterator found = trackers_by_file_id_.find(file_id);
+ if (found != trackers_by_file_id_.end())
+ MarkTrackerSetDirty(&found->second, batch);
+}
+
+void MetadataDatabase::MarkTrackersDirtyByPath(int64 parent_tracker_id,
+ const std::string& title,
+ leveldb::WriteBatch* batch) {
+ TrackersByParentAndTitle::iterator found =
+ trackers_by_parent_and_title_.find(parent_tracker_id);
+ if (found == trackers_by_parent_and_title_.end()) {
+ NOTREACHED() << "parent: " << parent_tracker_id
+ << ", title: " << title;
+ return;
+ }
+
+ TrackersByTitle::iterator itr = found->second.find(title);
+ if (itr != found->second.end())
+ MarkTrackerSetDirty(&itr->second, batch);
+}
+
+int64 MetadataDatabase::GetNextTrackerID(leveldb::WriteBatch* batch) {
+ int64 tracker_id = service_metadata_->next_tracker_id();
+ service_metadata_->set_next_tracker_id(tracker_id + 1);
+ PutServiceMetadataToBatch(*service_metadata_, batch);
+ DCHECK_GT(tracker_id, 0);
+ return tracker_id;
+}
+
void MetadataDatabase::WriteToDatabase(scoped_ptr<leveldb::WriteBatch> batch,
const SyncStatusCallback& callback) {
base::PostTaskAndReplyWithResult(
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database.h b/chrome/browser/sync_file_system/drive_backend/metadata_database.h
index d2cb9cd..1be2d1c 100644
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database.h
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database.h
@@ -42,21 +42,41 @@
class ServiceMetadata;
struct DatabaseContents;
-// MetadataDatabase instance holds and maintains database and its indexes. The
-// database holds metadata of the server-side files/folders as
-// DriveFileMetadata instances.
+// MetadataDatabase holds and maintains a LevelDB instance and its indexes,
+// which holds 1)ServiceMetadata, 2)FileMetadata and 3)FileTracker.
+// 1) ServiceMetadata is a singleton in the database which holds information for
+// the backend.
+// 2) FileMetadata represents a remote-side file and holds latest known
+// metadata of the remote file.
+// 3) FileTracker represents a synced or to-be-synced file and maintains
+// the local-side folder tree.
+//
// The term "file" includes files, folders and other resources on Drive.
//
+// FileTrackers form a tree structure on the database, which represents the
+// FileSystem trees of SyncFileSystem. The tree has a FileTracker named
+// sync-root as its root node, and a set of FileTracker named app-root. An
+// app-root represents a remote folder for an installed Chrome App and holds all
+// synced contents for the App.
+//
+// One FileMetadata is created for each tracked remote file, which is identified
+// by FileID.
+// One FileTracker is created for every different {parent tracker, FileID} pair,
+// excluding non-app-root inactive parent trackers. Multiple trackers may be
+// associated to one FileID when the file has multiple parents. Multiple
+// trackers may have the same {parent tracker, title} pair when the associated
+// remote files have the same title.
+//
// Files have following state:
// - Unknown file
-// - Is initial state of the files, only file_id and parent_folder_id field
+// - Has a dirty inactive tracker and empty synced_details.
+// - Is initial state of a tracker, only file_id and parent_tracker_id field
// are known.
-// - Has empty synced_details, must be active and dirty.
// - Folder
// - Is either one of sync-root folder, app-root folder or a regular folder.
// - Sync-root folder holds app-root folders as its direct children, and
-// holds entire SyncFileSystem files as its descentants. Its file_id is
-// stored in ServiceMetadata.
+// holds entire SyncFileSystem files as its descentants. Its tracker
+// should be stored in ServiceMetadata by its tracker_id.
// - App-root folder holds all files for an application as its descendants.
// - File
// - Unsupported file
@@ -64,16 +84,21 @@
// inactive.
//
// Invariants:
-// - Any file in the database must either:
+// - Any tracker in the database must either:
// - be sync-root,
-// - have an app-root as its parent folder, or
-// - have an active folder as its parent.
-// That is, all files must be reachable from sync-root via app-root folders
-// and active folders.
+// - have an app-root as its parent tracker, or
+// - have an active tracker as its parent.
+// That is, all trackers must be reachable from sync-root via app-root folders
+// and active trackers.
//
-// - Any active folder must either:
-// - have needs_folder_listing flag and dirty flag, or
-// - have all children at the stored largest change id.
+// - Any active tracker must either:
+// - have |needs_folder_listing| flag and dirty flag, or
+// - have all children at the stored largest change ID.
+//
+// - If multiple trackers have the same parent tracker and same title, they
+// must not have same |file_id|, and at most one of them may be active.
+// - If multiple trackers have the same |file_id|, at most one of them may be
+// active.
//
class MetadataDatabase {
public:
@@ -113,14 +138,49 @@
const SyncStatusCallback& callback);
// Unregisters the folder as the app-root for |app_id|. If |app_id| does not
- // exist, does nothing. The folder is left as an inactive normal folder.
+ // exist, does nothing. The folder is left as an inactive regular folder.
+ // Note that the inactivation drops all descendant files since they are no
+ // longer reachable from sync-root via active folder or app-root.
void UnregisterApp(const std::string& app_id,
const SyncStatusCallback& callback);
+ // Finds the app-root folder for |app_id|. Returns true if exists.
+ // Copies the result to |tracker| if it is non-NULL.
+ bool FindAppRootTracker(const std::string& app_id,
+ FileTracker* tracker) const;
+
+ // Finds the file identified by |file_id|. Returns true if the file is found.
+ // Copies the metadata identified by |file_id| into |file| if exists and
+ // |file| is non-NULL.
+ bool FindFileByFileID(const std::string& file_id, FileMetadata* file) const;
+
+ // Finds the tracker identified by |tracker_id|. Returns true if the tracker
+ // is found.
+ // Copies the tracker identified by |tracker_id| into |tracker| if exists and
+ // |tracker| is non-NULL.
+ bool FindTrackerByTrackerID(int64 tracker_id, FileTracker* tracker) const;
+
+ // Finds the trackers tracking |file_id|. Returns true if the trackers are
+ // found.
+ bool FindTrackersByFileID(const std::string& file_id,
+ TrackerSet* trackers) const;
+
+ // Finds the set of trackers whose parent's tracker ID is |parent_tracker_id|,
+ // and who has |title| as its title in the synced_details.
+ // Copies the tracker set to |trackers| if it is non-NULL.
+ size_t FindTrackersByParentAndTitle(
+ int64 parent_tracker_id,
+ const std::string& title,
+ TrackerSet* trackers) const;
+
+ // Builds the file path for the given tracker. Returns true on success.
+ // |path| can be NULL.
+ // The file path is relative to app-root and have a leading path separator.
+ bool BuildPathForTracker(int64 tracker_id, base::FilePath* path) const;
+
// Updates database by |changes|.
- // Marks dirty for each changed file if the file has the metadata in the
- // database. Adds new metadata to track the file if the file doesn't have
- // the metadata and its parent folder has the active metadata.
+ // Marks each tracker for modified file as dirty and adds new trackers if
+ // needed.
void UpdateByChangeList(ScopedVector<google_apis::ChangeResource> changes,
const SyncStatusCallback& callback);
@@ -145,6 +205,42 @@
SyncStatusCode InitializeOnTaskRunner(const base::FilePath& database_path);
void BuildIndexes(DatabaseContents* contents);
+ // Database manipulation methods.
+ void RegisterTrackerAsAppRoot(const std::string& app_id,
+ int64 tracker_id,
+ leveldb::WriteBatch* batch);
+ void MakeTrackerActive(int64 tracker_id, leveldb::WriteBatch* batch);
+ void MakeTrackerInactive(int64 tracker_id, leveldb::WriteBatch* batch);
+
+ void UnregisterTrackerAsAppRoot(const std::string& app_id,
+ leveldb::WriteBatch* batch);
+ void RemoveAllDescendantTrackers(int64 root_tracker_id,
+ leveldb::WriteBatch* batch);
+
+ void CreateTrackerForParentAndFileID(const FileTracker& parent_tracker,
+ const std::string& file_id,
+ leveldb::WriteBatch* batch);
+ void RemoveTrackerIgnoringSiblings(int64 tracker_id,
+ leveldb::WriteBatch* batch);
+ void MaybeAddTrackersForNewFile(const FileMetadata& file,
+ leveldb::WriteBatch* batch);
+
+ void MarkTrackerSetDirty(TrackerSet* trackers,
+ leveldb::WriteBatch* batch);
+ void MarkTrackersDirtyByFileID(const std::string& file_id,
+ leveldb::WriteBatch* batch);
+ void MarkTrackersDirtyByPath(int64 parent_tracker_id,
+ const std::string& title,
+ leveldb::WriteBatch* batch);
+
+ void EraseTrackerFromFileIDIndex(FileTracker* tracker,
+ leveldb::WriteBatch* batch);
+ void EraseTrackerFromPathIndex(FileTracker* tracker);
+ void EraseFileFromDatabase(const std::string& file_id,
+ leveldb::WriteBatch* batch);
+
+ int64 GetNextTrackerID(leveldb::WriteBatch* batch);
+
void WriteToDatabase(scoped_ptr<leveldb::WriteBatch> batch,
const SyncStatusCallback& callback);
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database.proto b/chrome/browser/sync_file_system/drive_backend/metadata_database.proto
index fbdfa2c..736f357 100644
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database.proto
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database.proto
@@ -11,9 +11,9 @@
package sync_file_system.drive_backend;
enum FileKind {
- KIND_UNSUPPORTED = 0;
- KIND_FILE = 1;
- KIND_FOLDER = 2;
+ FILE_KIND_UNSUPPORTED = 0;
+ FILE_KIND_FILE = 1;
+ FILE_KIND_FOLDER = 2;
}
message ServiceMetadata {
@@ -29,7 +29,7 @@
repeated string parent_folder_ids = 1;
optional string title = 2;
- optional FileKind kind = 3;
+ optional FileKind file_kind = 3;
optional string md5 = 4;
optional string etag = 5;
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc
index 608a180..c748860 100644
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc
@@ -23,6 +23,129 @@
namespace {
const int64 kInitialChangeID = 1234;
+const int64 kSyncRootTrackerID = 100;
+const char kSyncRootFolderID[] = "sync_root_folder_id";
+
+void ExpectEquivalent(const ServiceMetadata* left,
+ const ServiceMetadata* right) {
+ if (!left) {
+ ASSERT_FALSE(right);
+ return;
+ }
+ ASSERT_TRUE(right);
+
+ EXPECT_EQ(left->largest_change_id(), right->largest_change_id());
+ EXPECT_EQ(left->sync_root_tracker_id(), right->sync_root_tracker_id());
+ EXPECT_EQ(left->next_tracker_id(), right->next_tracker_id());
+}
+
+void ExpectEquivalent(const FileDetails* left, const FileDetails* right) {
+ if (!left) {
+ ASSERT_FALSE(right);
+ return;
+ }
+ ASSERT_TRUE(right);
+
+ std::set<std::string> parents;
+ for (int i = 0; i < left->parent_folder_ids_size(); ++i)
+ EXPECT_TRUE(parents.insert(left->parent_folder_ids(i)).second);
+
+ for (int i = 0; i < right->parent_folder_ids_size(); ++i)
+ EXPECT_EQ(1u, parents.erase(left->parent_folder_ids(i)));
+ EXPECT_TRUE(parents.empty());
+
+ EXPECT_EQ(left->title(), right->title());
+ EXPECT_EQ(left->file_kind(), right->file_kind());
+ EXPECT_EQ(left->md5(), right->md5());
+ EXPECT_EQ(left->etag(), right->etag());
+ EXPECT_EQ(left->creation_time(), right->creation_time());
+ EXPECT_EQ(left->modification_time(), right->modification_time());
+ EXPECT_EQ(left->deleted(), right->deleted());
+ EXPECT_EQ(left->change_id(), right->change_id());
+}
+
+void ExpectEquivalent(const FileMetadata* left, const FileMetadata* right) {
+ if (!left) {
+ ASSERT_FALSE(right);
+ return;
+ }
+ ASSERT_TRUE(right);
+
+ EXPECT_EQ(left->file_id(), right->file_id());
+ ExpectEquivalent(&left->details(), &right->details());
+}
+
+void ExpectEquivalent(const FileTracker* left, const FileTracker* right) {
+ if (!left) {
+ ASSERT_FALSE(right);
+ return;
+ }
+ ASSERT_TRUE(right);
+
+ EXPECT_EQ(left->tracker_id(), right->tracker_id());
+ EXPECT_EQ(left->parent_tracker_id(), right->parent_tracker_id());
+ EXPECT_EQ(left->file_id(), right->file_id());
+ EXPECT_EQ(left->app_id(), right->app_id());
+ EXPECT_EQ(left->is_app_root(), right->is_app_root());
+ ExpectEquivalent(&left->synced_details(), &right->synced_details());
+ EXPECT_EQ(left->dirty(), right->dirty());
+ EXPECT_EQ(left->active(), right->active());
+ EXPECT_EQ(left->needs_folder_listing(), right->needs_folder_listing());
+}
+
+template <typename Container>
+void ExpectEquivalentMaps(const Container& left, const Container& right);
+template <typename Key, typename Value, typename Compare>
+void ExpectEquivalent(const std::map<Key, Value, Compare>& left,
+ const std::map<Key, Value, Compare>& right) {
+ ExpectEquivalentMaps(left, right);
+}
+
+template <typename Container>
+void ExpectEquivalentSets(const Container& left, const Container& right);
+template <typename Value, typename Compare>
+void ExpectEquivalent(const std::set<Value, Compare>& left,
+ const std::set<Value, Compare>& right) {
+ return ExpectEquivalentSets(left, right);
+}
+
+void ExpectEquivalent(const TrackerSet& left,
+ const TrackerSet& right) {
+ {
+ SCOPED_TRACE("Expect equivalent active_tracker");
+ ExpectEquivalent(left.active_tracker(), right.active_tracker());
+ }
+ ExpectEquivalent(left.tracker_set(), right.tracker_set());
+}
+
+template <typename Container>
+void ExpectEquivalentMaps(const Container& left, const Container& right) {
+ ASSERT_EQ(left.size(), right.size());
+
+ typedef typename Container::const_iterator const_iterator;
+ const_iterator left_itr = left.begin();
+ const_iterator right_itr = right.begin();
+ while (left_itr != left.end()) {
+ EXPECT_EQ(left_itr->first, right_itr->first);
+ ExpectEquivalent(left_itr->second, right_itr->second);
+ ++left_itr;
+ ++right_itr;
+ }
+}
+
+template <typename Container>
+void ExpectEquivalentSets(const Container& left, const Container& right) {
+ ASSERT_EQ(left.size(), right.size());
+
+ typedef typename Container::const_iterator const_iterator;
+ const_iterator left_itr = left.begin();
+ const_iterator right_itr = right.begin();
+ while (left_itr != left.end()) {
+ ExpectEquivalent(*left_itr, *right_itr);
+ ++left_itr;
+ ++right_itr;
+ }
+}
void SyncStatusResultCallback(SyncStatusCode* status_out,
SyncStatusCode status) {
@@ -45,6 +168,7 @@
public:
MetadataDatabaseTest()
: next_change_id_(kInitialChangeID + 1),
+ next_tracker_id_(kSyncRootTrackerID + 1),
next_file_id_number_(1),
next_md5_sequence_number_(1) {}
@@ -61,6 +185,15 @@
return "file_id_" + base::Int64ToString(next_file_id_number_++);
}
+ int64 GetTrackerIDByFileID(const std::string& file_id) {
+ TrackerSet trackers;
+ if (metadata_database_->FindTrackersByFileID(file_id, &trackers)) {
+ EXPECT_FALSE(trackers.empty());
+ return (*trackers.begin())->tracker_id();
+ }
+ return 0;
+ }
+
SyncStatusCode InitializeMetadataDatabase() {
SyncStatusCode status = SYNC_STATUS_UNKNOWN;
MetadataDatabase::Create(base::MessageLoopProxy::current(),
@@ -102,16 +235,225 @@
void SetUpServiceMetadata(leveldb::DB* db) {
ServiceMetadata service_metadata;
service_metadata.set_largest_change_id(kInitialChangeID);
+ service_metadata.set_sync_root_tracker_id(kSyncRootTrackerID);
+ service_metadata.set_next_tracker_id(next_tracker_id_);
std::string value;
ASSERT_TRUE(service_metadata.SerializeToString(&value));
db->Put(leveldb::WriteOptions(), "SERVICE", value);
}
+ FileMetadata CreateSyncRootMetadata() {
+ FileMetadata sync_root;
+ sync_root.set_file_id(kSyncRootFolderID);
+ FileDetails* details = sync_root.mutable_details();
+ details->set_title("Chrome Syncable FileSystem");
+ details->set_file_kind(FILE_KIND_FOLDER);
+ return sync_root;
+ }
+
+ FileMetadata CreateFileMetadata(const FileMetadata& parent,
+ const std::string& title) {
+ FileMetadata file;
+ file.set_file_id(GenerateFileID());
+ FileDetails* details = file.mutable_details();
+ details->add_parent_folder_ids(parent.file_id());
+ details->set_title(title);
+ details->set_file_kind(FILE_KIND_FILE);
+ details->set_md5(
+ "md5_value_" + base::Int64ToString(next_md5_sequence_number_++));
+ return file;
+ }
+
+ FileMetadata CreateFolderMetadata(const FileMetadata& parent,
+ const std::string& title) {
+ FileMetadata folder;
+ folder.set_file_id(GenerateFileID());
+ FileDetails* details = folder.mutable_details();
+ details->add_parent_folder_ids(parent.file_id());
+ details->set_title(title);
+ details->set_file_kind(FILE_KIND_FOLDER);
+ return folder;
+ }
+
+ FileTracker CreateSyncRootTracker(const FileMetadata& sync_root) {
+ FileTracker sync_root_tracker;
+ sync_root_tracker.set_tracker_id(kSyncRootTrackerID);
+ sync_root_tracker.set_parent_tracker_id(0);
+ sync_root_tracker.set_file_id(sync_root.file_id());
+ sync_root_tracker.set_dirty(false);
+ sync_root_tracker.set_active(true);
+ sync_root_tracker.set_needs_folder_listing(false);
+ *sync_root_tracker.mutable_synced_details() = sync_root.details();
+ return sync_root_tracker;
+ }
+
+ FileTracker CreateTracker(const FileTracker& parent_tracker,
+ const FileMetadata& file) {
+ FileTracker tracker;
+ tracker.set_tracker_id(next_tracker_id_++);
+ tracker.set_parent_tracker_id(parent_tracker.tracker_id());
+ tracker.set_file_id(file.file_id());
+ tracker.set_app_id(parent_tracker.app_id());
+ tracker.set_is_app_root(false);
+ tracker.set_dirty(false);
+ tracker.set_active(true);
+ tracker.set_needs_folder_listing(false);
+ *tracker.mutable_synced_details() = file.details();
+ return tracker;
+ }
+
+ scoped_ptr<google_apis::ChangeResource> CreateChangeResourceFromMetadata(
+ const FileMetadata& file) {
+ scoped_ptr<google_apis::ChangeResource> change(
+ new google_apis::ChangeResource);
+ change->set_change_id(file.details().change_id());
+ change->set_file_id(file.file_id());
+ change->set_deleted(file.details().deleted());
+ if (change->is_deleted())
+ return change.Pass();
+
+ scoped_ptr<google_apis::FileResource> file_resource(
+ new google_apis::FileResource);
+ ScopedVector<google_apis::ParentReference> parents;
+ for (int i = 0; i < file.details().parent_folder_ids_size(); ++i) {
+ scoped_ptr<google_apis::ParentReference> parent(
+ new google_apis::ParentReference);
+ parent->set_file_id(file.details().parent_folder_ids(i));
+ parents.push_back(parent.release());
+ }
+
+ file_resource->set_file_id(file.file_id());
+ file_resource->set_parents(&parents);
+ file_resource->set_title(file.details().title());
+ if (file.details().file_kind() == FILE_KIND_FOLDER)
+ file_resource->set_mime_type("application/vnd.google-apps.folder");
+ else if (file.details().file_kind() == FILE_KIND_FILE)
+ file_resource->set_mime_type("text/plain");
+ else
+ file_resource->set_mime_type("application/vnd.google-apps.document");
+ file_resource->set_md5_checksum(file.details().md5());
+ file_resource->set_etag(file.details().etag());
+ file_resource->set_created_date(base::Time::FromInternalValue(
+ file.details().creation_time()));
+ file_resource->set_modified_date(base::Time::FromInternalValue(
+ file.details().modification_time()));
+
+ change->set_file(file_resource.Pass());
+ return change.Pass();
+ }
+
+ void ApplyRenameChangeToMetadata(const std::string& new_title,
+ FileMetadata* file) {
+ FileDetails* details = file->mutable_details();
+ details->set_title(new_title);
+ details->set_change_id(next_change_id_++);
+ }
+
+ void ApplyReorganizeChangeToMetadata(const std::string& new_parent,
+ FileMetadata* file) {
+ FileDetails* details = file->mutable_details();
+ details->clear_parent_folder_ids();
+ details->add_parent_folder_ids(new_parent);
+ details->set_change_id(next_change_id_++);
+ }
+
+ void ApplyContentChangeToMetadata(FileMetadata* file) {
+ FileDetails* details = file->mutable_details();
+ details->set_md5(
+ "md5_value_" + base::Int64ToString(next_md5_sequence_number_++));
+ details->set_change_id(next_change_id_++);
+ }
+
void PushToChangeList(scoped_ptr<google_apis::ChangeResource> change,
ScopedVector<google_apis::ChangeResource>* changes) {
changes->push_back(change.release());
}
+ leveldb::Status PutFileToDB(leveldb::DB* db, const FileMetadata& file) {
+ std::string key = "FILE: " + file.file_id();
+ std::string value;
+ file.SerializeToString(&value);
+ return db->Put(leveldb::WriteOptions(), key, value);
+ }
+
+ leveldb::Status PutTrackerToDB(leveldb::DB* db,
+ const FileTracker& tracker) {
+ std::string key = "TRACKER: " + base::Int64ToString(tracker.tracker_id());
+ std::string value;
+ tracker.SerializeToString(&value);
+ return db->Put(leveldb::WriteOptions(), key, value);
+ }
+
+ void VerifyReloadConsistency() {
+ scoped_ptr<MetadataDatabase> metadata_database_2;
+ ASSERT_EQ(SYNC_STATUS_OK,
+ MetadataDatabase::CreateForTesting(
+ metadata_database_->db_.Pass(),
+ &metadata_database_2));
+ metadata_database_->db_ = metadata_database_2->db_.Pass();
+
+ {
+ SCOPED_TRACE("Expect equivalent service_metadata");
+ ExpectEquivalent(metadata_database_->service_metadata_.get(),
+ metadata_database_2->service_metadata_.get());
+ }
+
+ {
+ SCOPED_TRACE("Expect equivalent file_by_id_ contents.");
+ ExpectEquivalent(metadata_database_->file_by_id_,
+ metadata_database_2->file_by_id_);
+ }
+
+ {
+ SCOPED_TRACE("Expect equivalent tracker_by_id_ contents.");
+ ExpectEquivalent(metadata_database_->tracker_by_id_,
+ metadata_database_2->tracker_by_id_);
+ }
+
+ {
+ SCOPED_TRACE("Expect equivalent trackers_by_file_id_ contents.");
+ ExpectEquivalent(metadata_database_->trackers_by_file_id_,
+ metadata_database_2->trackers_by_file_id_);
+ }
+
+ {
+ SCOPED_TRACE("Expect equivalent app_root_by_app_id_ contents.");
+ ExpectEquivalent(metadata_database_->app_root_by_app_id_,
+ metadata_database_2->app_root_by_app_id_);
+ }
+
+ {
+ SCOPED_TRACE("Expect equivalent trackers_by_parent_and_title_ contents.");
+ ExpectEquivalent(metadata_database_->trackers_by_parent_and_title_,
+ metadata_database_2->trackers_by_parent_and_title_);
+ }
+
+ {
+ SCOPED_TRACE("Expect equivalent dirty_trackers_ contents.");
+ ExpectEquivalent(metadata_database_->dirty_trackers_,
+ metadata_database_2->dirty_trackers_);
+ }
+ }
+
+ void VerifyFile(const FileMetadata& file) {
+ FileMetadata file_in_metadata_database;
+ ASSERT_TRUE(metadata_database()->FindFileByFileID(
+ file.file_id(), &file_in_metadata_database));
+
+ SCOPED_TRACE("Expect equivalent " + file.file_id());
+ ExpectEquivalent(&file, &file_in_metadata_database);
+ }
+
+ void VerifyTracker(const FileTracker& tracker) {
+ FileTracker tracker_in_metadata_database;
+ ASSERT_TRUE(metadata_database()->FindTrackerByTrackerID(
+ tracker.tracker_id(), &tracker_in_metadata_database));
+
+ SCOPED_TRACE("Expect equivalent tracker[" +
+ base::Int64ToString(tracker.tracker_id()) + "]");
+ ExpectEquivalent(&tracker, &tracker_in_metadata_database);
+ }
+
SyncStatusCode RegisterApp(const std::string& app_id,
const std::string& folder_id) {
SyncStatusCode status = SYNC_STATUS_UNKNOWN;
@@ -162,6 +504,7 @@
scoped_ptr<MetadataDatabase> metadata_database_;
int64 next_change_id_;
+ int64 next_tracker_id_;
int64 next_file_id_number_;
int64 next_md5_sequence_number_;
@@ -174,5 +517,319 @@
EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
}
+TEST_F(MetadataDatabaseTest, InitializationTest_SimpleTree) {
+ FileMetadata sync_root(CreateSyncRootMetadata());
+ FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
+
+ FileMetadata app_root(
+ CreateFolderMetadata(sync_root, "app_id" /* title */));
+ FileTracker app_root_tracker(
+ CreateTracker(sync_root_tracker, app_root));
+ app_root_tracker.set_app_id(app_root.details().title());
+ app_root_tracker.set_is_app_root(true);
+
+ FileMetadata file(CreateFileMetadata(app_root, "file"));
+ FileTracker file_tracker(CreateTracker(app_root_tracker, file));
+
+ FileMetadata folder(CreateFolderMetadata(app_root, "folder"));
+ FileTracker folder_tracker(CreateTracker(app_root_tracker, folder));
+
+ FileMetadata file_in_folder(
+ CreateFileMetadata(folder, "file_in_folder"));
+ FileTracker file_in_folder_tracker(
+ CreateTracker(folder_tracker, file_in_folder));
+
+ FileMetadata orphaned_file(
+ CreateFileMetadata(sync_root, "orphaned_file"));
+ orphaned_file.mutable_details()->clear_parent_folder_ids();
+ FileTracker orphaned_file_tracker(
+ CreateTracker(sync_root_tracker, orphaned_file));
+ orphaned_file_tracker.set_parent_tracker_id(0);
+
+ {
+ scoped_ptr<leveldb::DB> db = InitializeLevelDB();
+ ASSERT_TRUE(db);
+
+ EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), file_in_folder).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), file_in_folder_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), orphaned_file).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), orphaned_file_tracker).ok());
+ }
+
+ EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
+
+ VerifyFile(sync_root);
+ VerifyTracker(sync_root_tracker);
+ VerifyFile(app_root);
+ VerifyTracker(app_root_tracker);
+ VerifyFile(file);
+ VerifyTracker(file_tracker);
+ VerifyFile(folder);
+ VerifyTracker(folder_tracker);
+ VerifyFile(file_in_folder);
+ VerifyTracker(file_in_folder_tracker);
+
+ EXPECT_FALSE(metadata_database()->FindFileByFileID(
+ orphaned_file.file_id(), NULL));
+ EXPECT_FALSE(metadata_database()->FindTrackerByTrackerID(
+ orphaned_file_tracker.tracker_id(), NULL));
+}
+
+TEST_F(MetadataDatabaseTest, AppManagementTest) {
+ FileMetadata sync_root(CreateSyncRootMetadata());
+ FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
+
+ FileMetadata app_root(CreateFolderMetadata(sync_root, "app_id"));
+ FileTracker app_root_tracker(
+ CreateTracker(sync_root_tracker, app_root));
+ app_root_tracker.set_app_id(app_root.details().title());
+ app_root_tracker.set_is_app_root(true);
+
+ FileMetadata file(CreateFileMetadata(app_root, "file"));
+ FileTracker file_tracker(CreateTracker(app_root_tracker, file));
+
+ FileMetadata folder(CreateFolderMetadata(sync_root, "folder"));
+ FileTracker folder_tracker(CreateTracker(sync_root_tracker, folder));
+ folder_tracker.set_active(false);
+
+ {
+ scoped_ptr<leveldb::DB> db = InitializeLevelDB();
+ ASSERT_TRUE(db);
+
+ EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
+ }
+
+ EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
+ VerifyFile(sync_root);
+ VerifyTracker(sync_root_tracker);
+ VerifyFile(app_root);
+ VerifyTracker(app_root_tracker);
+ VerifyFile(file);
+ VerifyTracker(file_tracker);
+ VerifyFile(folder);
+ VerifyTracker(folder_tracker);
+
+ folder_tracker.set_app_id("foo");
+ folder_tracker.set_is_app_root(true);
+ folder_tracker.set_active(true);
+ folder_tracker.set_dirty(true);
+ folder_tracker.set_needs_folder_listing(true);
+ EXPECT_EQ(SYNC_STATUS_OK, RegisterApp(
+ folder_tracker.app_id(), folder.file_id()));
+ VerifyFile(folder);
+ VerifyTracker(folder_tracker);
+ VerifyReloadConsistency();
+
+ EXPECT_EQ(SYNC_STATUS_OK, DisableApp(folder_tracker.app_id()));
+ folder_tracker.set_active(false);
+ VerifyFile(folder);
+ VerifyTracker(folder_tracker);
+ VerifyReloadConsistency();
+
+ EXPECT_EQ(SYNC_STATUS_OK, EnableApp(folder_tracker.app_id()));
+ folder_tracker.set_active(true);
+ VerifyFile(folder);
+ VerifyTracker(folder_tracker);
+ VerifyReloadConsistency();
+
+ EXPECT_EQ(SYNC_STATUS_OK, UnregisterApp(folder_tracker.app_id()));
+ folder_tracker.set_app_id(std::string());
+ folder_tracker.set_is_app_root(false);
+ folder_tracker.set_active(false);
+ VerifyFile(folder);
+ VerifyTracker(folder_tracker);
+ VerifyReloadConsistency();
+
+ EXPECT_EQ(SYNC_STATUS_OK, UnregisterApp(app_root_tracker.app_id()));
+ app_root_tracker.set_app_id(std::string());
+ app_root_tracker.set_is_app_root(false);
+ app_root_tracker.set_active(false);
+ app_root_tracker.set_dirty(true);
+ VerifyFile(app_root);
+ VerifyTracker(app_root_tracker);
+ EXPECT_FALSE(metadata_database()->FindFileByFileID(file.file_id(), NULL));
+ EXPECT_FALSE(metadata_database()->FindTrackerByTrackerID(
+ file_tracker.tracker_id(), NULL));
+ VerifyReloadConsistency();
+}
+
+TEST_F(MetadataDatabaseTest, BuildPathTest) {
+ FileMetadata sync_root(CreateSyncRootMetadata());
+ FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
+
+ FileMetadata app_root(CreateFolderMetadata(sync_root, "app_id"));
+ FileTracker app_root_tracker(
+ CreateTracker(sync_root_tracker, app_root));
+ app_root_tracker.set_app_id(app_root.details().title());
+ app_root_tracker.set_is_app_root(true);
+
+ FileMetadata folder(CreateFolderMetadata(app_root, "folder"));
+ FileTracker folder_tracker(CreateTracker(app_root_tracker, folder));
+
+ FileMetadata file(CreateFolderMetadata(folder, "file"));
+ FileTracker file_tracker(CreateTracker(folder_tracker, file));
+
+ FileMetadata inactive_folder(CreateFolderMetadata(app_root, "folder"));
+ FileTracker inactive_folder_tracker(CreateTracker(app_root_tracker,
+ inactive_folder));
+ inactive_folder_tracker.set_active(false);
+
+ {
+ scoped_ptr<leveldb::DB> db = InitializeLevelDB();
+ ASSERT_TRUE(db);
+
+ EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
+ }
+
+ EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
+
+ base::FilePath path;
+ EXPECT_FALSE(metadata_database()->BuildPathForTracker(
+ sync_root_tracker.tracker_id(), &path));
+ EXPECT_TRUE(metadata_database()->BuildPathForTracker(
+ app_root_tracker.tracker_id(), &path));
+ EXPECT_EQ(base::FilePath(FPL("/")).NormalizePathSeparators(), path);
+ EXPECT_TRUE(metadata_database()->BuildPathForTracker(
+ file_tracker.tracker_id(), &path));
+ EXPECT_EQ(base::FilePath(FPL("/folder/file")).NormalizePathSeparators(),
+ path);
+}
+
+TEST_F(MetadataDatabaseTest, UpdateByChangeListTest) {
+ FileMetadata sync_root(CreateSyncRootMetadata());
+ FileTracker sync_root_tracker(CreateSyncRootTracker(sync_root));
+
+ FileMetadata app_root(CreateFolderMetadata(sync_root, "app_id"));
+ FileTracker app_root_tracker(
+ CreateTracker(sync_root_tracker, app_root));
+
+ FileMetadata disabled_app_root(
+ CreateFolderMetadata(sync_root, "disabled_app"));
+ FileTracker disabled_app_root_tracker(
+ CreateTracker(sync_root_tracker, disabled_app_root));
+
+ FileMetadata file(CreateFileMetadata(app_root, "file"));
+ FileTracker file_tracker(CreateTracker(app_root_tracker, file));
+
+ FileMetadata renamed_file(CreateFileMetadata(app_root, "to be renamed"));
+ FileTracker renamed_file_tracker(
+ CreateTracker(app_root_tracker, renamed_file));
+
+ FileMetadata folder(CreateFolderMetadata(app_root, "folder"));
+ FileTracker folder_tracker(CreateTracker(app_root_tracker, folder));
+
+ FileMetadata reorganized_file(
+ CreateFileMetadata(app_root, "to be reorganized"));
+ FileTracker reorganized_file_tracker(
+ CreateTracker(app_root_tracker, reorganized_file));
+
+ FileMetadata updated_file(CreateFileMetadata(app_root, "to be updated"));
+ FileTracker updated_file_tracker(
+ CreateTracker(app_root_tracker, updated_file));
+
+ FileMetadata noop_file(CreateFileMetadata(app_root, "have noop change"));
+ FileTracker noop_file_tracker(
+ CreateTracker(app_root_tracker, noop_file));
+
+ FileMetadata new_file(CreateFileMetadata(app_root, "to be added later"));
+
+ {
+ scoped_ptr<leveldb::DB> db = InitializeLevelDB();
+ ASSERT_TRUE(db);
+
+ EXPECT_TRUE(PutFileToDB(db.get(), sync_root).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), sync_root_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), app_root).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), app_root_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), disabled_app_root).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), disabled_app_root_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), file).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), file_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), renamed_file).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), renamed_file_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), folder).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), folder_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), reorganized_file).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), reorganized_file_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), updated_file).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), updated_file_tracker).ok());
+ EXPECT_TRUE(PutFileToDB(db.get(), noop_file).ok());
+ EXPECT_TRUE(PutTrackerToDB(db.get(), noop_file_tracker).ok());
+ }
+
+ EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
+
+ ApplyRenameChangeToMetadata("renamed", &renamed_file);
+ ApplyReorganizeChangeToMetadata(folder.file_id(), &reorganized_file);
+ ApplyContentChangeToMetadata(&updated_file);
+
+ ScopedVector<google_apis::ChangeResource> changes;
+ PushToChangeList(CreateChangeResourceFromMetadata(renamed_file), &changes);
+ PushToChangeList(CreateChangeResourceFromMetadata(
+ reorganized_file), &changes);
+ PushToChangeList(CreateChangeResourceFromMetadata(updated_file), &changes);
+ PushToChangeList(CreateChangeResourceFromMetadata(noop_file), &changes);
+ PushToChangeList(CreateChangeResourceFromMetadata(new_file), &changes);
+
+ renamed_file_tracker.set_dirty(true);
+ reorganized_file_tracker.set_dirty(true);
+ updated_file_tracker.set_dirty(true);
+ noop_file_tracker.set_dirty(true);
+
+ EXPECT_EQ(SYNC_STATUS_OK, UpdateByChangeList(changes.Pass()));
+
+ FileTracker new_file_tracker(CreateTracker(app_root_tracker, new_file));
+ new_file_tracker.set_tracker_id(GetTrackerIDByFileID(new_file.file_id()));
+ new_file_tracker.clear_synced_details();
+ new_file_tracker.set_active(false);
+ new_file_tracker.set_dirty(true);
+ EXPECT_NE(0, new_file_tracker.tracker_id());
+
+ VerifyFile(sync_root);
+ VerifyTracker(sync_root_tracker);
+ VerifyFile(app_root);
+ VerifyTracker(app_root_tracker);
+ VerifyFile(disabled_app_root);
+ VerifyTracker(disabled_app_root_tracker);
+ VerifyFile(file);
+ VerifyTracker(file_tracker);
+ VerifyFile(renamed_file);
+ VerifyTracker(renamed_file_tracker);
+ VerifyFile(folder);
+ VerifyTracker(folder_tracker);
+ VerifyFile(reorganized_file);
+ VerifyTracker(reorganized_file_tracker);
+ VerifyFile(updated_file);
+ VerifyTracker(updated_file_tracker);
+ VerifyFile(noop_file);
+ VerifyTracker(noop_file_tracker);
+ VerifyFile(new_file);
+ VerifyTracker(new_file_tracker);
+
+ VerifyReloadConsistency();
+}
+
} // namespace drive_backend
} // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/tracker_set.h b/chrome/browser/sync_file_system/drive_backend/tracker_set.h
index 68353a9..1b3f0e9 100644
--- a/chrome/browser/sync_file_system/drive_backend/tracker_set.h
+++ b/chrome/browser/sync_file_system/drive_backend/tracker_set.h
@@ -39,6 +39,7 @@
iterator end() { return tracker_set_.end(); }
const_iterator begin() const { return tracker_set_.begin(); }
const_iterator end() const { return tracker_set_.end(); }
+ bool empty() const { return tracker_set_.empty(); }
private:
FileTracker* active_tracker_;
diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc
index 79e62ee..77b4ff5 100644
--- a/chrome/browser/tab_contents/render_view_context_menu.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu.cc
@@ -30,7 +30,7 @@
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/download/download_service.h"
#include "chrome/browser/download/download_service_factory.h"
-#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/download_stats.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
@@ -838,7 +838,7 @@
menu_model_.AddItemWithStringId(
IDC_CONTENT_CONTEXT_COPYLINKLOCATION,
- params_.link_url.SchemeIs(chrome::kMailToScheme) ?
+ params_.link_url.SchemeIs(content::kMailToScheme) ?
IDS_CONTENT_CONTEXT_COPYEMAILADDRESS :
IDS_CONTENT_CONTEXT_COPYLINKLOCATION);
}
@@ -1566,8 +1566,7 @@
break;
case IDC_CONTENT_CONTEXT_SAVELINKAS: {
- download_util::RecordDownloadSource(
- download_util::INITIATED_BY_CONTEXT_MENU);
+ RecordDownloadSource(DOWNLOAD_INITIATED_BY_CONTEXT_MENU);
const GURL& referrer =
params_.frame_url.is_empty() ? params_.page_url : params_.frame_url;
const GURL& url = params_.link_url;
@@ -1584,8 +1583,7 @@
case IDC_CONTENT_CONTEXT_SAVEAVAS:
case IDC_CONTENT_CONTEXT_SAVEIMAGEAS: {
- download_util::RecordDownloadSource(
- download_util::INITIATED_BY_CONTEXT_MENU);
+ RecordDownloadSource(DOWNLOAD_INITIATED_BY_CONTEXT_MENU);
const GURL& referrer =
params_.frame_url.is_empty() ? params_.page_url : params_.frame_url;
const GURL& url = params_.src_url;
@@ -1980,11 +1978,6 @@
rvh->NotifyContextMenuClosed(params_.custom_context);
}
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_RENDER_VIEW_CONTEXT_MENU_CLOSED,
- content::Source<RenderViewContextMenu>(this),
- content::NotificationService::NoDetails());
-
if (!command_executed_) {
FOR_EACH_OBSERVER(RenderViewContextMenuObserver,
observers_,
diff --git a/chrome/browser/tab_contents/tab_util.cc b/chrome/browser/tab_contents/tab_util.cc
index fae1201..ae3100a 100644
--- a/chrome/browser/tab_contents/tab_util.cc
+++ b/chrome/browser/tab_contents/tab_util.cc
@@ -31,9 +31,8 @@
SiteInstance* GetSiteInstanceForNewTab(Profile* profile,
const GURL& url) {
- // If url is a WebUI or extension, we need to be sure to use the right type
- // of renderer process up front. Otherwise, we create a normal SiteInstance
- // as part of creating the tab.
+ // If |url| is a WebUI or extension, we set the SiteInstance up front so that
+ // we don't end up with an extra process swap on the first navigation.
ExtensionService* service = profile->GetExtensionService();
if (ChromeWebUIControllerFactory::GetInstance()->UseWebUIForURL(
profile, url) ||
@@ -44,7 +43,8 @@
// We used to share the SiteInstance for same-site links opened in new tabs,
// to leverage the in-memory cache and reduce process creation. It now
- // appears that it is more useful to have such links open in a new process.
+ // appears that it is more useful to have such links open in a new process,
+ // so we create new tabs in a new BrowsingInstance.
return NULL;
}
diff --git a/chrome/browser/themes/theme_properties.h b/chrome/browser/themes/theme_properties.h
index 2eaa1ed..2bea265 100644
--- a/chrome/browser/themes/theme_properties.h
+++ b/chrome/browser/themes/theme_properties.h
@@ -90,6 +90,7 @@
COLOR_NTP_TEXT_LIGHT,
COLOR_MANAGED_USER_LABEL,
COLOR_MANAGED_USER_LABEL_BACKGROUND,
+ COLOR_MANAGED_USER_LABEL_BORDER,
#if defined(OS_MACOSX)
COLOR_TOOLBAR_BEZEL,
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc
index 5038dff..fdb0244 100644
--- a/chrome/browser/themes/theme_service.cc
+++ b/chrome/browser/themes/theme_service.cc
@@ -13,6 +13,8 @@
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/managed_mode/managed_user_service.h"
+#include "chrome/browser/managed_mode/managed_user_service_factory.h"
#include "chrome/browser/managed_mode/managed_user_theme.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/themes/browser_theme_pack.h"
@@ -77,7 +79,8 @@
: ready_(false),
rb_(ResourceBundle::GetSharedInstance()),
profile_(NULL),
- number_of_infobars_(0) {
+ number_of_infobars_(0),
+ weak_ptr_factory_(this) {
}
ThemeService::~ThemeService() {
@@ -88,6 +91,9 @@
DCHECK(CalledOnValidThread());
profile_ = profile;
+ ManagedUserServiceFactory::GetForProfile(profile)->AddInitCallback(base::Bind(
+ &ThemeService::OnManagedUserInitialized, weak_ptr_factory_.GetWeakPtr()));
+
LoadThemePrefs();
if (!ready_) {
@@ -147,6 +153,11 @@
case Properties::COLOR_MANAGED_USER_LABEL_BACKGROUND:
return color_utils::BlendTowardOppositeLuminance(
GetColor(Properties::COLOR_FRAME), 0x80);
+ case Properties::COLOR_MANAGED_USER_LABEL_BORDER:
+ return color_utils::AlphaBlend(
+ GetColor(Properties::COLOR_MANAGED_USER_LABEL_BACKGROUND),
+ SK_ColorBLACK,
+ 230);
}
return Properties::GetDefaultColor(id);
@@ -455,6 +466,20 @@
SetCustomDefaultTheme(new ManagedUserTheme);
}
+void ThemeService::OnManagedUserInitialized() {
+ // Currently when creating a supervised user, the ThemeService is initialized
+ // before the boolean flag indicating the profile belongs to a supervised
+ // user gets set. In order to get the custom managed user theme, we get a
+ // callback when ManagedUserService is initialized, which happens some time
+ // after the boolean flag has been set in
+ // ProfileManager::InitProfileUserPrefs() and after the
+ // NOTIFICATION_EXTENSIONS_READY notification is sent.
+ if (theme_supplier_.get() || !IsManagedUser())
+ return;
+
+ SetManagedUserTheme();
+}
+
void ThemeService::OnInfobarDisplayed() {
number_of_infobars_++;
}
diff --git a/chrome/browser/themes/theme_service.h b/chrome/browser/themes/theme_service.h
index b573d2e..117844f 100644
--- a/chrome/browser/themes/theme_service.h
+++ b/chrome/browser/themes/theme_service.h
@@ -13,6 +13,7 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
#include "content/public/browser/notification_observer.h"
@@ -214,6 +215,9 @@
// managed user profiles.
void SetManagedUserTheme();
+ // Sets the managed user theme if the user has no custom theme yet.
+ void OnManagedUserInitialized();
+
#if defined(TOOLKIT_GTK)
// Loads an image and flips it horizontally if |rtl_enabled| is true.
GdkPixbuf* GetPixbufImpl(int id, bool rtl_enabled) const;
@@ -247,6 +251,8 @@
scoped_ptr<ThemeSyncableService> theme_syncable_service_;
+ base::WeakPtrFactory<ThemeService> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(ThemeService);
};
diff --git a/chrome/browser/themes/theme_service_unittest.cc b/chrome/browser/themes/theme_service_unittest.cc
index 4168f96..6288935 100644
--- a/chrome/browser/themes/theme_service_unittest.cc
+++ b/chrome/browser/themes/theme_service_unittest.cc
@@ -6,19 +6,26 @@
#include "base/json/json_reader.h"
#include "chrome/browser/extensions/extension_service_unittest.h"
+#include "chrome/browser/managed_mode/managed_user_service.h"
+#include "chrome/browser/managed_mode/managed_user_service_factory.h"
#include "chrome/browser/themes/custom_theme_supplier.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_manifest_constants.h"
#include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace theme_service_internal {
class ThemeServiceTest : public ExtensionServiceTestBase {
public:
- ThemeServiceTest() {}
+ ThemeServiceTest() {
+ manager_.reset(
+ new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
+ }
virtual ~ThemeServiceTest() {}
scoped_refptr<extensions::Extension> MakeThemeExtension(base::FilePath path) {
@@ -40,11 +47,20 @@
virtual void SetUp() {
ExtensionServiceTestBase::SetUp();
InitializeEmptyExtensionService();
+ bool success = manager_->SetUp();
+ ASSERT_TRUE(success);
}
const CustomThemeSupplier* get_theme_supplier(ThemeService* theme_service) {
return theme_service->get_theme_supplier();
}
+
+ TestingProfileManager* manager() {
+ return manager_.get();
+ }
+
+ private:
+ scoped_ptr<TestingProfileManager> manager_;
};
// Installs then uninstalls a theme and makes sure that the ThemeService
@@ -103,6 +119,18 @@
CustomThemeSupplier::MANAGED_USER_THEME);
}
+TEST_F(ThemeServiceTest, ManagedUserThemeNewUser) {
+ TestingProfile* profile = manager()->CreateTestingProfile("mu");
+ // Simulate the current initialization behavior: first the ThemeService is
+ // created, then the supervised user profile is initialized.
+ ThemeService* theme_service =
+ ThemeServiceFactory::GetForProfile(profile);
+ ManagedUserServiceFactory::GetForProfile(profile)->InitForTesting();
+ EXPECT_EQ(get_theme_supplier(theme_service)->get_theme_type(),
+ CustomThemeSupplier::MANAGED_USER_THEME);
+ manager()->DeleteTestingProfile("mu");
+}
+
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
// Checks that managed users don't use the system theme even if it is the
// default. The system theme is only available on Linux.
diff --git a/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.cc b/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.cc
new file mode 100644
index 0000000..00f5da8
--- /dev/null
+++ b/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.cc
@@ -0,0 +1,488 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/android/autofill/autofill_dialog_controller_android.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/autofill/personal_data_manager_factory.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/scoped_user_pref_update.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/android/autofill/autofill_dialog_result.h"
+#include "chrome/browser/ui/android/window_android_helper.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_common.h"
+#include "chrome/browser/ui/autofill/data_model_wrapper.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "components/autofill/content/browser/wallet/full_wallet.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/common/form_data.h"
+#include "components/user_prefs/pref_registry_syncable.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_details.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/web_contents.h"
+#include "grit/generated_resources.h"
+#include "jni/AutofillDialogControllerAndroid_jni.h"
+#include "ui/android/window_android.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/combobox_model.h"
+#include "ui/base/models/menu_model.h"
+#include "ui/gfx/android/java_bitmap.h"
+#include "ui/gfx/rect.h"
+#include "url/gurl.h"
+
+namespace autofill {
+
+namespace {
+
+// Keys in kAutofillDialogDefaults pref dictionary (do not change these values).
+const char kLastUsedAccountName[] = "last_used_account_name";
+const char kLastUsedChoiceIsAutofill[] = "last_used_choice_is_autofill";
+const char kLastUsedBillingAddressGuid[] = "last_used_billing";
+const char kLastUsedShippingAddressGuid[] = "last_used_shipping";
+const char kLastUsedCreditCardGuid[] = "last_used_card";
+
+scoped_ptr<DataModelWrapper> CreateWrapper(
+ DialogSection section, wallet::FullWallet* full_wallet) {
+ if (section == SECTION_CC_BILLING) {
+ if (!full_wallet->billing_address())
+ return scoped_ptr<DataModelWrapper>();
+
+ return scoped_ptr<DataModelWrapper>(
+ new FullWalletBillingWrapper(full_wallet));
+ }
+ if (section == SECTION_SHIPPING) {
+ if (!full_wallet->shipping_address())
+ return scoped_ptr<DataModelWrapper>();
+
+ return scoped_ptr<DataModelWrapper>(
+ new FullWalletShippingWrapper(full_wallet));
+ }
+ NOTREACHED();
+ return scoped_ptr<DataModelWrapper>();
+}
+
+void FillOutputForSectionWithComparator(
+ DialogSection section, const DetailInputs& inputs,
+ const InputFieldComparator& compare,
+ FormStructure& form_structure, wallet::FullWallet* full_wallet,
+ const base::string16& email_address) {
+
+ // Email is hidden while using Wallet, special case it.
+ if (section == SECTION_EMAIL) {
+ AutofillProfile profile;
+ profile.SetRawInfo(EMAIL_ADDRESS, email_address);
+ AutofillProfileWrapper profile_wrapper(&profile, 0);
+ profile_wrapper.FillFormStructure(inputs, compare, &form_structure);
+ return;
+ }
+
+ scoped_ptr<DataModelWrapper> wrapper = CreateWrapper(section, full_wallet);
+ if (wrapper)
+ wrapper->FillFormStructure(inputs, compare, &form_structure);
+}
+
+void FillOutputForSection(
+ DialogSection section,
+ FormStructure& form_structure,
+ wallet::FullWallet* full_wallet,
+ const base::string16& email_address) {
+ DetailInputs inputs;
+ common::BuildInputsForSection(section, &inputs);
+
+ FillOutputForSectionWithComparator(
+ section, inputs,
+ base::Bind(common::DetailInputMatchesField, section),
+ form_structure, full_wallet, email_address);
+}
+
+} // namespace
+
+
+// static
+base::WeakPtr<AutofillDialogController> AutofillDialogControllerAndroid::Create(
+ content::WebContents* contents,
+ const FormData& form_structure,
+ const GURL& source_url,
+ const DialogType dialog_type,
+ const base::Callback<void(const FormStructure*,
+ const std::string&)>& callback) {
+ // AutofillDialogControllerAndroid owns itself.
+ AutofillDialogControllerAndroid* autofill_dialog_controller =
+ new AutofillDialogControllerAndroid(contents,
+ form_structure,
+ source_url,
+ dialog_type,
+ callback);
+ return autofill_dialog_controller->weak_ptr_factory_.GetWeakPtr();
+}
+
+// static
+void AutofillDialogControllerAndroid::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterDictionaryPref(
+ ::prefs::kAutofillDialogDefaults,
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+}
+
+// static
+base::WeakPtr<AutofillDialogController>
+AutofillDialogController::Create(
+ content::WebContents* contents,
+ const FormData& form_structure,
+ const GURL& source_url,
+ const DialogType dialog_type,
+ const base::Callback<void(const FormStructure*,
+ const std::string&)>& callback) {
+ return AutofillDialogControllerAndroid::Create(contents,
+ form_structure,
+ source_url,
+ dialog_type,
+ callback);
+}
+
+// static
+void AutofillDialogController::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ AutofillDialogControllerAndroid::RegisterProfilePrefs(registry);
+}
+
+AutofillDialogControllerAndroid::~AutofillDialogControllerAndroid() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_AutofillDialogControllerAndroid_onDestroy(env, java_object_.obj());
+}
+
+void AutofillDialogControllerAndroid::Show() {
+ dialog_shown_timestamp_ = base::Time::Now();
+
+ content::NavigationEntry* entry = contents_->GetController().GetActiveEntry();
+ const GURL& active_url = entry ? entry->GetURL() : contents_->GetURL();
+ invoked_from_same_origin_ = active_url.GetOrigin() == source_url_.GetOrigin();
+
+ // Log any relevant UI metrics and security exceptions.
+ GetMetricLogger().LogDialogUiEvent(
+ GetDialogType(), AutofillMetrics::DIALOG_UI_SHOWN);
+
+ GetMetricLogger().LogDialogSecurityMetric(
+ GetDialogType(), AutofillMetrics::SECURITY_METRIC_DIALOG_SHOWN);
+
+ if (RequestingCreditCardInfo() && !TransmissionWillBeSecure()) {
+ GetMetricLogger().LogDialogSecurityMetric(
+ GetDialogType(),
+ AutofillMetrics::SECURITY_METRIC_CREDIT_CARD_OVER_HTTP);
+ }
+
+ if (!invoked_from_same_origin_) {
+ GetMetricLogger().LogDialogSecurityMetric(
+ GetDialogType(),
+ AutofillMetrics::SECURITY_METRIC_CROSS_ORIGIN_FRAME);
+ }
+
+ // Determine what field types should be included in the dialog.
+ bool has_types = false;
+ bool has_sections = false;
+ form_structure_.ParseFieldTypesFromAutocompleteAttributes(
+ &has_types, &has_sections);
+
+ // Fail if the author didn't specify autocomplete types.
+ if (!has_types) {
+ callback_.Run(NULL, std::string());
+ delete this;
+ return;
+ }
+
+ bool request_full_billing_address = true;
+ bool request_shipping_address = false;
+ bool request_phone_numbers = false;
+
+ for (size_t i = 0; i < form_structure_.field_count(); ++i) {
+ const ServerFieldType type =
+ form_structure_.field(i)->Type().GetStorableType();
+ if (type == PHONE_HOME_WHOLE_NUMBER || type == PHONE_BILLING_WHOLE_NUMBER) {
+ request_phone_numbers = true;
+ }
+ if (type == NAME_FULL ||
+ type == ADDRESS_HOME_LINE1 || type == ADDRESS_HOME_LINE2 ||
+ type == ADDRESS_HOME_CITY || type == ADDRESS_HOME_STATE ||
+ type == ADDRESS_HOME_ZIP || type == ADDRESS_HOME_COUNTRY ||
+ type == PHONE_HOME_WHOLE_NUMBER) {
+ request_shipping_address = true;
+ }
+ if (type == ADDRESS_BILLING_LINE1 || type == ADDRESS_BILLING_LINE2 ||
+ type == ADDRESS_BILLING_CITY || type == ADDRESS_BILLING_STATE ||
+ type == PHONE_BILLING_WHOLE_NUMBER) {
+ request_full_billing_address = true;
+ }
+ }
+
+ if (request_shipping_address)
+ request_full_billing_address = true;
+
+ const bool incognito_mode = profile_->IsOffTheRecord();
+
+ bool last_used_choice_is_autofill = false;
+ base::string16 last_used_account_name;
+ std::string last_used_billing;
+ std::string last_used_shipping;
+ std::string last_used_credit_card;
+ {
+ const base::DictionaryValue* defaults =
+ profile_->GetPrefs()->GetDictionary(::prefs::kAutofillDialogDefaults);
+ if (defaults) {
+ defaults->GetString(kLastUsedAccountName, &last_used_account_name);
+ defaults->GetBoolean(kLastUsedChoiceIsAutofill,
+ &last_used_choice_is_autofill);
+ defaults->GetString(kLastUsedBillingAddressGuid, &last_used_billing);
+ defaults->GetString(kLastUsedShippingAddressGuid, &last_used_shipping);
+ defaults->GetString(kLastUsedCreditCardGuid, &last_used_credit_card);
+ } else {
+ DLOG(ERROR) << "Failed to read AutofillDialog preferences";
+ }
+ }
+
+ if (contents_->GetBrowserContext()->IsOffTheRecord())
+ last_used_choice_is_autofill = true;
+
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jstring> jlast_used_account_name =
+ base::android::ConvertUTF16ToJavaString(
+ env, last_used_account_name);
+ ScopedJavaLocalRef<jstring> jlast_used_billing =
+ base::android::ConvertUTF8ToJavaString(
+ env, last_used_billing);
+ ScopedJavaLocalRef<jstring> jlast_used_shipping =
+ base::android::ConvertUTF8ToJavaString(
+ env, last_used_shipping);
+ ScopedJavaLocalRef<jstring> jlast_used_card =
+ base::android::ConvertUTF8ToJavaString(
+ env, last_used_credit_card);
+ ScopedJavaLocalRef<jstring> jmerchant_domain =
+ base::android::ConvertUTF8ToJavaString(
+ env, source_url_.GetOrigin().spec());
+ java_object_.Reset(Java_AutofillDialogControllerAndroid_create(
+ env,
+ reinterpret_cast<jint>(this),
+ WindowAndroidHelper::FromWebContents(contents_)->
+ GetWindowAndroid()->GetJavaObject().obj(),
+ request_full_billing_address, request_shipping_address,
+ request_phone_numbers, incognito_mode,
+ last_used_choice_is_autofill, jlast_used_account_name.obj(),
+ jlast_used_billing.obj(), jlast_used_shipping.obj(),
+ jlast_used_card.obj(),
+ jmerchant_domain.obj()));
+}
+
+void AutofillDialogControllerAndroid::Hide() {
+ // TODO(aruslan): http://crbug.com/177373 Autocheckout.
+ NOTIMPLEMENTED();
+}
+
+void AutofillDialogControllerAndroid::TabActivated() {}
+
+void AutofillDialogControllerAndroid::AddAutocheckoutStep(
+ AutocheckoutStepType step_type) {
+ // TODO(aruslan): http://crbug.com/177373 Autocheckout.
+ NOTIMPLEMENTED() << " step_type = " << step_type;
+}
+
+void AutofillDialogControllerAndroid::UpdateAutocheckoutStep(
+ AutocheckoutStepType step_type,
+ AutocheckoutStepStatus step_status) {
+ // TODO(aruslan): http://crbug.com/177373 Autocheckout.
+ NOTIMPLEMENTED() << " step_type=" << step_type
+ << " step_status=" << step_status;
+}
+
+void AutofillDialogControllerAndroid::OnAutocheckoutError() {
+ // TODO(aruslan): http://crbug.com/177373 Autocheckout.
+ NOTIMPLEMENTED();
+ DCHECK_EQ(AUTOCHECKOUT_IN_PROGRESS, autocheckout_state_);
+ GetMetricLogger().LogAutocheckoutDuration(
+ base::Time::Now() - autocheckout_started_timestamp_,
+ AutofillMetrics::AUTOCHECKOUT_FAILED);
+ SetAutocheckoutState(AUTOCHECKOUT_ERROR);
+ autocheckout_started_timestamp_ = base::Time();
+}
+
+void AutofillDialogControllerAndroid::OnAutocheckoutSuccess() {
+ // TODO(aruslan): http://crbug.com/177373 Autocheckout.
+ NOTIMPLEMENTED();
+ DCHECK_EQ(AUTOCHECKOUT_IN_PROGRESS, autocheckout_state_);
+ GetMetricLogger().LogAutocheckoutDuration(
+ base::Time::Now() - autocheckout_started_timestamp_,
+ AutofillMetrics::AUTOCHECKOUT_SUCCEEDED);
+ SetAutocheckoutState(AUTOCHECKOUT_SUCCESS);
+ autocheckout_started_timestamp_ = base::Time();
+}
+
+DialogType AutofillDialogControllerAndroid::GetDialogType() const {
+ return dialog_type_;
+}
+
+// static
+bool AutofillDialogControllerAndroid::
+ RegisterAutofillDialogControllerAndroid(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+void AutofillDialogControllerAndroid::DialogCancel(JNIEnv* env,
+ jobject obj) {
+ if (autocheckout_state_ == AUTOCHECKOUT_NOT_STARTED)
+ LogOnCancelMetrics();
+
+ if (autocheckout_state_ == AUTOCHECKOUT_IN_PROGRESS) {
+ GetMetricLogger().LogAutocheckoutDuration(
+ base::Time::Now() - autocheckout_started_timestamp_,
+ AutofillMetrics::AUTOCHECKOUT_CANCELLED);
+ }
+
+ callback_.Run(NULL, std::string());
+}
+
+void AutofillDialogControllerAndroid::DialogContinue(
+ JNIEnv* env,
+ jobject obj,
+ jobject wallet,
+ jboolean jlast_used_choice_is_autofill,
+ jstring jlast_used_account_name,
+ jstring jlast_used_billing,
+ jstring jlast_used_shipping,
+ jstring jlast_used_card) {
+ const string16 email = AutofillDialogResult::GetWalletEmail(env, wallet);
+ const std::string google_transaction_id =
+ AutofillDialogResult::GetWalletGoogleTransactionId(env, wallet);
+
+ const string16 last_used_account_name =
+ base::android::ConvertJavaStringToUTF16(env, jlast_used_account_name);
+ const std::string last_used_billing =
+ base::android::ConvertJavaStringToUTF8(env, jlast_used_billing);
+ const std::string last_used_shipping =
+ base::android::ConvertJavaStringToUTF8(env, jlast_used_shipping);
+ const std::string last_used_card =
+ base::android::ConvertJavaStringToUTF8(env, jlast_used_card);
+
+ scoped_ptr<wallet::FullWallet> full_wallet =
+ AutofillDialogResult::ConvertFromJava(env, wallet);
+ FillOutputForSection(
+ SECTION_EMAIL, form_structure_, full_wallet.get(), email);
+ FillOutputForSection(
+ SECTION_CC_BILLING, form_structure_, full_wallet.get(), email);
+ FillOutputForSection(
+ SECTION_SHIPPING, form_structure_, full_wallet.get(), email);
+
+ {
+ DictionaryPrefUpdate updater(profile_->GetPrefs(),
+ ::prefs::kAutofillDialogDefaults);
+ base::DictionaryValue* defaults = updater.Get();
+ if (defaults) {
+ const bool last_used_choice_is_autofill = !!jlast_used_choice_is_autofill;
+ defaults->SetString(kLastUsedAccountName, last_used_account_name);
+ defaults->SetBoolean(kLastUsedChoiceIsAutofill,
+ last_used_choice_is_autofill);
+ if (!last_used_billing.empty())
+ defaults->SetString(kLastUsedBillingAddressGuid, last_used_billing);
+ if (!last_used_shipping.empty())
+ defaults->SetString(kLastUsedShippingAddressGuid, last_used_shipping);
+ if (!last_used_card.empty())
+ defaults->SetString(kLastUsedCreditCardGuid, last_used_card);
+ } else {
+ LOG(ERROR) << "Failed to save AutofillDialog preferences";
+ }
+ }
+
+ if (GetDialogType() == DIALOG_TYPE_AUTOCHECKOUT) {
+ autocheckout_started_timestamp_ = base::Time::Now();
+ SetAutocheckoutState(AUTOCHECKOUT_IN_PROGRESS);
+ }
+
+ LogOnFinishSubmitMetrics();
+
+ // Callback should be called as late as possible.
+ callback_.Run(&form_structure_, google_transaction_id);
+
+ // This might delete us.
+ if (GetDialogType() == DIALOG_TYPE_REQUEST_AUTOCOMPLETE)
+ Hide();
+}
+
+AutofillDialogControllerAndroid::AutofillDialogControllerAndroid(
+ content::WebContents* contents,
+ const FormData& form_structure,
+ const GURL& source_url,
+ const DialogType dialog_type,
+ const base::Callback<void(const FormStructure*,
+ const std::string&)>& callback)
+ : profile_(Profile::FromBrowserContext(contents->GetBrowserContext())),
+ contents_(contents),
+ initial_user_state_(AutofillMetrics::DIALOG_USER_STATE_UNKNOWN),
+ dialog_type_(dialog_type),
+ form_structure_(form_structure, std::string()),
+ invoked_from_same_origin_(true),
+ source_url_(source_url),
+ callback_(callback),
+ cares_about_shipping_(true),
+ weak_ptr_factory_(this),
+ autocheckout_state_(AUTOCHECKOUT_NOT_STARTED),
+ was_ui_latency_logged_(false) {
+ DCHECK(!callback_.is_null());
+}
+
+bool AutofillDialogControllerAndroid::RequestingCreditCardInfo() const {
+ DCHECK_GT(form_structure_.field_count(), 0U);
+
+ for (size_t i = 0; i < form_structure_.field_count(); ++i) {
+ AutofillType type = form_structure_.field(i)->Type();
+ if (common::IsCreditCardType(type.GetStorableType()))
+ return true;
+ }
+
+ return false;
+}
+
+bool AutofillDialogControllerAndroid::TransmissionWillBeSecure() const {
+ return source_url_.SchemeIs(chrome::kHttpsScheme);
+}
+
+void AutofillDialogControllerAndroid::SetAutocheckoutState(
+ AutocheckoutState autocheckout_state) {
+ if (autocheckout_state_ == autocheckout_state)
+ return;
+
+ autocheckout_state_ = autocheckout_state;
+}
+
+void AutofillDialogControllerAndroid::LogOnFinishSubmitMetrics() {
+ GetMetricLogger().LogDialogUiDuration(
+ base::Time::Now() - dialog_shown_timestamp_,
+ GetDialogType(),
+ AutofillMetrics::DIALOG_ACCEPTED);
+
+ GetMetricLogger().LogDialogUiEvent(
+ GetDialogType(), AutofillMetrics::DIALOG_UI_ACCEPTED);
+}
+
+void AutofillDialogControllerAndroid::LogOnCancelMetrics() {
+ GetMetricLogger().LogDialogUiDuration(
+ base::Time::Now() - dialog_shown_timestamp_,
+ GetDialogType(),
+ AutofillMetrics::DIALOG_CANCELED);
+
+ GetMetricLogger().LogDialogUiEvent(
+ GetDialogType(), AutofillMetrics::DIALOG_UI_CANCELED);
+}
+
+} // namespace autofill
diff --git a/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.h b/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.h
new file mode 100644
index 0000000..01a08d6
--- /dev/null
+++ b/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.h
@@ -0,0 +1,144 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_ANDROID_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_ANDROID_H_
+#define CHROME_BROWSER_UI_ANDROID_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_ANDROID_H_
+
+#include <jni.h>
+
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/time/time.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_types.h"
+
+class Profile;
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+namespace autofill {
+
+// This class defines the form-filling host and JNI glue for the Java-side
+// implementation of the requestAutocomplete dialog.
+class AutofillDialogControllerAndroid : public AutofillDialogController {
+ public:
+ // Creates an instance of the AutofillDialogControllerAndroid.
+ static base::WeakPtr<AutofillDialogController> Create(
+ content::WebContents* contents,
+ const FormData& form_structure,
+ const GURL& source_url,
+ const DialogType dialog_type,
+ const base::Callback<void(const FormStructure*,
+ const std::string&)>& callback);
+
+ // Registers profile preferences for the AutofillDialogControllerAndroid.
+ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+ virtual ~AutofillDialogControllerAndroid();
+
+ // AutofillDialogController implementation:
+ virtual void Show() OVERRIDE;
+ virtual void Hide() OVERRIDE;
+ virtual void TabActivated() OVERRIDE;
+ virtual void AddAutocheckoutStep(AutocheckoutStepType step_type) OVERRIDE;
+ virtual void UpdateAutocheckoutStep(
+ AutocheckoutStepType step_type,
+ AutocheckoutStepStatus step_status) OVERRIDE;
+ virtual void OnAutocheckoutError() OVERRIDE;
+ virtual void OnAutocheckoutSuccess() OVERRIDE;
+ virtual DialogType GetDialogType() const OVERRIDE;
+
+ // JNI bindings for Java-side AutofillDialogDelegate:
+ void DialogCancel(JNIEnv* env, jobject obj);
+ void DialogContinue(JNIEnv* env,
+ jobject obj,
+ jobject full_wallet,
+ jboolean last_used_choice_is_autofill,
+ jstring last_used_account_name,
+ jstring last_used_billing,
+ jstring last_used_shipping,
+ jstring last_used_credit_card);
+
+ // Establishes JNI bindings.
+ static bool RegisterAutofillDialogControllerAndroid(JNIEnv* env);
+
+ private:
+ AutofillDialogControllerAndroid(
+ content::WebContents* contents,
+ const FormData& form_structure,
+ const GURL& source_url,
+ const DialogType dialog_type,
+ const base::Callback<void(const FormStructure*,
+ const std::string&)>& callback);
+
+ const AutofillMetrics& GetMetricLogger() const {
+ return metric_logger_;
+ }
+
+ // Logs metrics when the dialog is submitted.
+ void LogOnFinishSubmitMetrics();
+
+ // Logs metrics when the dialog is canceled.
+ void LogOnCancelMetrics();
+
+ bool RequestingCreditCardInfo() const;
+ bool TransmissionWillBeSecure() const;
+
+ void SetAutocheckoutState(AutocheckoutState autocheckout_state);
+
+ // The |profile| for |contents_|.
+ Profile* const profile_;
+
+ // The WebContents where the Autocomplete/Checkout action originated.
+ content::WebContents* const contents_;
+
+ // For logging UMA metrics.
+ const AutofillMetrics metric_logger_;
+ base::Time dialog_shown_timestamp_;
+ AutofillMetrics::DialogInitialUserStateMetric initial_user_state_;
+
+ // The time that Autocheckout started running. Reset on error. While this is
+ // a valid time, |AutocheckoutIsRunning()| will return true.
+ base::Time autocheckout_started_timestamp_;
+
+ // Whether this is an Autocheckout or a requestAutocomplete dialog.
+ const DialogType dialog_type_;
+
+ FormStructure form_structure_;
+
+ // Whether the URL visible to the user when this dialog was requested to be
+ // invoked is the same as |source_url_|.
+ bool invoked_from_same_origin_;
+
+ // The URL of the invoking site.
+ GURL source_url_;
+
+ // The callback via which we return the collected data and, if Online Wallet
+ // was used, the Google transaction id.
+ base::Callback<void(const FormStructure*, const std::string&)> callback_;
+
+ // Whether |form_structure_| has asked for any details that would indicate
+ // we should show a shipping section.
+ bool cares_about_shipping_;
+
+ base::WeakPtrFactory<AutofillDialogControllerAndroid>
+ weak_ptr_factory_;
+
+ // The current state of the Autocheckout flow.
+ AutocheckoutState autocheckout_state_;
+
+ // Whether the latency to display to the UI was logged to UMA yet.
+ bool was_ui_latency_logged_;
+
+ // The corresponding java object.
+ base::android::ScopedJavaGlobalRef<jobject> java_object_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutofillDialogControllerAndroid);
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_ANDROID_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_ANDROID_H_
diff --git a/chrome/browser/ui/android/autofill/autofill_dialog_result.cc b/chrome/browser/ui/android/autofill/autofill_dialog_result.cc
new file mode 100644
index 0000000..7c223a1
--- /dev/null
+++ b/chrome/browser/ui/android/autofill/autofill_dialog_result.cc
@@ -0,0 +1,138 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/android/autofill/autofill_dialog_result.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/autofill/data_model_wrapper.h"
+#include "components/autofill/content/browser/wallet/full_wallet.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/common/form_data.h"
+#include "jni/AutofillDialogResult_jni.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace autofill {
+
+namespace {
+
+std::string ConvertNullOrJavaStringToUTF8(JNIEnv* env, jstring str) {
+ return str ? base::android::ConvertJavaStringToUTF8(env, str) : std::string();
+}
+
+base::string16 ConvertNullOrJavaStringToUTF16(JNIEnv* env, jstring str) {
+ return str ? base::android::ConvertJavaStringToUTF16(env, str)
+ : base::string16();
+}
+
+#define FETCH_JFIELD(env, jobj, cls, getter) \
+ (Java_##cls##_get##getter((env), (jobj)))
+
+#define FETCH_JSTRING(utf, env, jobj, cls, getter) \
+ (ConvertNullOrJavaStringTo##utf( \
+ (env), FETCH_JFIELD((env), (jobj), cls, getter).obj()))
+
+scoped_ptr<wallet::Address> ParseJavaWalletAddress(
+ JNIEnv* env, jobject address) {
+ if (!address)
+ return scoped_ptr<wallet::Address>();
+
+ const base::string16 recipient_name =
+ FETCH_JSTRING(UTF16, env, address, ResultAddress, Name);
+ const base::string16 address_line_1 =
+ FETCH_JSTRING(UTF16, env, address, ResultAddress, Address1);
+ const base::string16 address_line_2 =
+ FETCH_JSTRING(UTF16, env, address, ResultAddress, Address2);
+ const base::string16 locality_name =
+ FETCH_JSTRING(UTF16, env, address, ResultAddress, City);
+ const base::string16 administrative_area_name =
+ FETCH_JSTRING(UTF16, env, address, ResultAddress, State);
+ const base::string16 postal_code_number =
+ FETCH_JSTRING(UTF16, env, address, ResultAddress, PostalCode);
+ const base::string16 phone_number =
+ FETCH_JSTRING(UTF16, env, address, ResultAddress, PhoneNumber);
+ const std::string country_name_code =
+ FETCH_JSTRING(UTF8, env, address, ResultAddress, CountryCode);
+ DCHECK(!country_name_code.empty());
+
+ return scoped_ptr<wallet::Address>(new wallet::Address(
+ country_name_code,
+ recipient_name,
+ address_line_1,
+ address_line_2,
+ locality_name,
+ administrative_area_name,
+ postal_code_number,
+ phone_number,
+ std::string()));
+}
+
+scoped_ptr<wallet::FullWallet> ParseJavaWallet(JNIEnv* env, jobject wallet) {
+ const ScopedJavaLocalRef<jobject> billing_address(
+ FETCH_JFIELD(env, wallet, ResultWallet, BillingAddress));
+ const ScopedJavaLocalRef<jobject> shipping_address(
+ FETCH_JFIELD(env, wallet, ResultWallet, ShippingAddress));
+ const ScopedJavaLocalRef<jobject> card(
+ FETCH_JFIELD(env, wallet, ResultWallet, Card));
+
+ const int expiration_month =
+ FETCH_JFIELD(env, card.obj(), ResultCard, ExpirationMonth);
+ const int expiration_year =
+ FETCH_JFIELD(env, card.obj(), ResultCard, ExpirationYear);
+ const std::string pan =
+ FETCH_JSTRING(UTF8, env, card.obj(), ResultCard, Pan);
+ const std::string cvn =
+ FETCH_JSTRING(UTF8, env, card.obj(), ResultCard, Cvn);
+
+ return wallet::FullWallet::CreateFullWalletFromClearText(
+ expiration_month,
+ expiration_year,
+ pan,
+ cvn,
+ ParseJavaWalletAddress(env, billing_address.obj()),
+ ParseJavaWalletAddress(env, shipping_address.obj()));
+}
+
+base::string16 ParseWalletEmail(JNIEnv* env, jobject wallet) {
+ return FETCH_JSTRING(UTF16, env, wallet, ResultWallet, Email);
+}
+
+std::string ParseGoogleTransactionId(JNIEnv* env, jobject wallet) {
+ return FETCH_JSTRING(UTF8, env, wallet, ResultWallet, GoogleTransactionId);
+}
+
+#undef FETCH_JSTRING
+#undef FETCH_FIELD
+
+} // namespace
+
+// static
+scoped_ptr<wallet::FullWallet> AutofillDialogResult::ConvertFromJava(
+ JNIEnv* env, jobject wallet) {
+ return ParseJavaWallet(env, wallet);
+}
+
+// static
+base::string16 AutofillDialogResult::GetWalletEmail(
+ JNIEnv* env, jobject wallet) {
+ return ParseWalletEmail(env, wallet);
+}
+
+// static
+std::string AutofillDialogResult::GetWalletGoogleTransactionId(
+ JNIEnv* env, jobject wallet) {
+ return ParseGoogleTransactionId(env, wallet);
+}
+
+// static
+bool AutofillDialogResult::RegisterAutofillDialogResult(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // namespace autofill
diff --git a/chrome/browser/ui/android/autofill/autofill_dialog_result.h b/chrome/browser/ui/android/autofill/autofill_dialog_result.h
new file mode 100644
index 0000000..2fe26a9
--- /dev/null
+++ b/chrome/browser/ui/android/autofill/autofill_dialog_result.h
@@ -0,0 +1,49 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_ANDROID_AUTOFILL_AUTOFILL_DIALOG_RESULT_H_
+#define CHROME_BROWSER_UI_ANDROID_AUTOFILL_AUTOFILL_DIALOG_RESULT_H_
+
+#include <jni.h>
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string16.h"
+
+namespace autofill {
+namespace wallet {
+class FullWallet;
+}
+}
+
+namespace autofill {
+
+// A result of the non-cancelled Java-side AutofillDialog invocation.
+// Passed to the AutofillDialogControllerAndroid in dialogContinue.
+class AutofillDialogResult {
+ public:
+ // Converts the requested information to wallet::FullWallet.
+ // The dialog stores the requested information in the same format
+ // regardless if the information was obtained from Autofill or Google Wallet.
+ static scoped_ptr<wallet::FullWallet> ConvertFromJava(
+ JNIEnv* env, jobject wallet);
+
+ // Returns the email address to be associated with this request,
+ // or an empty string.
+ static base::string16 GetWalletEmail(JNIEnv* env, jobject wallet);
+
+ // Returns the Google Transaction ID to be associated with this request,
+ // or an empty string.
+ static std::string GetWalletGoogleTransactionId(JNIEnv* env, jobject wallet);
+
+ // Establishes JNI bindings.
+ static bool RegisterAutofillDialogResult(JNIEnv* env);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AutofillDialogResult);
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_ANDROID_AUTOFILL_AUTOFILL_DIALOG_RESULT_H_
diff --git a/chrome/browser/ui/app_list/app_list_service.cc b/chrome/browser/ui/app_list/app_list_service.cc
index 8120aae..5a5f933 100644
--- a/chrome/browser/ui/app_list/app_list_service.cc
+++ b/chrome/browser/ui/app_list/app_list_service.cc
@@ -47,11 +47,12 @@
else
UMA_HISTOGRAM_LONG_TIMES("Startup.ShowAppListWarmStart", elapsed);
} else {
- // base::CurrentProcessInfo::CreationTime() is only defined on win/mac.
-#if defined(OS_WIN) || defined(OS_MACOSX)
+ // base::CurrentProcessInfo::CreationTime() is only defined on some
+ // platforms.
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
UMA_HISTOGRAM_LONG_TIMES(
"Startup.ShowAppListColdStart",
- base::Time::Now() - *base::CurrentProcessInfo::CreationTime());
+ base::Time::Now() - base::CurrentProcessInfo::CreationTime());
#endif
}
}
diff --git a/chrome/browser/ui/app_list/app_list_service.h b/chrome/browser/ui/app_list/app_list_service.h
index edac211..441fdc1 100644
--- a/chrome/browser/ui/app_list/app_list_service.h
+++ b/chrome/browser/ui/app_list/app_list_service.h
@@ -48,6 +48,9 @@
// current browser process.
virtual void Show() = 0;
+ // Create the app list UI, and maintain its state, but do not show it.
+ virtual void CreateForProfile(Profile* requested_profile) = 0;
+
// Show the app list for the given profile. If it differs from the profile the
// app list is currently showing, repopulate the app list and save the new
// profile to local prefs as the default app list profile.
diff --git a/chrome/browser/ui/app_list/app_list_service_disabled.cc b/chrome/browser/ui/app_list/app_list_service_disabled.cc
index 6c1ec63..b3c879d 100644
--- a/chrome/browser/ui/app_list/app_list_service_disabled.cc
+++ b/chrome/browser/ui/app_list/app_list_service_disabled.cc
@@ -31,6 +31,7 @@
virtual void SetProfilePath(const base::FilePath& profile_path) OVERRIDE {}
virtual void Show() OVERRIDE {}
+ virtual void CreateForProfile(Profile* profile) OVERRIDE {}
virtual void ShowForProfile(Profile* profile) OVERRIDE {}
virtual void DismissAppList() OVERRIDE {}
diff --git a/chrome/browser/ui/app_list/app_list_service_impl.cc b/chrome/browser/ui/app_list/app_list_service_impl.cc
index 8054e87..102809c 100644
--- a/chrome/browser/ui/app_list/app_list_service_impl.cc
+++ b/chrome/browser/ui/app_list/app_list_service_impl.cc
@@ -69,6 +69,11 @@
}
}
+bool HasAppListEnabledPreference() {
+ PrefService* local_state = g_browser_process->local_state();
+ return local_state->GetBoolean(apps::prefs::kAppLauncherHasBeenEnabled);
+}
+
void SetAppListEnabledPreference(bool enabled) {
PrefService* local_state = g_browser_process->local_state();
local_state->SetBoolean(apps::prefs::kAppLauncherHasBeenEnabled, enabled);
@@ -184,8 +189,11 @@
}
void AppListServiceImpl::EnableAppList(Profile* initial_profile) {
- SetAppListEnabledPreference(true);
SetProfilePath(initial_profile->GetPath());
+ if (HasAppListEnabledPreference())
+ return;
+
+ SetAppListEnabledPreference(true);
CreateShortcut();
}
diff --git a/chrome/browser/ui/app_list/app_list_service_mac.mm b/chrome/browser/ui/app_list/app_list_service_mac.mm
index 56b9db4..bc34424 100644
--- a/chrome/browser/ui/app_list/app_list_service_mac.mm
+++ b/chrome/browser/ui/app_list/app_list_service_mac.mm
@@ -59,11 +59,11 @@
LeakySingletonTraits<AppListServiceMac> >::get();
}
- void CreateAppList(Profile* profile);
void ShowWindowNearDock();
// AppListService overrides:
virtual void Init(Profile* initial_profile) OVERRIDE;
+ virtual void CreateForProfile(Profile* requested_profile) OVERRIDE;
virtual void ShowForProfile(Profile* requested_profile) OVERRIDE;
virtual void DismissAppList() OVERRIDE;
virtual bool IsAppListVisible() const OVERRIDE;
@@ -241,7 +241,7 @@
bool AppListControllerDelegateCocoa::CanDoCreateShortcutsFlow(
bool is_platform_app) {
- return is_platform_app && apps::IsAppShimsEnabled();
+ return false;
}
void AppListControllerDelegateCocoa::DoCreateShortcutsFlow(
@@ -268,22 +268,6 @@
profile, extension, NEW_FOREGROUND_TAB));
}
-void AppListServiceMac::CreateAppList(Profile* requested_profile) {
- if (profile() == requested_profile)
- return;
-
- // The Objective C objects might be released at some unknown point in the
- // future, so explicitly clear references to C++ objects.
- [[window_controller_ appListViewController]
- setDelegate:scoped_ptr<app_list::AppListViewDelegate>()];
-
- SetProfile(requested_profile);
- scoped_ptr<app_list::AppListViewDelegate> delegate(
- new AppListViewDelegate(new AppListControllerDelegateCocoa(), profile()));
- window_controller_.reset([[AppListWindowController alloc] init]);
- [[window_controller_ appListViewController] setDelegate:delegate.Pass()];
-}
-
void AppListServiceMac::Init(Profile* initial_profile) {
// On Mac, Init() is called multiple times for a process: any time there is no
// browser window open and a new window is opened, and during process startup
@@ -311,6 +295,22 @@
AppListServiceMac::GetInstance());
}
+void AppListServiceMac::CreateForProfile(Profile* requested_profile) {
+ if (profile() == requested_profile)
+ return;
+
+ // The Objective C objects might be released at some unknown point in the
+ // future, so explicitly clear references to C++ objects.
+ [[window_controller_ appListViewController]
+ setDelegate:scoped_ptr<app_list::AppListViewDelegate>()];
+
+ SetProfile(requested_profile);
+ scoped_ptr<app_list::AppListViewDelegate> delegate(
+ new AppListViewDelegate(new AppListControllerDelegateCocoa(), profile()));
+ window_controller_.reset([[AppListWindowController alloc] init]);
+ [[window_controller_ appListViewController] setDelegate:delegate.Pass()];
+}
+
void AppListServiceMac::ShowForProfile(Profile* requested_profile) {
InvalidatePendingProfileLoads();
@@ -322,7 +322,7 @@
SetProfilePath(requested_profile->GetPath());
DismissAppList();
- CreateAppList(requested_profile);
+ CreateForProfile(requested_profile);
ShowWindowNearDock();
}
diff --git a/chrome/browser/ui/app_list/apps_model_builder_unittest.cc b/chrome/browser/ui/app_list/apps_model_builder_unittest.cc
index 3781da0..4dca6ee 100644
--- a/chrome/browser/ui/app_list/apps_model_builder_unittest.cc
+++ b/chrome/browser/ui/app_list/apps_model_builder_unittest.cc
@@ -9,6 +9,7 @@
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/prefs/pref_service.h"
+#include "base/run_loop.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/extensions/extension_service_unittest.h"
@@ -160,7 +161,7 @@
EXPECT_EQ(std::string("Packaged App 1,Hosted App"),
GetModelContent(model.get()));
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
TEST_F(AppsModelBuilderTest, UninstallTerminatedApp) {
@@ -180,7 +181,7 @@
EXPECT_EQ(std::string("Packaged App 1,Hosted App"),
GetModelContent(model.get()));
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
TEST_F(AppsModelBuilderTest, OrdinalPrefsChange) {
diff --git a/chrome/browser/ui/app_list/search/app_result.cc b/chrome/browser/ui/app_list/search/app_result.cc
index 3877c74..4cd6328 100644
--- a/chrome/browser/ui/app_list/search/app_result.cc
+++ b/chrome/browser/ui/app_list/search/app_result.cc
@@ -6,6 +6,8 @@
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system_factory.h"
+#include "chrome/browser/extensions/install_tracker.h"
+#include "chrome/browser/extensions/install_tracker_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_list/app_context_menu.h"
#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
@@ -24,7 +26,8 @@
AppListControllerDelegate* controller)
: profile_(profile),
app_id_(app_id),
- controller_(controller) {
+ controller_(controller),
+ install_tracker_(NULL) {
set_id(extensions::Extension::GetBaseURLFromExtensionId(app_id_).spec());
const extensions::Extension* extension =
@@ -42,8 +45,12 @@
extensions::IconsInfo::GetDefaultAppIcon(),
this));
SetIcon(icon_->image_skia());
+ StartObservingInstall();
}
-AppResult::~AppResult() {}
+
+AppResult::~AppResult() {
+ StopObservingInstall();
+}
void AppResult::UpdateFromMatch(const TokenizedString& title,
const TokenizedStringMatch& match) {
@@ -97,8 +104,21 @@
return context_menu_->GetMenuModel();
}
-void AppResult::OnExtensionIconImageChanged(
- extensions::IconImage* image) {
+void AppResult::StartObservingInstall() {
+ DCHECK(!install_tracker_);
+
+ install_tracker_ = extensions::InstallTrackerFactory::GetForProfile(profile_);
+ install_tracker_->AddObserver(this);
+}
+
+void AppResult::StopObservingInstall() {
+ if (install_tracker_)
+ install_tracker_->RemoveObserver(this);
+
+ install_tracker_ = NULL;
+}
+
+void AppResult::OnExtensionIconImageChanged(extensions::IconImage* image) {
DCHECK_EQ(icon_.get(), image);
SetIcon(icon_->image_skia());
}
@@ -107,4 +127,34 @@
Open(event_flags);
}
+void AppResult::OnBeginExtensionInstall(const std::string& extension_id,
+ const std::string& extension_name,
+ const gfx::ImageSkia& installing_icon,
+ bool is_app,
+ bool is_platform_app) {}
+
+void AppResult::OnDownloadProgress(const std::string& extension_id,
+ int percent_downloaded) {}
+
+void AppResult::OnInstallFailure(const std::string& extension_id) {}
+
+void AppResult::OnExtensionInstalled(const extensions::Extension* extension) {}
+
+void AppResult::OnExtensionLoaded(const extensions::Extension* extension) {}
+
+void AppResult::OnExtensionUnloaded(const extensions::Extension* extension) {}
+
+void AppResult::OnExtensionUninstalled(const extensions::Extension* extension) {
+ if (extension->id() != app_id_)
+ return;
+
+ NotifyItemUninstalled();
+}
+
+void AppResult::OnAppsReordered() {}
+
+void AppResult::OnAppInstalledToAppList(const std::string& extension_id) {}
+
+void AppResult::OnShutdown() { StopObservingInstall(); }
+
} // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/app_result.h b/chrome/browser/ui/app_list/search/app_result.h
index f270058..bb46181 100644
--- a/chrome/browser/ui/app_list/search/app_result.h
+++ b/chrome/browser/ui/app_list/search/app_result.h
@@ -9,12 +9,17 @@
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/extensions/extension_icon_image.h"
+#include "chrome/browser/extensions/install_observer.h"
#include "chrome/browser/ui/app_list/app_context_menu_delegate.h"
#include "chrome/browser/ui/app_list/search/chrome_search_result.h"
class AppListControllerDelegate;
class Profile;
+namespace extensions {
+class InstallTracker;
+}
+
namespace app_list {
class AppContextMenu;
@@ -23,7 +28,8 @@
class AppResult : public ChromeSearchResult,
public extensions::IconImage::Observer,
- public AppContextMenuDelegate {
+ public AppContextMenuDelegate,
+ public extensions::InstallObserver {
public:
AppResult(Profile* profile,
const std::string& app_id,
@@ -41,6 +47,9 @@
virtual ChromeSearchResultType GetType() OVERRIDE;
private:
+ void StartObservingInstall();
+ void StopObservingInstall();
+
// extensions::IconImage::Observer overrides:
virtual void OnExtensionIconImageChanged(
extensions::IconImage* image) OVERRIDE;
@@ -48,6 +57,28 @@
// AppContextMenuDelegate overrides:
virtual void ExecuteLaunchCommand(int event_flags) OVERRIDE;
+ // extensions::InstallObserver overrides:
+ virtual void OnBeginExtensionInstall(const std::string& extension_id,
+ const std::string& extension_name,
+ const gfx::ImageSkia& installing_icon,
+ bool is_app,
+ bool is_platform_app) OVERRIDE;
+ virtual void OnDownloadProgress(const std::string& extension_id,
+ int percent_downloaded) OVERRIDE;
+ virtual void OnInstallFailure(const std::string& extension_id) OVERRIDE;
+ virtual void OnExtensionInstalled(
+ const extensions::Extension* extension) OVERRIDE;
+ virtual void OnExtensionLoaded(
+ const extensions::Extension* extension) OVERRIDE;
+ virtual void OnExtensionUnloaded(
+ const extensions::Extension* extension) OVERRIDE;
+ virtual void OnExtensionUninstalled(
+ const extensions::Extension* extension) OVERRIDE;
+ virtual void OnAppsReordered() OVERRIDE;
+ virtual void OnAppInstalledToAppList(
+ const std::string& extension_id) OVERRIDE;
+ virtual void OnShutdown() OVERRIDE;
+
Profile* profile_;
const std::string app_id_;
AppListControllerDelegate* controller_;
@@ -56,6 +87,8 @@
scoped_ptr<extensions::IconImage> icon_;
scoped_ptr<AppContextMenu> context_menu_;
+ extensions::InstallTracker* install_tracker_; // Not owned.
+
DISALLOW_COPY_AND_ASSIGN(AppResult);
};
diff --git a/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc
index 4e0d064..f487c67 100644
--- a/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc
+++ b/chrome/browser/ui/app_list/search/app_search_provider_unittest.cc
@@ -6,6 +6,7 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_service_unittest.h"
#include "chrome/browser/ui/app_list/search/app_search_provider.h"
@@ -104,7 +105,7 @@
EXPECT_EQ("", RunQuery("pa1"));
// Let uninstall code to clean up.
- loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
} // namespace test
diff --git a/chrome/browser/ui/apps/OWNERS b/chrome/browser/ui/apps/OWNERS
index 8391787..34cff5f 100644
--- a/chrome/browser/ui/apps/OWNERS
+++ b/chrome/browser/ui/apps/OWNERS
@@ -3,4 +3,5 @@
benwells@chromium.org
koz@chromium.org
miket@chromium.org
+scheib@chromium.org
tapted@chromium.org
diff --git a/chrome/browser/ui/ash/app_list/app_list_service_ash.cc b/chrome/browser/ui/ash/app_list/app_list_service_ash.cc
index cf10ee6..1e9d69f 100644
--- a/chrome/browser/ui/ash/app_list/app_list_service_ash.cc
+++ b/chrome/browser/ui/ash/app_list/app_list_service_ash.cc
@@ -28,6 +28,7 @@
// AppListService overrides:
virtual base::FilePath GetProfilePath(
const base::FilePath& user_data_dir) OVERRIDE;
+ virtual void CreateForProfile(Profile* default_profile) OVERRIDE;
virtual void ShowForProfile(Profile* default_profile) OVERRIDE;
virtual bool IsAppListVisible() const OVERRIDE;
virtual void DismissAppList() OVERRIDE;
@@ -42,6 +43,8 @@
return ChromeLauncherController::instance()->profile()->GetPath();
}
+void AppListServiceAsh::CreateForProfile(Profile* default_profile) {}
+
void AppListServiceAsh::ShowForProfile(Profile* default_profile) {
// This may not work correctly if the profile passed in is different from the
// one the ash Shell is currently using.
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index 1d0d4f6..2a22df0 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -6,6 +6,7 @@
#include "apps/native_app_window.h"
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "ash/ash_switches.h"
#include "ash/host/root_window_host_factory.h"
#include "ash/launcher/launcher_types.h"
@@ -21,7 +22,6 @@
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/app_mode/app_mode_utils.h"
#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/sessions/tab_restore_service.h"
@@ -187,7 +187,7 @@
}
// |window| may belong to a shell window.
- apps::ShellWindow* shell_window = extensions::ShellWindowRegistry::
+ apps::ShellWindow* shell_window = apps::ShellWindowRegistry::
GetShellWindowForNativeWindowAnyProfile(window);
if (shell_window) {
if (is_fullscreen)
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc b/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
index d8cb05b..e8194fa 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/ui/ash/chrome_shell_delegate.h"
#include "apps/native_app_window.h"
+#include "apps/shell_window_registry.h"
#include "ash/keyboard_overlay/keyboard_overlay_view.h"
#include "ash/wm/window_util.h"
#include "base/command_line.h"
@@ -20,7 +21,6 @@
#include "chrome/browser/chromeos/system/ash_system_tray_delegate.h"
#include "chrome/browser/extensions/api/terminal/terminal_extension_helper.h"
#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/speech/tts_controller.h"
#include "chrome/browser/ui/ash/caps_lock_delegate_chromeos.h"
@@ -45,7 +45,7 @@
bool ChromeShellDelegate::IsFirstRunAfterBoot() const {
return CommandLine::ForCurrentProcess()->HasSwitch(
- chromeos::switches::kFirstBoot);
+ chromeos::switches::kFirstExecAfterBoot);
}
void ChromeShellDelegate::PreInit() {
@@ -70,9 +70,9 @@
}
} else {
Profile* const profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
- const extensions::ShellWindowRegistry* const registry =
- extensions::ShellWindowRegistry::Get(profile);
- const extensions::ShellWindowRegistry::ShellWindowList list =
+ const apps::ShellWindowRegistry* const registry =
+ apps::ShellWindowRegistry::Get(profile);
+ const apps::ShellWindowRegistry::ShellWindowList list =
registry->GetShellWindowsForApp(kFileBrowserDomain);
if (list.empty()) {
// Open the new window.
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
index 11bdcca..61a3e59 100644
--- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
@@ -45,6 +45,10 @@
profile_(profile) {
}
+BrowserShortcutLauncherItemController::
+ ~BrowserShortcutLauncherItemController() {
+}
+
string16 BrowserShortcutLauncherItemController::GetTitle() {
return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
}
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
index 7d30b8e..4454b71 100644
--- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
@@ -23,9 +23,10 @@
class BrowserShortcutLauncherItemController : public LauncherItemController {
public:
BrowserShortcutLauncherItemController(
- ChromeLauncherControllerPerApp* controller, Profile* profile);
+ ChromeLauncherControllerPerApp* controller,
+ Profile* profile);
- virtual ~BrowserShortcutLauncherItemController() {}
+ virtual ~BrowserShortcutLauncherItemController();
// LauncherItemController overrides:
virtual string16 GetTitle() OVERRIDE;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
index 1cae4cc..801538a 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -6,6 +6,7 @@
#include "apps/native_app_window.h"
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "ash/ash_switches.h"
#include "ash/launcher/launcher.h"
#include "ash/launcher/launcher_model.h"
@@ -25,7 +26,6 @@
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/extensions/platform_app_browsertest_util.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_browsertest.cc
index 8c0cfba..248b19a 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_browsertest.cc
@@ -6,6 +6,7 @@
#include "apps/native_app_window.h"
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "ash/ash_switches.h"
#include "ash/display/display_controller.h"
#include "ash/launcher/launcher.h"
@@ -26,7 +27,6 @@
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/extensions/platform_app_browsertest_util.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_list/app_list_service.h"
#include "chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h"
@@ -72,16 +72,16 @@
};
class TestShellWindowRegistryObserver
- : public extensions::ShellWindowRegistry::Observer {
+ : public apps::ShellWindowRegistry::Observer {
public:
explicit TestShellWindowRegistryObserver(Profile* profile)
: profile_(profile),
icon_updates_(0) {
- extensions::ShellWindowRegistry::Get(profile_)->AddObserver(this);
+ apps::ShellWindowRegistry::Get(profile_)->AddObserver(this);
}
virtual ~TestShellWindowRegistryObserver() {
- extensions::ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
+ apps::ShellWindowRegistry::Get(profile_)->RemoveObserver(this);
}
// Overridden from ShellWindowRegistry::Observer:
diff --git a/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.cc
index 779a8f9..618397c 100644
--- a/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.cc
@@ -28,7 +28,7 @@
ShellWindowLauncherController::ShellWindowLauncherController(
ChromeLauncherController* owner)
: owner_(owner),
- registry_(extensions::ShellWindowRegistry::Get(owner->profile())),
+ registry_(apps::ShellWindowRegistry::Get(owner->profile())),
activation_client_(NULL) {
registry_->AddObserver(this);
if (ash::Shell::HasInstance()) {
diff --git a/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h b/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h
index c47c357..3669f72 100644
--- a/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h
+++ b/chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h
@@ -9,7 +9,7 @@
#include <map>
#include <string>
-#include "chrome/browser/extensions/shell_window_registry.h"
+#include "apps/shell_window_registry.h"
#include "ui/aura/client/activation_change_observer.h"
#include "ui/aura/window_observer.h"
@@ -34,7 +34,7 @@
// aura window manager. It handles adding and removing launcher items from
// ChromeLauncherController.
class ShellWindowLauncherController
- : public extensions::ShellWindowRegistry::Observer,
+ : public apps::ShellWindowRegistry::Observer,
public aura::WindowObserver,
public aura::client::ActivationChangeObserver {
public:
@@ -68,7 +68,7 @@
ShellWindowLauncherItemController* ControllerForWindow(aura::Window* window);
ChromeLauncherController* owner_;
- extensions::ShellWindowRegistry* registry_; // Unowned convenience pointer
+ apps::ShellWindowRegistry* registry_; // Unowned convenience pointer
aura::client::ActivationClient* activation_client_;
// Map of app launcher id to controller.
diff --git a/chrome/browser/ui/ash/screenshot_taker.cc b/chrome/browser/ui/ash/screenshot_taker.cc
index 548e93f..f1764fb 100644
--- a/chrome/browser/ui/ash/screenshot_taker.cc
+++ b/chrome/browser/ui/ash/screenshot_taker.cc
@@ -39,6 +39,7 @@
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/notifications/desktop_notification_service.h"
#include "chrome/browser/notifications/desktop_notification_service_factory.h"
+#include "chromeos/login/login_state.h"
#endif
namespace {
@@ -352,6 +353,12 @@
const base::FilePath& screenshot_path) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
#if defined(OS_CHROMEOS)
+ // Do not show a notification that a screenshot was taken while no user is
+ // logged in, since it is confusing for the user to get a message about it
+ // after he logs in (crbug.com/235217).
+ if (!chromeos::LoginState::Get()->IsUserLoggedIn())
+ return;
+
// TODO(sschmitz): make this work for Windows.
DesktopNotificationService* const service =
DesktopNotificationServiceFactory::GetForProfile(GetProfile());
diff --git a/chrome/browser/ui/ash/screenshot_taker_unittest.cc b/chrome/browser/ui/ash/screenshot_taker_unittest.cc
index a35339a..f27b97a 100644
--- a/chrome/browser/ui/ash/screenshot_taker_unittest.cc
+++ b/chrome/browser/ui/ash/screenshot_taker_unittest.cc
@@ -22,6 +22,10 @@
#include "ui/aura/root_window.h"
#include "ui/message_center/message_center_switches.h"
+#if defined(OS_CHROMEOS)
+#include "chromeos/login/login_state.h"
+#endif
+
namespace ash {
namespace test {
@@ -94,6 +98,12 @@
};
TEST_F(ScreenshotTakerTest, TakeScreenshot) {
+#if defined(OS_CHROMEOS)
+ // Note that within the test framework the LoginState object will always
+ // claim that the user did log in.
+ ASSERT_FALSE(chromeos::LoginState::IsInitialized());
+ chromeos::LoginState::Initialize();
+#endif
scoped_ptr<TestingProfileManager> profile_manager(
new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
ASSERT_TRUE(profile_manager->SetUp());
@@ -127,6 +137,10 @@
if (ScreenshotTakerObserver::SCREENSHOT_SUCCESS == screenshot_result_)
EXPECT_TRUE(base::PathExists(screenshot_path_));
+
+#if defined(OS_CHROMEOS)
+ chromeos::LoginState::Shutdown();
+#endif
}
} // namespace test
diff --git a/chrome/browser/ui/auto_login_prompter.cc b/chrome/browser/ui/auto_login_prompter.cc
index f77cbb1..9d9bff0 100644
--- a/chrome/browser/ui/auto_login_prompter.cc
+++ b/chrome/browser/ui/auto_login_prompter.cc
@@ -11,12 +11,10 @@
#include "chrome/browser/google/google_url_tracker.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/profile_oauth2_token_service.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager.h"
#include "chrome/browser/signin/signin_manager_factory.h"
-#include "chrome/browser/signin/token_service.h"
-#include "chrome/browser/signin/token_service_factory.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
@@ -32,14 +30,10 @@
namespace {
bool FetchUsernameThroughSigninManager(Profile* profile, std::string* output) {
- // In an incognito window, there may not be a profile sync service and/or
- // signin manager.
- if (!ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService(
- profile)) {
- return false;
- }
-
- if (!TokenServiceFactory::GetForProfile(profile)->AreCredentialsValid())
+ // In an incognito window these services are not available.
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
+ if (!token_service || !token_service->RefreshTokenIsAvailable())
return false;
SigninManagerBase* signin_manager =
diff --git a/chrome/browser/ui/autofill/OWNERS b/chrome/browser/ui/autofill/OWNERS
index b05d196..8c68959 100644
--- a/chrome/browser/ui/autofill/OWNERS
+++ b/chrome/browser/ui/autofill/OWNERS
@@ -3,6 +3,7 @@
per-file autofill_dialog*=dbeam@chromium.org
per-file data_model*=dbeam@chromium.org
+per-file *credit_card_bubble*=dbeam@chromium.org
# Temporary owner, for refactoring changes only.
joi@chromium.org
diff --git a/chrome/browser/ui/autofill/autofill_credit_card_bubble.cc b/chrome/browser/ui/autofill/autofill_credit_card_bubble.cc
deleted file mode 100644
index 133de0a..0000000
--- a/chrome/browser/ui/autofill/autofill_credit_card_bubble.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble.h"
-
-namespace autofill {
-
-// static
-const int AutofillCreditCardBubble::kContentWidth = 300;
-
-AutofillCreditCardBubble::~AutofillCreditCardBubble() {}
-
-#if !defined(TOOLKIT_VIEWS)
-// static
-base::WeakPtr<AutofillCreditCardBubble> AutofillCreditCardBubble::Create(
- const base::WeakPtr<AutofillCreditCardBubbleController>& controller) {
- // TODO(dbeam): make a bubble on all applicable platforms.
- return base::WeakPtr<AutofillCreditCardBubble>();
-}
-#endif
-
-} // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_credit_card_bubble.h b/chrome/browser/ui/autofill/autofill_credit_card_bubble.h
deleted file mode 100644
index 2ef632a..0000000
--- a/chrome/browser/ui/autofill/autofill_credit_card_bubble.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_H_
-#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_H_
-
-#include "base/memory/weak_ptr.h"
-
-namespace autofill {
-
-class AutofillCreditCardBubbleController;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// AutofillCreditCardBubble
-//
-// An interface to be implemented on each platform to show a bubble after the
-// Autofill dialog is sucessfully submitted. Shows anchored to an icon that
-// looks like a credit card or the Google Wallet logo in the omnibox. Hidden
-// when focus is lost.
-//
-////////////////////////////////////////////////////////////////////////////////
-class AutofillCreditCardBubble {
- public:
- // The preferred size of the bubble's contents.
- static const int kContentWidth;
-
- virtual ~AutofillCreditCardBubble();
-
- // Visually reveals the dialog bubble.
- virtual void Show() = 0;
-
- // Hides the bubble from view.
- virtual void Hide() = 0;
-
- // Returns whether the bubble is currently in the process of hiding itself.
- virtual bool IsHiding() const = 0;
-
- // Creates a bubble view that's operated by |controller| and owned by the
- // platform's widget or view management framework. |controller| is invalid
- // while the bubble is closing.
- static base::WeakPtr<AutofillCreditCardBubble> Create(
- const base::WeakPtr<AutofillCreditCardBubbleController>& controller);
-};
-
-} // namespace autofill
-
-#endif // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_H_
diff --git a/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.cc b/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.cc
deleted file mode 100644
index 5d79a69..0000000
--- a/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.cc
+++ /dev/null
@@ -1,335 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h"
-
-#include <climits>
-#include <string>
-
-#include "base/prefs/pref_service.h"
-#include "base/strings/string_split.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble.h"
-#include "chrome/browser/ui/autofill/tab_autofill_manager_delegate.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_navigator.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/omnibox/location_bar.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/pref_names.h"
-#include "components/user_prefs/pref_registry_syncable.h"
-#include "content/public/browser/navigation_details.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/web_contents.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "grit/webkit_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/range/range.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/image/image.h"
-
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(autofill::AutofillCreditCardBubbleController);
-
-namespace autofill {
-
-namespace {
-
-// TODO(dbeam): add back a sensible limit once it's decided or remove
-// kMaxGeneratedCardTimesToShow if this behavior is finalized.
-static const int kMaxGeneratedCardTimesToShow = INT_MAX;
-static const base::char16 kRangeSeparator = '|';
-static const char kWalletGeneratedCardLearnMoreLink[] =
- "http://support.google.com/wallet/bin/answer.py?hl=en&answer=2740044";
-
-AutofillCreditCardBubbleController* GetOrCreate(content::WebContents* wc) {
- AutofillCreditCardBubbleController::CreateForWebContents(wc);
- return AutofillCreditCardBubbleController::FromWebContents(wc);
-}
-
-} // namespace
-
-AutofillCreditCardBubbleController::AutofillCreditCardBubbleController(
- content::WebContents* web_contents)
- : WebContentsObserver(web_contents),
- web_contents_(web_contents),
- should_show_anchor_(true),
- weak_ptr_factory_(this) {}
-
-AutofillCreditCardBubbleController::~AutofillCreditCardBubbleController() {
- // In the case that the tab is closed, the controller can be deleted while the
- // bubble is showing. Always calling |Hide()| ensures the bubble is closed.
- Hide();
-}
-
-// static
-void AutofillCreditCardBubbleController::RegisterUserPrefs(
- user_prefs::PrefRegistrySyncable* registry) {
- registry->RegisterIntegerPref(
- ::prefs::kAutofillGeneratedCardBubbleTimesShown,
- 0,
- user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
-}
-
-// static
-void AutofillCreditCardBubbleController::ShowGeneratedCardUI(
- content::WebContents* contents,
- const base::string16& fronting_card_name,
- const base::string16& backing_card_name) {
- GetOrCreate(contents)->ShowAsGeneratedCardBubble(fronting_card_name,
- backing_card_name);
-}
-
-// static
-void AutofillCreditCardBubbleController::ShowNewCardSavedBubble(
- content::WebContents* contents,
- const base::string16& new_card_name) {
- GetOrCreate(contents)->ShowAsNewCardSavedBubble(new_card_name);
-}
-
-void AutofillCreditCardBubbleController::DidNavigateMainFrame(
- const content::LoadCommittedDetails& details,
- const content::FrameNavigateParams& params) {
- if (details.entry &&
- !content::PageTransitionIsRedirect(details.entry->GetTransitionType())) {
- should_show_anchor_ = false;
- UpdateAnchor();
- web_contents()->RemoveUserData(UserDataKey());
- // |this| is now deleted.
- }
-}
-
-bool AutofillCreditCardBubbleController::IsHiding() const {
- return bubble_ && bubble_->IsHiding();
-}
-
-gfx::Image AutofillCreditCardBubbleController::AnchorIcon() const {
- if (!should_show_anchor_)
- return gfx::Image();
-
- return ui::ResourceBundle::GetSharedInstance().GetImageNamed(
- IsGeneratedCardBubble() ? IDR_WALLET_ICON : IDR_AUTOFILL_CC_GENERIC);
-}
-
-base::string16 AutofillCreditCardBubbleController::BubbleTitle() const {
- return !IsGeneratedCardBubble() ?
- ASCIIToUTF16("Lorem ipsum, savum cardum") :
- l10n_util::GetStringUTF16(
- IDS_AUTOFILL_CREDIT_CARD_BUBBLE_GENERATED_TITLE);
-}
-
-base::string16 AutofillCreditCardBubbleController::BubbleText() const {
- DCHECK(IsSetUp());
- return bubble_text_;
-}
-
-const std::vector<ui::Range>& AutofillCreditCardBubbleController::
- BubbleTextRanges() const {
- DCHECK(IsSetUp());
- return bubble_text_ranges_;
-}
-
-base::string16 AutofillCreditCardBubbleController::LinkText() const {
- return l10n_util::GetStringUTF16(
- IsGeneratedCardBubble() ? IDS_LEARN_MORE :
- IDS_AUTOFILL_CREDIT_CARD_BUBBLE_MANAGE_CARDS);
-}
-
-void AutofillCreditCardBubbleController::OnAnchorClicked() {
- Show(true);
-}
-
-void AutofillCreditCardBubbleController::OnLinkClicked() {
- if (IsGeneratedCardBubble()) {
-#if !defined(OS_ANDROID)
- // Open a new tab to the Online Wallet help link.
- chrome::NavigateParams params(
- chrome::FindBrowserWithWebContents(web_contents()),
- GURL(kWalletGeneratedCardLearnMoreLink),
- content::PAGE_TRANSITION_AUTO_BOOKMARK);
- params.disposition = NEW_FOREGROUND_TAB;
- chrome::Navigate(¶ms);
-#else
- // TODO(dbeam): implement.
-#endif
- } else {
- TabAutofillManagerDelegate::FromWebContents(web_contents())->
- ShowAutofillSettings();
- }
- Hide();
-}
-
-base::WeakPtr<AutofillCreditCardBubbleController>
- AutofillCreditCardBubbleController::GetWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
-}
-
-base::WeakPtr<AutofillCreditCardBubble> AutofillCreditCardBubbleController::
- CreateBubble() {
- return AutofillCreditCardBubble::Create(GetWeakPtr());
-}
-
-base::WeakPtr<AutofillCreditCardBubble> AutofillCreditCardBubbleController::
- bubble() {
- return bubble_;
-}
-
-bool AutofillCreditCardBubbleController::CanShow() const {
-#if !defined(OS_ANDROID)
- Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
- return web_contents() == browser->tab_strip_model()->GetActiveWebContents();
-#else
- return true;
-#endif
-}
-
-bool AutofillCreditCardBubbleController::ShouldDisplayBubbleInitially() const {
- Profile* profile = Profile::FromBrowserContext(
- web_contents_->GetBrowserContext());
- int times_shown = profile->GetPrefs()->GetInteger(
- ::prefs::kAutofillGeneratedCardBubbleTimesShown);
- return times_shown < kMaxGeneratedCardTimesToShow;
-}
-
-void AutofillCreditCardBubbleController::ShowAsGeneratedCardBubble(
- const base::string16& fronting_card_name,
- const base::string16& backing_card_name) {
- Reset();
-
- DCHECK(!fronting_card_name.empty());
- DCHECK(!backing_card_name.empty());
- fronting_card_name_ = fronting_card_name;
- backing_card_name_ = backing_card_name;
-
- SetUp();
-
- if (ShouldDisplayBubbleInitially())
- Show(false);
-}
-
-void AutofillCreditCardBubbleController::ShowAsNewCardSavedBubble(
- const base::string16& new_card_name) {
- Reset();
-
- DCHECK(!new_card_name.empty());
- new_card_name_ = new_card_name;
-
- SetUp();
- Show(false);
-}
-
-void AutofillCreditCardBubbleController::Reset() {
- Hide();
-
- // Clear any generated state or stored |ShowAs*()| arguments.
- fronting_card_name_.clear();
- backing_card_name_.clear();
- new_card_name_.clear();
- bubble_text_.clear();
- bubble_text_ranges_.clear();
-
- DCHECK(!IsSetUp());
-}
-
-void AutofillCreditCardBubbleController::SetUp() {
- base::string16 full_text;
- if (IsGeneratedCardBubble()) {
- full_text = l10n_util::GetStringFUTF16(
- IDS_AUTOFILL_CREDIT_CARD_BUBBLE_GENERATED_TEXT,
- fronting_card_name_,
- backing_card_name_);
- } else {
- full_text = ReplaceStringPlaceholders(
- ASCIIToUTF16("Lorem ipsum, savum cardem |$1|. Replacem before launch."),
- new_card_name_,
- NULL);
- }
-
- // Split the full text on '|' to highlight certain parts. For example, "sly"
- // and "jumped" would be bolded in "The |sly| fox |jumped| over the lazy dog".
- std::vector<base::string16> pieces;
- base::SplitStringDontTrim(full_text, kRangeSeparator, &pieces);
-
- while (!pieces.empty()) {
- base::string16 piece = pieces.front();
-
- // Every second piece should be bolded. Because |base::SplitString*()|
- // leaves an empty "" even if '|' is the first character, this is guaranteed
- // to work for "|highlighting| starts here". Ignore empty pieces because
- // there's nothing to highlight.
- if (!piece.empty() && pieces.size() % 2 == 0) {
- const size_t start = bubble_text_.size();
- bubble_text_ranges_.push_back(ui::Range(start, start + piece.size()));
- }
-
- // Append the piece whether it's bolded or not and move on to the next one.
- bubble_text_.append(piece);
- pieces.erase(pieces.begin(), pieces.begin() + 1);
- }
-
- UpdateAnchor();
- DCHECK(IsSetUp());
-}
-
-bool AutofillCreditCardBubbleController::IsSetUp() const {
- // Because |bubble_text_| should never be empty after |SetUp()|, and all
- // translations should have some text highlighting (i.e. "some |pipes|"),
- // if there is text there should be text ranges as well. Sanity check this.
- DCHECK_EQ(bubble_text_.empty(), bubble_text_ranges_.empty());
- return !bubble_text_.empty();
-}
-
-bool AutofillCreditCardBubbleController::IsGeneratedCardBubble() const {
- // Do a quick sanity check to ensure that the bubble isn't partially set up as
- // the other type (i.e. a fronting card and a new card doesn't make sense).
- DCHECK_EQ(fronting_card_name_.empty(), backing_card_name_.empty());
- DCHECK_NE(backing_card_name_.empty(), new_card_name_.empty());
- return !fronting_card_name_.empty();
-}
-
-void AutofillCreditCardBubbleController::Show(bool was_anchor_click) {
- if (!CanShow())
- return;
-
- bubble_ = CreateBubble();
- if (!bubble_) {
- // TODO(dbeam): Make a bubble on all applicable platforms.
- return;
- }
-
- bubble_->Show();
-
- if (IsGeneratedCardBubble() && !was_anchor_click) {
- // If the bubble was an automatically created "you generated a card" bubble,
- // count it as a show. If the user clicked the omnibox icon, don't count it.
- PrefService* prefs = Profile::FromBrowserContext(
- web_contents()->GetBrowserContext())->GetPrefs();
- prefs->SetInteger(::prefs::kAutofillGeneratedCardBubbleTimesShown,
- prefs->GetInteger(::prefs::kAutofillGeneratedCardBubbleTimesShown) + 1);
- }
-}
-
-void AutofillCreditCardBubbleController::UpdateAnchor() {
-#if !defined(OS_ANDROID)
- Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
- if (browser && browser->window() && browser->window()->GetLocationBar())
- browser->window()->GetLocationBar()->UpdateAutofillCreditCardView();
-#else
- // TODO(dbeam): implement.
-#endif
-}
-
-void AutofillCreditCardBubbleController::Hide() {
- // Sever |bubble_|'s reference to the controller and hide (if it exists).
- weak_ptr_factory_.InvalidateWeakPtrs();
-
- if (bubble_ && !bubble_->IsHiding())
- bubble_->Hide();
-
- DCHECK(!bubble_ || bubble_->IsHiding());
-}
-
-} // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h b/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h
deleted file mode 100644
index dfe5b55..0000000
--- a/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_CONTROLLER_H_
-#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_CONTROLLER_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/weak_ptr.h"
-#include "base/strings/string16.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "content/public/browser/web_contents_user_data.h"
-
-class Profile;
-
-namespace content {
-class WebContents;
-}
-
-namespace gfx {
-class Image;
-}
-
-namespace ui {
-class Range;
-}
-
-namespace user_prefs {
-class PrefRegistrySyncable;
-}
-
-namespace autofill {
-
-class AutofillCreditCardBubble;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// AutofillCreditCardBubbleController
-//
-// A class to show a bubble after successfully submitting the Autofill dialog.
-// The bubble is shown when a new credit card is saved locally or to explain
-// generated Online Wallet cards to the user. This class does not own the shown
-// bubble, but only has a weak reference to it (it is often owned by the native
-// platform's ui toolkit).
-//
-////////////////////////////////////////////////////////////////////////////////
-class AutofillCreditCardBubbleController
- : public content::WebContentsObserver,
- public content::WebContentsUserData<AutofillCreditCardBubbleController> {
- public:
- virtual ~AutofillCreditCardBubbleController();
-
- // Registers preferences this class cares about.
- static void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry);
-
- // Shows a clickable icon in the omnibox that informs the user about generated
- // (fronting) cards and how they are used to bill their original (backing)
- // card. Additionally, if |ShouldDisplayBubbleInitially()| is true, the bubble
- // will be shown initially (doesn't require being clicked).
- static void ShowGeneratedCardUI(content::WebContents* contents,
- const base::string16& backing_card_name,
- const base::string16& fronting_card_name);
-
- // Show a bubble and clickable omnibox icon notifying the user that new credit
- // card data has been saved. This bubble always shows initially.
- static void ShowNewCardSavedBubble(content::WebContents* contents,
- const base::string16& new_card_name);
-
- // content::WebContentsObserver implementation.
- virtual void DidNavigateMainFrame(
- const content::LoadCommittedDetails& details,
- const content::FrameNavigateParams& params) OVERRIDE;
-
- // Returns whether |bubble_| is currently in the process of hiding.
- bool IsHiding() const;
-
- // The image that should be shown as an icon in the omnibox.
- gfx::Image AnchorIcon() const;
-
- // The title of the bubble. May be empty.
- base::string16 BubbleTitle() const;
-
- // The main text of the bubble.
- base::string16 BubbleText() const;
-
- // Ranges of text styles in the bubble's main content.
- const std::vector<ui::Range>& BubbleTextRanges() const;
-
- // The text of the link shown at the bubble of the bubble.
- base::string16 LinkText() const;
-
- // Called when the anchor for this bubble is clicked. Shows a new bubble.
- void OnAnchorClicked();
-
- // Called when the link at the bottom of the bubble is clicked. Opens and
- // navigates a new tab to an informational page and hides the bubble.
- void OnLinkClicked();
-
- // The web contents that successfully submitted the Autofill dialog (causing
- // this bubble to show).
- content::WebContents* web_contents() { return web_contents_; }
- const content::WebContents* web_contents() const { return web_contents_; }
-
- protected:
- // Creates a bubble connected to |web_contents|. Its content will be based on
- // which |ShowAs*()| method is called.
- explicit AutofillCreditCardBubbleController(content::WebContents* contents);
-
- // Returns a base::WeakPtr that references |this|. Exposed for testing.
- base::WeakPtr<AutofillCreditCardBubbleController> GetWeakPtr();
-
- // Creates and returns an Autofill credit card bubble. Exposed for testing.
- virtual base::WeakPtr<AutofillCreditCardBubble> CreateBubble();
-
- // Returns a weak reference to |bubble_|. May be invalid/NULL.
- virtual base::WeakPtr<AutofillCreditCardBubble> bubble();
-
- // Returns whether the bubble can currently show itself.
- virtual bool CanShow() const;
-
- // Whether the generated card bubble should be shown initially when showing
- // the anchor icon. This does not affect whether the generated card's icon
- // will show in the omnibox.
- bool ShouldDisplayBubbleInitially() const;
-
- // Show a bubble to educate the user about generated (fronting) cards and how
- // they are used to bill their original (backing) card. Exposed for testing.
- virtual void ShowAsGeneratedCardBubble(
- const base::string16& backing_card_name,
- const base::string16& fronting_card_name);
-
- // Shows a bubble notifying the user that new credit card data has been saved.
- // Exposed for testing.
- virtual void ShowAsNewCardSavedBubble(const base::string16& new_card_name);
-
- private:
- friend class content::WebContentsUserData<AutofillCreditCardBubbleController>;
-
- // Nukes the state of this controller and hides |bubble_| (if it exists).
- void Reset();
-
- // Generates the correct bubble text and text highlighting ranges for the
- // types of bubble being shown. Must be called before showing the bubble.
- void SetUp();
-
- // Returns whether the controller has been setup as a certain type of bubble.
- bool IsSetUp() const;
-
- // Returns whether the bubble is an educational bubble about generated cards.
- bool IsGeneratedCardBubble() const;
-
- // Hides any existing bubbles and creates and shows a new one. Called in
- // response to successful Autofill dialog submission or anchor click.
- void Show(bool was_anchor_click);
-
- // Updates the omnibox icon that |bubble_| will be anchored to.
- void UpdateAnchor();
-
- // Hides |bubble_| (if it exists and isn't already hiding).
- void Hide();
-
- // The web contents associated with this bubble.
- content::WebContents* const web_contents_;
-
- // The newly saved credit card.
- base::string16 new_card_name_;
-
- // The generated credit card number and associated backing card.
- base::string16 fronting_card_name_;
- base::string16 backing_card_name_;
-
- // Bubble contents text and text ranges generated in |SetUp()|.
- base::string16 bubble_text_;
- std::vector<ui::Range> bubble_text_ranges_;
-
- // A bubble view that's created by calling either |Show*()| method; owned by
- // the native widget/hierarchy, not this class (though this class must outlive
- // |bubble_|). NULL in many cases.
- base::WeakPtr<AutofillCreditCardBubble> bubble_;
-
- // Whether the anchor should currently be showing.
- bool should_show_anchor_;
-
- // A weak pointer factory for |Create()|.
- base::WeakPtrFactory<AutofillCreditCardBubbleController> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(AutofillCreditCardBubbleController);
-};
-
-} // namespace autofill
-
-#endif // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller_unittest.cc
deleted file mode 100644
index 63efafe..0000000
--- a/chrome/browser/ui/autofill/autofill_credit_card_bubble_controller_unittest.cc
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/prefs/pref_service.h"
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h"
-#include "chrome/browser/ui/autofill/test_autofill_credit_card_bubble.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/test/base/testing_profile.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/page_transition_types.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "content/public/test/web_contents_tester.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/range/range.h"
-
-#if defined(OS_WIN)
-#include "ui/base/win/scoped_ole_initializer.h"
-#endif
-
-namespace autofill {
-
-namespace {
-
-base::string16 BackingCard() {
- return ASCIIToUTF16("Visa - 1111");
-}
-base::string16 FrontingCard() {
- return ASCIIToUTF16("Mastercard - 4444");
-}
-base::string16 NewCard() {
- return ASCIIToUTF16("Discover - 7777");
-}
-
-base::string16 RangeOfString(const base::string16& string,
- const ui::Range& range) {
- return string.substr(range.start(), range.end() - range.start());
-}
-
-class TestAutofillCreditCardBubbleController
- : public AutofillCreditCardBubbleController {
- public:
- explicit TestAutofillCreditCardBubbleController(
- content::WebContents* contents)
- : AutofillCreditCardBubbleController(contents) {
- contents->SetUserData(UserDataKey(), this);
- }
-
- virtual ~TestAutofillCreditCardBubbleController() {}
-
- bool IsInstalled() const {
- return web_contents()->GetUserData(UserDataKey()) == this;
- }
-
- TestAutofillCreditCardBubble* GetTestingBubble() {
- return static_cast<TestAutofillCreditCardBubble*>(
- AutofillCreditCardBubbleController::bubble().get());
- }
-
- protected:
- virtual base::WeakPtr<AutofillCreditCardBubble> CreateBubble() OVERRIDE {
- return TestAutofillCreditCardBubble::Create(GetWeakPtr());
- }
-
- virtual bool CanShow() const OVERRIDE {
- return true;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestAutofillCreditCardBubbleController);
-};
-
-class AutofillCreditCardBubbleControllerTest : public testing::Test {
- public:
- AutofillCreditCardBubbleControllerTest()
- : test_web_contents_(
- content::WebContentsTester::CreateTestWebContents(
- profile(), NULL)) {}
-
- virtual void SetUp() OVERRIDE {
- // Attaches immediately to |test_web_contents_| so a test version will exist
- // before a non-test version can be created.
- new TestAutofillCreditCardBubbleController(test_web_contents_.get());
- ASSERT_TRUE(controller()->IsInstalled());
- }
-
- protected:
- TestAutofillCreditCardBubbleController* controller() {
- return static_cast<TestAutofillCreditCardBubbleController*>(
- TestAutofillCreditCardBubbleController::FromWebContents(
- test_web_contents_.get()));
- }
-
- int GeneratedCardBubbleTimesShown() {
- return profile()->GetPrefs()->GetInteger(
- ::prefs::kAutofillGeneratedCardBubbleTimesShown);
- }
-
- Profile* profile() { return &profile_; }
-
- content::WebContentsTester* test_web_contents() {
- return content::WebContentsTester::For(test_web_contents_.get());
- }
-
- void ShowGeneratedCardUI() {
- ASSERT_TRUE(controller()->IsInstalled());
- TestAutofillCreditCardBubbleController::ShowGeneratedCardUI(
- test_web_contents_.get(), BackingCard(), FrontingCard());
- }
-
- void ShowNewCardSavedBubble() {
- ASSERT_TRUE(controller()->IsInstalled());
- TestAutofillCreditCardBubbleController::ShowNewCardSavedBubble(
- test_web_contents_.get(), NewCard());
- }
-
- void Navigate() {
- NavigateWithTransition(content::PAGE_TRANSITION_LINK);
- }
-
- void Redirect() {
- NavigateWithTransition(content::PAGE_TRANSITION_CLIENT_REDIRECT);
- }
-
- private:
- void NavigateWithTransition(content::PageTransition trans) {
- test_web_contents()->TestDidNavigate(
- test_web_contents_->GetRenderViewHost(), 1, GURL("about:blank"), trans);
- }
-
- content::TestBrowserThreadBundle thread_bundle_;
-#if defined(OS_WIN)
- // Without this there will be drag and drop failures. http://crbug.com/227221
- ui::ScopedOleInitializer ole_initializer_;
-#endif
- TestingProfile profile_;
- scoped_ptr<content::WebContents> test_web_contents_;
-};
-
-} // namespace
-
-TEST_F(AutofillCreditCardBubbleControllerTest, GeneratedCardBubbleTimesShown) {
- ASSERT_EQ(0, GeneratedCardBubbleTimesShown());
-
- // Ensure that showing the generated card UI bumps the persistent count.
- ShowGeneratedCardUI();
- EXPECT_EQ(1, GeneratedCardBubbleTimesShown());
- EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-
- ShowGeneratedCardUI();
- ShowGeneratedCardUI();
- EXPECT_EQ(3, GeneratedCardBubbleTimesShown());
- EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-}
-
-TEST_F(AutofillCreditCardBubbleControllerTest, BubbleText) {
- // Ensure that while showing the generated card UI that the bubble's text
- // contains "Visa - 1111" and "Mastercard - 4444".
- ShowGeneratedCardUI();
- base::string16 generated_text = controller()->BubbleText();
- EXPECT_NE(base::string16::npos, generated_text.find(BackingCard()));
- EXPECT_NE(base::string16::npos, generated_text.find(FrontingCard()));
- EXPECT_EQ(base::string16::npos, generated_text.find(NewCard()));
-
- // Ensure that while showing the new card bubble that "Discover - 7777" is in
- // the bubble text.
- ShowNewCardSavedBubble();
- base::string16 new_text = controller()->BubbleText();
- EXPECT_NE(new_text, generated_text);
- EXPECT_EQ(base::string16::npos, new_text.find(BackingCard()));
- EXPECT_EQ(base::string16::npos, new_text.find(FrontingCard()));
- EXPECT_NE(base::string16::npos, new_text.find(NewCard()));
-
- // Make sure that |bubble_text_| is regenerated the same way in |Setup()|.
- ShowGeneratedCardUI();
- EXPECT_EQ(generated_text, controller()->BubbleText());
-
- ShowNewCardSavedBubble();
- EXPECT_EQ(new_text, controller()->BubbleText());
-}
-
-TEST_F(AutofillCreditCardBubbleControllerTest, BubbleTextRanges) {
- // Check that the highlighted ranges in the bubble's text are correct.
- ShowGeneratedCardUI();
- base::string16 text = controller()->BubbleText();
- std::vector<ui::Range> ranges = controller()->BubbleTextRanges();
-
- ASSERT_EQ(2U, ranges.size());
- EXPECT_EQ(BackingCard(), RangeOfString(text, ranges[0]));
- EXPECT_EQ(FrontingCard(), RangeOfString(text, ranges[1]));
-
- ShowNewCardSavedBubble();
- text = controller()->BubbleText();
- ranges = controller()->BubbleTextRanges();
-
- ASSERT_EQ(1U, ranges.size());
- EXPECT_EQ(NewCard(), RangeOfString(text, ranges[0]));
-}
-
-TEST_F(AutofillCreditCardBubbleControllerTest, HideOnNavigate) {
- // When a user navigates away from a page (or refreshes) normally, the bubbles
- // should be hidden.
- EXPECT_FALSE(controller()->GetTestingBubble());
- ShowGeneratedCardUI();
- EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-
- Navigate();
- EXPECT_FALSE(controller());
-
- SetUp();
-
- EXPECT_FALSE(controller()->GetTestingBubble());
- ShowNewCardSavedBubble();
- EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-
- Navigate();
- EXPECT_FALSE(controller());
-}
-
-TEST_F(AutofillCreditCardBubbleControllerTest, StayOnRedirect) {
- // If a page redirects right after submitting, the bubble should remain.
- EXPECT_FALSE(controller()->GetTestingBubble());
- ShowGeneratedCardUI();
- EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-
- Redirect();
- EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-
- SetUp();
-
- EXPECT_FALSE(controller()->GetTestingBubble());
- ShowNewCardSavedBubble();
- EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-
- Redirect();
- EXPECT_TRUE(controller()->GetTestingBubble()->showing());
-}
-
-} // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_common.cc b/chrome/browser/ui/autofill/autofill_dialog_common.cc
new file mode 100644
index 0000000..4cb8cd3
--- /dev/null
+++ b/chrome/browser/ui/autofill/autofill_dialog_common.cc
@@ -0,0 +1,224 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/autofill/autofill_dialog_common.h"
+
+#include "components/autofill/core/browser/autofill_field.h"
+#include "components/autofill/core/browser/autofill_type.h"
+#include "grit/chromium_strings.h"
+#include "grit/component_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "grit/webkit_resources.h"
+
+namespace autofill {
+namespace common {
+
+// Returns true if |input| should be shown when |field_type| has been requested.
+bool InputTypeMatchesFieldType(const DetailInput& input,
+ const AutofillType& field_type) {
+ // If any credit card expiration info is asked for, show both month and year
+ // inputs.
+ ServerFieldType server_type = field_type.GetStorableType();
+ if (server_type == CREDIT_CARD_EXP_4_DIGIT_YEAR ||
+ server_type == CREDIT_CARD_EXP_2_DIGIT_YEAR ||
+ server_type == CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR ||
+ server_type == CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR ||
+ server_type == CREDIT_CARD_EXP_MONTH) {
+ return input.type == CREDIT_CARD_EXP_4_DIGIT_YEAR ||
+ input.type == CREDIT_CARD_EXP_MONTH;
+ }
+
+ if (server_type == CREDIT_CARD_TYPE)
+ return input.type == CREDIT_CARD_NUMBER;
+
+ // Check the groups to distinguish billing types from shipping ones.
+ AutofillType input_type = AutofillType(input.type);
+ return input_type.GetStorableType() == server_type &&
+ input_type.group() == field_type.group();
+}
+
+// Returns true if |input| in the given |section| should be used for a
+// site-requested |field|.
+bool DetailInputMatchesField(DialogSection section,
+ const DetailInput& input,
+ const AutofillField& field) {
+ AutofillType field_type = field.Type();
+
+ // The credit card name is filled from the billing section's data.
+ if (field_type.GetStorableType() == CREDIT_CARD_NAME &&
+ (section == SECTION_BILLING || section == SECTION_CC_BILLING)) {
+ return input.type == NAME_BILLING_FULL;
+ }
+
+ return InputTypeMatchesFieldType(input, field_type);
+}
+
+bool IsCreditCardType(ServerFieldType type) {
+ return AutofillType(type).group() == CREDIT_CARD;
+}
+
+// Constructs |inputs| from template data.
+void BuildInputs(const DetailInput* input_template,
+ size_t template_size,
+ DetailInputs* inputs) {
+ for (size_t i = 0; i < template_size; ++i) {
+ const DetailInput* input = &input_template[i];
+ inputs->push_back(*input);
+ }
+}
+
+// Constructs |inputs| from template data for a given |dialog_section|.
+void BuildInputsForSection(DialogSection dialog_section,
+ DetailInputs* inputs) {
+ const DetailInput kEmailInputs[] = {
+ { 1, EMAIL_ADDRESS, IDS_AUTOFILL_DIALOG_PLACEHOLDER_EMAIL },
+ };
+
+ const DetailInput kCCInputs[] = {
+ { 2, CREDIT_CARD_NUMBER, IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARD_NUMBER },
+ { 3, CREDIT_CARD_EXP_MONTH, IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_MONTH },
+ { 3, CREDIT_CARD_EXP_4_DIGIT_YEAR,
+ IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_YEAR },
+ { 3, CREDIT_CARD_VERIFICATION_CODE, IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC,
+ 1.5 },
+ };
+
+ const DetailInput kBillingInputs[] = {
+ { 4, NAME_BILLING_FULL, IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARDHOLDER_NAME },
+ { 5, ADDRESS_BILLING_LINE1,
+ IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1 },
+ { 6, ADDRESS_BILLING_LINE2,
+ IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2 },
+ { 7, ADDRESS_BILLING_CITY,
+ IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY },
+ // TODO(estade): state placeholder should depend on locale.
+ { 8, ADDRESS_BILLING_STATE, IDS_AUTOFILL_FIELD_LABEL_STATE },
+ { 8, ADDRESS_BILLING_ZIP,
+ IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE },
+ // We don't allow the user to change the country: http://crbug.com/247518
+ { -1, ADDRESS_BILLING_COUNTRY, 0 },
+ { 10, PHONE_BILLING_WHOLE_NUMBER,
+ IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER },
+ };
+
+ const DetailInput kShippingInputs[] = {
+ { 11, NAME_FULL, IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESSEE_NAME },
+ { 12, ADDRESS_HOME_LINE1, IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1 },
+ { 13, ADDRESS_HOME_LINE2, IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2 },
+ { 14, ADDRESS_HOME_CITY, IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY },
+ { 15, ADDRESS_HOME_STATE, IDS_AUTOFILL_FIELD_LABEL_STATE },
+ { 15, ADDRESS_HOME_ZIP, IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE },
+ { -1, ADDRESS_HOME_COUNTRY, 0 },
+ { 17, PHONE_HOME_WHOLE_NUMBER,
+ IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER },
+ };
+
+ switch (dialog_section) {
+ case SECTION_EMAIL:
+ BuildInputs(kEmailInputs,
+ arraysize(kEmailInputs),
+ inputs);
+ break;
+
+ case SECTION_CC:
+ BuildInputs(kCCInputs,
+ arraysize(kCCInputs),
+ inputs);
+ break;
+
+ case SECTION_BILLING:
+ BuildInputs(kBillingInputs,
+ arraysize(kBillingInputs),
+ inputs);
+ break;
+
+ case SECTION_CC_BILLING:
+ BuildInputs(kCCInputs,
+ arraysize(kCCInputs),
+ inputs);
+ BuildInputs(kBillingInputs,
+ arraysize(kBillingInputs),
+ inputs);
+ break;
+
+ case SECTION_SHIPPING:
+ BuildInputs(kShippingInputs,
+ arraysize(kShippingInputs),
+ inputs);
+ break;
+ }
+}
+
+AutofillMetrics::DialogUiEvent DialogSectionToUiEditEvent(
+ DialogSection section) {
+ switch (section) {
+ case SECTION_EMAIL:
+ return AutofillMetrics::DIALOG_UI_EMAIL_EDIT_UI_SHOWN;
+
+ case SECTION_BILLING:
+ return AutofillMetrics::DIALOG_UI_BILLING_EDIT_UI_SHOWN;
+
+ case SECTION_CC_BILLING:
+ return AutofillMetrics::DIALOG_UI_CC_BILLING_EDIT_UI_SHOWN;
+
+ case SECTION_SHIPPING:
+ return AutofillMetrics::DIALOG_UI_SHIPPING_EDIT_UI_SHOWN;
+
+ case SECTION_CC:
+ return AutofillMetrics::DIALOG_UI_CC_EDIT_UI_SHOWN;
+ }
+
+ NOTREACHED();
+ return AutofillMetrics::NUM_DIALOG_UI_EVENTS;
+}
+
+AutofillMetrics::DialogUiEvent DialogSectionToUiItemAddedEvent(
+ DialogSection section) {
+ switch (section) {
+ case SECTION_EMAIL:
+ return AutofillMetrics::DIALOG_UI_EMAIL_ITEM_ADDED;
+
+ case SECTION_BILLING:
+ return AutofillMetrics::DIALOG_UI_BILLING_ITEM_ADDED;
+
+ case SECTION_CC_BILLING:
+ return AutofillMetrics::DIALOG_UI_CC_BILLING_ITEM_ADDED;
+
+ case SECTION_SHIPPING:
+ return AutofillMetrics::DIALOG_UI_SHIPPING_ITEM_ADDED;
+
+ case SECTION_CC:
+ return AutofillMetrics::DIALOG_UI_CC_ITEM_ADDED;
+ }
+
+ NOTREACHED();
+ return AutofillMetrics::NUM_DIALOG_UI_EVENTS;
+}
+
+AutofillMetrics::DialogUiEvent DialogSectionToUiSelectionChangedEvent(
+ DialogSection section) {
+ switch (section) {
+ case SECTION_EMAIL:
+ return AutofillMetrics::DIALOG_UI_EMAIL_SELECTED_SUGGESTION_CHANGED;
+
+ case SECTION_BILLING:
+ return AutofillMetrics::DIALOG_UI_BILLING_SELECTED_SUGGESTION_CHANGED;
+
+ case SECTION_CC_BILLING:
+ return AutofillMetrics::DIALOG_UI_CC_BILLING_SELECTED_SUGGESTION_CHANGED;
+
+ case SECTION_SHIPPING:
+ return AutofillMetrics::DIALOG_UI_SHIPPING_SELECTED_SUGGESTION_CHANGED;
+
+ case SECTION_CC:
+ return AutofillMetrics::DIALOG_UI_CC_SELECTED_SUGGESTION_CHANGED;
+ }
+
+ NOTREACHED();
+ return AutofillMetrics::NUM_DIALOG_UI_EVENTS;
+}
+
+} // namespace common
+} // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_common.h b/chrome/browser/ui/autofill/autofill_dialog_common.h
new file mode 100644
index 0000000..be5261e
--- /dev/null
+++ b/chrome/browser/ui/autofill/autofill_dialog_common.h
@@ -0,0 +1,57 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_COMMON_H_
+#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_COMMON_H_
+
+#include "chrome/browser/ui/autofill/autofill_dialog_types.h"
+#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/field_types.h"
+
+namespace autofill {
+class AutofillProfile;
+}
+
+namespace wallet {
+class Address;
+}
+
+namespace autofill {
+namespace common {
+
+// Returns true if |input| should be shown when |field_type| has been requested.
+bool InputTypeMatchesFieldType(const DetailInput& input,
+ const AutofillType& field_type);
+
+// Returns true if |input| in the given |section| should be used for a
+// site-requested |field|.
+bool DetailInputMatchesField(DialogSection section,
+ const DetailInput& input,
+ const AutofillField& field);
+
+// Returns true if the |type| belongs to the CREDIT_CARD field type group.
+bool IsCreditCardType(ServerFieldType type);
+
+// Constructs |inputs| from template data for a given |dialog_section|.
+void BuildInputsForSection(DialogSection dialog_section, DetailInputs* inputs);
+
+// Returns the AutofillMetrics::DIALOG_UI_*_EDIT_UI_SHOWN metric corresponding
+// to the |section|.
+AutofillMetrics::DialogUiEvent DialogSectionToUiEditEvent(
+ DialogSection section);
+
+// Returns the AutofillMetrics::DIALOG_UI_*_ITEM_ADDED metric corresponding
+// to the |section|.
+AutofillMetrics::DialogUiEvent DialogSectionToUiItemAddedEvent(
+ DialogSection section);
+
+// Returns the AutofillMetrics::DIALOG_UI_*_ITEM_ADDED metric corresponding
+// to the |section|.
+AutofillMetrics::DialogUiEvent DialogSectionToUiSelectionChangedEvent(
+ DialogSection section);
+
+} // namespace common
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_COMMON_H_
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller.cc b/chrome/browser/ui/autofill/autofill_dialog_controller.cc
new file mode 100644
index 0000000..69a03a8
--- /dev/null
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller.cc
@@ -0,0 +1,30 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
+
+namespace autofill {
+
+AutofillDialogController::~AutofillDialogController() {}
+
+#if !defined(ENABLE_AUTOFILL_DIALOG)
+// static
+base::WeakPtr<AutofillDialogController>
+AutofillDialogController::Create(
+ content::WebContents* contents,
+ const FormData& form_structure,
+ const GURL& source_url,
+ const DialogType dialog_type,
+ const base::Callback<void(const FormStructure*,
+ const std::string&)>& callback) {
+ NOTIMPLEMENTED();
+ return base::WeakPtr<AutofillDialogController>();
+}
+
+// static
+void AutofillDialogController::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {}
+#endif // !defined(ENABLE_AUTOFILL_DIALOG)
+
+} // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller.h b/chrome/browser/ui/autofill/autofill_dialog_controller.h
new file mode 100644
index 0000000..819f654
--- /dev/null
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller.h
@@ -0,0 +1,76 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_H_
+#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_types.h"
+#include "components/autofill/content/browser/autocheckout_steps.h"
+#include "components/autofill/core/browser/form_structure.h"
+
+class GURL;
+
+namespace content {
+class WebContents;
+}
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+namespace autofill {
+
+// This class defines the interface to the controller for TabAutofillManager.
+class AutofillDialogController {
+ public:
+ virtual ~AutofillDialogController();
+
+ // Creates the AutofillDialogController.
+ static base::WeakPtr<AutofillDialogController> Create(
+ content::WebContents* contents,
+ const FormData& form_structure,
+ const GURL& source_url,
+ const DialogType dialog_type,
+ const base::Callback<void(const FormStructure*,
+ const std::string&)>& callback);
+
+ // Registers profile preferences.
+ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+ // Shows the Autofill dialog.
+ virtual void Show() = 0;
+
+ // Hides the Autofill dialog.
+ virtual void Hide() = 0;
+
+ // Called when the tab hosting this dialog is activated by a user gesture.
+ // Used to trigger a refresh of the user's Wallet data.
+ virtual void TabActivated() = 0;
+
+ // Adds a step in the flow to the Autocheckout UI.
+ virtual void AddAutocheckoutStep(AutocheckoutStepType step_type) = 0;
+
+ // Updates the status of a step in the Autocheckout UI.
+ virtual void UpdateAutocheckoutStep(
+ AutocheckoutStepType step_type,
+ AutocheckoutStepStatus step_status) = 0;
+
+ // Called when there is an error in an active Autocheckout flow.
+ virtual void OnAutocheckoutError() = 0;
+
+ // Called when an Autocheckout flow completes successfully.
+ virtual void OnAutocheckoutSuccess() = 0;
+
+ // Returns the dialog type.
+ virtual DialogType GetDialogType() const = 0;
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc
index 6aa1712..92a893d 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc
@@ -140,7 +140,7 @@
section, inputs, validation_type);
}
- // Saving to Chrome is tested in AutofillDialogController unit tests.
+ // Saving to Chrome is tested in AutofillDialogControllerImpl unit tests.
// TODO(estade): test that the view defaults to saving to Chrome.
virtual bool ShouldOfferToSaveInChrome() const OVERRIDE {
return false;
@@ -301,7 +301,8 @@
ExpectDomMessage("clicked");
AutofillDialogControllerImpl* controller =
- delegate->GetDialogControllerForTesting();
+ static_cast<AutofillDialogControllerImpl*>(
+ delegate->GetDialogControllerForTesting());
DCHECK(controller);
return controller;
}
@@ -562,8 +563,17 @@
// Tests that changing the value of a CC expiration date combobox works as
// expected when Autofill is used to fill text inputs.
+//
+// Flaky on Win7, WinXP, and Win Aura. http://crbug.com/270314.
+// TODO(groby): Enable this test on mac once AutofillDialogCocoa handles
+// comboboxes for GetTextContentsForInput. http://crbug.com/270205
+#if defined(OS_MACOSX) || defined(OS_WIN)
+#define MAYBE_FillComboboxFromAutofill DISABLED_FillComboboxFromAutofill
+#else
+#define MAYBE_FillComboboxFromAutofill FillComboboxFromAutofill
+#endif
IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest,
- FillComboboxFromAutofill) {
+ MAYBE_FillComboboxFromAutofill) {
InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
CreditCard card1;
@@ -793,7 +803,13 @@
controller()->GetTestableView()->SubmitForTesting());
}
-IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, PreservedSections) {
+// Flaky on Win7, WinXP, and Win Aura. http://crbug.com/270314.
+#if defined(OS_WIN)
+#define MAYBE_PreservedSections DISABLED_PreservedSections
+#else
+#define MAYBE_PreservedSections PreservedSections
+#endif
+IN_PROC_BROWSER_TEST_F(AutofillDialogControllerTest, MAYBE_PreservedSections) {
InitializeControllerOfType(DIALOG_TYPE_REQUEST_AUTOCOMPLETE);
controller()->set_use_validation(true);
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
index 3a42603..0ac504d 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
@@ -10,6 +10,7 @@
#include "apps/native_app_window.h"
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "base/base64.h"
#include "base/bind.h"
#include "base/i18n/rtl.h"
@@ -22,12 +23,15 @@
#include "base/time/time.h"
#include "chrome/browser/autofill/personal_data_manager_factory.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_common.h"
#include "chrome/browser/ui/autofill/autofill_dialog_view.h"
#include "chrome/browser/ui/autofill/data_model_wrapper.h"
+#if !defined(OS_ANDROID)
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/autofill/new_credit_card_bubble_controller.h"
+#endif
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_navigator.h"
@@ -110,50 +114,6 @@
card_type == autofill::kDiscoverCard;
}
-// Returns true if |input| should be shown when |field_type| has been requested.
-bool InputTypeMatchesFieldType(const DetailInput& input,
- const AutofillType& field_type) {
- // If any credit card expiration info is asked for, show both month and year
- // inputs.
- ServerFieldType server_type = field_type.GetStorableType();
- if (server_type == CREDIT_CARD_EXP_4_DIGIT_YEAR ||
- server_type == CREDIT_CARD_EXP_2_DIGIT_YEAR ||
- server_type == CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR ||
- server_type == CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR ||
- server_type == CREDIT_CARD_EXP_MONTH) {
- return input.type == CREDIT_CARD_EXP_4_DIGIT_YEAR ||
- input.type == CREDIT_CARD_EXP_MONTH;
- }
-
- if (server_type == CREDIT_CARD_TYPE)
- return input.type == CREDIT_CARD_NUMBER;
-
- // Check the groups to distinguish billing types from shipping ones.
- AutofillType input_type = AutofillType(input.type);
- return input_type.GetStorableType() == server_type &&
- input_type.group() == field_type.group();
-}
-
-// Returns true if |input| in the given |section| should be used for a
-// site-requested |field|.
-bool DetailInputMatchesField(DialogSection section,
- const DetailInput& input,
- const AutofillField& field) {
- AutofillType field_type = field.Type();
-
- // The credit card name is filled from the billing section's data.
- if (field_type.GetStorableType() == CREDIT_CARD_NAME &&
- (section == SECTION_BILLING || section == SECTION_CC_BILLING)) {
- return input.type == NAME_BILLING_FULL;
- }
-
- return InputTypeMatchesFieldType(input, field_type);
-}
-
-bool IsCreditCardType(ServerFieldType type) {
- return AutofillType(type).group() == CREDIT_CARD;
-}
-
// Returns true if |input| should be used to fill a site-requested |field| which
// is notated with a "shipping" tag, for use when the user has decided to use
// the billing address as the shipping address.
@@ -165,17 +125,7 @@
AutofillType::GetEquivalentBillingFieldType(
field.Type().GetStorableType());
- return InputTypeMatchesFieldType(input, AutofillType(field_type));
-}
-
-// Constructs |inputs| from template data.
-void BuildInputs(const DetailInput* input_template,
- size_t template_size,
- DetailInputs* inputs) {
- for (size_t i = 0; i < template_size; ++i) {
- const DetailInput* input = &input_template[i];
- inputs->push_back(*input);
- }
+ return common::InputTypeMatchesFieldType(input, AutofillType(field_type));
}
// Initializes |form_group| from user-entered data.
@@ -225,7 +175,7 @@
if (card && it->first->type == NAME_FULL)
card->SetRawInfo(CREDIT_CARD_NAME, trimmed);
- if (IsCreditCardType(it->first->type)) {
+ if (common::IsCreditCardType(it->first->type)) {
if (card)
card->SetRawInfo(it->first->type, trimmed);
} else if (profile) {
@@ -247,7 +197,7 @@
gfx::NativeWindow native_window =
web_contents->GetView()->GetTopLevelNativeWindow();
apps::ShellWindow* shell_window =
- extensions::ShellWindowRegistry::
+ apps::ShellWindowRegistry::
GetShellWindowForNativeWindowAnyProfile(native_window);
return shell_window->GetBaseWindow();
}
@@ -385,6 +335,14 @@
case wallet::WalletClient::BUYER_ACCOUNT_ERROR:
return l10n_util::GetStringUTF16(IDS_AUTOFILL_WALLET_BUYER_ACCOUNT_ERROR);
+ case wallet::WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED:
+ return l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_WALLET_BUYER_COUNTRY_NOT_SUPPORTED);
+
+ case wallet::WalletClient::UNSUPPORTED_MERCHANT:
+ return l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_WALLET_UNSUPPORTED_MERCHANT);
+
case wallet::WalletClient::BAD_REQUEST:
return l10n_util::GetStringFUTF16(
IDS_AUTOFILL_WALLET_UPGRADE_CHROME_ERROR,
@@ -395,6 +353,10 @@
IDS_AUTOFILL_WALLET_UPGRADE_CHROME_ERROR,
ASCIIToUTF16("42"));
+ case wallet::WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS:
+ return l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS);
+
case wallet::WalletClient::UNSUPPORTED_API_VERSION:
return l10n_util::GetStringFUTF16(
IDS_AUTOFILL_WALLET_UPGRADE_CHROME_ERROR,
@@ -432,7 +394,6 @@
gfx::Canvas canvas(card->size(), ui::SCALE_FACTOR_100P, false);
canvas.DrawImageInt(*card, 0, 0);
-#if !defined(OS_ANDROID)
gfx::Rect display_rect(gfx::Point(), card->size());
display_rect.Inset(14, 0, 14, 0);
// TODO(estade): fallback font for systems that don't have Helvetica?
@@ -446,7 +407,6 @@
helvetica,
SK_ColorWHITE,
display_rect, 0, 0, shadows);
-#endif
gfx::ImageSkia skia(canvas.ExtractImageRep());
return gfx::Image(skia);
@@ -470,7 +430,6 @@
}
}
-#if !defined(OS_ANDROID)
// static
base::WeakPtr<AutofillDialogControllerImpl>
AutofillDialogControllerImpl::Create(
@@ -489,7 +448,6 @@
callback);
return autofill_dialog_controller->weak_ptr_factory_.GetWeakPtr();
}
-#endif // !defined(OS_ANDROID)
// static
void AutofillDialogControllerImpl::RegisterProfilePrefs(
@@ -511,6 +469,27 @@
user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
}
+// static
+base::WeakPtr<AutofillDialogController> AutofillDialogController::Create(
+ content::WebContents* contents,
+ const FormData& form_structure,
+ const GURL& source_url,
+ const DialogType dialog_type,
+ const base::Callback<void(const FormStructure*,
+ const std::string&)>& callback) {
+ return AutofillDialogControllerImpl::Create(contents,
+ form_structure,
+ source_url,
+ dialog_type,
+ callback);
+}
+
+// static
+void AutofillDialogController::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ AutofillDialogControllerImpl::RegisterProfilePrefs(registry);
+}
+
void AutofillDialogControllerImpl::Show() {
dialog_shown_timestamp_ = base::Time::Now();
@@ -551,70 +530,16 @@
return;
}
- const DetailInput kEmailInputs[] = {
- { 1, EMAIL_ADDRESS, IDS_AUTOFILL_DIALOG_PLACEHOLDER_EMAIL },
- };
-
- const DetailInput kCCInputs[] = {
- { 2, CREDIT_CARD_NUMBER, IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARD_NUMBER },
- { 3, CREDIT_CARD_EXP_MONTH },
- { 3, CREDIT_CARD_EXP_4_DIGIT_YEAR },
- { 3, CREDIT_CARD_VERIFICATION_CODE, IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC,
- 1.5 },
- };
-
- const DetailInput kBillingInputs[] = {
- { 4, NAME_BILLING_FULL, IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARDHOLDER_NAME },
- { 5, ADDRESS_BILLING_LINE1,
- IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1 },
- { 6, ADDRESS_BILLING_LINE2,
- IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2 },
- { 7, ADDRESS_BILLING_CITY,
- IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY },
- // TODO(estade): state placeholder should depend on locale.
- { 8, ADDRESS_BILLING_STATE, IDS_AUTOFILL_FIELD_LABEL_STATE },
- { 8, ADDRESS_BILLING_ZIP,
- IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE },
- // We don't allow the user to change the country: http://crbug.com/247518
- { -1, ADDRESS_BILLING_COUNTRY, 0 },
- { 10, PHONE_BILLING_WHOLE_NUMBER,
- IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER },
- };
-
- const DetailInput kShippingInputs[] = {
- { 11, NAME_FULL, IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESSEE_NAME },
- { 12, ADDRESS_HOME_LINE1, IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1 },
- { 13, ADDRESS_HOME_LINE2, IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2 },
- { 14, ADDRESS_HOME_CITY, IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY },
- { 15, ADDRESS_HOME_STATE, IDS_AUTOFILL_FIELD_LABEL_STATE },
- { 15, ADDRESS_HOME_ZIP, IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE },
- { -1, ADDRESS_HOME_COUNTRY, 0 },
- { 17, PHONE_HOME_WHOLE_NUMBER,
- IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER },
- };
-
- BuildInputs(kEmailInputs,
- arraysize(kEmailInputs),
- &requested_email_fields_);
-
- BuildInputs(kCCInputs,
- arraysize(kCCInputs),
- &requested_cc_fields_);
-
- BuildInputs(kBillingInputs,
- arraysize(kBillingInputs),
- &requested_billing_fields_);
-
- BuildInputs(kCCInputs,
- arraysize(kCCInputs),
- &requested_cc_billing_fields_);
- BuildInputs(kBillingInputs,
- arraysize(kBillingInputs),
- &requested_cc_billing_fields_);
-
- BuildInputs(kShippingInputs,
- arraysize(kShippingInputs),
- &requested_shipping_fields_);
+ common::BuildInputsForSection(SECTION_EMAIL,
+ &requested_email_fields_);
+ common::BuildInputsForSection(SECTION_CC,
+ &requested_cc_fields_);
+ common::BuildInputsForSection(SECTION_BILLING,
+ &requested_billing_fields_);
+ common::BuildInputsForSection(SECTION_CC_BILLING,
+ &requested_cc_billing_fields_);
+ common::BuildInputsForSection(SECTION_SHIPPING,
+ &requested_shipping_fields_);
// Test whether we need to show the shipping section. If filling that section
// would be a no-op, don't show it.
@@ -622,7 +547,7 @@
EmptyDataModelWrapper empty_wrapper;
cares_about_shipping_ = empty_wrapper.FillFormStructure(
inputs,
- base::Bind(DetailInputMatchesField, SECTION_SHIPPING),
+ base::Bind(common::DetailInputMatchesField, SECTION_SHIPPING),
&form_structure_);
SuggestionsUpdated();
@@ -788,9 +713,8 @@
}
string16 AutofillDialogControllerImpl::AccountChooserText() const {
- // TODO(aruslan): this should be l10n "Not using Google Wallet".
if (!account_chooser_model_.WalletIsSelected())
- return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PAY_WITHOUT_WALLET);
+ return l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PAYING_WITHOUT_WALLET);
if (SignedInState() == SIGNED_IN)
return account_chooser_model_.active_wallet_account_name();
@@ -802,14 +726,15 @@
string16 AutofillDialogControllerImpl::SignInLinkText() const {
return l10n_util::GetStringUTF16(
signin_registrar_.IsEmpty() ? IDS_AUTOFILL_DIALOG_SIGN_IN :
- IDS_AUTOFILL_DIALOG_PAY_WITHOUT_WALLET);
+ IDS_AUTOFILL_DIALOG_CANCEL_SIGN_IN);
}
bool AutofillDialogControllerImpl::ShouldOfferToSaveInChrome() const {
return !IsPayingWithWallet() &&
!profile_->IsOffTheRecord() &&
IsManuallyEditingAnySection() &&
- ShouldShowDetailArea();
+ ShouldShowDetailArea() &&
+ !ShouldShowSpinner();
}
int AutofillDialogControllerImpl::GetDialogButtons() const {
@@ -853,10 +778,7 @@
state.strings.push_back(DialogOverlayString());
DialogOverlayString& string = state.strings.back();
-#if !defined(OS_ANDROID)
- // gfx::Font isn't implemented on Android; DeriveFont() causes a null deref.
string.font = rb.GetFont(ui::ResourceBundle::BaseFont).DeriveFont(4);
-#endif
// First-run, post-submit, Wallet expository page.
if (full_wallet_ && full_wallet_->required_actions().empty()) {
@@ -1102,13 +1024,13 @@
}
}
-bool AutofillDialogControllerImpl::InputWasEdited(const DetailInput& input,
+bool AutofillDialogControllerImpl::InputWasEdited(ServerFieldType type,
const base::string16& value) {
if (value.empty())
return false;
- // If this is a combobox at the default value, don't preserve.
- ui::ComboboxModel* model = ComboboxModelForAutofillType(input.type);
+ // If this is a combobox at the default value, don't preserve it.
+ ui::ComboboxModel* model = ComboboxModelForAutofillType(type);
if (model && model->GetItemAt(model->GetDefaultIndex()) == value)
return false;
@@ -1131,7 +1053,7 @@
// Remove fields that are empty, at their default values, or invalid.
for (DetailOutputMap::iterator it = outputs.begin(); it != outputs.end();
++it) {
- if (InputWasEdited(*it->first, it->second) &&
+ if (InputWasEdited(it->first->type, it->second) &&
InputValidityMessage(section, it->first->type, it->second).empty()) {
snapshot.insert(std::make_pair(it->first, it->second));
}
@@ -1156,7 +1078,7 @@
wrapper.FillInputs(inputs);
for (size_t i = 0; i < inputs->size(); ++i) {
- if (InputWasEdited((*inputs)[i], (*inputs)[i].initial_value)) {
+ if (InputWasEdited((*inputs)[i].type, (*inputs)[i].initial_value)) {
SuggestionsMenuModelForSection(section)->SetCheckedItem(kAddNewItemKey);
break;
}
@@ -1507,7 +1429,7 @@
UpdateSection(section);
GetMetricLogger().LogDialogUiEvent(
- GetDialogType(), DialogSectionToUiEditEvent(section));
+ GetDialogType(), common::DialogSectionToUiEditEvent(section));
}
void AutofillDialogControllerImpl::EditCancelledForSection(
@@ -1602,7 +1524,17 @@
}
case CREDIT_CARD_EXP_MONTH:
+ if (!InputWasEdited(CREDIT_CARD_EXP_MONTH, value)) {
+ return l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_DIALOG_VALIDATION_MISSING_VALUE);
+ }
+ break;
+
case CREDIT_CARD_EXP_4_DIGIT_YEAR:
+ if (!InputWasEdited(CREDIT_CARD_EXP_4_DIGIT_YEAR, value)) {
+ return l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_DIALOG_VALIDATION_MISSING_VALUE);
+ }
break;
case CREDIT_CARD_VERIFICATION_CODE:
@@ -1672,11 +1604,16 @@
std::map<ServerFieldType, string16> field_values;
for (DetailOutputMap::const_iterator iter = inputs.begin();
iter != inputs.end(); ++iter) {
- // Skip empty fields in edit mode.
- if (validation_type == VALIDATE_EDIT && iter->second.empty())
- continue;
-
const ServerFieldType type = iter->first->type;
+
+ // Skip empty/unchanged fields in edit mode. Ignore country code as it
+ // always has a value.
+ if (validation_type == VALIDATE_EDIT &&
+ !InputWasEdited(type, iter->second) &&
+ ComboboxModelForAutofillType(type) != &country_combobox_model_) {
+ continue;
+ }
+
string16 message = InputValidityMessage(section, type, iter->second);
if (!message.empty())
invalid_messages[type] = message;
@@ -1688,6 +1625,10 @@
// never supposed to have 2-digit years, so not checked).
if (field_values.count(CREDIT_CARD_EXP_4_DIGIT_YEAR) &&
field_values.count(CREDIT_CARD_EXP_MONTH) &&
+ InputWasEdited(CREDIT_CARD_EXP_4_DIGIT_YEAR,
+ field_values[CREDIT_CARD_EXP_4_DIGIT_YEAR]) &&
+ InputWasEdited(CREDIT_CARD_EXP_MONTH,
+ field_values[CREDIT_CARD_EXP_MONTH]) &&
!IsCreditCardExpirationValid(field_values[CREDIT_CARD_EXP_4_DIGIT_YEAR],
field_values[CREDIT_CARD_EXP_MONTH])) {
// The dialog shows the same error message for the month and year fields.
@@ -1761,7 +1702,7 @@
}
std::vector<string16> popup_values, popup_labels, popup_icons;
- if (IsCreditCardType(input->type)) {
+ if (common::IsCreditCardType(input->type)) {
GetManager()->GetCreditCardSuggestions(AutofillType(input->type),
field_contents,
&popup_values,
@@ -2063,7 +2004,7 @@
const PersonalDataManager::GUIDPair& pair = popup_guids_[identifier];
scoped_ptr<DataModelWrapper> wrapper;
- if (IsCreditCardType(input_showing_popup_->type)) {
+ if (common::IsCreditCardType(input_showing_popup_->type)) {
wrapper.reset(new AutofillCreditCardWrapper(
GetManager()->GetCreditCardByGUID(pair.first)));
} else {
@@ -2338,7 +2279,7 @@
for (size_t i = 0; i < form_structure_.field_count(); ++i) {
AutofillType type = form_structure_.field(i)->Type();
- if (IsCreditCardType(type.GetStorableType()))
+ if (common::IsCreditCardType(type.GetStorableType()))
return true;
}
@@ -2349,6 +2290,16 @@
return source_url_.SchemeIs(chrome::kHttpsScheme);
}
+void AutofillDialogControllerImpl::ShowNewCreditCardBubble(
+ scoped_ptr<CreditCard> new_card,
+ scoped_ptr<AutofillProfile> billing_profile) {
+#if !defined(OS_ANDROID)
+ NewCreditCardBubbleController::Show(profile(),
+ new_card.Pass(),
+ billing_profile.Pass());
+#endif
+}
+
AutofillDialogControllerImpl::AutofillDialogControllerImpl(
content::WebContents* contents,
const FormData& form_structure,
@@ -2416,9 +2367,7 @@
DCHECK(success);
gfx::Rect window_bounds;
-#if !defined(OS_ANDROID)
window_bounds = GetBaseWindowForWebContents(web_contents())->GetBounds();
-#endif
PrefService* user_prefs = profile_->GetPrefs();
std::string charset = user_prefs->GetString(::prefs::kDefaultCharset);
@@ -2448,14 +2397,12 @@
}
void AutofillDialogControllerImpl::OpenTabWithUrl(const GURL& url) {
-#if !defined(OS_ANDROID)
chrome::NavigateParams params(
chrome::FindBrowserWithWebContents(web_contents()),
url,
content::PAGE_TRANSITION_AUTO_BOOKMARK);
params.disposition = NEW_FOREGROUND_TAB;
chrome::Navigate(¶ms);
-#endif
}
bool AutofillDialogControllerImpl::IsEditingExistingData(
@@ -2782,7 +2729,7 @@
void AutofillDialogControllerImpl::FillOutputForSection(DialogSection section) {
FillOutputForSectionWithComparator(
- section, base::Bind(DetailInputMatchesField, section));
+ section, base::Bind(common::DetailInputMatchesField, section));
}
bool AutofillDialogControllerImpl::FormStructureCaresAboutSection(
@@ -3384,10 +3331,10 @@
AutofillMetrics::DialogUiEvent dialog_ui_event;
if (model.GetItemKeyForCheckedItem() == kAddNewItemKey) {
// Selected to add a new item.
- dialog_ui_event = DialogSectionToUiItemAddedEvent(section);
+ dialog_ui_event = common::DialogSectionToUiItemAddedEvent(section);
} else if (IsASuggestionItemKey(model.GetItemKeyForCheckedItem())) {
// Selected an existing item.
- dialog_ui_event = DialogSectionToUiSelectionChangedEvent(section);
+ dialog_ui_event = common::DialogSectionToUiSelectionChangedEvent(section);
} else {
// TODO(estade): add logging for "Manage items" or "Use billing for
// shipping"?
@@ -3463,8 +3410,28 @@
return;
if (newly_saved_card_) {
- AutofillCreditCardBubbleController::ShowNewCardSavedBubble(
- web_contents(), newly_saved_card_->TypeAndLastFourDigits());
+ scoped_ptr<AutofillProfile> billing_profile;
+ if (IsManuallyEditingSection(SECTION_BILLING)) {
+ // Scrape the view as the user's entering or updating information.
+ DetailOutputMap outputs;
+ view_->GetUserInput(SECTION_BILLING, &outputs);
+ billing_profile.reset(new AutofillProfile);
+ FillFormGroupFromOutputs(outputs, billing_profile.get());
+ } else {
+ // Just snag the currently suggested profile.
+ std::string item_key = SuggestionsMenuModelForSection(SECTION_BILLING)->
+ GetItemKeyForCheckedItem();
+ AutofillProfile* profile = GetManager()->GetProfileByGUID(item_key);
+ billing_profile.reset(new AutofillProfile(*profile));
+ }
+
+ // The bubble also needs the associated email address.
+ billing_profile->SetRawInfo(
+ EMAIL_ADDRESS,
+ GetValueFromSection(SECTION_EMAIL, EMAIL_ADDRESS));
+
+ ShowNewCreditCardBubble(newly_saved_card_.Pass(),
+ billing_profile.Pass());
return;
}
@@ -3487,8 +3454,12 @@
GetBillingInfoFromOutputs(output, &card, NULL, NULL);
backing_last_four = card.TypeAndLastFourDigits();
}
- AutofillCreditCardBubbleController::ShowGeneratedCardUI(
- web_contents(), backing_last_four, full_wallet_->TypeAndLastFourDigits());
+#if !defined(OS_ANDROID)
+ GeneratedCreditCardBubbleController::Show(
+ web_contents(),
+ backing_last_four,
+ full_wallet_->TypeAndLastFourDigits());
+#endif
}
} // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
index 6aa4ae1..6a98284 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
@@ -14,6 +14,7 @@
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "chrome/browser/ui/autofill/account_chooser_model.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
#include "chrome/browser/ui/autofill/autofill_dialog_models.h"
#include "chrome/browser/ui/autofill/autofill_dialog_types.h"
#include "chrome/browser/ui/autofill/autofill_dialog_view_delegate.h"
@@ -68,6 +69,7 @@
// This class drives the dialog that appears when a site uses the imperative
// autocomplete API to fill out a form.
class AutofillDialogControllerImpl : public AutofillDialogViewDelegate,
+ public AutofillDialogController,
public AutofillPopupDelegate,
public content::NotificationObserver,
public content::WebContentsObserver,
@@ -89,25 +91,16 @@
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
- void Show();
- void Hide();
-
- // Called when the tab hosting this dialog is activated by a user gesture.
- // Used to trigger a refresh of the user's Wallet data.
- void TabActivated();
-
- // Adds a step in the flow to the Autocheckout UI.
- void AddAutocheckoutStep(AutocheckoutStepType step_type);
-
- // Updates the status of a step in the Autocheckout UI.
- void UpdateAutocheckoutStep(AutocheckoutStepType step_type,
- AutocheckoutStepStatus step_status);
-
- // Called when there is an error in an active Autocheckout flow.
- void OnAutocheckoutError();
-
- // Called when an Autocheckout flow completes successfully.
- void OnAutocheckoutSuccess();
+ // AutofillDialogController implementation.
+ virtual void Show() OVERRIDE;
+ virtual void Hide() OVERRIDE;
+ virtual void TabActivated() OVERRIDE;
+ virtual void AddAutocheckoutStep(AutocheckoutStepType step_type) OVERRIDE;
+ virtual void UpdateAutocheckoutStep(
+ AutocheckoutStepType step_type,
+ AutocheckoutStepStatus step_status) OVERRIDE;
+ virtual void OnAutocheckoutError() OVERRIDE;
+ virtual void OnAutocheckoutSuccess() OVERRIDE;
// Returns |view_| as a testable version of itself (if |view_| exists and
// actually implements |AutofillDialogView::GetTestableView()|).
@@ -294,6 +287,12 @@
AutocheckoutState autocheckout_state() const { return autocheckout_state_; }
+ // Shows a new credit card saved bubble and passes ownership of |new_card| and
+ // |billing_profile| to the bubble. Exposed for testing.
+ virtual void ShowNewCreditCardBubble(
+ scoped_ptr<CreditCard> new_card,
+ scoped_ptr<AutofillProfile> billing_profile);
+
private:
// Whether or not the current request wants credit info back.
bool RequestingCreditCardInfo() const;
@@ -333,7 +332,7 @@
void ShowEditUiIfBadSuggestion(DialogSection section);
// Whether the |value| of |input| should be preserved on account change.
- bool InputWasEdited(const DetailInput& input,
+ bool InputWasEdited(ServerFieldType type,
const base::string16& value);
// Takes a snapshot of the newly inputted user data in |view_| (if it exists).
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
index 7d16140..7a616b8 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
@@ -14,10 +14,11 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/tuple.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h"
#include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h"
#include "chrome/browser/ui/autofill/autofill_dialog_view.h"
-#include "chrome/browser/ui/autofill/test_autofill_credit_card_bubble.h"
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/autofill/mock_new_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/render_messages.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
@@ -193,7 +194,8 @@
const AutofillMetrics& metric_logger,
const DialogType dialog_type,
const base::Callback<void(const FormStructure*,
- const std::string&)>& callback)
+ const std::string&)>& callback,
+ MockNewCreditCardBubbleController* mock_new_card_bubble_controller)
: AutofillDialogControllerImpl(contents,
form_structure,
source_url,
@@ -203,7 +205,9 @@
mock_wallet_client_(
Profile::FromBrowserContext(contents->GetBrowserContext())->
GetRequestContext(), this),
- dialog_type_(dialog_type) {}
+ dialog_type_(dialog_type),
+ mock_new_card_bubble_controller_(mock_new_card_bubble_controller) {}
+
virtual ~TestAutofillDialogController() {}
virtual AutofillDialogView* CreateView() OVERRIDE {
@@ -265,6 +269,13 @@
return true;
}
+ virtual void ShowNewCreditCardBubble(
+ scoped_ptr<CreditCard> new_card,
+ scoped_ptr<AutofillProfile> billing_profile) OVERRIDE {
+ mock_new_card_bubble_controller_->Show(new_card.Pass(),
+ billing_profile.Pass());
+ }
+
private:
// To specify our own metric logger.
virtual const AutofillMetrics& GetMetricLogger() const OVERRIDE {
@@ -276,31 +287,29 @@
testing::NiceMock<wallet::MockWalletClient> mock_wallet_client_;
GURL open_tab_url_;
DialogType dialog_type_;
+ MockNewCreditCardBubbleController* mock_new_card_bubble_controller_;
DISALLOW_COPY_AND_ASSIGN(TestAutofillDialogController);
};
-class TestAutofillCreditCardBubbleController :
- public AutofillCreditCardBubbleController {
+class TestGeneratedCreditCardBubbleController :
+ public GeneratedCreditCardBubbleController {
public:
- explicit TestAutofillCreditCardBubbleController(
+ explicit TestGeneratedCreditCardBubbleController(
content::WebContents* contents)
- : AutofillCreditCardBubbleController(contents) {
+ : GeneratedCreditCardBubbleController(contents) {
contents->SetUserData(UserDataKey(), this);
CHECK_EQ(contents->GetUserData(UserDataKey()), this);
}
- virtual ~TestAutofillCreditCardBubbleController() {}
+ virtual ~TestGeneratedCreditCardBubbleController() {}
- MOCK_METHOD2(ShowAsGeneratedCardBubble,
- void(const base::string16& backing_card_name,
- const base::string16& fronting_card_name));
- MOCK_METHOD1(ShowAsNewCardSavedBubble,
- void(const base::string16& newly_saved_card_name));
+ MOCK_METHOD2(SetupAndShow, void(const base::string16& backing_card_name,
+ const base::string16& fronting_card_name));
protected:
- virtual base::WeakPtr<AutofillCreditCardBubble> CreateBubble() OVERRIDE {
- return TestAutofillCreditCardBubble::Create(GetWeakPtr());
+ virtual base::WeakPtr<GeneratedCreditCardBubbleView> CreateBubble() OVERRIDE {
+ return TestGeneratedCreditCardBubbleView::Create(GetWeakPtr());
}
virtual bool CanShow() const OVERRIDE {
@@ -308,7 +317,7 @@
}
private:
- DISALLOW_COPY_AND_ASSIGN(TestAutofillCreditCardBubbleController);
+ DISALLOW_COPY_AND_ASSIGN(TestGeneratedCreditCardBubbleController);
};
class AutofillDialogControllerTest : public ChromeRenderViewHostTestHarness {
@@ -318,16 +327,7 @@
// testing::Test implementation:
virtual void SetUp() OVERRIDE {
ChromeRenderViewHostTestHarness::SetUp();
-
- test_bubble_controller_ =
- new testing::NiceMock<TestAutofillCreditCardBubbleController>(
- web_contents());
-
- // Don't get stuck on the first run wallet interstitial.
- profile()->GetPrefs()->SetBoolean(::prefs::kAutofillDialogHasPaidWithWallet,
- true);
-
- SetUpControllerWithFormData(DefaultFormData());
+ Reset();
}
virtual void TearDown() OVERRIDE {
@@ -340,9 +340,11 @@
if (controller_)
controller_->ViewClosed();
- test_bubble_controller_ =
- new testing::NiceMock<TestAutofillCreditCardBubbleController>(
+ test_generated_bubble_controller_ =
+ new testing::NiceMock<TestGeneratedCreditCardBubbleController>(
web_contents());
+ mock_new_card_bubble_controller_.reset(
+ new MockNewCreditCardBubbleController);
// Don't get stuck on the first run wallet interstitial.
profile()->GetPrefs()->SetBoolean(::prefs::kAutofillDialogHasPaidWithWallet,
@@ -374,7 +376,8 @@
GURL(),
metric_logger_,
DIALOG_TYPE_REQUEST_AUTOCOMPLETE,
- callback))->AsWeakPtr();
+ callback,
+ mock_new_card_bubble_controller_.get()))->AsWeakPtr();
controller_->Init(profile());
controller_->Show();
controller_->OnUserNameFetchSuccess(kFakeEmail);
@@ -461,8 +464,12 @@
const FormStructure* form_structure() { return form_structure_; }
- TestAutofillCreditCardBubbleController* test_bubble_controller() {
- return test_bubble_controller_;
+ TestGeneratedCreditCardBubbleController* test_generated_bubble_controller() {
+ return test_generated_bubble_controller_;
+ }
+
+ const MockNewCreditCardBubbleController* mock_new_card_bubble_controller() {
+ return mock_new_card_bubble_controller_.get();
}
private:
@@ -489,7 +496,11 @@
// Used to monitor if the Autofill credit card bubble is shown. Owned by
// |web_contents()|.
- TestAutofillCreditCardBubbleController* test_bubble_controller_;
+ TestGeneratedCreditCardBubbleController* test_generated_bubble_controller_;
+
+ // Used to record when new card bubbles would show. Created in |Reset()|.
+ scoped_ptr<MockNewCreditCardBubbleController>
+ mock_new_card_bubble_controller_;
};
} // namespace
@@ -1488,10 +1499,12 @@
TEST_F(AutofillDialogControllerTest, EditAutofillProfile) {
SwitchToAutofill();
- EXPECT_CALL(*controller()->GetView(), ModelChanged()).Times(1);
+ EXPECT_CALL(*controller()->GetView(), ModelChanged()).Times(2);
AutofillProfile full_profile(test::GetVerifiedProfile());
+ CreditCard credit_card(test::GetVerifiedCreditCard());
controller()->GetTestingManager()->AddTestingProfile(&full_profile);
+ controller()->GetTestingManager()->AddTestingCreditCard(&credit_card);
controller()->EditClickedForSection(SECTION_SHIPPING);
DetailOutputMap outputs;
@@ -1521,6 +1534,7 @@
// Tests that adding an autofill profile and then submitting works.
TEST_F(AutofillDialogControllerTest, AddAutofillProfile) {
+ SwitchToAutofill();
EXPECT_CALL(*controller()->GetView(), ModelChanged()).Times(2);
AutofillProfile full_profile(test::GetVerifiedProfile());
@@ -1567,10 +1581,13 @@
// Makes sure that a newly added email address gets added to an existing profile
// (as opposed to creating its own profile). http://crbug.com/240926
TEST_F(AutofillDialogControllerTest, AddEmail) {
- EXPECT_CALL(*controller()->GetView(), ModelChanged()).Times(1);
+ SwitchToAutofill();
+ EXPECT_CALL(*controller()->GetView(), ModelChanged()).Times(2);
AutofillProfile full_profile(test::GetVerifiedProfile());
+ CreditCard credit_card(test::GetVerifiedCreditCard());
controller()->GetTestingManager()->AddTestingProfile(&full_profile);
+ controller()->GetTestingManager()->AddTestingCreditCard(&credit_card);
ui::MenuModel* model = controller()->MenuModelForSection(SECTION_EMAIL);
ASSERT_TRUE(model);
@@ -2078,6 +2095,7 @@
}
TEST_F(AutofillDialogControllerTest, SaveDetailsInChrome) {
+ SwitchToAutofill();
EXPECT_CALL(*controller()->GetView(), ModelChanged()).Times(2);
AutofillProfile full_profile(test::GetVerifiedProfile());
@@ -2392,27 +2410,25 @@
EXPECT_FALSE(ReadSetVisuallyDeemphasizedIpc());
}
-
TEST_F(AutofillDialogControllerTest, NewCardBubbleShown) {
- EXPECT_CALL(*test_bubble_controller(),
- ShowAsNewCardSavedBubble(ASCIIToUTF16("Visa - 1111"))).Times(1);
- EXPECT_CALL(*test_bubble_controller(),
- ShowAsGeneratedCardBubble(_, _)).Times(0);
+ EXPECT_CALL(*test_generated_bubble_controller(), SetupAndShow(_, _)).Times(0);
SwitchToAutofill();
FillCreditCardInputs();
controller()->OnAccept();
controller()->ViewClosed();
+
+ EXPECT_EQ(1, mock_new_card_bubble_controller()->bubbles_shown());
}
TEST_F(AutofillDialogControllerTest, GeneratedCardBubbleShown) {
- EXPECT_CALL(*test_bubble_controller(),
- ShowAsGeneratedCardBubble(_, _)).Times(1);
- EXPECT_CALL(*test_bubble_controller(), ShowAsNewCardSavedBubble(_)).Times(0);
+ EXPECT_CALL(*test_generated_bubble_controller(), SetupAndShow(_, _)).Times(1);
SubmitWithWalletItems(CompleteAndValidWalletItems());
controller()->OnDidGetFullWallet(wallet::GetTestFullWallet());
controller()->ViewClosed();
+
+ EXPECT_EQ(0, mock_new_card_bubble_controller()->bubbles_shown());
}
TEST_F(AutofillDialogControllerTest, ReloadWalletItemsOnActivation) {
@@ -2488,15 +2504,15 @@
}
TEST_F(AutofillDialogControllerTest, GeneratedCardBubbleNotShown) {
- EXPECT_CALL(*test_bubble_controller(),
- ShowAsGeneratedCardBubble(_, _)).Times(0);
- EXPECT_CALL(*test_bubble_controller(), ShowAsNewCardSavedBubble(_)).Times(0);
+ EXPECT_CALL(*test_generated_bubble_controller(), SetupAndShow(_, _)).Times(0);
SubmitWithWalletItems(CompleteAndValidWalletItems());
controller()->set_dialog_type(DIALOG_TYPE_AUTOCHECKOUT);
controller()->OnDidGetFullWallet(wallet::GetTestFullWallet());
controller()->OnAutocheckoutError();
controller()->ViewClosed();
+
+ EXPECT_EQ(0, mock_new_card_bubble_controller()->bubbles_shown());
}
} // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_models.cc b/chrome/browser/ui/autofill/autofill_dialog_models.cc
index f5c7849..297896e 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_models.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_models.cc
@@ -155,7 +155,9 @@
}
string16 MonthComboboxModel::GetItemAt(int index) {
- return index == 0 ? string16() : FormatMonth(index);
+ return index == 0 ?
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_MONTH) :
+ FormatMonth(index);
}
// YearComboboxModel -----------------------------------------------------------
@@ -175,10 +177,12 @@
}
string16 YearComboboxModel::GetItemAt(int index) {
- if (index == 0)
- return string16();
+ if (index == 0) {
+ return l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_YEAR);
+ }
return base::IntToString16(this_year_ + index - 1);
}
-} // autofill
+} // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_types.cc b/chrome/browser/ui/autofill/autofill_dialog_types.cc
index a10aa43..e326419 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_types.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_types.cc
@@ -247,73 +247,4 @@
DialogOverlayState::DialogOverlayState() {}
DialogOverlayState::~DialogOverlayState() {}
-AutofillMetrics::DialogUiEvent DialogSectionToUiEditEvent(
- DialogSection section) {
- switch (section) {
- case SECTION_EMAIL:
- return AutofillMetrics::DIALOG_UI_EMAIL_EDIT_UI_SHOWN;
-
- case SECTION_BILLING:
- return AutofillMetrics::DIALOG_UI_BILLING_EDIT_UI_SHOWN;
-
- case SECTION_CC_BILLING:
- return AutofillMetrics::DIALOG_UI_CC_BILLING_EDIT_UI_SHOWN;
-
- case SECTION_SHIPPING:
- return AutofillMetrics::DIALOG_UI_SHIPPING_EDIT_UI_SHOWN;
-
- case SECTION_CC:
- return AutofillMetrics::DIALOG_UI_CC_EDIT_UI_SHOWN;
- }
-
- NOTREACHED();
- return AutofillMetrics::NUM_DIALOG_UI_EVENTS;
-}
-
-AutofillMetrics::DialogUiEvent DialogSectionToUiItemAddedEvent(
- DialogSection section) {
- switch (section) {
- case SECTION_EMAIL:
- return AutofillMetrics::DIALOG_UI_EMAIL_ITEM_ADDED;
-
- case SECTION_BILLING:
- return AutofillMetrics::DIALOG_UI_BILLING_ITEM_ADDED;
-
- case SECTION_CC_BILLING:
- return AutofillMetrics::DIALOG_UI_CC_BILLING_ITEM_ADDED;
-
- case SECTION_SHIPPING:
- return AutofillMetrics::DIALOG_UI_SHIPPING_ITEM_ADDED;
-
- case SECTION_CC:
- return AutofillMetrics::DIALOG_UI_CC_ITEM_ADDED;
- }
-
- NOTREACHED();
- return AutofillMetrics::NUM_DIALOG_UI_EVENTS;
-}
-
-AutofillMetrics::DialogUiEvent DialogSectionToUiSelectionChangedEvent(
- DialogSection section) {
- switch (section) {
- case SECTION_EMAIL:
- return AutofillMetrics::DIALOG_UI_EMAIL_SELECTED_SUGGESTION_CHANGED;
-
- case SECTION_BILLING:
- return AutofillMetrics::DIALOG_UI_BILLING_SELECTED_SUGGESTION_CHANGED;
-
- case SECTION_CC_BILLING:
- return AutofillMetrics::DIALOG_UI_CC_BILLING_SELECTED_SUGGESTION_CHANGED;
-
- case SECTION_SHIPPING:
- return AutofillMetrics::DIALOG_UI_SHIPPING_SELECTED_SUGGESTION_CHANGED;
-
- case SECTION_CC:
- return AutofillMetrics::DIALOG_UI_CC_SELECTED_SUGGESTION_CHANGED;
- }
-
- NOTREACHED();
- return AutofillMetrics::NUM_DIALOG_UI_EVENTS;
-}
-
} // namespace autofill
diff --git a/chrome/browser/ui/autofill/autofill_dialog_types.h b/chrome/browser/ui/autofill/autofill_dialog_types.h
index c31b0d7..d40d90a 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_types.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_types.h
@@ -236,21 +236,6 @@
typedef std::map<ServerFieldType, string16> ValidityData;
-// Returns the AutofillMetrics::DIALOG_UI_*_EDIT_UI_SHOWN metric corresponding
-// to the |section|.
-AutofillMetrics::DialogUiEvent DialogSectionToUiEditEvent(
- DialogSection section);
-
-// Returns the AutofillMetrics::DIALOG_UI_*_ITEM_ADDED metric corresponding
-// to the |section|.
-AutofillMetrics::DialogUiEvent DialogSectionToUiItemAddedEvent(
- DialogSection section);
-
-// Returns the AutofillMetrics::DIALOG_UI_*_ITEM_ADDED metric corresponding
-// to the |section|.
-AutofillMetrics::DialogUiEvent DialogSectionToUiSelectionChangedEvent(
- DialogSection section);
-
} // namespace autofill
#endif // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_DIALOG_TYPES_H_
diff --git a/chrome/browser/ui/autofill/autofill_dialog_view.cc b/chrome/browser/ui/autofill/autofill_dialog_view.cc
index 4267180..10024d2 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_view.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_view.cc
@@ -12,7 +12,7 @@
AutofillDialogView::~AutofillDialogView() {}
-#if defined(TOOLKIT_GTK) || defined(OS_ANDROID)
+#if defined(TOOLKIT_GTK)
// TODO(estade): implement the dialog on GTK. See http://crbug.com/157275.
AutofillDialogView* AutofillDialogView::Create(
AutofillDialogViewDelegate* delegate) {
diff --git a/chrome/browser/ui/autofill/generated_credit_card_bubble_controller.cc b/chrome/browser/ui/autofill/generated_credit_card_bubble_controller.cc
new file mode 100644
index 0000000..1c8a170
--- /dev/null
+++ b/chrome/browser/ui/autofill/generated_credit_card_bubble_controller.cc
@@ -0,0 +1,258 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
+
+#include <climits>
+
+#include "base/logging.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/string_split.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_view.h"
+#include "chrome/browser/ui/autofill/tab_autofill_manager_delegate.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/omnibox/location_bar.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/pref_names.h"
+#include "components/user_prefs/pref_registry_syncable.h"
+#include "content/public/browser/navigation_details.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/web_contents.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(
+ autofill::GeneratedCreditCardBubbleController);
+
+namespace autofill {
+
+namespace {
+
+static const int kMaxGeneratedCardTimesToShow = INT_MAX;
+static const base::char16 kRangeSeparator = '|';
+static const char kWalletGeneratedCardLearnMoreLink[] =
+ "http://support.google.com/wallet/bin/answer.py?hl=en&answer=2740044";
+
+GeneratedCreditCardBubbleController* GetOrCreate(content::WebContents* wc) {
+ GeneratedCreditCardBubbleController::CreateForWebContents(wc);
+ return GeneratedCreditCardBubbleController::FromWebContents(wc);
+}
+
+} // namespace
+
+bool TextRange::operator==(const TextRange& other) const {
+ return other.range == range && other.is_link == is_link;
+}
+
+GeneratedCreditCardBubbleController::GeneratedCreditCardBubbleController(
+ content::WebContents* web_contents)
+ : WebContentsObserver(web_contents),
+ web_contents_(web_contents),
+ title_text_(l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_TITLE)),
+ should_show_anchor_(true),
+ weak_ptr_factory_(this) {}
+
+GeneratedCreditCardBubbleController::~GeneratedCreditCardBubbleController() {
+ // In the case that the tab is closed, the controller can be deleted while
+ // bubble is showing. Always calling |Hide()| ensures that the bubble closes.
+ Hide();
+}
+
+// static
+void GeneratedCreditCardBubbleController::RegisterUserPrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterIntegerPref(
+ ::prefs::kAutofillGeneratedCardBubbleTimesShown,
+ 0,
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+}
+
+// static
+void GeneratedCreditCardBubbleController::Show(
+ content::WebContents* contents,
+ const base::string16& fronting_card_name,
+ const base::string16& backing_card_name) {
+ GetOrCreate(contents)->SetupAndShow(fronting_card_name, backing_card_name);
+}
+
+void GeneratedCreditCardBubbleController::DidNavigateMainFrame(
+ const content::LoadCommittedDetails& details,
+ const content::FrameNavigateParams& params) {
+ if (details.entry &&
+ !content::PageTransitionIsRedirect(details.entry->GetTransitionType())) {
+ should_show_anchor_ = false;
+ UpdateAnchor();
+ web_contents()->RemoveUserData(UserDataKey());
+ // |this| is now deleted.
+ }
+}
+
+bool GeneratedCreditCardBubbleController::IsHiding() const {
+ return bubble_ && bubble_->IsHiding();
+}
+
+gfx::Image GeneratedCreditCardBubbleController::AnchorIcon() const {
+ if (!should_show_anchor_)
+ return gfx::Image();
+ return ui::ResourceBundle::GetSharedInstance().GetImageNamed(IDR_WALLET_ICON);
+}
+
+const base::string16& GeneratedCreditCardBubbleController::TitleText() const {
+ return title_text_;
+}
+
+const base::string16& GeneratedCreditCardBubbleController::ContentsText()
+ const {
+ return contents_text_;
+}
+
+const std::vector<TextRange>& GeneratedCreditCardBubbleController::
+ ContentsTextRanges() const {
+ return contents_text_ranges_;
+}
+
+void GeneratedCreditCardBubbleController::OnAnchorClicked() {
+ Show(true);
+}
+
+void GeneratedCreditCardBubbleController::OnLinkClicked() {
+ // Open a new tab to the Online Wallet help link.
+ chrome::NavigateParams params(
+ chrome::FindBrowserWithWebContents(web_contents()),
+ GURL(kWalletGeneratedCardLearnMoreLink),
+ content::PAGE_TRANSITION_AUTO_BOOKMARK);
+ params.disposition = NEW_FOREGROUND_TAB;
+ chrome::Navigate(¶ms);
+
+ Hide();
+}
+
+base::WeakPtr<GeneratedCreditCardBubbleController>
+ GeneratedCreditCardBubbleController::GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
+base::WeakPtr<GeneratedCreditCardBubbleView>
+ GeneratedCreditCardBubbleController::CreateBubble() {
+ return GeneratedCreditCardBubbleView::Create(GetWeakPtr());
+}
+
+base::WeakPtr<GeneratedCreditCardBubbleView>
+ GeneratedCreditCardBubbleController::bubble() {
+ return bubble_;
+}
+
+bool GeneratedCreditCardBubbleController::CanShow() const {
+ Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
+ return web_contents() == browser->tab_strip_model()->GetActiveWebContents();
+}
+
+bool GeneratedCreditCardBubbleController::ShouldDisplayBubbleInitially() const {
+ Profile* profile = Profile::FromBrowserContext(
+ web_contents_->GetBrowserContext());
+ int times_shown = profile->GetPrefs()->GetInteger(
+ ::prefs::kAutofillGeneratedCardBubbleTimesShown);
+ return times_shown < kMaxGeneratedCardTimesToShow;
+}
+
+void GeneratedCreditCardBubbleController::SetupAndShow(
+ const base::string16& fronting_card_name,
+ const base::string16& backing_card_name) {
+ DCHECK(!fronting_card_name.empty());
+ DCHECK(!backing_card_name.empty());
+
+ fronting_card_name_ = fronting_card_name;
+ backing_card_name_ = backing_card_name;
+
+ // Clear any generated state or from the last |SetupAndShow()| call.
+ contents_text_.clear();
+ contents_text_ranges_.clear();
+
+ base::string16 to_split = l10n_util::GetStringFUTF16(
+ IDS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_CONTENTS,
+ fronting_card_name_,
+ backing_card_name_);
+
+ // Split the full text on '|' to highlight certain parts. For example, "sly"
+ // and "jumped" would be bolded in "The |sly| fox |jumped| over the lazy dog".
+ std::vector<base::string16> pieces;
+ base::SplitStringDontTrim(to_split, kRangeSeparator, &pieces);
+
+ while (!pieces.empty()) {
+ base::string16 piece = pieces.front();
+
+ // Every second piece should be bolded. Because |base::SplitString*()|
+ // leaves an empty "" even if '|' is the first character, this is guaranteed
+ // to work for "|highlighting| starts here". Ignore empty pieces because
+ // there's nothing to highlight.
+ if (!piece.empty() && pieces.size() % 2 == 0) {
+ const size_t start = contents_text_.size();
+ TextRange bold_text;
+ bold_text.range = ui::Range(start, start + piece.size());
+ bold_text.is_link = false;
+ contents_text_ranges_.push_back(bold_text);
+ }
+
+ // Append the piece whether it's bolded or not and move on to the next one.
+ contents_text_.append(piece);
+ pieces.erase(pieces.begin(), pieces.begin() + 1);
+ }
+
+ // Add a "Learn more" link at the end of the header text if it's a generated
+ // card bubble.
+ base::string16 learn_more = l10n_util::GetStringUTF16(IDS_LEARN_MORE);
+ contents_text_.append(ASCIIToUTF16(" ") + learn_more);
+ const size_t header_size = contents_text_.size();
+ TextRange end_link;
+ end_link.range = ui::Range(header_size - learn_more.size(), header_size);
+ end_link.is_link = true;
+ contents_text_ranges_.push_back(end_link);
+
+ UpdateAnchor();
+
+ if (ShouldDisplayBubbleInitially())
+ Show(false);
+}
+
+void GeneratedCreditCardBubbleController::Show(bool was_anchor_click) {
+ if (!CanShow())
+ return;
+
+ bubble_ = CreateBubble();
+ if (!bubble_) {
+ // TODO(dbeam): Make a bubble on all applicable platforms.
+ return;
+ }
+
+ bubble_->Show();
+
+ if (!was_anchor_click) {
+ // If the bubble was an automatically created "you generated a card" bubble,
+ // count it as a show. If the user clicked the omnibox icon, don't count it.
+ PrefService* prefs = Profile::FromBrowserContext(
+ web_contents()->GetBrowserContext())->GetPrefs();
+ prefs->SetInteger(::prefs::kAutofillGeneratedCardBubbleTimesShown,
+ prefs->GetInteger(::prefs::kAutofillGeneratedCardBubbleTimesShown) + 1);
+ }
+}
+
+void GeneratedCreditCardBubbleController::UpdateAnchor() {
+ Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
+ if (browser && browser->window() && browser->window()->GetLocationBar())
+ browser->window()->GetLocationBar()->UpdateGeneratedCreditCardView();
+}
+
+void GeneratedCreditCardBubbleController::Hide() {
+ if (bubble_ && !bubble_->IsHiding())
+ bubble_->Hide();
+}
+
+} // namespace autofill
diff --git a/chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h b/chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h
new file mode 100644
index 0000000..0f6f638
--- /dev/null
+++ b/chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h
@@ -0,0 +1,169 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_CONTROLLER_H_
+#define CHROME_BROWSER_UI_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_CONTROLLER_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+#include "ui/base/range/range.h"
+#include "ui/gfx/image/image.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+namespace autofill {
+
+class GeneratedCreditCardBubbleView;
+
+// A simple struct of text highlighting range information. If |is_link| is true
+// this portion of the text should be clickable (and trigger |OnLinkClicked()|).
+// If |is_link| is false, the text denoted by |range| should be bolded.
+struct TextRange {
+ // The range of text this TextRange applies to (start and end).
+ ui::Range range;
+ // Whether this text range should be styled like a link (e.g. clickable).
+ bool is_link;
+ // An equality operator for testing.
+ bool operator==(const TextRange& other) const;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// GeneratedCreditCardBubbleController
+//
+// A class to control showing and hiding a bubble after a credit card is
+// generated.
+//
+////////////////////////////////////////////////////////////////////////////////
+class GeneratedCreditCardBubbleController
+ : public content::WebContentsObserver,
+ public content::WebContentsUserData<GeneratedCreditCardBubbleController> {
+ public:
+ virtual ~GeneratedCreditCardBubbleController();
+
+ // Registers preferences this class cares about.
+ static void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry);
+
+ // Show a bubble to educate the user about generated (fronting) cards and how
+ // they are used to bill their original (backing) card.
+ static void Show(content::WebContents* contents,
+ const base::string16& backing_card_name,
+ const base::string16& fronting_card_name);
+
+ // content::WebContentsObserver:
+ virtual void DidNavigateMainFrame(
+ const content::LoadCommittedDetails& details,
+ const content::FrameNavigateParams& params) OVERRIDE;
+
+ // Returns whether |bubble_| is currently in the process of hiding.
+ bool IsHiding() const;
+
+ // Returns the image that should be shown as an icon in the omnibox.
+ gfx::Image AnchorIcon() const;
+
+ // The title of the bubble.
+ const base::string16& TitleText() const;
+
+ // Text in the contents of the bubble.
+ const base::string16& ContentsText() const;
+
+ // Ranges of text styles in the bubble's main content.
+ const std::vector<TextRange>& ContentsTextRanges() const;
+
+ // Called when the anchor for this bubble is clicked. Shows a new bubble.
+ void OnAnchorClicked();
+
+ // Called when the link at the bottom of the bubble is clicked. Opens and
+ // navigates a new tab to an informational page and hides the bubble.
+ void OnLinkClicked();
+
+ // The web contents that successfully submitted the Autofill dialog (causing
+ // this bubble to show).
+ content::WebContents* web_contents() { return web_contents_; }
+ const content::WebContents* web_contents() const { return web_contents_; }
+
+ protected:
+ // Creates a bubble connected to |web_contents|.
+ explicit GeneratedCreditCardBubbleController(content::WebContents* contents);
+
+ // Returns a base::WeakPtr that references |this|. Exposed for testing.
+ base::WeakPtr<GeneratedCreditCardBubbleController> GetWeakPtr();
+
+ // Creates and returns an Autofill credit card bubble. Exposed for testing.
+ virtual base::WeakPtr<GeneratedCreditCardBubbleView> CreateBubble();
+
+ // Returns a weak reference to |bubble_|. May be invalid/NULL.
+ virtual base::WeakPtr<GeneratedCreditCardBubbleView> bubble();
+
+ // Returns whether the bubble can currently show itself.
+ virtual bool CanShow() const;
+
+ // Whether the generated card bubble should be shown initially when showing
+ // the anchor icon. This does not affect whether the generated card's icon
+ // will show in the omnibox.
+ bool ShouldDisplayBubbleInitially() const;
+
+ // Generates the correct bubble text and text highlighting ranges and shows a
+ // bubble to educate the user about generated (fronting) cards and how they
+ // are used to bill their original (backing) card. Exposed for testing.
+ virtual void SetupAndShow(const base::string16& backing_card_name,
+ const base::string16& fronting_card_name);
+
+ private:
+ friend class
+ content::WebContentsUserData<GeneratedCreditCardBubbleController>;
+
+ // An internal helper to show the bubble.
+ void Show(bool was_anchor_click);
+
+ // Updates the omnibox icon that |bubble_| is anchored to.
+ void UpdateAnchor();
+
+ // Hides |bubble_| (if it exists and isn't already hiding).
+ void Hide();
+
+ // The web contents associated with this bubble.
+ content::WebContents* const web_contents_;
+
+ // The generated credit card number and associated backing card.
+ base::string16 fronting_card_name_;
+ base::string16 backing_card_name_;
+
+ // The title text of the bubble.
+ const base::string16 title_text_;
+
+ // Strings and ranges generated based on |backing_card_name_| and
+ // |fronting_card_name_|.
+ base::string16 contents_text_;
+ std::vector<TextRange> contents_text_ranges_;
+
+ // A bubble view that's created by calling either |Show*()| method; owned by
+ // the native widget/hierarchy, not this class (though this class must outlive
+ // |bubble_|). NULL in many cases.
+ base::WeakPtr<GeneratedCreditCardBubbleView> bubble_;
+
+ // Whether the anchor should currently be showing.
+ bool should_show_anchor_;
+
+ // A weak pointer factory for |Create()|.
+ base::WeakPtrFactory<GeneratedCreditCardBubbleController> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeneratedCreditCardBubbleController);
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill/generated_credit_card_bubble_controller_unittest.cc b/chrome/browser/ui/autofill/generated_credit_card_bubble_controller_unittest.cc
new file mode 100644
index 0000000..206f354
--- /dev/null
+++ b/chrome/browser/ui/autofill/generated_credit_card_bubble_controller_unittest.cc
@@ -0,0 +1,214 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/autofill/core/browser/autofill_common_test.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/page_transition_types.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/web_contents_tester.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/range/range.h"
+
+#if defined(OS_WIN)
+#include "ui/base/win/scoped_ole_initializer.h"
+#endif
+
+namespace autofill {
+
+namespace {
+
+base::string16 BackingCard() {
+ return ASCIIToUTF16("Visa - 1111");
+}
+
+base::string16 FrontingCard() {
+ return ASCIIToUTF16("Mastercard - 4444");
+}
+
+base::string16 RangeOfString(const base::string16& string,
+ const ui::Range& range) {
+ return string.substr(range.start(), range.end() - range.start());
+}
+
+class TestGeneratedCreditCardBubbleController
+ : public GeneratedCreditCardBubbleController {
+ public:
+ explicit TestGeneratedCreditCardBubbleController(
+ content::WebContents* contents)
+ : GeneratedCreditCardBubbleController(contents) {
+ contents->SetUserData(UserDataKey(), this);
+ }
+
+ virtual ~TestGeneratedCreditCardBubbleController() {}
+
+ bool IsInstalled() const {
+ return web_contents()->GetUserData(UserDataKey()) == this;
+ }
+
+ TestGeneratedCreditCardBubbleView* GetTestingBubble() {
+ return static_cast<TestGeneratedCreditCardBubbleView*>(
+ GeneratedCreditCardBubbleController::bubble().get());
+ }
+
+ protected:
+ virtual base::WeakPtr<GeneratedCreditCardBubbleView> CreateBubble() OVERRIDE {
+ return TestGeneratedCreditCardBubbleView::Create(GetWeakPtr());
+ }
+
+ virtual bool CanShow() const OVERRIDE {
+ return true;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestGeneratedCreditCardBubbleController);
+};
+
+class GeneratedCreditCardBubbleControllerTest : public testing::Test {
+ public:
+ GeneratedCreditCardBubbleControllerTest()
+ : test_web_contents_(
+ content::WebContentsTester::CreateTestWebContents(
+ &profile_, NULL)) {}
+
+ virtual void SetUp() OVERRIDE {
+ // Attaches immediately to |test_web_contents_| so a test version will exist
+ // before a non-test version can be created.
+ new TestGeneratedCreditCardBubbleController(test_web_contents_.get());
+ ASSERT_TRUE(controller()->IsInstalled());
+ }
+
+ protected:
+ TestGeneratedCreditCardBubbleController* controller() {
+ return static_cast<TestGeneratedCreditCardBubbleController*>(
+ TestGeneratedCreditCardBubbleController::FromWebContents(
+ test_web_contents_.get()));
+ }
+
+ int GeneratedCardBubbleTimesShown() {
+ return profile_.GetPrefs()->GetInteger(
+ ::prefs::kAutofillGeneratedCardBubbleTimesShown);
+ }
+
+ void Show() {
+ ASSERT_TRUE(controller()->IsInstalled());
+ TestGeneratedCreditCardBubbleController::Show(test_web_contents_.get(),
+ BackingCard(),
+ FrontingCard());
+ }
+
+ void Navigate() {
+ NavigateWithTransition(content::PAGE_TRANSITION_LINK);
+ }
+
+ void Redirect() {
+ NavigateWithTransition(content::PAGE_TRANSITION_CLIENT_REDIRECT);
+ }
+
+ private:
+ void NavigateWithTransition(content::PageTransition trans) {
+ content::WebContentsTester::For(test_web_contents_.get())->TestDidNavigate(
+ test_web_contents_->GetRenderViewHost(), 1, GURL("about:blank"), trans);
+ }
+
+ content::TestBrowserThreadBundle thread_bundle_;
+#if defined(OS_WIN)
+ // Without this there will be drag and drop failures. http://crbug.com/227221
+ ui::ScopedOleInitializer ole_initializer_;
+#endif
+ TestingProfile profile_;
+ scoped_ptr<content::WebContents> test_web_contents_;
+};
+
+} // namespace
+
+TEST_F(GeneratedCreditCardBubbleControllerTest, GeneratedCardBubbleTimesShown) {
+ ASSERT_EQ(0, GeneratedCardBubbleTimesShown());
+
+ // Ensure that showing the generated card UI bumps the persistent count.
+ Show();
+ EXPECT_EQ(1, GeneratedCardBubbleTimesShown());
+ EXPECT_TRUE(controller()->GetTestingBubble()->showing());
+
+ Show();
+ Show();
+ EXPECT_EQ(3, GeneratedCardBubbleTimesShown());
+ EXPECT_TRUE(controller()->GetTestingBubble()->showing());
+}
+
+TEST_F(GeneratedCreditCardBubbleControllerTest, TitleText) {
+ Show();
+ EXPECT_FALSE(controller()->TitleText().empty());
+}
+
+TEST_F(GeneratedCreditCardBubbleControllerTest, ContentsText) {
+ // Ensure that while showing the generated card UI that the bubble's text
+ // contains "Visa - 1111" and "Mastercard - 4444".
+ Show();
+ base::string16 contents_text = controller()->ContentsText();
+ EXPECT_NE(base::string16::npos, contents_text.find(BackingCard()));
+ EXPECT_NE(base::string16::npos, contents_text.find(FrontingCard()));
+
+ // Make sure that |bubble_text_| is regenerated the same way in |Setup()|.
+ Show();
+ EXPECT_EQ(contents_text, controller()->ContentsText());
+}
+
+TEST_F(GeneratedCreditCardBubbleControllerTest, ContentsTextRanges) {
+ // Check that the highlighted ranges in the bubble's text are correct.
+ Show();
+ const base::string16& contents_text = controller()->ContentsText();
+ const std::vector<TextRange>& ranges = controller()->ContentsTextRanges();
+
+ ASSERT_EQ(3U, ranges.size());
+
+ EXPECT_EQ(BackingCard(), RangeOfString(contents_text, ranges[0].range));
+ EXPECT_FALSE(ranges[0].is_link);
+
+ EXPECT_EQ(FrontingCard(), RangeOfString(contents_text, ranges[1].range));
+ EXPECT_FALSE(ranges[1].is_link);
+
+ EXPECT_TRUE(ranges[2].is_link);
+
+ Show();
+ EXPECT_EQ(ranges, controller()->ContentsTextRanges());
+}
+
+TEST_F(GeneratedCreditCardBubbleControllerTest, AnchorIcon) {
+ Show();
+ EXPECT_FALSE(controller()->AnchorIcon().IsEmpty());
+}
+
+TEST_F(GeneratedCreditCardBubbleControllerTest, HideOnNavigate) {
+ // When a user navigates away from a page (or refreshes) normally, the bubble
+ // should be hidden.
+ EXPECT_FALSE(controller()->GetTestingBubble());
+ Show();
+ EXPECT_TRUE(controller()->GetTestingBubble()->showing());
+
+ Navigate();
+ EXPECT_FALSE(controller());
+}
+
+TEST_F(GeneratedCreditCardBubbleControllerTest, StayOnRedirect) {
+ // If a page redirects right after submitting, the bubble should remain.
+ EXPECT_FALSE(controller()->GetTestingBubble());
+ Show();
+ EXPECT_TRUE(controller()->GetTestingBubble()->showing());
+
+ Redirect();
+ EXPECT_TRUE(controller()->GetTestingBubble()->showing());
+}
+
+} // namespace autofill
diff --git a/chrome/browser/ui/autofill/generated_credit_card_bubble_view.cc b/chrome/browser/ui/autofill/generated_credit_card_bubble_view.cc
new file mode 100644
index 0000000..9044a1e
--- /dev/null
+++ b/chrome/browser/ui/autofill/generated_credit_card_bubble_view.cc
@@ -0,0 +1,24 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_view.h"
+
+namespace autofill {
+
+// static
+const int GeneratedCreditCardBubbleView::kContentsWidth = 350;
+
+GeneratedCreditCardBubbleView::~GeneratedCreditCardBubbleView() {}
+
+#if !defined(TOOLKIT_VIEWS)
+// static
+base::WeakPtr<GeneratedCreditCardBubbleView>
+ GeneratedCreditCardBubbleView::Create(
+ const base::WeakPtr<GeneratedCreditCardBubbleController>& controller) {
+ // TODO(dbeam): make a bubble on all applicable platforms.
+ return base::WeakPtr<GeneratedCreditCardBubbleView>();
+}
+#endif
+
+} // namespace autofill
diff --git a/chrome/browser/ui/autofill/generated_credit_card_bubble_view.h b/chrome/browser/ui/autofill/generated_credit_card_bubble_view.h
new file mode 100644
index 0000000..565495f
--- /dev/null
+++ b/chrome/browser/ui/autofill/generated_credit_card_bubble_view.h
@@ -0,0 +1,41 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_VIEW_H_
+#define CHROME_BROWSER_UI_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_VIEW_H_
+
+#include "base/memory/weak_ptr.h"
+
+namespace autofill {
+
+class GeneratedCreditCardBubbleController;
+
+// A cross-platform interface for a bubble shown to educate users after a credit
+// card number is generated. Anchored to an omnibox icon and shown either on
+// creation or when the anchor is clicked. Hidden when focus is lost.
+class GeneratedCreditCardBubbleView {
+ public:
+ // The preferred size of the bubble's contents.
+ static const int kContentsWidth;
+
+ virtual ~GeneratedCreditCardBubbleView();
+
+ // Visually reveals the bubble.
+ virtual void Show() = 0;
+
+ // Hides the bubble from view.
+ virtual void Hide() = 0;
+
+ // Returns whether the bubble is currently in the process of hiding itself.
+ virtual bool IsHiding() const = 0;
+
+ // Creates a bubble that's operated by |controller| and owns itself.
+ // |controller| may be invalid while the bubble is closing.
+ static base::WeakPtr<GeneratedCreditCardBubbleView> Create(
+ const base::WeakPtr<GeneratedCreditCardBubbleController>& controller);
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/autofill/mock_new_credit_card_bubble_controller.cc b/chrome/browser/ui/autofill/mock_new_credit_card_bubble_controller.cc
new file mode 100644
index 0000000..e2dfa87
--- /dev/null
+++ b/chrome/browser/ui/autofill/mock_new_credit_card_bubble_controller.cc
@@ -0,0 +1,30 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/autofill/mock_new_credit_card_bubble_controller.h"
+
+#include "base/logging.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+
+namespace autofill {
+
+MockNewCreditCardBubbleController::MockNewCreditCardBubbleController()
+ : bubbles_shown_(0) {}
+
+MockNewCreditCardBubbleController::~MockNewCreditCardBubbleController() {}
+
+void MockNewCreditCardBubbleController::Show(
+ scoped_ptr<CreditCard> new_card,
+ scoped_ptr<AutofillProfile> billing_profile) {
+ CHECK(new_card);
+ CHECK(billing_profile);
+
+ new_card_ = new_card.Pass();
+ billing_profile_ = billing_profile.Pass();
+
+ ++bubbles_shown_;
+}
+
+} // namespace autofill
diff --git a/chrome/browser/ui/autofill/mock_new_credit_card_bubble_controller.h b/chrome/browser/ui/autofill/mock_new_credit_card_bubble_controller.h
new file mode 100644
index 0000000..c3b7d9e
--- /dev/null
+++ b/chrome/browser/ui/autofill/mock_new_credit_card_bubble_controller.h
@@ -0,0 +1,44 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_AUTOFILL_MOCK_NEW_CREDIT_CARD_BUBBLE_CONTROLLER_H_
+#define CHROME_BROWSER_UI_AUTOFILL_MOCK_NEW_CREDIT_CARD_BUBBLE_CONTROLLER_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace autofill {
+
+class AutofillProfile;
+class CreditCard;
+
+class MockNewCreditCardBubbleController {
+ public:
+ MockNewCreditCardBubbleController();
+
+ ~MockNewCreditCardBubbleController();
+
+ void Show(scoped_ptr<CreditCard> new_card,
+ scoped_ptr<AutofillProfile> billing_profile);
+
+ const CreditCard* new_card() const { return new_card_.get(); }
+
+ const AutofillProfile* billing_profile() const {
+ return billing_profile_.get();
+ }
+
+ int bubbles_shown() const { return bubbles_shown_; }
+
+ private:
+ scoped_ptr<CreditCard> new_card_;
+ scoped_ptr<AutofillProfile> billing_profile_;
+
+ int bubbles_shown_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockNewCreditCardBubbleController);
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_AUTOFILL_MOCK_NEW_CREDIT_CARD_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill/new_credit_card_bubble_controller.cc b/chrome/browser/ui/autofill/new_credit_card_bubble_controller.cc
new file mode 100644
index 0000000..2fb5db3
--- /dev/null
+++ b/chrome/browser/ui/autofill/new_credit_card_bubble_controller.cc
@@ -0,0 +1,132 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/autofill/new_credit_card_bubble_controller.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/autofill/data_model_wrapper.h"
+#include "chrome/browser/ui/autofill/new_credit_card_bubble_view.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/chrome_pages.h"
+#include "chrome/browser/ui/host_desktop.h"
+#include "chrome/common/url_constants.h"
+#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/credit_card.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace autofill {
+
+namespace {
+
+static const int kMaxGeneratedCardTimesToShow = 5;
+static const char kWalletGeneratedCardLearnMoreLink[] =
+ "http://support.google.com/wallet/bin/answer.py?hl=en&answer=2740044";
+
+} // namespace
+
+CreditCardDescription::CreditCardDescription() {}
+CreditCardDescription::~CreditCardDescription() {}
+
+NewCreditCardBubbleController::~NewCreditCardBubbleController() {
+ Hide();
+}
+
+// static
+void NewCreditCardBubbleController::Show(
+ Profile* profile,
+ scoped_ptr<CreditCard> new_card,
+ scoped_ptr<AutofillProfile> billing_profile) {
+ (new NewCreditCardBubbleController(profile))->SetupAndShow(
+ new_card.Pass(),
+ billing_profile.Pass());
+}
+
+const base::string16& NewCreditCardBubbleController::TitleText() const {
+ return title_text_;
+}
+
+const CreditCardDescription& NewCreditCardBubbleController::CardDescription()
+ const {
+ return card_desc_;
+}
+
+const base::string16& NewCreditCardBubbleController::LinkText() const {
+ return link_text_;
+}
+
+void NewCreditCardBubbleController::OnBubbleDestroyed() {
+ delete this;
+}
+
+void NewCreditCardBubbleController::OnLinkClicked() {
+ Browser* browser = chrome::FindTabbedBrowser(profile_, false,
+ chrome::GetActiveDesktop());
+ if (browser)
+ chrome::ShowSettingsSubPage(browser, chrome::kAutofillSubPage);
+
+ Hide();
+}
+
+NewCreditCardBubbleController::NewCreditCardBubbleController(Profile* profile)
+ : profile_(profile),
+ title_text_(l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_TITLE)),
+ link_text_(l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_LINK)),
+ weak_ptr_factory_(this) {}
+
+base::WeakPtr<NewCreditCardBubbleView> NewCreditCardBubbleController::
+ CreateBubble() {
+ return NewCreditCardBubbleView::Create(this);
+}
+
+base::WeakPtr<NewCreditCardBubbleView> NewCreditCardBubbleController::
+ bubble() {
+ return bubble_;
+}
+
+void NewCreditCardBubbleController::SetupAndShow(
+ scoped_ptr<CreditCard> new_card,
+ scoped_ptr<AutofillProfile> billing_profile) {
+ DCHECK(new_card);
+ DCHECK(billing_profile);
+
+ new_card_ = new_card.Pass();
+ billing_profile_ = billing_profile.Pass();
+
+ const base::string16 card_number =
+ new_card_->GetRawInfo(CREDIT_CARD_NUMBER);
+ ui::ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ card_desc_.icon = rb.GetImageNamed(
+ CreditCard::IconResourceId(CreditCard::GetCreditCardType(card_number)));
+ card_desc_.name = new_card_->TypeAndLastFourDigits();
+
+ AutofillProfileWrapper wrapper(billing_profile_.get(), 0);
+ card_desc_.description = wrapper.GetDisplayText();
+
+ bubble_ = CreateBubble();
+ if (!bubble_) {
+ // TODO(dbeam): Make a bubble on all applicable platforms.
+ delete this;
+ return;
+ }
+
+ bubble_->Show();
+}
+
+void NewCreditCardBubbleController::Hide() {
+ if (bubble_)
+ bubble_->Hide();
+}
+
+} // namespace autofill
diff --git a/chrome/browser/ui/autofill/new_credit_card_bubble_controller.h b/chrome/browser/ui/autofill/new_credit_card_bubble_controller.h
new file mode 100644
index 0000000..2b7f6d9
--- /dev/null
+++ b/chrome/browser/ui/autofill/new_credit_card_bubble_controller.h
@@ -0,0 +1,132 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_CONTROLLER_H_
+#define CHROME_BROWSER_UI_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_CONTROLLER_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
+#include "ui/gfx/image/image.h"
+
+class Profile;
+
+namespace autofill {
+
+class NewCreditCardBubbleView;
+class AutofillProfile;
+class CreditCard;
+
+// A simple wrapper that contains descriptive information about a credit card
+// that should be shown in the content of the bubble.
+struct CreditCardDescription {
+ CreditCardDescription();
+ ~CreditCardDescription();
+ // The icon of the credit card issuer (i.e. Visa, Mastercard).
+ gfx::Image icon;
+ // The display name of the card. Shown next to the icon.
+ base::string16 name;
+ // A longer description of the card being shown in the bubble.
+ base::string16 description;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// NewCreditCardBubbleController
+//
+// A class to control showing/hiding a bubble after saved a new card in Chrome.
+// Here's a visual reference to what this bubble looks like:
+//
+// @----------------------------------------@
+// | Bubble title text |
+// | |
+// | [ Card icon ] Card name |
+// | Card description that will probably |
+// | also span multiple lines. |
+// | |
+// | Learn more link |
+// @----------------------------------------@
+//
+////////////////////////////////////////////////////////////////////////////////
+class NewCreditCardBubbleController {
+ public:
+ virtual ~NewCreditCardBubbleController();
+
+ // Show a bubble informing the user that new credit card data has been saved.
+ // This bubble points to the settings menu. Ownership of |new_card|
+ // and |billing_profile| are transferred by this call.
+ static void Show(Profile* profile,
+ scoped_ptr<CreditCard> new_card,
+ scoped_ptr<AutofillProfile> billing_profile);
+
+ // The bubble's title text.
+ const base::string16& TitleText() const;
+
+ // A card description to show in the bubble.
+ const CreditCardDescription& CardDescription() const;
+
+ // The text of the link shown at the bubble of the bubble.
+ const base::string16& LinkText() const;
+
+ // Called when |bubble_| is destroyed.
+ void OnBubbleDestroyed();
+
+ // Called when the link at the bottom of the bubble is clicked.
+ void OnLinkClicked();
+
+ // Returns the profile this bubble is associated with.
+ Profile* profile() { return profile_; }
+
+ protected:
+ // Create a bubble attached to |profile|.
+ explicit NewCreditCardBubbleController(Profile* profile);
+
+ // Creates and returns an Autofill credit card bubble. Exposed for testing.
+ virtual base::WeakPtr<NewCreditCardBubbleView> CreateBubble();
+
+ // Returns a weak reference to |bubble_|. May be invalid/NULL.
+ virtual base::WeakPtr<NewCreditCardBubbleView> bubble();
+
+ // Show a bubble notifying the user that new credit card data has been saved.
+ // Exposed for testing.
+ virtual void SetupAndShow(scoped_ptr<CreditCard> new_card,
+ scoped_ptr<AutofillProfile> billing_profile);
+
+ private:
+ // Hides |bubble_| if it exists.
+ void Hide();
+
+ // The profile this bubble is associated with.
+ Profile* const profile_;
+
+ // The newly saved credit card and assocated billing information.
+ scoped_ptr<CreditCard> new_card_;
+ scoped_ptr<AutofillProfile> billing_profile_;
+
+ // The title text of the bubble.
+ const base::string16 title_text_;
+
+ // The bubble's link text.
+ const base::string16 link_text_;
+
+ // Strings and descriptions that are generated based on |new_card_| and
+ // |billing_profile_|.
+ struct CreditCardDescription card_desc_;
+
+ // A bubble view that's created by calling either |Show*()| method; owned by
+ // the native widget/hierarchy, not this class (though this class must outlive
+ // |bubble_|). NULL in many cases.
+ base::WeakPtr<NewCreditCardBubbleView> bubble_;
+
+ // A weak pointer factory for |Create()|.
+ base::WeakPtrFactory<NewCreditCardBubbleController> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(NewCreditCardBubbleController);
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill/new_credit_card_bubble_view.cc b/chrome/browser/ui/autofill/new_credit_card_bubble_view.cc
new file mode 100644
index 0000000..2b86d4e
--- /dev/null
+++ b/chrome/browser/ui/autofill/new_credit_card_bubble_view.cc
@@ -0,0 +1,23 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/autofill/new_credit_card_bubble_view.h"
+
+namespace autofill {
+
+NewCreditCardBubbleView::~NewCreditCardBubbleView() {}
+
+// static
+const int NewCreditCardBubbleView::kContentsWidth = 400;
+
+#if !defined(TOOLKIT_VIEWS)
+// static
+base::WeakPtr<NewCreditCardBubbleView> NewCreditCardBubbleView::Create(
+ NewCreditCardBubbleController* controller) {
+ // TODO(dbeam): make a bubble on all applicable platforms.
+ return base::WeakPtr<NewCreditCardBubbleView>();
+}
+#endif
+
+} // namespace autofill
diff --git a/chrome/browser/ui/autofill/new_credit_card_bubble_view.h b/chrome/browser/ui/autofill/new_credit_card_bubble_view.h
new file mode 100644
index 0000000..e6ef8f8
--- /dev/null
+++ b/chrome/browser/ui/autofill/new_credit_card_bubble_view.h
@@ -0,0 +1,38 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_VIEW_H_
+#define CHROME_BROWSER_UI_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_VIEW_H_
+
+#include "base/memory/weak_ptr.h"
+
+namespace autofill {
+
+class NewCreditCardBubbleController;
+
+// A cross-platform interface for a bubble that is shown when a new credit card
+// is saved. Points at the settings menu in the toolbar and hides when
+// activation is lost.
+class NewCreditCardBubbleView {
+ public:
+ // The preferred width of the bubble's contents.
+ static const int kContentsWidth;
+
+ virtual ~NewCreditCardBubbleView();
+
+ // Visually reveals the bubble.
+ virtual void Show() = 0;
+
+ // Hides the bubble from view.
+ virtual void Hide() = 0;
+
+ // Creates a bubble that's operated by |controller| and owns itself.
+ // |controller| may be invalid while the bubble is closing.
+ static base::WeakPtr<NewCreditCardBubbleView> Create(
+ NewCreditCardBubbleController* controller);
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc
index cf4ab39..4b50949 100644
--- a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc
+++ b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.cc
@@ -13,7 +13,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/autofill/autocheckout_bubble.h"
#include "chrome/browser/ui/autofill/autocheckout_bubble_controller.h"
-#include "chrome/browser/ui/autofill/autofill_dialog_controller_impl.h"
+#include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
@@ -150,19 +150,19 @@
DialogType dialog_type,
const base::Callback<void(const FormStructure*,
const std::string&)>& callback) {
-#if defined(ENABLE_AUTOFILL_DIALOG)
HideRequestAutocompleteDialog();
- dialog_controller_ = AutofillDialogControllerImpl::Create(web_contents_,
- form,
- source_url,
- dialog_type,
- callback);
- dialog_controller_->Show();
-#else
- callback.Run(NULL, std::string());
- NOTIMPLEMENTED();
-#endif // #if !defined(ENABLE_AUTOFILL_DIALOG)
+ dialog_controller_ = AutofillDialogController::Create(web_contents_,
+ form,
+ source_url,
+ dialog_type,
+ callback);
+ if (dialog_controller_) {
+ dialog_controller_->Show();
+ } else {
+ callback.Run(NULL, std::string());
+ NOTIMPLEMENTED();
+ }
}
void TabAutofillManagerDelegate::ShowAutofillPopup(
@@ -246,7 +246,7 @@
bool was_redirect = details.entry &&
content::PageTransitionIsRedirect(details.entry->GetTransitionType());
- if (dialog_controller_->dialog_type() == DIALOG_TYPE_REQUEST_AUTOCOMPLETE ||
+ if (dialog_controller_->GetDialogType() == DIALOG_TYPE_REQUEST_AUTOCOMPLETE ||
(!was_redirect && !preserve_dialog)) {
HideRequestAutocompleteDialog();
}
diff --git a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h
index 40588b5..21d9a61 100644
--- a/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h
+++ b/chrome/browser/ui/autofill/tab_autofill_manager_delegate.h
@@ -25,7 +25,7 @@
namespace autofill {
class AutocheckoutBubble;
-class AutofillDialogControllerImpl;
+class AutofillDialogController;
class AutofillPopupControllerImpl;
struct FormData;
@@ -92,7 +92,7 @@
virtual void WasShown() OVERRIDE;
// Exposed for testing.
- AutofillDialogControllerImpl* GetDialogControllerForTesting() {
+ AutofillDialogController* GetDialogControllerForTesting() {
return dialog_controller_.get();
}
@@ -101,7 +101,7 @@
friend class content::WebContentsUserData<TabAutofillManagerDelegate>;
content::WebContents* const web_contents_;
- base::WeakPtr<AutofillDialogControllerImpl> dialog_controller_;
+ base::WeakPtr<AutofillDialogController> dialog_controller_;
base::WeakPtr<AutocheckoutBubble> autocheckout_bubble_;
base::WeakPtr<AutofillPopupControllerImpl> popup_controller_;
diff --git a/chrome/browser/ui/autofill/test_autofill_credit_card_bubble.cc b/chrome/browser/ui/autofill/test_autofill_credit_card_bubble.cc
deleted file mode 100644
index 237b969..0000000
--- a/chrome/browser/ui/autofill/test_autofill_credit_card_bubble.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/autofill/test_autofill_credit_card_bubble.h"
-
-namespace autofill {
-
-// static
-base::WeakPtr<TestAutofillCreditCardBubble>
- TestAutofillCreditCardBubble::Create(
- const base::WeakPtr<AutofillCreditCardBubbleController>& controller) {
- return (new TestAutofillCreditCardBubble(controller))->GetWeakPtr();
-}
-
-TestAutofillCreditCardBubble::~TestAutofillCreditCardBubble() {}
-
-void TestAutofillCreditCardBubble::Show() {
- showing_ = true;
-}
-
-void TestAutofillCreditCardBubble::Hide() {
- delete this;
-}
-
-bool TestAutofillCreditCardBubble::IsHiding() const {
- return !showing_;
-}
-
-base::WeakPtr<TestAutofillCreditCardBubble>
- TestAutofillCreditCardBubble::GetWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
-}
-
-TestAutofillCreditCardBubble::TestAutofillCreditCardBubble(
- const base::WeakPtr<AutofillCreditCardBubbleController>& controller)
- : showing_(false),
- weak_ptr_factory_(this) {}
-
-} // namespace autofill
diff --git a/chrome/browser/ui/autofill/test_autofill_credit_card_bubble.h b/chrome/browser/ui/autofill/test_autofill_credit_card_bubble.h
deleted file mode 100644
index 4eef7b7..0000000
--- a/chrome/browser/ui/autofill/test_autofill_credit_card_bubble.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_AUTOFILL_TEST_AUTOFILL_CREDIT_CARD_BUBBLE_H_
-#define CHROME_BROWSER_UI_AUTOFILL_TEST_AUTOFILL_CREDIT_CARD_BUBBLE_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble.h"
-
-namespace autofill {
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// TestAutofillCreditCardBubble
-//
-// A cross-platform, headless bubble that doesn't conflict with other top-level
-// widgets/windows.
-////////////////////////////////////////////////////////////////////////////////
-class TestAutofillCreditCardBubble : public AutofillCreditCardBubble {
- public:
- // Creates a bubble and returns a weak reference to it.
- static base::WeakPtr<TestAutofillCreditCardBubble> Create(
- const base::WeakPtr<AutofillCreditCardBubbleController>& controller);
-
- virtual ~TestAutofillCreditCardBubble();
-
- // AutofillCreditCardBubble:
- virtual void Show() OVERRIDE;
- virtual void Hide() OVERRIDE;
- virtual bool IsHiding() const OVERRIDE;
-
- base::WeakPtr<TestAutofillCreditCardBubble> GetWeakPtr();
-
- bool showing() const { return showing_; }
-
- private:
- explicit TestAutofillCreditCardBubble(
- const base::WeakPtr<AutofillCreditCardBubbleController>& controller);
-
- // Whether the bubble is currently showing or not.
- bool showing_;
-
- base::WeakPtrFactory<TestAutofillCreditCardBubble> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(TestAutofillCreditCardBubble);
-};
-
-} // namespace autofill
-
-#endif // CHROME_BROWSER_UI_AUTOFILL_TEST_AUTOFILL_CREDIT_CARD_BUBBLE_H_
diff --git a/chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.cc b/chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.cc
new file mode 100644
index 0000000..dd19c63
--- /dev/null
+++ b/chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.cc
@@ -0,0 +1,43 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.h"
+
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
+
+namespace autofill {
+
+// static
+base::WeakPtr<TestGeneratedCreditCardBubbleView>
+ TestGeneratedCreditCardBubbleView::Create(
+ const base::WeakPtr<GeneratedCreditCardBubbleController>& controller) {
+ return (new TestGeneratedCreditCardBubbleView(controller))->GetWeakPtr();
+}
+
+TestGeneratedCreditCardBubbleView::~TestGeneratedCreditCardBubbleView() {}
+
+void TestGeneratedCreditCardBubbleView::Show() {
+ showing_ = true;
+}
+
+void TestGeneratedCreditCardBubbleView::Hide() {
+ delete this;
+}
+
+bool TestGeneratedCreditCardBubbleView::IsHiding() const {
+ return !showing_;
+}
+
+base::WeakPtr<TestGeneratedCreditCardBubbleView>
+ TestGeneratedCreditCardBubbleView::GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
+TestGeneratedCreditCardBubbleView::TestGeneratedCreditCardBubbleView(
+ const base::WeakPtr<GeneratedCreditCardBubbleController>& controller)
+ : controller_(controller),
+ showing_(false),
+ weak_ptr_factory_(this) {}
+
+} // namespace autofill
diff --git a/chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.h b/chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.h
new file mode 100644
index 0000000..5892ff0
--- /dev/null
+++ b/chrome/browser/ui/autofill/test_generated_credit_card_bubble_view.h
@@ -0,0 +1,57 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_AUTOFILL_TEST_GENERATED_CREDIT_CARD_BUBBLE_VIEW_H_
+#define CHROME_BROWSER_UI_AUTOFILL_TEST_GENERATED_CREDIT_CARD_BUBBLE_VIEW_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_view.h"
+
+namespace autofill {
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// TestGeneratedCreditCardBubbleView
+//
+// A cross-platform, headless bubble that doesn't conflict with other top-level
+// widgets/windows.
+//
+////////////////////////////////////////////////////////////////////////////////
+class TestGeneratedCreditCardBubbleView : public GeneratedCreditCardBubbleView {
+ public:
+ // Creates a bubble and returns a weak reference to it.
+ static base::WeakPtr<TestGeneratedCreditCardBubbleView> Create(
+ const base::WeakPtr<GeneratedCreditCardBubbleController>& controller);
+
+ virtual ~TestGeneratedCreditCardBubbleView();
+
+ // GeneratedCreditCardBubbleView:
+ virtual void Show() OVERRIDE;
+ virtual void Hide() OVERRIDE;
+ virtual bool IsHiding() const OVERRIDE;
+
+ base::WeakPtr<TestGeneratedCreditCardBubbleView> GetWeakPtr();
+
+ bool showing() const { return showing_; }
+
+ private:
+ explicit TestGeneratedCreditCardBubbleView(
+ const base::WeakPtr<GeneratedCreditCardBubbleController>& controller);
+
+ // A weak reference to the controller that operates this bubble.
+ base::WeakPtr<GeneratedCreditCardBubbleController> controller_;
+
+ // Whether the bubble is currently showing or not.
+ bool showing_;
+
+ base::WeakPtrFactory<TestGeneratedCreditCardBubbleView> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestGeneratedCreditCardBubbleView);
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_AUTOFILL_TEST_GENERATED_CREDIT_CARD_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 54251d0..1424f7e 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -747,6 +747,13 @@
UpdateToolbar(false);
}
+void Browser::OnWebContentsInstantSupportDisabled(
+ const content::WebContents* web_contents) {
+ DCHECK(web_contents);
+ if (tab_strip_model_->GetActiveWebContents() == web_contents)
+ UpdateToolbar(false);
+}
+
///////////////////////////////////////////////////////////////////////////////
// Browser, Assorted browser commands:
@@ -1211,25 +1218,24 @@
return;
window_has_shown_ = true;
-// CurrentProcessInfo::CreationTime() is currently only implemented on Mac and
-// Windows.
-#if defined(OS_MACOSX) || defined(OS_WIN)
+// CurrentProcessInfo::CreationTime() is missing on some platforms.
+#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
// Measure the latency from startup till the first browser window becomes
// visible.
static bool is_first_browser_window = true;
if (is_first_browser_window &&
!startup_metric_utils::WasNonBrowserUIDisplayed()) {
is_first_browser_window = false;
- const base::Time* process_creation_time =
+ const base::Time process_creation_time =
base::CurrentProcessInfo::CreationTime();
- if (process_creation_time) {
+ if (!process_creation_time.is_null()) {
UMA_HISTOGRAM_LONG_TIMES(
"Startup.BrowserWindowDisplay",
- base::Time::Now() - *process_creation_time);
+ base::Time::Now() - process_creation_time);
}
}
-#endif // defined(OS_MACOSX) || defined(OS_WIN)
+#endif // defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_LINUX)
// Nothing to do for non-tabbed windows.
if (!is_type_tabbed())
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index 2093f48..22e7fb0 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -320,7 +320,7 @@
DownloadClosePreventionType OkToCloseWithInProgressDownloads(
int* num_downloads_blocking) const;
- // Tab adding/showing functions /////////////////////////////////////////////
+ // External state change handling ////////////////////////////////////////////
// Invoked when the fullscreen state of the window changes.
// BrowserWindow::EnterFullscreen invokes this after the window has become
@@ -330,6 +330,11 @@
// Invoked when visible SSL state (as defined by SSLStatus) changes.
void VisibleSSLStateChanged(content::WebContents* web_contents);
+ // Invoked when the |web_contents| no longer supports Instant. Refreshes the
+ // omnibox so it no longer shows search terms.
+ void OnWebContentsInstantSupportDisabled(
+ const content::WebContents* web_contents);
+
// Assorted browser commands ////////////////////////////////////////////////
// NOTE: Within each of the following sections, the IDs are ordered roughly by
diff --git a/chrome/browser/ui/browser_instant_controller.cc b/chrome/browser/ui/browser_instant_controller.cc
index 650da0d..2e6c12d 100644
--- a/chrome/browser/ui/browser_instant_controller.cc
+++ b/chrome/browser/ui/browser_instant_controller.cc
@@ -18,6 +18,7 @@
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/omnibox/location_bar.h"
+#include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
#include "chrome/browser/ui/omnibox/omnibox_view.h"
#include "chrome/browser/ui/search/instant_ntp.h"
#include "chrome/browser/ui/search/search_model.h"
@@ -30,6 +31,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_view.h"
using content::UserMetricsAction;
@@ -151,18 +153,42 @@
index);
}
-void BrowserInstantController::FocusOmnibox(bool caret_visibility) {
+void BrowserInstantController::FocusOmnibox(OmniboxFocusState state) {
OmniboxView* omnibox_view = browser_->window()->GetLocationBar()->
GetLocationEntry();
- omnibox_view->SetFocus();
- omnibox_view->model()->SetCaretVisibility(caret_visibility);
- if (!caret_visibility) {
- // If the user clicked on the fakebox, any text already in the omnibox
- // should get cleared when they start typing. Selecting all the existing
- // text is a convenient way to accomplish this. It also gives a slight
- // visual cue to users who really understand selection state about what will
- // happen if they start typing.
- omnibox_view->SelectAll(false);
+
+ // Do not add a default case in the switch block for the following reasons:
+ // (1) Explicitly handle the new states. If new states are added in the
+ // OmniboxFocusState, the compiler will warn the developer to handle the new
+ // states.
+ // (2) An attacker may control the renderer and sends the browser process a
+ // malformed IPC. This function responds to the invalid |state| values by
+ // doing nothing instead of crashing the browser process (intentional no-op).
+ switch (state) {
+ case OMNIBOX_FOCUS_VISIBLE:
+ omnibox_view->SetFocus();
+ omnibox_view->model()->SetCaretVisibility(true);
+ break;
+ case OMNIBOX_FOCUS_INVISIBLE:
+ omnibox_view->SetFocus();
+ omnibox_view->model()->SetCaretVisibility(false);
+ // If the user clicked on the fakebox, any text already in the omnibox
+ // should get cleared when they start typing. Selecting all the existing
+ // text is a convenient way to accomplish this. It also gives a slight
+ // visual cue to users who really understand selection state about what
+ // will happen if they start typing.
+ omnibox_view->SelectAll(false);
+ break;
+ case OMNIBOX_FOCUS_NONE:
+ // Remove focus only if the popup is closed. This will prevent someone
+ // from changing the omnibox value and closing the popup without user
+ // interaction.
+ if (!omnibox_view->model()->popup_model()->IsOpen()) {
+ content::WebContents* contents = GetActiveWebContents();
+ if (contents)
+ contents->GetView()->Focus();
+ }
+ break;
}
}
@@ -189,6 +215,27 @@
false));
}
+void BrowserInstantController::PasteIntoOmnibox(const string16& text) {
+ OmniboxView* omnibox_view = browser_->window()->GetLocationBar()->
+ GetLocationEntry();
+ // The first case is for right click to paste, where the text is retrieved
+ // from the clipboard already sanitized. The second case is needed to handle
+ // drag-and-drop value and it has to be sanitazed before setting it into the
+ // omnibox.
+ string16 text_to_paste = text.empty() ?
+ omnibox_view->GetClipboardText() :
+ omnibox_view->SanitizeTextForPaste(text);
+
+ if (!text_to_paste.empty()) {
+ if (!omnibox_view->model()->has_focus())
+ omnibox_view->SetFocus();
+ omnibox_view->OnBeforePossibleChange();
+ omnibox_view->model()->on_paste();
+ omnibox_view->SetUserText(text_to_paste);
+ omnibox_view->OnAfterPossibleChange();
+ }
+}
+
void BrowserInstantController::SetOmniboxBounds(const gfx::Rect& bounds) {
instant_.SetOmniboxBounds(bounds);
}
diff --git a/chrome/browser/ui/browser_instant_controller.h b/chrome/browser/ui/browser_instant_controller.h
index 0d99aaa..8ddcb48 100644
--- a/chrome/browser/ui/browser_instant_controller.h
+++ b/chrome/browser/ui/browser_instant_controller.h
@@ -55,9 +55,8 @@
// this BrowserInstantController.
InstantController* instant() { return &instant_; }
- // Invoked by |instant_| to give the omnibox focus, with the option of making
- // the caret invisible.
- void FocusOmnibox(bool caret_visibility);
+ // Invoked by |instant_| to change the omnibox focus.
+ void FocusOmnibox(OmniboxFocusState state);
// Invoked by |instant_| to get the currently active tab.
content::WebContents* GetActiveWebContents() const;
@@ -73,6 +72,11 @@
content::PageTransition transition,
WindowOpenDisposition disposition);
+ // Invoked by |instant_| to paste the |text| (or clipboard content if text is
+ // empty) into the omnibox. It will set focus to the omnibox if the omnibox is
+ // not focused.
+ void PasteIntoOmnibox(const string16& text);
+
// Sets the stored omnibox bounds.
void SetOmniboxBounds(const gfx::Rect& bounds);
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc
index a9caa99..34d9b6b 100644
--- a/chrome/browser/ui/chrome_pages.cc
+++ b/chrome/browser/ui/chrome_pages.cc
@@ -147,6 +147,12 @@
ShowSingletonTab(browser, GURL(kChromeUIPolicyURL));
}
+void ShowSlow(Browser* browser) {
+#if defined(OS_CHROMEOS)
+ ShowSingletonTab(browser, GURL(kChromeUISlowURL));
+#endif
+}
+
void ShowSettings(Browser* browser) {
content::RecordAction(UserMetricsAction("ShowOptions"));
ShowSettingsSubPage(browser, std::string());
diff --git a/chrome/browser/ui/chrome_pages.h b/chrome/browser/ui/chrome_pages.h
index d4174fa..792fb6d 100644
--- a/chrome/browser/ui/chrome_pages.h
+++ b/chrome/browser/ui/chrome_pages.h
@@ -45,6 +45,7 @@
void ShowHelp(Browser* browser, HelpSource source);
void ShowPolicy(Browser* browser);
+void ShowSlow(Browser* browser);
// Various things that open in a settings UI.
void ShowSettings(Browser* browser);
diff --git a/chrome/browser/ui/cocoa/OWNERS b/chrome/browser/ui/cocoa/OWNERS
index 1ced4d8..75b56c8 100644
--- a/chrome/browser/ui/cocoa/OWNERS
+++ b/chrome/browser/ui/cocoa/OWNERS
@@ -1,6 +1,5 @@
asvitkine@chromium.org
avi@chromium.org
-isherman@chromium.org
jeremy@chromium.org
mark@chromium.org
rohitrao@chromium.org
diff --git a/chrome/browser/ui/cocoa/autofill/OWNERS b/chrome/browser/ui/cocoa/autofill/OWNERS
new file mode 100644
index 0000000..c539e57
--- /dev/null
+++ b/chrome/browser/ui/cocoa/autofill/OWNERS
@@ -0,0 +1,2 @@
+groby@chromium.org
+isherman@chromium.org
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_section_container_unittest.mm b/chrome/browser/ui/cocoa/autofill/autofill_section_container_unittest.mm
index a9aea29..6b79aa2 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_section_container_unittest.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_section_container_unittest.mm
@@ -78,27 +78,38 @@
using namespace testing;
const DetailInput kTestInputs[] = {
- { 2, CREDIT_CARD_EXP_MONTH }
+ { 2, CREDIT_CARD_EXP_MONTH },
+ { 3, CREDIT_CARD_EXP_4_DIGIT_YEAR }
};
DetailInputs inputs;
inputs.push_back(kTestInputs[0]);
+ inputs.push_back(kTestInputs[1]);
- autofill::MonthComboboxModel comboModel;
+ autofill::MonthComboboxModel monthComboModel;
+ autofill::YearComboboxModel yearComboModel;
EXPECT_CALL(delegate_, RequestedFieldsForSection(section_))
.WillOnce(ReturnRef(inputs));
EXPECT_CALL(delegate_, ComboboxModelForAutofillType(CREDIT_CARD_EXP_MONTH))
- .WillRepeatedly(Return(&comboModel));
+ .WillRepeatedly(Return(&monthComboModel));
+ EXPECT_CALL(
+ delegate_, ComboboxModelForAutofillType(CREDIT_CARD_EXP_4_DIGIT_YEAR))
+ .WillRepeatedly(Return(&yearComboModel));
ResetContainer();
NSPopUpButton* popup = base::mac::ObjCCastStrict<NSPopUpButton>(
[container_ getField:CREDIT_CARD_EXP_MONTH]);
EXPECT_EQ(13, [popup numberOfItems]);
- EXPECT_NSEQ(@"", [popup itemTitleAtIndex:0]);
+ EXPECT_NSEQ(@"Month", [popup itemTitleAtIndex:0]);
EXPECT_NSEQ(@"01", [popup itemTitleAtIndex:1]);
EXPECT_NSEQ(@"02", [popup itemTitleAtIndex:2]);
EXPECT_NSEQ(@"03", [popup itemTitleAtIndex:3]);
EXPECT_NSEQ(@"12", [popup itemTitleAtIndex:12]);
+
+ NSPopUpButton* yearPopup = base::mac::ObjCCastStrict<NSPopUpButton>(
+ [container_ getField:CREDIT_CARD_EXP_4_DIGIT_YEAR]);
+ EXPECT_EQ(11, [yearPopup numberOfItems]);
+ EXPECT_NSEQ(@"Year", [yearPopup itemTitleAtIndex:0]);
};
TEST_F(AutofillSectionContainerTest, OutputMatchesDefinition) {
diff --git a/chrome/browser/ui/cocoa/browser/avatar_button_controller.h b/chrome/browser/ui/cocoa/browser/avatar_button_controller.h
index f61ccad..54b9849 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_button_controller.h
+++ b/chrome/browser/ui/cocoa/browser/avatar_button_controller.h
@@ -10,6 +10,7 @@
#import "base/mac/scoped_nsobject.h"
#include "base/memory/scoped_ptr.h"
+@class AvatarLabelButton;
@class AvatarMenuBubbleController;
class Browser;
@@ -17,10 +18,6 @@
class Observer;
}
-namespace ui {
-class ThemeProvider;
-}
-
// This view controller manages the button/image that sits in the top of the
// window frame when using multi-profiles. It shows the current profile's
// avatar, or, when in Incognito, the spy dude. With multi-profiles, clicking
@@ -38,8 +35,8 @@
// The avatar button.
base::scoped_nsobject<NSButton> button_;
- // The managed user avatar label. Only used for managed user profiles.
- base::scoped_nsobject<NSButton> labelButton_;
+ // The managed user avatar label button. Only used for managed user profiles.
+ base::scoped_nsobject<AvatarLabelButton> labelButton_;
}
// The avatar button view.
diff --git a/chrome/browser/ui/cocoa/browser/avatar_button_controller.mm b/chrome/browser/ui/cocoa/browser/avatar_button_controller.mm
index 471b64d..6c37962 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_button_controller.mm
+++ b/chrome/browser/ui/cocoa/browser/avatar_button_controller.mm
@@ -14,11 +14,10 @@
#include "chrome/browser/profiles/profile_info_util.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_metrics.h"
-#include "chrome/browser/themes/theme_properties.h"
-#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_window.h"
+#import "chrome/browser/ui/cocoa/browser/avatar_label_button.h"
#import "chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.h"
#import "chrome/browser/ui/cocoa/browser_window_controller.h"
#include "content/public/browser/notification_service.h"
@@ -31,9 +30,21 @@
namespace {
-// Space between the avatar icon and the managed user avatar label.
+// Space between the avatar icon and the avatar menu bubble.
+const CGFloat kMenuYOffsetAdjust = 1.0;
+
+// Space between the avatar label and the left edge of the container containing
+// the label and the icon.
const CGFloat kAvatarSpacing = 4;
+// Space between the bottom of the avatar icon and the bottom of the avatar
+// label.
+const CGFloat kAvatarLabelBottomSpacing = 3;
+
+// Space between the right edge of the avatar label and the right edge of the
+// avatar icon.
+const CGFloat kAvatarLabelRightSpacing = 2;
+
} // namespace
@interface AvatarButtonController (Private)
@@ -83,12 +94,6 @@
} // namespace AvatarButtonControllerInternal
-namespace {
-
-const CGFloat kMenuYOffsetAdjust = 1.0;
-
-} // namespace
-
////////////////////////////////////////////////////////////////////////////////
@implementation AvatarButtonController
@@ -136,8 +141,6 @@
l10n_util::GetNSString(IDS_PROFILES_BUBBLE_ACCESSIBLE_DESCRIPTION)
forAttribute:NSAccessibilityDescriptionAttribute];
- [[self view] addSubview:button_];
-
Profile* profile = browser_->profile();
if (profile->IsOffTheRecord()) {
ResourceBundle& bundle = ResourceBundle::GetSharedInstance();
@@ -152,32 +155,26 @@
// Managed users cannot enter incognito mode, so we only need to check
// it in this code path.
if (profile->IsManaged()) {
- labelButton_.reset([[NSButton alloc] initWithFrame:NSZeroRect]);
- [labelButton_ setButtonType:NSMomentaryLightButton];
- [labelButton_ setBezelStyle:NSRecessedBezelStyle];
- [labelButton_ setTitle:
- l10n_util::GetNSString(IDS_MANAGED_USER_AVATAR_LABEL)];
- [labelButton_ setShowsBorderOnlyWhileMouseInside:YES];
-
+ // Initialize the avatar label button.
+ CGFloat extraWidth =
+ profiles::kAvatarIconWidth + kAvatarLabelRightSpacing;
+ NSRect frame = NSMakeRect(
+ kAvatarSpacing, kAvatarLabelBottomSpacing, extraWidth, 0);
+ labelButton_.reset([[AvatarLabelButton alloc] initWithFrame:frame]);
[labelButton_ setTarget:self];
[labelButton_ setAction:@selector(buttonClicked:)];
-
- [labelButton_ sizeToFit];
- [labelButton_ setFrameOrigin:
- NSMakePoint(kAvatarSpacing,
- (profiles::kAvatarIconHeight -
- NSHeight([labelButton_ frame])) / 2)];
[[self view] addSubview:labelButton_];
- // Reposition the avatar button and resize the container.
- CGFloat avatarButtonXOffset =
- NSWidth([labelButton_ frame]) + 2 * kAvatarSpacing;
+ // Resize the container and reposition the avatar button.
+ NSSize textSize = [[labelButton_ cell] labelTextSize];
[container setFrameSize:
- NSMakeSize(avatarButtonXOffset + NSWidth([button_ frame]),
+ NSMakeSize([labelButton_ frame].size.width + kAvatarSpacing,
profiles::kAvatarIconHeight)];
- [button_ setFrameOrigin:NSMakePoint(avatarButtonXOffset, 0)];
+ [button_
+ setFrameOrigin:NSMakePoint(kAvatarSpacing + textSize.width, 0)];
}
}
+ [[self view] addSubview:button_];
}
return self;
}
@@ -241,7 +238,7 @@
- (IBAction)buttonClicked:(id)sender {
DCHECK(sender == button_.get() || sender == labelButton_.get());
- [self showAvatarBubble:sender];
+ [self showAvatarBubble:button_];
}
- (void)bubbleWillClose:(NSNotification*)notif {
@@ -282,7 +279,7 @@
[destination unlockFocus];
- return [destination.release() autorelease];
+ return destination.autorelease();
}
// Updates the avatar information from the profile cache.
diff --git a/chrome/browser/ui/cocoa/browser/avatar_label_button.h b/chrome/browser/ui/cocoa/browser/avatar_label_button.h
new file mode 100644
index 0000000..6244c27
--- /dev/null
+++ b/chrome/browser/ui/cocoa/browser/avatar_label_button.h
@@ -0,0 +1,24 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_AVATAR_LABEL_BUTTON_H_
+#define CHROME_BROWSER_UI_COCOA_AVATAR_LABEL_BUTTON_H_
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/nine_part_button_cell.h"
+
+@interface AvatarLabelButton : NSButton
+@end
+
+// Draws the button cell for the avatar label.
+@interface AvatarLabelButtonCell : NinePartButtonCell
+
+// Returns the size of the label text (including boundaries).
+- (NSSize)labelTextSize;
+
+@end
+
+#endif // CHROME_BROWSER_UI_COCOA_AVATAR_LABEL_BUTTON_H_
diff --git a/chrome/browser/ui/cocoa/browser/avatar_label_button.mm b/chrome/browser/ui/cocoa/browser/avatar_label_button.mm
new file mode 100644
index 0000000..a37d011
--- /dev/null
+++ b/chrome/browser/ui/cocoa/browser/avatar_label_button.mm
@@ -0,0 +1,144 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/browser/avatar_label_button.h"
+
+#include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/ui/cocoa/themed_window.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/theme_provider.h"
+
+namespace {
+
+// Space between the left edge of the label background and the left edge of the
+// label text.
+const CGFloat kLabelTextLeftSpacing = 10;
+
+// Space between the right edge of the label text and the avatar icon.
+const CGFloat kLabelTextRightSpacing = 4;
+
+// Space between the top edge of the label background and the top edge of the
+// label text.
+const CGFloat kLabelTextTopSpacing = 3;
+
+// Space between the bottom edge of the label background and the bottom edge of
+// the label text.
+const CGFloat kLabelTextBottomSpacing = 4;
+
+} // namespace
+
+@implementation AvatarLabelButton
+
+- (id)initWithFrame:(NSRect)frameRect {
+ if ((self = [super initWithFrame:frameRect])) {
+ // Increase the frame by the size of the label to be displayed.
+ NSSize textSize = [[self cell] labelTextSize];
+ frameRect.size = NSMakeSize(frameRect.size.width + textSize.width,
+ frameRect.size.height + textSize.height);
+ [self setFrame:frameRect];
+ }
+ return self;
+}
+
++ (Class)cellClass {
+ return [AvatarLabelButtonCell class];
+}
+
+@end
+
+@implementation AvatarLabelButtonCell
+
+- (id)init {
+ const int resourceIds[9] = {
+ IDR_MANAGED_USER_LABEL_TOP_LEFT, IDR_MANAGED_USER_LABEL_TOP,
+ IDR_MANAGED_USER_LABEL_TOP_RIGHT, IDR_MANAGED_USER_LABEL_LEFT,
+ IDR_MANAGED_USER_LABEL_CENTER, IDR_MANAGED_USER_LABEL_RIGHT,
+ IDR_MANAGED_USER_LABEL_BOTTOM_LEFT, IDR_MANAGED_USER_LABEL_BOTTOM,
+ IDR_MANAGED_USER_LABEL_BOTTOM_RIGHT
+ };
+ if ((self = [super initWithResourceIds:resourceIds])) {
+ NSString* title = l10n_util::GetNSString(IDS_MANAGED_USER_AVATAR_LABEL);
+ [self accessibilitySetOverrideValue:title
+ forAttribute:NSAccessibilityTitleAttribute];
+ [self setTitle:title];
+ [self setFont:[NSFont labelFontOfSize:12.0]];
+ }
+ return self;
+}
+
+- (NSSize)labelTextSize {
+ NSSize size = [[self attributedTitle] size];
+ size.width += kLabelTextLeftSpacing + kLabelTextRightSpacing;
+ size.height += kLabelTextTopSpacing + kLabelTextBottomSpacing;
+ return size;
+}
+
+- (NSRect)titleRectForBounds:(NSRect)theRect {
+ theRect.origin = NSMakePoint(kLabelTextLeftSpacing, kLabelTextBottomSpacing);
+ theRect.size = [[self attributedTitle] size];
+ return theRect;
+}
+
+- (NSRect)drawTitle:(NSAttributedString*)title
+ withFrame:(NSRect)frame
+ inView:(NSView*)controlView {
+ base::scoped_nsobject<NSMutableAttributedString> themedTitle(
+ [[NSMutableAttributedString alloc] initWithAttributedString:title]);
+ ui::ThemeProvider* themeProvider = [[controlView window] themeProvider];
+ if (themeProvider) {
+ NSColor* textColor = themeProvider->GetNSColor(
+ ThemeProperties::COLOR_MANAGED_USER_LABEL);
+ [themedTitle addAttribute:NSForegroundColorAttributeName
+ value:textColor
+ range:NSMakeRange(0, title.length)];
+ }
+ [themedTitle drawInRect:frame];
+ return frame;
+}
+
+- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
+ ui::ThemeProvider* themeProvider = [[controlView window] themeProvider];
+ if (themeProvider) {
+ // Draw the label button background using the color provided by
+ // |themeProvider|. First paint the border.
+ NSColor* borderColor = themeProvider->GetNSColor(
+ ThemeProperties::COLOR_MANAGED_USER_LABEL_BORDER);
+ if ([self isHighlighted]) {
+ borderColor = [borderColor blendedColorWithFraction:0.5
+ ofColor:[NSColor blackColor]];
+ }
+ NSSize frameSize = cellFrame.size;
+ NSRect backgroundRect;
+ backgroundRect.origin = NSMakePoint(1, 1);
+ backgroundRect.size = NSMakeSize(frameSize.width - 2, frameSize.height - 2);
+ NSBezierPath* path =
+ [NSBezierPath bezierPathWithRoundedRect:backgroundRect
+ xRadius:2.0
+ yRadius:2.0];
+ [borderColor set];
+ [path fill];
+
+ // Now paint the background.
+ NSColor* backgroundColor = themeProvider->GetNSColor(
+ ThemeProperties::COLOR_MANAGED_USER_LABEL_BACKGROUND);
+ if ([self isHighlighted]) {
+ backgroundColor =
+ [backgroundColor blendedColorWithFraction:0.5
+ ofColor:[NSColor blackColor]];
+ }
+ backgroundRect.origin = NSMakePoint(2, 2);
+ backgroundRect.size = NSMakeSize(frameSize.width - 4, frameSize.height - 4);
+ path = [NSBezierPath bezierPathWithRoundedRect:backgroundRect
+ xRadius:2.0
+ yRadius:2.0];
+ [backgroundColor set];
+ [path fill];
+ }
+ [super drawInteriorWithFrame:cellFrame inView:controlView];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/browser/avatar_label_button_unittest.mm b/chrome/browser/ui/cocoa/browser/avatar_label_button_unittest.mm
new file mode 100644
index 0000000..c080fb3
--- /dev/null
+++ b/chrome/browser/ui/cocoa/browser/avatar_label_button_unittest.mm
@@ -0,0 +1,32 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/mac/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/browser/avatar_label_button.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#include "grit/theme_resources.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class AvatarLabelButtonTest : public CocoaTest {
+ public:
+ AvatarLabelButtonTest() {
+ NSRect content_frame = [[test_window() contentView] frame];
+ button_.reset([[AvatarLabelButton alloc] initWithFrame:content_frame]);
+ [[test_window() contentView] addSubview:button_];
+ }
+
+ protected:
+ base::scoped_nsobject<AvatarLabelButton> button_;
+};
+
+TEST_VIEW(AvatarLabelButtonTest, button_)
+
+TEST_F(AvatarLabelButtonTest, TestHighlight) {
+ EXPECT_FALSE([[button_ cell] isHighlighted]);
+ [button_ display];
+ [[button_ cell] setHighlighted:YES];
+ [button_ display];
+}
diff --git a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm
index 74d1890..7900efe 100644
--- a/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm
+++ b/chrome/browser/ui/cocoa/content_settings/content_setting_bubble_cocoa.mm
@@ -70,6 +70,18 @@
// The minimum width of the media menu buttons.
const CGFloat kMinMediaMenuButtonWidth = 100;
+// Height of each of the labels in the MIDI bubble.
+const int kMIDISysExLabelHeight = 14;
+
+// Height of the "Clear" button in the MIDI bubble.
+const int kMIDISysExClearButtonHeight = 17;
+
+// General padding between elements in the MIDI bubble.
+const int kMIDISysExPadding = 8;
+
+// Padding between host names in the MIDI bubble.
+const int kMIDISysExHostPadding = 4;
+
void SetControlSize(NSControl* control, NSControlSize controlSize) {
CGFloat fontSize = [NSFont systemFontSizeForControlSize:controlSize];
NSCell* cell = [control cell];
@@ -171,11 +183,13 @@
- (void)initializePopupList;
- (void)initializeGeoLists;
- (void)initializeMediaMenus;
+- (void)initializeMIDISysExLists;
- (void)sizeToFitLoadButton;
- (void)initManageDoneButtons;
- (void)removeInfoButton;
- (void)popupLinkClicked:(id)sender;
- (void)clearGeolocationForCurrentHost:(id)sender;
+- (void)clearMIDISysExForCurrentHost:(id)sender;
@end
@implementation ContentSettingBubbleController
@@ -221,6 +235,8 @@
nibPath = @"ContentBlockedMedia"; break;
case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
nibPath = @"ContentBlockedDownloads"; break;
+ case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
+ nibPath = @"ContentBlockedMIDISysEx"; break;
// These content types have no bubble:
case CONTENT_SETTINGS_TYPE_DEFAULT:
case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
@@ -229,7 +245,6 @@
case CONTENT_SETTINGS_TYPE_MOUSELOCK:
case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
- case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
case CONTENT_SETTINGS_NUM_TYPES:
NOTREACHED();
}
@@ -449,14 +464,10 @@
frame.origin.y = NSMaxY([control frame]) + kGeoPadding;
}
- typedef
- std::vector<ContentSettingBubbleModel::DomainList>::const_reverse_iterator
- GeolocationGroupIterator;
- for (GeolocationGroupIterator i = content.domain_lists.rbegin();
+ for (auto i = content.domain_lists.rbegin();
i != content.domain_lists.rend(); ++i) {
// Add all hosts in the current domain list.
- for (std::set<std::string>::const_reverse_iterator j = i->hosts.rbegin();
- j != i->hosts.rend(); ++j) {
+ for (auto j = i->hosts.rbegin(); j != i->hosts.rend(); ++j) {
NSTextField* title = LabelWithFrame(base::SysUTF8ToNSString(*j), frame);
SetControlSize(title, NSSmallControlSize);
[contentsContainer_ addSubview:title];
@@ -579,6 +590,88 @@
}
}
+- (void)initializeMIDISysExLists {
+ const ContentSettingBubbleModel::BubbleContent& content =
+ contentSettingBubbleModel_->bubble_content();
+ NSRect containerFrame = [contentsContainer_ frame];
+ NSRect frame =
+ NSMakeRect(0, 0, NSWidth(containerFrame), kMIDISysExLabelHeight);
+
+ // "Clear" button / text field.
+ if (!content.custom_link.empty()) {
+ base::scoped_nsobject<NSControl> control;
+ if (content.custom_link_enabled) {
+ NSRect buttonFrame = NSMakeRect(0, 0,
+ NSWidth(containerFrame),
+ kMIDISysExClearButtonHeight);
+ NSButton* button = [[NSButton alloc] initWithFrame:buttonFrame];
+ control.reset(button);
+ [button setTitle:base::SysUTF8ToNSString(content.custom_link)];
+ [button setTarget:self];
+ [button setAction:@selector(clearMIDISysExForCurrentHost:)];
+ [button setBezelStyle:NSRoundRectBezelStyle];
+ SetControlSize(button, NSSmallControlSize);
+ [button sizeToFit];
+ } else {
+ // Add the notification that settings will be cleared on next reload.
+ control.reset([LabelWithFrame(
+ base::SysUTF8ToNSString(content.custom_link), frame) retain]);
+ SetControlSize(control.get(), NSSmallControlSize);
+ }
+
+ // If the new control is wider than the container, widen the window.
+ CGFloat controlWidth = NSWidth([control frame]);
+ if (controlWidth > NSWidth(containerFrame)) {
+ NSRect windowFrame = [[self window] frame];
+ windowFrame.size.width += controlWidth - NSWidth(containerFrame);
+ [[self window] setFrame:windowFrame display:NO];
+ // Fetch the updated sizes.
+ containerFrame = [contentsContainer_ frame];
+ frame = NSMakeRect(0, 0, NSWidth(containerFrame), kMIDISysExLabelHeight);
+ }
+
+ DCHECK(control);
+ [contentsContainer_ addSubview:control];
+ frame.origin.y = NSMaxY([control frame]) + kMIDISysExPadding;
+ }
+
+ for (auto i = content.domain_lists.rbegin();
+ i != content.domain_lists.rend(); ++i) {
+ // Add all hosts in the current domain list.
+ for (auto j = i->hosts.rbegin(); j != i->hosts.rend(); ++j) {
+ NSTextField* title = LabelWithFrame(base::SysUTF8ToNSString(*j), frame);
+ SetControlSize(title, NSSmallControlSize);
+ [contentsContainer_ addSubview:title];
+
+ frame.origin.y = NSMaxY(frame) + kMIDISysExHostPadding +
+ [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:title];
+ }
+ if (!i->hosts.empty())
+ frame.origin.y += kMIDISysExPadding - kMIDISysExHostPadding;
+
+ // Add the domain list's title.
+ NSTextField* title =
+ LabelWithFrame(base::SysUTF8ToNSString(i->title), frame);
+ SetControlSize(title, NSSmallControlSize);
+ [contentsContainer_ addSubview:title];
+
+ frame.origin.y = NSMaxY(frame) + kMIDISysExPadding +
+ [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:title];
+ }
+
+ CGFloat containerHeight = frame.origin.y;
+ // Undo last padding.
+ if (!content.domain_lists.empty())
+ containerHeight -= kMIDISysExPadding;
+
+ // Resize container to fit its subviews, and window to fit the container.
+ NSRect windowFrame = [[self window] frame];
+ windowFrame.size.height += containerHeight - NSHeight(containerFrame);
+ [[self window] setFrame:windowFrame display:NO];
+ containerFrame.size.height = containerHeight;
+ [contentsContainer_ setFrame:containerFrame];
+}
+
- (void)sizeToFitLoadButton {
const ContentSettingBubbleModel::BubbleContent& content =
contentSettingBubbleModel_->bubble_content();
@@ -640,6 +733,8 @@
[self initializeGeoLists];
if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM)
[self initializeMediaMenus];
+ if (type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX)
+ [self initializeMIDISysExLists];
}
///////////////////////////////////////////////////////////////////////////////
@@ -661,6 +756,11 @@
[self close];
}
+- (void)clearMIDISysExForCurrentHost:(id)sender {
+ contentSettingBubbleModel_->OnCustomLinkClicked();
+ [self close];
+}
+
- (IBAction)showMoreInfo:(id)sender {
contentSettingBubbleModel_->OnCustomLinkClicked();
[self close];
diff --git a/chrome/browser/ui/cocoa/dev_tools_controller.h b/chrome/browser/ui/cocoa/dev_tools_controller.h
index cfb12c6..8684e9c 100644
--- a/chrome/browser/ui/cocoa/dev_tools_controller.h
+++ b/chrome/browser/ui/cocoa/dev_tools_controller.h
@@ -10,6 +10,7 @@
#include "base/mac/scoped_nsobject.h"
#include "chrome/browser/devtools/devtools_window.h"
+@class FocusTracker;
@class GraySplitView;
class Profile;
@@ -30,6 +31,8 @@
// Docked devtools window instance. NULL when current tab is not inspected
// or is inspected with undocked version of DevToolsWindow.
DevToolsWindow* devToolsWindow_;
+
+ base::scoped_nsobject<FocusTracker> focusTracker_;
}
- (id)init;
diff --git a/chrome/browser/ui/cocoa/dev_tools_controller.mm b/chrome/browser/ui/cocoa/dev_tools_controller.mm
index d9e5b77..4c90907 100644
--- a/chrome/browser/ui/cocoa/dev_tools_controller.mm
+++ b/chrome/browser/ui/cocoa/dev_tools_controller.mm
@@ -15,6 +15,7 @@
#include "chrome/common/pref_names.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
+#include "ui/base/cocoa/focus_tracker.h"
using content::WebContents;
@@ -119,6 +120,8 @@
NSArray* subviews = [splitView_ subviews];
DCHECK_EQ([subviews count], 1u);
WebContents* devToolsContents = devToolsWindow_->web_contents();
+ focusTracker_.reset(
+ [[FocusTracker alloc] initWithWindow:[splitView_ window]]);
// |devToolsView| is a TabContentsViewCocoa object, whose ViewID was
// set to VIEW_ID_TAB_CONTAINER initially, so we need to change it to
@@ -138,6 +141,8 @@
NSView* oldDevToolsContentsView = [subviews objectAtIndex:1];
[oldDevToolsContentsView removeFromSuperview];
[splitView_ adjustSubviews];
+ [focusTracker_ restoreFocusInWindow:[splitView_ window]];
+ focusTracker_.reset();
}
- (void)updateDevToolsSplitPosition {
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_controller.mm b/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
index be8355b..687da1b 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
+++ b/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
@@ -7,7 +7,7 @@
#include "base/mac/bundle_locations.h"
#include "base/mac/mac_util.h"
#include "base/strings/sys_string_conversions.h"
-#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/download_stats.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/themes/theme_service_factory.h"
@@ -243,7 +243,7 @@
if (item->GetState() == DownloadItem::IN_PROGRESS)
++numInProgress;
}
- download_util::RecordShelfClose(
+ RecordDownloadShelfClose(
[downloadItemControllers_ count], numInProgress, !isUserAction);
}
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
index d682305..44d3ac0 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
+++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
@@ -63,7 +63,7 @@
virtual void UpdatePageActions() OVERRIDE;
virtual void InvalidatePageActions() OVERRIDE;
virtual void UpdateOpenPDFInReaderPrompt() OVERRIDE;
- virtual void UpdateAutofillCreditCardView() OVERRIDE;
+ virtual void UpdateGeneratedCreditCardView() OVERRIDE;
virtual void SaveStateToContents(content::WebContents* contents) OVERRIDE;
virtual void Revert() OVERRIDE;
virtual const OmniboxView* GetLocationEntry() const OVERRIDE;
@@ -153,7 +153,6 @@
virtual string16 GetTitle() const OVERRIDE;
virtual InstantController* GetInstant() OVERRIDE;
virtual content::WebContents* GetWebContents() const OVERRIDE;
- virtual gfx::Rect GetOmniboxBounds() const OVERRIDE;
NSImage* GetKeywordImage(const string16& keyword);
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
index ec510a6..b28c4aa 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
+++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
@@ -218,7 +218,7 @@
// Not implemented on Mac.
}
-void LocationBarViewMac::UpdateAutofillCreditCardView() {
+void LocationBarViewMac::UpdateGeneratedCreditCardView() {
// TODO(dbeam): encourage groby@ to implement via prodding or chocolate.
NOTIMPLEMENTED();
}
@@ -357,10 +357,6 @@
return browser_->tab_strip_model()->GetActiveWebContents();
}
-gfx::Rect LocationBarViewMac::GetOmniboxBounds() const {
- return gfx::Rect(NSRectToCGRect([field_ frame]));
-}
-
PageActionDecoration* LocationBarViewMac::GetPageActionDecoration(
ExtensionAction* page_action) {
DCHECK(page_action);
diff --git a/chrome/browser/ui/cocoa/nine_part_button_cell.h b/chrome/browser/ui/cocoa/nine_part_button_cell.h
new file mode 100644
index 0000000..493c698
--- /dev/null
+++ b/chrome/browser/ui/cocoa/nine_part_button_cell.h
@@ -0,0 +1,31 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_COCOA_NINE_PART_BUTTON_CELL_H_
+#define CHROME_BROWSER_UI_COCOA_NINE_PART_BUTTON_CELL_H_
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/scoped_nsobject.h"
+
+// Handles painting of a button using images from a ResourceBundle. The
+// constructor expects an array of 9 image resource ids. The images
+// corresponding to the resource ids are assigned to a 3 by 3 grid in row major
+// order, i.e.
+// _________________
+// |_id0_|_id1_|_id2_|
+// |_id3_|_id4_|_id5_|
+// |_id6_|_id7_|_id8_|
+@interface NinePartButtonCell : NSButtonCell {
+ @private
+ base::scoped_nsobject<NSMutableArray> images_;
+}
+
+// Loads the images from the ResourceBundle using the provided image resource
+// ids and sets the image of the cell.
+- (id)initWithResourceIds:(const int[9])ids;
+
+@end // @interface NinePartButtonCell
+
+#endif // CHROME_BROWSER_UI_COCOA_NINE_PART_BUTTON_CELL_H_
diff --git a/chrome/browser/ui/cocoa/nine_part_button_cell.mm b/chrome/browser/ui/cocoa/nine_part_button_cell.mm
new file mode 100644
index 0000000..e156232
--- /dev/null
+++ b/chrome/browser/ui/cocoa/nine_part_button_cell.mm
@@ -0,0 +1,125 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "chrome/browser/ui/cocoa/nine_part_button_cell.h"
+
+#include <algorithm>
+
+#include "ui/base/resource/resource_bundle.h"
+
+@implementation NinePartButtonCell
+
+- (id)initWithResourceIds:(const int[9])ids {
+ if ((self = [super initImageCell:nil])) {
+ images_.reset([[NSMutableArray alloc] initWithCapacity:9]);
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ for (NSInteger i = 0; i < 9; ++i)
+ [images_ addObject:rb.GetNativeImageNamed(ids[i]).ToNSImage()];
+ [self setBezeled:YES];
+ [self setBezelStyle:NSSmallSquareBezelStyle];
+ }
+ return self;
+}
+
+- (void)drawBezelWithFrame:(NSRect)frame inView:(NSView*)controlView {
+ NSSize targetSize = frame.size;
+
+ // Retrieve the sizes of the images (except the size of the center image,
+ // which will be scaled anyway).
+ NSSize topLeft = [[images_ objectAtIndex:0] size];
+ NSSize top = [[images_ objectAtIndex:1] size];
+ NSSize topRight = [[images_ objectAtIndex:2] size];
+ NSSize left = [[images_ objectAtIndex:3] size];
+ NSSize right = [[images_ objectAtIndex:5] size];
+ NSSize bottomLeft = [[images_ objectAtIndex:6] size];
+ NSSize bottom = [[images_ objectAtIndex:7] size];
+ NSSize bottomRight = [[images_ objectAtIndex:8] size];
+
+ // Determine the minimum width of images on the left side.
+ CGFloat minLeftWidth =
+ std::min(topLeft.width, std::min(left.width, bottomLeft.width));
+ // Determine the minimum width of images on the right side.
+ CGFloat minRightWidth =
+ std::min(topRight.width, std::min(right.width, bottomRight.width));
+ // Determine the minimum height of images on the top side.
+ CGFloat minTopHeight =
+ std::min(topLeft.height, std::min(top.height, topRight.height));
+ // Determine the minimum height of images on the bottom side.
+ CGFloat minBottomHeight =
+ std::min(bottomLeft.height, std::min(bottom.height, bottomRight.height));
+
+ // Now paint the center image and extend it in all directions to the edges of
+ // images with the smallest height/width.
+ NSSize centerSize =
+ NSMakeSize(targetSize.width - minLeftWidth - minRightWidth,
+ targetSize.height - minTopHeight - minBottomHeight);
+ NSRect centerRect = NSMakeRect(
+ minLeftWidth, minBottomHeight, centerSize.width, centerSize.height);
+ [[images_ objectAtIndex:4] drawInRect:centerRect
+ fromRect:NSZeroRect
+ operation:NSCompositeSourceOver
+ fraction:1.0];
+
+ // Paint the corner images next.
+ NSRect topLeftRect = NSMakeRect(
+ 0, targetSize.height - topLeft.height, topLeft.width, topLeft.height);
+ [[images_ objectAtIndex:0] drawInRect:topLeftRect
+ fromRect:NSZeroRect
+ operation:NSCompositeSourceOver
+ fraction:1.0];
+ NSRect topRightRect = NSMakeRect(targetSize.width - topRight.width,
+ targetSize.height - topRight.height,
+ topRight.width,
+ topRight.height);
+ [[images_ objectAtIndex:2] drawInRect:topRightRect
+ fromRect:NSZeroRect
+ operation:NSCompositeSourceOver
+ fraction:1.0];
+ NSRect bottomLeftRect = NSMakeRect(
+ 0, 0, bottomLeft.width, bottomLeft.height);
+ [[images_ objectAtIndex:6] drawInRect:bottomLeftRect
+ fromRect:NSZeroRect
+ operation:NSCompositeSourceOver
+ fraction:1.0];
+ NSRect bottomRightRect = NSMakeRect(targetSize.width - bottomRight.width,
+ 0,
+ bottomRight.width,
+ bottomRight.height);
+ [[images_ objectAtIndex:8] drawInRect:bottomRightRect
+ fromRect:NSZeroRect
+ operation:NSCompositeSourceOver
+ fraction:1.0];
+
+ // Now paint the remaining images.
+ NSRect topRect = NSMakeRect(minLeftWidth,
+ targetSize.height - top.height,
+ centerSize.width,
+ top.height);
+ [[images_ objectAtIndex:1] drawInRect:topRect
+ fromRect:NSZeroRect
+ operation:NSCompositeSourceOver
+ fraction:1.0];
+ NSRect leftRect =
+ NSMakeRect(0, minBottomHeight, left.width, centerSize.height);
+ [[images_ objectAtIndex:3] drawInRect:leftRect
+ fromRect:NSZeroRect
+ operation:NSCompositeSourceOver
+ fraction:1.0];
+ NSRect rightRect = NSMakeRect(targetSize.width - minRightWidth,
+ minBottomHeight,
+ right.width,
+ centerSize.height);
+ [[images_ objectAtIndex:5] drawInRect:rightRect
+ fromRect:NSZeroRect
+ operation:NSCompositeSourceOver
+ fraction:1.0];
+ NSRect bottomRect =
+ NSMakeRect(minLeftWidth, 0, centerSize.width, bottom.height);
+ [[images_ objectAtIndex:7] drawInRect:bottomRect
+ fromRect:NSZeroRect
+ operation:NSCompositeSourceOver
+ fraction:1.0];
+}
+
+@end
diff --git a/chrome/browser/ui/cocoa/nine_part_button_cell_unittest.mm b/chrome/browser/ui/cocoa/nine_part_button_cell_unittest.mm
new file mode 100644
index 0000000..e44da40
--- /dev/null
+++ b/chrome/browser/ui/cocoa/nine_part_button_cell_unittest.mm
@@ -0,0 +1,35 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/mac/scoped_nsobject.h"
+#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
+#import "chrome/browser/ui/cocoa/nine_part_button_cell.h"
+#include "grit/theme_resources.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class NinePartButtonCellTest : public CocoaTest {
+ public:
+ NinePartButtonCellTest() {
+ const int resourceIds[9] = {
+ IDR_MANAGED_USER_LABEL_TOP_LEFT, IDR_MANAGED_USER_LABEL_TOP,
+ IDR_MANAGED_USER_LABEL_TOP_RIGHT, IDR_MANAGED_USER_LABEL_LEFT,
+ IDR_MANAGED_USER_LABEL_CENTER, IDR_MANAGED_USER_LABEL_RIGHT,
+ IDR_MANAGED_USER_LABEL_BOTTOM_LEFT, IDR_MANAGED_USER_LABEL_BOTTOM,
+ IDR_MANAGED_USER_LABEL_BOTTOM_RIGHT
+ };
+ NSRect content_frame = [[test_window() contentView] frame];
+ button_.reset([[NSButton alloc] initWithFrame:content_frame]);
+ base::scoped_nsobject<NinePartButtonCell> cell(
+ [[NinePartButtonCell alloc] initWithResourceIds:resourceIds]);
+ [button_ setCell:cell.get()];
+ [[test_window() contentView] addSubview:button_];
+ }
+
+ protected:
+ base::scoped_nsobject<NSButton> button_;
+};
+
+TEST_VIEW(NinePartButtonCellTest, button_)
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
index e011276..cac4fc7 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
@@ -16,7 +16,6 @@
#include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
#include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
#include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
-#include "chrome/browser/ui/omnibox/omnibox_popup_non_view.h"
#include "chrome/common/autocomplete_match_type.h"
#include "grit/theme_resources.h"
#include "skia/ext/skia_utils_mac.h"
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm
index de9f42a..0749f66 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm
@@ -13,7 +13,6 @@
#include "chrome/browser/ui/toolbar/toolbar_model_impl.h"
#include "testing/platform_test.h"
#include "ui/gfx/image/image.h"
-#include "ui/gfx/rect.h"
namespace {
@@ -98,7 +97,6 @@
virtual content::WebContents* GetWebContents() const OVERRIDE {
return NULL;
}
- virtual gfx::Rect GetOmniboxBounds() const OVERRIDE { return gfx::Rect(); }
private:
DISALLOW_COPY_AND_ASSIGN(TestingOmniboxEditController);
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
index 63e06d9..98d0091 100644
--- a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
+++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
@@ -163,6 +163,7 @@
{CONTENT_SETTINGS_TYPE_MEDIASTREAM, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK},
{CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK},
{CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOADS_LINK},
+ {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK},
};
set_manage_link(l10n_util::GetStringUTF8(
GetIdForContentType(kLinkIDs, arraysize(kLinkIDs), content_type())));
@@ -1162,6 +1163,93 @@
}
}
+// TODO(toyoshim): Should share as many code with geolocation as possible.
+class ContentSettingMIDISysExBubbleModel
+ : public ContentSettingTitleAndLinkModel {
+ public:
+ ContentSettingMIDISysExBubbleModel(Delegate* delegate,
+ WebContents* web_contents,
+ Profile* profile,
+ ContentSettingsType content_type);
+ virtual ~ContentSettingMIDISysExBubbleModel() {}
+
+ private:
+ void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
+ void SetDomainsAndCustomLink();
+ virtual void OnCustomLinkClicked() OVERRIDE;
+};
+
+ContentSettingMIDISysExBubbleModel::ContentSettingMIDISysExBubbleModel(
+ Delegate* delegate,
+ WebContents* web_contents,
+ Profile* profile,
+ ContentSettingsType content_type)
+ : ContentSettingTitleAndLinkModel(
+ delegate, web_contents, profile, content_type) {
+ DCHECK_EQ(CONTENT_SETTINGS_TYPE_MIDI_SYSEX, content_type);
+ SetDomainsAndCustomLink();
+}
+
+void ContentSettingMIDISysExBubbleModel::MaybeAddDomainList(
+ const std::set<std::string>& hosts, int title_id) {
+ if (!hosts.empty()) {
+ DomainList domain_list;
+ domain_list.title = l10n_util::GetStringUTF8(title_id);
+ domain_list.hosts = hosts;
+ add_domain_list(domain_list);
+ }
+}
+
+void ContentSettingMIDISysExBubbleModel::SetDomainsAndCustomLink() {
+ TabSpecificContentSettings* content_settings =
+ TabSpecificContentSettings::FromWebContents(web_contents());
+ const ContentSettingsUsagesState& usages_state =
+ content_settings->midi_usages_state();
+ ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
+ unsigned int tab_state_flags = 0;
+ usages_state.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
+ // Divide the tab's current MIDI sysex users into sets according to their
+ // permission state.
+ MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
+ IDS_MIDI_SYSEX_BUBBLE_ALLOWED);
+
+ MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
+ IDS_MIDI_SYSEX_BUBBLE_DENIED);
+
+ if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
+ set_custom_link(l10n_util::GetStringUTF8(
+ IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK));
+ set_custom_link_enabled(true);
+ } else if (tab_state_flags &
+ ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
+ set_custom_link(l10n_util::GetStringUTF8(
+ IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
+ }
+}
+
+void ContentSettingMIDISysExBubbleModel::OnCustomLinkClicked() {
+ if (!web_contents())
+ return;
+ // Reset this embedder's entry to default for each of the requesting
+ // origins currently on the page.
+ TabSpecificContentSettings* content_settings =
+ TabSpecificContentSettings::FromWebContents(web_contents());
+ const ContentSettingsUsagesState::StateMap& state_map =
+ content_settings->midi_usages_state().state_map();
+ HostContentSettingsMap* settings_map =
+ profile()->GetHostContentSettingsMap();
+
+ for (ContentSettingsUsagesState::StateMap::const_iterator it =
+ state_map.begin(); it != state_map.end(); ++it) {
+ settings_map->SetContentSetting(
+ ContentSettingsPattern::FromURLNoWildcard(it->first),
+ ContentSettingsPattern::Wildcard(),
+ CONTENT_SETTINGS_TYPE_MIDI_SYSEX,
+ std::string(),
+ CONTENT_SETTING_DEFAULT);
+ }
+}
+
// static
ContentSettingBubbleModel*
ContentSettingBubbleModel::CreateContentSettingBubbleModel(
@@ -1199,6 +1287,10 @@
return new ContentSettingRPHBubbleModel(delegate, web_contents, profile,
registry, content_type);
}
+ if (content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
+ return new ContentSettingMIDISysExBubbleModel(delegate, web_contents,
+ profile, content_type);
+ }
return new ContentSettingSingleRadioGroup(delegate, web_contents, profile,
content_type);
}
diff --git a/chrome/browser/ui/content_settings/content_setting_image_model.cc b/chrome/browser/ui/content_settings/content_setting_image_model.cc
index c49163b..9e564a2 100644
--- a/chrome/browser/ui/content_settings/content_setting_image_model.cc
+++ b/chrome/browser/ui/content_settings/content_setting_image_model.cc
@@ -52,6 +52,13 @@
virtual void UpdateFromWebContents(WebContents* web_contents) OVERRIDE;
};
+class ContentSettingMIDISysExImageModel : public ContentSettingImageModel {
+ public:
+ ContentSettingMIDISysExImageModel();
+
+ virtual void UpdateFromWebContents(WebContents* web_contents) OVERRIDE;
+};
+
namespace {
struct ContentSettingsTypeIdEntry {
@@ -297,6 +304,36 @@
set_visible(false);
}
+ContentSettingMIDISysExImageModel::ContentSettingMIDISysExImageModel()
+ : ContentSettingImageModel(CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
+}
+
+void ContentSettingMIDISysExImageModel::UpdateFromWebContents(
+ WebContents* web_contents) {
+ set_visible(false);
+ if (!web_contents)
+ return;
+ TabSpecificContentSettings* content_settings =
+ TabSpecificContentSettings::FromWebContents(web_contents);
+ if (!content_settings)
+ return;
+ const ContentSettingsUsagesState& usages_state =
+ content_settings->midi_usages_state();
+ if (usages_state.state_map().empty())
+ return;
+ set_visible(true);
+
+ // If any embedded site has access the allowed icon takes priority over the
+ // blocked icon.
+ unsigned int state_flags = 0;
+ usages_state.GetDetailedInfo(NULL, &state_flags);
+ bool allowed =
+ !!(state_flags & ContentSettingsUsagesState::TABSTATE_HAS_ANY_ALLOWED);
+ set_icon(allowed ? IDR_ALLOWED_MIDI_SYSEX : IDR_BLOCKED_MIDI_SYSEX);
+ set_tooltip(l10n_util::GetStringUTF8(allowed ?
+ IDS_MIDI_SYSEX_ALLOWED_TOOLTIP : IDS_MIDI_SYSEX_BLOCKED_TOOLTIP));
+}
+
ContentSettingImageModel::ContentSettingImageModel(
ContentSettingsType content_settings_type)
: content_settings_type_(content_settings_type),
@@ -320,6 +357,8 @@
case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
return new ContentSettingMediaImageModel(content_settings_type);
+ case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
+ return new ContentSettingMIDISysExImageModel();
default:
return new ContentSettingBlockedImageModel(content_settings_type);
}
diff --git a/chrome/browser/ui/extensions/application_launch.cc b/chrome/browser/ui/extensions/application_launch.cc
index 02112d1..cec680a 100644
--- a/chrome/browser/ui/extensions/application_launch.cc
+++ b/chrome/browser/ui/extensions/application_launch.cc
@@ -20,7 +20,6 @@
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/extensions/app_metro_infobar_delegate_win.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/web_applications/web_app.h"
@@ -343,17 +342,6 @@
UMA_HISTOGRAM_ENUMERATION("Extensions.AppLaunchContainer", container, 100);
if (extension->is_platform_app()) {
-#if defined(OS_WIN)
- // On Windows 8's single window Metro mode we can not launch platform apps.
- // Offer to switch Chrome to desktop mode.
- if (win8::IsSingleWindowMetroMode()) {
- AppMetroInfoBarDelegateWin::Create(
- profile, AppMetroInfoBarDelegateWin::LAUNCH_PACKAGED_APP,
- extension->id());
- return NULL;
- }
-#endif
-
apps::LaunchPlatformAppWithCommandLine(
profile, extension, params.command_line, params.current_directory);
return NULL;
diff --git a/chrome/browser/ui/extensions/apps_metro_handler_win.cc b/chrome/browser/ui/extensions/apps_metro_handler_win.cc
index 0f253b2..f59f675 100644
--- a/chrome/browser/ui/extensions/apps_metro_handler_win.cc
+++ b/chrome/browser/ui/extensions/apps_metro_handler_win.cc
@@ -5,7 +5,7 @@
#include "chrome/browser/ui/extensions/apps_metro_handler_win.h"
#include "apps/shell_window.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
+#include "apps/shell_window_registry.h"
#include "chrome/browser/ui/simple_message_box.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
@@ -14,7 +14,7 @@
namespace chrome {
bool VerifySwitchToMetroForApps(gfx::NativeWindow parent_window) {
- if (!extensions::ShellWindowRegistry::IsShellWindowRegisteredInAnyProfile(
+ if (!apps::ShellWindowRegistry::IsShellWindowRegisteredInAnyProfile(
apps::ShellWindow::WINDOW_TYPE_DEFAULT)) {
return true;
}
diff --git a/chrome/browser/ui/extensions/extension_enable_flow.cc b/chrome/browser/ui/extensions/extension_enable_flow.cc
index c1d59a6..b1ec1a9 100644
--- a/chrome/browser/ui/extensions/extension_enable_flow.cc
+++ b/chrome/browser/ui/extensions/extension_enable_flow.cc
@@ -4,10 +4,13 @@
#include "chrome/browser/ui/extensions/extension_enable_flow.h"
+#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_source.h"
using extensions::Extension;
@@ -48,10 +51,30 @@
// the user clicked on it.
if (!extension)
return;
- // If the app was terminated, reload it first. (This reallocates the
- // Extension object.)
+ // If the app was terminated, reload it first.
service->ReloadExtension(extension_id_);
+
+ // ReloadExtension reallocates the Extension object.
extension = service->GetExtensionById(extension_id_, true);
+
+ // |extension| could be NULL for asynchronous load, such as the case of
+ // an unpacked extension. Wait for the load to continue the flow.
+ if (!extension) {
+ StartObserving();
+ return;
+ }
+ }
+
+ CheckPermissionAndMaybePromptUser();
+}
+
+void ExtensionEnableFlow::CheckPermissionAndMaybePromptUser() {
+ ExtensionService* service =
+ extensions::ExtensionSystem::Get(profile_)->extension_service();
+ const Extension* extension = service->GetExtensionById(extension_id_, true);
+ if (!extension) {
+ delegate_->ExtensionEnableFlowAborted(false); // |delegate_| may delete us.
+ return;
}
extensions::ExtensionPrefs* extension_prefs = service->extension_prefs();
@@ -74,6 +97,53 @@
new ExtensionInstallPrompt(profile_, parent_window_, this));
}
+void ExtensionEnableFlow::StartObserving() {
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
+ content::Source<Profile>(profile_));
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOAD_ERROR,
+ content::Source<Profile>(profile_));
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
+ content::Source<Profile>(profile_));
+}
+
+void ExtensionEnableFlow::StopObserving() {
+ registrar_.RemoveAll();
+}
+
+void ExtensionEnableFlow::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ switch (type) {
+ case chrome::NOTIFICATION_EXTENSION_LOADED: {
+ const Extension* extension =
+ content::Details<const Extension>(details).ptr();
+ if (extension->id() == extension_id_) {
+ StopObserving();
+ CheckPermissionAndMaybePromptUser();
+ }
+
+ break;
+ }
+ case chrome::NOTIFICATION_EXTENSION_LOAD_ERROR: {
+ StopObserving();
+ delegate_->ExtensionEnableFlowAborted(false);
+ break;
+ }
+ case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: {
+ const Extension* extension =
+ content::Details<const Extension>(details).ptr();
+ if (extension->id() == extension_id_) {
+ StopObserving();
+ delegate_->ExtensionEnableFlowAborted(false);
+ }
+
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+}
+
void ExtensionEnableFlow::InstallUIProceed() {
ExtensionService* service =
extensions::ExtensionSystem::Get(profile_)->extension_service();
diff --git a/chrome/browser/ui/extensions/extension_enable_flow.h b/chrome/browser/ui/extensions/extension_enable_flow.h
index 1581e56..4a1548c 100644
--- a/chrome/browser/ui/extensions/extension_enable_flow.h
+++ b/chrome/browser/ui/extensions/extension_enable_flow.h
@@ -10,6 +10,8 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "chrome/browser/extensions/extension_install_prompt.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/page_navigator.h"
class ExtensionEnableFlowDelegate;
@@ -27,7 +29,8 @@
// shown to user. The extension is enabled when user acknowledges it or the
// flow is aborted when user declines it.
class ExtensionEnableFlow : public ExtensionInstallPrompt::Delegate,
- public content::PageNavigator {
+ public content::PageNavigator,
+ public content::NotificationObserver {
public:
ExtensionEnableFlow(Profile* profile,
const std::string& extension_id,
@@ -45,15 +48,30 @@
const std::string& extension_id() const { return extension_id_; }
private:
- // Runs the enable flow. Currently, it checks if there is permission
- // escalation while the extension is disabled/terminated. If no, enables the
- // extension and notify |delegate_| synchronously. Otherwise, creates an
- // ExtensionInstallPrompt and asks user to confirm.
+ // Runs the enable flow. It starts by checking if the extension is loaded.
+ // If not, it tries to reload it. If the load is asynchronous, wait for the
+ // load to finish before continuing the flow. Otherwise, calls
+ // CheckPermissionAndMaybePromptUser finish the flow.
void Run();
+ // Checks if there is permission escalation while the extension is
+ // disabled/terminated. If no, enables the extension and notify |delegate_|
+ // synchronously. Otherwise, creates an ExtensionInstallPrompt and asks user
+ // to confirm.
+ void CheckPermissionAndMaybePromptUser();
+
// Creates an ExtensionInstallPrompt in |prompt_|.
void CreatePrompt();
+ // Starts/stops observing extension load notifications.
+ void StartObserving();
+ void StopObserving();
+
+ // content::NotificationObserver overrides:
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
// ExtensionInstallPrompt::Delegate overrides:
virtual void InstallUIProceed() OVERRIDE;
virtual void InstallUIAbort(bool user_initiated) OVERRIDE;
@@ -75,6 +93,7 @@
gfx::NativeWindow parent_window_;
scoped_ptr<ExtensionInstallPrompt> prompt_;
+ content::NotificationRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(ExtensionEnableFlow);
};
diff --git a/chrome/browser/ui/find_bar/find_match_rects_details.cc b/chrome/browser/ui/find_bar/find_match_rects_details.cc
deleted file mode 100644
index 7e8e9da..0000000
--- a/chrome/browser/ui/find_bar/find_match_rects_details.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/find_bar/find_match_rects_details.h"
-
-FindMatchRectsDetails::FindMatchRectsDetails()
- : version_(-1) {
-}
-
-FindMatchRectsDetails::FindMatchRectsDetails(
- int version,
- const std::vector<gfx::RectF>& rects,
- const gfx::RectF& active_rect)
- : version_(version),
- rects_(rects),
- active_rect_(active_rect) {
-}
-
-FindMatchRectsDetails::~FindMatchRectsDetails() {
-}
diff --git a/chrome/browser/ui/find_bar/find_match_rects_details.h b/chrome/browser/ui/find_bar/find_match_rects_details.h
deleted file mode 100644
index 98c0380..0000000
--- a/chrome/browser/ui/find_bar/find_match_rects_details.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_FIND_BAR_FIND_MATCH_RECTS_DETAILS_H_
-#define CHROME_BROWSER_UI_FIND_BAR_FIND_MATCH_RECTS_DETAILS_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "ui/gfx/rect_f.h"
-
-// Holds the result details of a RequestFindMatchRects reply.
-class FindMatchRectsDetails {
- public:
- FindMatchRectsDetails();
-
- FindMatchRectsDetails(int version,
- const std::vector<gfx::RectF>& rects,
- const gfx::RectF& active_rect);
-
- ~FindMatchRectsDetails();
-
- int version() const { return version_; }
-
- const std::vector<gfx::RectF>& rects() const { return rects_; }
-
- const gfx::RectF& active_rect() const { return active_rect_; }
-
- private:
- // The version of the rects in this structure.
- int version_;
-
- // The rects of the find matches in find-in-page coordinates.
- std::vector<gfx::RectF> rects_;
-
- // The rect of the active find match in find-in-page coordinates.
- gfx::RectF active_rect_;
-};
-
-#endif // CHROME_BROWSER_UI_FIND_BAR_FIND_MATCH_RECTS_DETAILS_H_
diff --git a/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc b/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
index 82895ff..4e73dcc 100644
--- a/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
+++ b/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
@@ -151,6 +151,31 @@
// Clear for migration.
prefs->ClearPref(kTouchScreenFlingAccelerationAdjustment);
+ // TODO(mohsen): Remove following code in M32. By then, gesture prefs will
+ // have been cleared for majority of the users: crbug.com/269292.
+ // Do a one-time wipe of all gesture preferences.
+ if (!prefs->GetBoolean(prefs::kGestureConfigIsTrustworthy)) {
+ for (size_t i = 0; i < arraysize(kPrefsToObserve); ++i)
+ prefs->ClearPref(kPrefsToObserve[i]);
+
+ const std::vector<OverscrollPref>& overscroll_prefs = GetOverscrollPrefs();
+ for (size_t i = 0; i < overscroll_prefs.size(); ++i)
+ prefs->ClearPref(overscroll_prefs[i].pref_name);
+
+ for (size_t i = 0; i < arraysize(kFlingTouchpadPrefs); ++i)
+ prefs->ClearPref(kFlingTouchpadPrefs[i]);
+
+ for (size_t i = 0; i < arraysize(kFlingTouchscreenPrefs); ++i)
+ prefs->ClearPref(kFlingTouchscreenPrefs[i]);
+
+#if defined(USE_ASH)
+ for (size_t i = 0; i < arraysize(kImmersiveModePrefs); ++i)
+ prefs->ClearPref(kImmersiveModePrefs[i]);
+#endif // USE_ASH
+
+ prefs->SetBoolean(prefs::kGestureConfigIsTrustworthy, true);
+ }
+
registrar_.Init(prefs);
registrar_.RemoveAll();
base::Closure callback = base::Bind(&GesturePrefsObserver::Update,
@@ -481,6 +506,12 @@
RegisterOverscrollPrefs(registry);
RegisterFlingCurveParameters(registry);
RegisterImmersiveModePrefs(registry);
+
+ // Register pref for a one-time wipe of all gesture preferences.
+ registry->RegisterBooleanPref(
+ prefs::kGestureConfigIsTrustworthy,
+ false,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}
bool
diff --git a/chrome/browser/ui/gtk/download/download_shelf_gtk.cc b/chrome/browser/ui/gtk/download/download_shelf_gtk.cc
index 638fb10..a799604 100644
--- a/chrome/browser/ui/gtk/download/download_shelf_gtk.cc
+++ b/chrome/browser/ui/gtk/download/download_shelf_gtk.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/download/download_item_model.h"
-#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/download_stats.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/chrome_pages.h"
@@ -209,7 +209,7 @@
if (download_items_[i]->download()->GetState() == DownloadItem::IN_PROGRESS)
++num_in_progress;
}
- download_util::RecordShelfClose(
+ RecordDownloadShelfClose(
download_items_.size(), num_in_progress, reason == AUTOMATIC);
SetCloseOnMouseOut(false);
}
diff --git a/chrome/browser/ui/gtk/gtk_theme_service.cc b/chrome/browser/ui/gtk/gtk_theme_service.cc
index 76befd6..97e0ec5 100644
--- a/chrome/browser/ui/gtk/gtk_theme_service.cc
+++ b/chrome/browser/ui/gtk/gtk_theme_service.cc
@@ -17,6 +17,7 @@
#include "base/stl_util.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/themes/custom_theme_supplier.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/browser/ui/browser.h"
@@ -347,6 +348,7 @@
void GtkThemeService::SetTheme(const extensions::Extension* extension) {
profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, false);
+ use_gtk_ = false;
LoadDefaultValues();
ThemeService::SetTheme(extension);
}
@@ -370,6 +372,14 @@
return !use_gtk_ && ThemeService::UsingDefaultTheme();
}
+void GtkThemeService::SetCustomDefaultTheme(
+ scoped_refptr<CustomThemeSupplier> theme_supplier) {
+ profile()->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, false);
+ use_gtk_ = false;
+ LoadDefaultValues();
+ ThemeService::SetCustomDefaultTheme(theme_supplier);
+}
+
bool GtkThemeService::ShouldInitWithNativeTheme() const {
return profile()->GetPrefs()->GetBoolean(prefs::kUsesSystemTheme);
}
diff --git a/chrome/browser/ui/gtk/gtk_theme_service.h b/chrome/browser/ui/gtk/gtk_theme_service.h
index 18a840e..fbb487b 100644
--- a/chrome/browser/ui/gtk/gtk_theme_service.h
+++ b/chrome/browser/ui/gtk/gtk_theme_service.h
@@ -18,6 +18,7 @@
#include "ui/base/gtk/owned_widget_gtk.h"
#include "ui/gfx/color_utils.h"
+class CustomThemeSupplier;
class Profile;
namespace content {
@@ -79,6 +80,8 @@
virtual void SetNativeTheme() OVERRIDE;
virtual bool UsingDefaultTheme() const OVERRIDE;
virtual bool UsingNativeTheme() const OVERRIDE;
+ virtual void SetCustomDefaultTheme(
+ scoped_refptr<CustomThemeSupplier> theme_supplier) OVERRIDE;
virtual bool ShouldInitWithNativeTheme() const OVERRIDE;
// Creates a GtkChromeButton instance, registered with this theme provider,
diff --git a/chrome/browser/ui/gtk/location_bar_view_gtk.cc b/chrome/browser/ui/gtk/location_bar_view_gtk.cc
index 8f8b8b0..95693c2 100644
--- a/chrome/browser/ui/gtk/location_bar_view_gtk.cc
+++ b/chrome/browser/ui/gtk/location_bar_view_gtk.cc
@@ -92,7 +92,6 @@
#include "ui/gfx/font.h"
#include "ui/gfx/gtk_util.h"
#include "ui/gfx/image/image.h"
-#include "ui/gfx/rect.h"
using content::NavigationEntry;
using content::OpenURLParams;
@@ -618,12 +617,6 @@
return browser_->tab_strip_model()->GetActiveWebContents();
}
-gfx::Rect LocationBarViewGtk::GetOmniboxBounds() const {
- GtkAllocation hbox_allocation;
- gtk_widget_get_allocation(hbox_.get(), &hbox_allocation);
- return AllocationToRect(hbox_allocation);
-}
-
void LocationBarViewGtk::SetPreviewEnabledPageAction(
ExtensionAction* page_action,
bool preview_enabled) {
@@ -949,7 +942,7 @@
// Not implemented on Gtk.
}
-void LocationBarViewGtk::UpdateAutofillCreditCardView() {
+void LocationBarViewGtk::UpdateGeneratedCreditCardView() {
NOTIMPLEMENTED();
}
diff --git a/chrome/browser/ui/gtk/location_bar_view_gtk.h b/chrome/browser/ui/gtk/location_bar_view_gtk.h
index c886f32..b8dc178 100644
--- a/chrome/browser/ui/gtk/location_bar_view_gtk.h
+++ b/chrome/browser/ui/gtk/location_bar_view_gtk.h
@@ -122,7 +122,6 @@
virtual string16 GetTitle() const OVERRIDE;
virtual InstantController* GetInstant() OVERRIDE;
virtual content::WebContents* GetWebContents() const OVERRIDE;
- virtual gfx::Rect GetOmniboxBounds() const OVERRIDE;
// LocationBar:
virtual void ShowFirstRunBubble() OVERRIDE;
@@ -136,7 +135,7 @@
virtual void UpdatePageActions() OVERRIDE;
virtual void InvalidatePageActions() OVERRIDE;
virtual void UpdateOpenPDFInReaderPrompt() OVERRIDE;
- virtual void UpdateAutofillCreditCardView() OVERRIDE;
+ virtual void UpdateGeneratedCreditCardView() OVERRIDE;
virtual void SaveStateToContents(content::WebContents* contents) OVERRIDE;
virtual void Revert() OVERRIDE;
virtual const OmniboxView* GetLocationEntry() const OVERRIDE;
diff --git a/chrome/browser/ui/gtk/menu_gtk.cc b/chrome/browser/ui/gtk/menu_gtk.cc
index 27fff39..bbed502 100644
--- a/chrome/browser/ui/gtk/menu_gtk.cc
+++ b/chrome/browser/ui/gtk/menu_gtk.cc
@@ -322,7 +322,7 @@
GtkWidget* MenuGtk::AppendMenuItemWithLabel(int command_id,
const std::string& label) {
std::string converted_label = ui::ConvertAcceleratorsFromWindowsStyle(label);
- GtkWidget* menu_item = BuildMenuItemWithLabel(label, command_id);
+ GtkWidget* menu_item = BuildMenuItemWithLabel(converted_label, command_id);
return AppendMenuItem(command_id, menu_item);
}
diff --git a/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk_unittest.cc b/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk_unittest.cc
index b3e429c..a77871a 100644
--- a/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk_unittest.cc
+++ b/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk_unittest.cc
@@ -16,7 +16,6 @@
#include "testing/platform_test.h"
#include "ui/base/gtk/gtk_hig_constants.h"
#include "ui/gfx/image/image.h"
-#include "ui/gfx/rect.h"
namespace {
class OmniboxEditControllerMock : public OmniboxEditController {
@@ -34,7 +33,6 @@
MOCK_CONST_METHOD0(GetTitle, string16());
MOCK_METHOD0(GetInstant, InstantController*());
MOCK_CONST_METHOD0(GetWebContents, content::WebContents*());
- MOCK_CONST_METHOD0(GetOmniboxBounds, gfx::Rect());
virtual ~OmniboxEditControllerMock() {}
};
diff --git a/chrome/browser/ui/omnibox/location_bar.h b/chrome/browser/ui/omnibox/location_bar.h
index 6a759b1..3a4fc68 100644
--- a/chrome/browser/ui/omnibox/location_bar.h
+++ b/chrome/browser/ui/omnibox/location_bar.h
@@ -64,10 +64,10 @@
// Updates the state of the button to open a PDF in Adobe Reader.
virtual void UpdateOpenPDFInReaderPrompt() = 0;
- // Updates the Autofill credit card view. This views serves as an anchor for
- // the Autofill credit card bubble, which might show on successful run of the
- // Autofill dialog.
- virtual void UpdateAutofillCreditCardView() = 0;
+ // Updates the generated credit card view. This view serves as an anchor for
+ // the generated credit card bubble, which can show on successful generation
+ // of a new credit card number.
+ virtual void UpdateGeneratedCreditCardView() = 0;
// Saves the state of the location bar to the specified WebContents, so that
// it can be restored later. (Done when switching tabs).
diff --git a/chrome/browser/ui/omnibox/omnibox_controller.cc b/chrome/browser/ui/omnibox/omnibox_controller.cc
index 31ae5e5..a15dd14 100644
--- a/chrome/browser/ui/omnibox/omnibox_controller.cc
+++ b/chrome/browser/ui/omnibox/omnibox_controller.cc
@@ -43,16 +43,10 @@
AutocompleteInput::PageClassification current_page_classification,
bool prevent_inline_autocomplete,
bool prefer_keyword,
- bool allow_exact_keyword_match,
- int omnibox_start_margin) const {
+ bool allow_exact_keyword_match) const {
ClearPopupKeywordMode();
popup_->SetHoveredLine(OmniboxPopupModel::kNoMatch);
- if (chrome::IsInstantExtendedAPIEnabled()) {
- autocomplete_controller_->search_provider()->
- SetOmniboxStartMargin(omnibox_start_margin);
- }
-
// We don't explicitly clear OmniboxPopupModel::manually_selected_match, as
// Start ends up invoking OmniboxPopupModel::OnResultChanged which clears it.
autocomplete_controller_->Start(AutocompleteInput(
diff --git a/chrome/browser/ui/omnibox/omnibox_controller.h b/chrome/browser/ui/omnibox/omnibox_controller.h
index 977bd4c..e5e2d97 100644
--- a/chrome/browser/ui/omnibox/omnibox_controller.h
+++ b/chrome/browser/ui/omnibox/omnibox_controller.h
@@ -48,8 +48,7 @@
AutocompleteInput::PageClassification current_page_classification,
bool prevent_inline_autocomplete,
bool prefer_keyword,
- bool allow_exact_keyword_match,
- int omnibox_start_margin) const;
+ bool allow_exact_keyword_match) const;
// AutocompleteControllerDelegate:
virtual void OnResultChanged(bool default_match_changed) OVERRIDE;
diff --git a/chrome/browser/ui/omnibox/omnibox_current_page_delegate.h b/chrome/browser/ui/omnibox/omnibox_current_page_delegate.h
index b21495b..560b2c3 100644
--- a/chrome/browser/ui/omnibox/omnibox_current_page_delegate.h
+++ b/chrome/browser/ui/omnibox/omnibox_current_page_delegate.h
@@ -35,6 +35,9 @@
// Returns true if the visible entry is a New Tab Page rendered by Instant.
virtual bool IsInstantNTP() const = 0;
+ // Returns true if the committed entry is a search results page.
+ virtual bool IsSearchResultsPage() const = 0;
+
// Returns whether the current page is loading.
virtual bool IsLoading() const = 0;
diff --git a/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.cc b/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.cc
index e26f8d5..952497c 100644
--- a/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.cc
+++ b/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.cc
@@ -11,6 +11,8 @@
#include "chrome/browser/predictors/autocomplete_action_predictor_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/search.h"
+#include "chrome/browser/search_engines/template_url_service.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/omnibox/omnibox_edit_controller.h"
#include "chrome/browser/ui/search/search_tab_helper.h"
@@ -40,6 +42,13 @@
return chrome::IsInstantNTP(controller_->GetWebContents());
}
+bool OmniboxCurrentPageDelegateImpl::IsSearchResultsPage() const {
+ Profile* profile = Profile::FromBrowserContext(
+ controller_->GetWebContents()->GetBrowserContext());
+ return TemplateURLServiceFactory::GetForProfile(profile)->
+ IsSearchResultsPageFromDefaultSearchProvider(GetURL());
+}
+
bool OmniboxCurrentPageDelegateImpl::IsLoading() const {
return controller_->GetWebContents()->IsLoading();
}
diff --git a/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.h b/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.h
index 5546ad0..9f5b024 100644
--- a/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.h
+++ b/chrome/browser/ui/omnibox/omnibox_current_page_delegate_impl.h
@@ -21,6 +21,7 @@
virtual bool CurrentPageExists() const OVERRIDE;
virtual const GURL& GetURL() const OVERRIDE;
virtual bool IsInstantNTP() const OVERRIDE;
+ virtual bool IsSearchResultsPage() const OVERRIDE;
virtual bool IsLoading() const OVERRIDE;
virtual content::NavigationController&
GetNavigationController() const OVERRIDE;
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_controller.h b/chrome/browser/ui/omnibox/omnibox_edit_controller.h
index 5825500..b651739 100644
--- a/chrome/browser/ui/omnibox/omnibox_edit_controller.h
+++ b/chrome/browser/ui/omnibox/omnibox_edit_controller.h
@@ -18,7 +18,6 @@
namespace gfx {
class Image;
-class Rect;
}
// I am in hack-and-slash mode right now.
@@ -70,9 +69,6 @@
// Returns the WebContents of the currently active tab.
virtual content::WebContents* GetWebContents() const = 0;
- // Returns the bounds for the omnibox.
- virtual gfx::Rect GetOmniboxBounds() const = 0;
-
protected:
virtual ~OmniboxEditController() {}
};
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_model.cc b/chrome/browser/ui/omnibox/omnibox_edit_model.cc
index b4c9087..4ee0baf 100644
--- a/chrome/browser/ui/omnibox/omnibox_edit_model.cc
+++ b/chrome/browser/ui/omnibox/omnibox_edit_model.cc
@@ -502,8 +502,7 @@
(has_selected_text && inline_autocomplete_text_.empty()) ||
(paste_state_ != NONE),
keyword_is_selected,
- keyword_is_selected || allow_exact_keyword_match_,
- controller_->GetOmniboxBounds().x());
+ keyword_is_selected || allow_exact_keyword_match_);
}
void OmniboxEditModel::StopAutocomplete() {
@@ -728,12 +727,11 @@
// Track whether the destination URL sends us to a search results page
// using the default search provider.
- TemplateURL* default_provider =
- TemplateURLServiceFactory::GetForProfile(profile_)->
- GetDefaultSearchProvider();
- if (default_provider && default_provider->IsSearchURL(destination_url))
+ if (TemplateURLServiceFactory::GetForProfile(profile_)->
+ IsSearchResultsPageFromDefaultSearchProvider(destination_url)) {
content::RecordAction(
UserMetricsAction("OmniboxDestinationURLIsSearchOnDSP"));
+ }
// This calls RevertAll again.
base::AutoReset<bool> tmp(&in_revert_, true);
@@ -860,8 +858,9 @@
}
bool OmniboxEditModel::OnEscapeKeyPressed() {
+ const AutocompleteMatch& match = CurrentMatch(NULL);
if (has_temporary_text_) {
- if (CurrentMatch(NULL).destination_url != original_url_) {
+ if (match.destination_url != original_url_) {
RevertTemporaryText(true);
return true;
}
@@ -879,7 +878,10 @@
// When the permanent text isn't all selected we still fall through to the
// SelectAll() call below so users can arrow around in the text and then hit
// <esc> to quickly replace all the text; this matches IE.
- if (!user_input_in_progress_ && view_->IsSelectAll())
+ const bool has_zero_suggest_match = match.provider &&
+ (match.provider->type() == AutocompleteProvider::TYPE_ZERO_SUGGEST);
+ if (!has_zero_suggest_match && !user_input_in_progress_ &&
+ view_->IsSelectAll())
return false;
if (!user_text_.empty()) {
@@ -1294,6 +1296,9 @@
if (view_->toolbar_model()->WouldReplaceSearchURLWithSearchTerms(true)) {
return AutocompleteInput::SEARCH_RESULT_PAGE_DOING_SEARCH_TERM_REPLACEMENT;
}
+ if (delegate_->IsSearchResultsPage()) {
+ return AutocompleteInput::SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT;
+ }
return AutocompleteInput::OTHER;
}
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc b/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc
index 7fd366a..1424011 100644
--- a/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc
@@ -14,7 +14,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/font.h"
#include "ui/gfx/image/image.h"
-#include "ui/gfx/rect.h"
using content::WebContents;
@@ -105,7 +104,6 @@
virtual WebContents* GetWebContents() const OVERRIDE {
return NULL;
}
- virtual gfx::Rect GetOmniboxBounds() const OVERRIDE { return gfx::Rect(); }
private:
DISALLOW_COPY_AND_ASSIGN(TestingOmniboxEditController);
diff --git a/chrome/browser/ui/omnibox/omnibox_popup_non_view.cc b/chrome/browser/ui/omnibox/omnibox_popup_non_view.cc
deleted file mode 100644
index 4c22d7e..0000000
--- a/chrome/browser/ui/omnibox/omnibox_popup_non_view.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/omnibox/omnibox_popup_non_view.h"
-
-#include "ui/gfx/image/image.h"
-#include "ui/gfx/rect.h"
-
-OmniboxPopupNonView::OmniboxPopupNonView(OmniboxEditModel* edit_model)
- : model_(this, edit_model),
- is_open_(false) {
-}
-
-OmniboxPopupNonView::~OmniboxPopupNonView() {
-}
-
-bool OmniboxPopupNonView::IsOpen() const {
- return is_open_;
-}
-
-void OmniboxPopupNonView::InvalidateLine(size_t line) {
-}
-
-void OmniboxPopupNonView::UpdatePopupAppearance() {
- is_open_ = !model_.result().empty();
-}
-
-gfx::Rect OmniboxPopupNonView::GetTargetBounds() {
- // Non-view bounds never obscure the page, so return an empty rect.
- return gfx::Rect();
-}
-
-void OmniboxPopupNonView::PaintUpdatesNow() {
- // TODO(beng): remove this from the interface.
-}
-
-void OmniboxPopupNonView::OnDragCanceled() {
-}
diff --git a/chrome/browser/ui/omnibox/omnibox_popup_non_view.h b/chrome/browser/ui/omnibox/omnibox_popup_non_view.h
deleted file mode 100644
index 5e9b24b..0000000
--- a/chrome/browser/ui/omnibox/omnibox_popup_non_view.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_POPUP_NON_VIEW_H_
-#define CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_POPUP_NON_VIEW_H_
-
-#include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
-#include "chrome/browser/ui/omnibox/omnibox_popup_view.h"
-
-class OmniboxEditModel;
-
-// A view representing the contents of the omnibox popup. This headless view is
-// used when Instant is doing the actual rendering of the suggestions. The
-// Omnibox still needs a model-like object, so that is provided here. But the
-// view portion itself is not displayed.
-class OmniboxPopupNonView : public OmniboxPopupView {
- public:
- explicit OmniboxPopupNonView(OmniboxEditModel* edit_model);
-
- // Overridden from OmniboxPopupView:
- virtual bool IsOpen() const OVERRIDE;
- virtual void InvalidateLine(size_t line) OVERRIDE;
- virtual void UpdatePopupAppearance() OVERRIDE;
- virtual gfx::Rect GetTargetBounds() OVERRIDE;
- virtual void PaintUpdatesNow() OVERRIDE;
- virtual void OnDragCanceled() OVERRIDE;
-
- protected:
- virtual ~OmniboxPopupNonView();
-
- private:
- OmniboxPopupModel model_;
-
- // |is_open_| reflects whether the OmniboxEditModel has a non-empty result
- // set. However, we can't get rid of this variable and just use the model's
- // state directly, as there's at least one situation when the model's result
- // set has been emptied, but the popup should still be considered to be open
- // until UpdatePopupAppearance() is called (cf: |was_open| in
- // OmniboxEditModel::OnResultChanged()).
- bool is_open_;
-
- DISALLOW_COPY_AND_ASSIGN(OmniboxPopupNonView);
-};
-
-#endif // CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_POPUP_NON_VIEW_H_
diff --git a/chrome/browser/ui/omnibox/omnibox_view.cc b/chrome/browser/ui/omnibox/omnibox_view.cc
index 50cc536..9d8f50f 100644
--- a/chrome/browser/ui/omnibox/omnibox_view.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view.cc
@@ -24,6 +24,26 @@
}
// static
+string16 OmniboxView::SanitizeTextForPaste(const string16& text) {
+ // Check for non-newline whitespace; if found, collapse whitespace runs down
+ // to single spaces.
+ // TODO(shess): It may also make sense to ignore leading or
+ // trailing whitespace when making this determination.
+ for (size_t i = 0; i < text.size(); ++i) {
+ if (IsWhitespace(text[i]) && text[i] != '\n' && text[i] != '\r') {
+ const string16 collapsed = CollapseWhitespace(text, false);
+ // If the user is pasting all-whitespace, paste a single space
+ // rather than nothing, since pasting nothing feels broken.
+ return collapsed.empty() ?
+ ASCIIToUTF16(" ") : StripJavascriptSchemas(collapsed);
+ }
+ }
+
+ // Otherwise, all whitespace is newlines; remove it entirely.
+ return StripJavascriptSchemas(CollapseWhitespace(text, true));
+}
+
+// static
string16 OmniboxView::GetClipboardText() {
// Try text format.
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
@@ -31,26 +51,7 @@
ui::Clipboard::BUFFER_STANDARD)) {
string16 text;
clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &text);
-
- // If the input contains non-newline whitespace, treat it as
- // search data and convert newlines to spaces. For instance, a
- // street address.
- // TODO(shess): It may also make sense to ignore leading or
- // trailing whitespace when making this determination.
- for (size_t i = 0; i < text.size(); ++i) {
- if (IsWhitespace(text[i]) && text[i] != '\n' && text[i] != '\r') {
- const string16 collapsed = CollapseWhitespace(text, false);
- // If the user is pasting all-whitespace, paste a single space
- // rather than nothing, since pasting nothing feels broken.
- return collapsed.empty() ?
- ASCIIToUTF16(" ") : StripJavascriptSchemas(collapsed);
- }
- }
-
- // Otherwise, the only whitespace in |text| is newlines. Remove
- // these entirely, because users are most likely pasting URLs
- // split into multiple lines by terminals, email programs, etc.
- return StripJavascriptSchemas(CollapseWhitespace(text, true));
+ return SanitizeTextForPaste(text);
}
// Try bookmark format.
diff --git a/chrome/browser/ui/omnibox/omnibox_view.h b/chrome/browser/ui/omnibox/omnibox_view.h
index 9fb5b94..a138de5 100644
--- a/chrome/browser/ui/omnibox/omnibox_view.h
+++ b/chrome/browser/ui/omnibox/omnibox_view.h
@@ -231,10 +231,18 @@
virtual int OnPerformDrop(const ui::DropTargetEvent& event) = 0;
#endif
- // Returns a string with any leading javascript schemas stripped from the
- // input text.
+ // Returns |text| with any leading javascript schemas stripped.
static string16 StripJavascriptSchemas(const string16& text);
+ // First, calls StripJavascriptSchemas(). Then automatically collapses
+ // internal whitespace as follows:
+ // * If the only whitespace in |text| is newlines, users are most likely
+ // pasting in URLs split into multiple lines by terminals, email programs,
+ // etc. So all newlines are removed.
+ // * Otherwise, users may be pasting in search data, e.g. street addresses. In
+ // this case, runs of whitespace are collapsed down to single spaces.
+ static string16 SanitizeTextForPaste(const string16& text);
+
// Returns the current clipboard contents as a string that can be pasted in.
// In addition to just getting CF_UNICODETEXT out, this can also extract URLs
// from bookmarks on the clipboard.
diff --git a/chrome/browser/ui/omnibox/omnibox_view_unittest.cc b/chrome/browser/ui/omnibox/omnibox_view_unittest.cc
index c00574b..24607d3 100644
--- a/chrome/browser/ui/omnibox/omnibox_view_unittest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view_unittest.cc
@@ -44,6 +44,26 @@
}
}
+TEST_F(OmniboxViewTest, SanitizeTextForPaste) {
+ // Broken URL has newlines stripped.
+ const string16 kWrappedURL(ASCIIToUTF16(
+ "http://www.chromium.org/developers/testing/chromium-\n"
+ "build-infrastructure/tour-of-the-chromium-buildbot"));
+
+ const string16 kFixedURL(ASCIIToUTF16(
+ "http://www.chromium.org/developers/testing/chromium-"
+ "build-infrastructure/tour-of-the-chromium-buildbot"));
+ EXPECT_EQ(kFixedURL, OmniboxView::SanitizeTextForPaste(kWrappedURL));
+
+ // Multi-line address is converted to a single-line address.
+ const string16 kWrappedAddress(ASCIIToUTF16(
+ "1600 Amphitheatre Parkway\nMountain View, CA"));
+
+ const string16 kFixedAddress(ASCIIToUTF16(
+ "1600 Amphitheatre Parkway Mountain View, CA"));
+ EXPECT_EQ(kFixedAddress, OmniboxView::SanitizeTextForPaste(kWrappedAddress));
+}
+
TEST_F(OmniboxViewTest, GetClipboardText) {
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
@@ -107,34 +127,6 @@
clipboard_writer.WriteHTML(kMarkup, kURL);
}
EXPECT_TRUE(OmniboxView::GetClipboardText().empty());
-
- // Broken URL has newlines stripped.
- {
- const string16 kWrappedURL(ASCIIToUTF16(
- "http://www.chromium.org/developers/testing/chromium-\n"
- "build-infrastructure/tour-of-the-chromium-buildbot"));
- ui::ScopedClipboardWriter clipboard_writer(clipboard,
- ui::Clipboard::BUFFER_STANDARD);
- clipboard_writer.WriteText(kWrappedURL);
- }
-
- const string16 kFixedURL(ASCIIToUTF16(
- "http://www.chromium.org/developers/testing/chromium-"
- "build-infrastructure/tour-of-the-chromium-buildbot"));
- EXPECT_EQ(kFixedURL, OmniboxView::GetClipboardText());
-
- // Multi-line address is converted to a single-line address.
- {
- const string16 kWrappedAddress(ASCIIToUTF16(
- "1600 Amphitheatre Parkway\nMountain View, CA"));
- ui::ScopedClipboardWriter clipboard_writer(clipboard,
- ui::Clipboard::BUFFER_STANDARD);
- clipboard_writer.WriteText(kWrappedAddress);
- }
-
- const string16 kFixedAddress(ASCIIToUTF16(
- "1600 Amphitheatre Parkway Mountain View, CA"));
- EXPECT_EQ(kFixedAddress, OmniboxView::GetClipboardText());
}
} // namespace
diff --git a/chrome/browser/ui/pdf/pdf_tab_helper.cc b/chrome/browser/ui/pdf/pdf_tab_helper.cc
index d78bb81..126b8a7 100644
--- a/chrome/browser/ui/pdf/pdf_tab_helper.cc
+++ b/chrome/browser/ui/pdf/pdf_tab_helper.cc
@@ -4,7 +4,7 @@
#include "chrome/browser/ui/pdf/pdf_tab_helper.h"
-#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/download_stats.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
@@ -75,7 +75,7 @@
void PDFTabHelper::OnSaveURLAs(const GURL& url,
const content::Referrer& referrer) {
- download_util::RecordDownloadSource(download_util::INITIATED_BY_PDF_SAVE);
+ RecordDownloadSource(DOWNLOAD_INITIATED_BY_PDF_SAVE);
web_contents()->SaveFrame(url, referrer);
}
diff --git a/chrome/browser/ui/search/instant_controller.cc b/chrome/browser/ui/search/instant_controller.cc
index 8c86635..3b42999 100644
--- a/chrome/browser/ui/search/instant_controller.cc
+++ b/chrome/browser/ui/search/instant_controller.cc
@@ -307,27 +307,7 @@
void InstantController::FocusOmnibox(const content::WebContents* contents,
OmniboxFocusState state) {
DCHECK(IsContentsFrom(instant_tab(), contents));
-
- // Do not add a default case in the switch block for the following reasons:
- // (1) Explicitly handle the new states. If new states are added in the
- // OmniboxFocusState, the compiler will warn the developer to handle the new
- // states.
- // (2) An attacker may control the renderer and sends the browser process a
- // malformed IPC. This function responds to the invalid |state| values by
- // doing nothing instead of crashing the browser process (intentional no-op).
- switch (state) {
- case OMNIBOX_FOCUS_VISIBLE:
- // TODO(samarth): re-enable this once setValue() correctly handles
- // URL-shaped queries.
- // browser_->FocusOmnibox(true);
- break;
- case OMNIBOX_FOCUS_INVISIBLE:
- browser_->FocusOmnibox(false);
- break;
- case OMNIBOX_FOCUS_NONE:
- contents->GetView()->Focus();
- break;
- }
+ browser_->FocusOmnibox(state);
}
void InstantController::NavigateToURL(const content::WebContents* contents,
@@ -351,6 +331,16 @@
browser_->OpenURL(url, transition, disposition);
}
+void InstantController::PasteIntoOmnibox(const content::WebContents* contents,
+ const string16& text) {
+ if (search_mode_.is_origin_default())
+ return;
+
+ DCHECK(IsContentsFrom(instant_tab(), contents));
+
+ browser_->PasteIntoOmnibox(text);
+}
+
void InstantController::ResetInstantTab() {
if (!search_mode_.is_origin_default()) {
content::WebContents* active_tab = browser_->GetActiveWebContents();
diff --git a/chrome/browser/ui/search/instant_controller.h b/chrome/browser/ui/search/instant_controller.h
index e117a3a..412a9b3 100644
--- a/chrome/browser/ui/search/instant_controller.h
+++ b/chrome/browser/ui/search/instant_controller.h
@@ -33,6 +33,10 @@
class WebContents;
}
+namespace gfx {
+class Rect;
+}
+
// Macro used for logging debug events. |message| should be a std::string.
#define LOG_INSTANT_DEBUG_EVENT(controller, message) \
controller->LogDebugEvent(message)
@@ -93,6 +97,11 @@
return debug_events_;
}
+ // Gets the stored start-edge margin and width of the omnibox.
+ const gfx::Rect omnibox_bounds() {
+ return omnibox_bounds_;
+ }
+
// Used by BrowserInstantController to notify InstantController about the
// instant support change event for the active web contents.
void InstantSupportChanged(InstantSupportState instant_support);
@@ -155,6 +164,8 @@
content::PageTransition transition,
WindowOpenDisposition disposition,
bool is_search_type) OVERRIDE;
+ virtual void PasteIntoOmnibox(const content::WebContents* contents,
+ const string16& text) OVERRIDE;
virtual void InstantPageLoadFailed(content::WebContents* contents) OVERRIDE;
// Invoked by the InstantLoader when the Instant page wants to delete a
diff --git a/chrome/browser/ui/search/instant_loader.cc b/chrome/browser/ui/search/instant_loader.cc
index 4daf19a..949cf60 100644
--- a/chrome/browser/ui/search/instant_loader.cc
+++ b/chrome/browser/ui/search/instant_loader.cc
@@ -107,8 +107,10 @@
SearchTabHelper::CreateForWebContents(contents());
+#if !defined(OS_ANDROID)
// Observers.
extensions::WebNavigationTabObserver::CreateForWebContents(contents());
+#endif // OS_ANDROID
// Favicons, required by the Task Manager.
FaviconTabHelper::CreateForWebContents(contents());
diff --git a/chrome/browser/ui/search/instant_ntp_prerenderer.cc b/chrome/browser/ui/search/instant_ntp_prerenderer.cc
index 2edfc11..7b3957a 100644
--- a/chrome/browser/ui/search/instant_ntp_prerenderer.cc
+++ b/chrome/browser/ui/search/instant_ntp_prerenderer.cc
@@ -197,29 +197,37 @@
}
void InstantNTPPrerenderer::InstantPageAboutToNavigateMainFrame(
- const content::WebContents* contents,
- const GURL& url) {
+ const content::WebContents* /* contents */,
+ const GURL& /* url */) {
NOTREACHED();
}
-void InstantNTPPrerenderer::FocusOmnibox(const content::WebContents* contents,
- OmniboxFocusState state) {
+void InstantNTPPrerenderer::FocusOmnibox(
+ const content::WebContents* /* contents */,
+ OmniboxFocusState /* state */) {
NOTREACHED();
}
-void InstantNTPPrerenderer::NavigateToURL(const content::WebContents* contents,
- const GURL& url,
- content::PageTransition transition,
- WindowOpenDisposition disposition,
- bool is_search_type) {
+void InstantNTPPrerenderer::NavigateToURL(
+ const content::WebContents* /* contents */,
+ const GURL& /* url */,
+ content::PageTransition /* transition */,
+ WindowOpenDisposition /* disposition */,
+ bool /* is_search_type */) {
NOTREACHED();
}
-void InstantNTPPrerenderer::DeleteMostVisitedItem(const GURL& url) {
+void InstantNTPPrerenderer::PasteIntoOmnibox(
+ const content::WebContents* /* contents */,
+ const string16& /* text */) {
NOTREACHED();
}
-void InstantNTPPrerenderer::UndoMostVisitedDeletion(const GURL& url) {
+void InstantNTPPrerenderer::DeleteMostVisitedItem(const GURL& /* url */) {
+ NOTREACHED();
+}
+
+void InstantNTPPrerenderer::UndoMostVisitedDeletion(const GURL& /* url */) {
NOTREACHED();
}
diff --git a/chrome/browser/ui/search/instant_ntp_prerenderer.h b/chrome/browser/ui/search/instant_ntp_prerenderer.h
index 8fbaf83..933e0a8 100644
--- a/chrome/browser/ui/search/instant_ntp_prerenderer.h
+++ b/chrome/browser/ui/search/instant_ntp_prerenderer.h
@@ -130,6 +130,8 @@
content::PageTransition transition,
WindowOpenDisposition disposition,
bool is_search_type) OVERRIDE;
+ virtual void PasteIntoOmnibox(const content::WebContents* contents,
+ const string16& text) OVERRIDE;
virtual void DeleteMostVisitedItem(const GURL& url) OVERRIDE;
virtual void UndoMostVisitedDeletion(const GURL& url) OVERRIDE;
virtual void UndoAllMostVisitedDeletions() OVERRIDE;
diff --git a/chrome/browser/ui/search/instant_page.cc b/chrome/browser/ui/search/instant_page.cc
index f963d2d..9149ea7 100644
--- a/chrome/browser/ui/search/instant_page.cc
+++ b/chrome/browser/ui/search/instant_page.cc
@@ -122,6 +122,10 @@
return false;
}
+bool InstantPage::ShouldProcessPasteIntoOmnibox() {
+ return false;
+}
+
bool InstantPage::ShouldProcessDeleteMostVisitedItem() {
return false;
}
@@ -143,6 +147,8 @@
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_FocusOmnibox, OnFocusOmnibox)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SearchBoxNavigate,
OnSearchBoxNavigate);
+ IPC_MESSAGE_HANDLER(ChromeViewHostMsg_PasteAndOpenDropdown,
+ OnSearchBoxPaste);
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_CountMouseover, OnCountMouseover);
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_SearchBoxDeleteMostVisitedItem,
OnDeleteMostVisitedItem);
@@ -244,6 +250,17 @@
contents(), url, transition, disposition, is_search_type);
}
+void InstantPage::OnSearchBoxPaste(int page_id, const string16& text) {
+ if (!contents()->IsActiveEntry(page_id))
+ return;
+
+ SearchTabHelper::FromWebContents(contents())->InstantSupportChanged(true);
+ if (!ShouldProcessPasteIntoOmnibox())
+ return;
+
+ delegate_->PasteIntoOmnibox(contents(), text);
+}
+
void InstantPage::OnCountMouseover(int page_id) {
if (!contents()->IsActiveEntry(page_id))
return;
diff --git a/chrome/browser/ui/search/instant_page.h b/chrome/browser/ui/search/instant_page.h
index 926ad5e..1cb5dfe 100644
--- a/chrome/browser/ui/search/instant_page.h
+++ b/chrome/browser/ui/search/instant_page.h
@@ -72,6 +72,11 @@
WindowOpenDisposition disposition,
bool is_search_type) = 0;
+ // Called when the page wants to paste the |text| (or the clipboard content
+ // if the |text| is empty) into the omnibox.
+ virtual void PasteIntoOmnibox(const content::WebContents* contents,
+ const string16& text) = 0;
+
// Called when the SearchBox wants to delete a Most Visited item.
virtual void DeleteMostVisitedItem(const GURL& url) = 0;
@@ -133,6 +138,7 @@
virtual bool ShouldProcessAboutToNavigateMainFrame();
virtual bool ShouldProcessFocusOmnibox();
virtual bool ShouldProcessNavigateToURL();
+ virtual bool ShouldProcessPasteIntoOmnibox();
virtual bool ShouldProcessDeleteMostVisitedItem();
virtual bool ShouldProcessUndoMostVisitedDeletion();
virtual bool ShouldProcessUndoAllMostVisitedDeletions();
@@ -188,6 +194,7 @@
content::PageTransition transition,
WindowOpenDisposition disposition,
bool is_search_type);
+ void OnSearchBoxPaste(int page_id, const string16& text);
void OnCountMouseover(int page_id);
void OnDeleteMostVisitedItem(int page_id, const GURL& url);
void OnUndoMostVisitedDeletion(int page_id, const GURL& url);
diff --git a/chrome/browser/ui/search/instant_page_unittest.cc b/chrome/browser/ui/search/instant_page_unittest.cc
index 3a537c4..c8e838c 100644
--- a/chrome/browser/ui/search/instant_page_unittest.cc
+++ b/chrome/browser/ui/search/instant_page_unittest.cc
@@ -46,6 +46,9 @@
content::PageTransition transition,
WindowOpenDisposition disposition,
bool is_search_type));
+ MOCK_METHOD2(PasteIntoOmnibox,
+ void(const content::WebContents* contents,
+ const string16& text));
MOCK_METHOD1(DeleteMostVisitedItem, void(const GURL& url));
MOCK_METHOD1(UndoMostVisitedDeletion, void(const GURL& url));
MOCK_METHOD0(UndoAllMostVisitedDeletions, void());
diff --git a/chrome/browser/ui/search/instant_tab.cc b/chrome/browser/ui/search/instant_tab.cc
index ef2500d..3112930 100644
--- a/chrome/browser/ui/search/instant_tab.cc
+++ b/chrome/browser/ui/search/instant_tab.cc
@@ -46,6 +46,10 @@
return true;
}
+bool InstantTab::ShouldProcessPasteIntoOmnibox() {
+ return true;
+}
+
bool InstantTab::ShouldProcessDeleteMostVisitedItem() {
return true;
}
diff --git a/chrome/browser/ui/search/instant_tab.h b/chrome/browser/ui/search/instant_tab.h
index 2aac53d..b608490 100644
--- a/chrome/browser/ui/search/instant_tab.h
+++ b/chrome/browser/ui/search/instant_tab.h
@@ -33,6 +33,7 @@
virtual bool ShouldProcessAboutToNavigateMainFrame() OVERRIDE;
virtual bool ShouldProcessFocusOmnibox() OVERRIDE;
virtual bool ShouldProcessNavigateToURL() OVERRIDE;
+ virtual bool ShouldProcessPasteIntoOmnibox() OVERRIDE;
virtual bool ShouldProcessDeleteMostVisitedItem() OVERRIDE;
virtual bool ShouldProcessUndoMostVisitedDeletion() OVERRIDE;
virtual bool ShouldProcessUndoAllMostVisitedDeletions() OVERRIDE;
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc
index 6dc1b7f..077e7f6 100644
--- a/chrome/browser/ui/search/search_tab_helper.cc
+++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -4,10 +4,13 @@
#include "chrome/browser/ui/search/search_tab_helper.h"
+#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/instant_service.h"
#include "chrome/browser/search/instant_service_factory.h"
#include "chrome/browser/search/search.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/navigation_controller.h"
@@ -57,6 +60,20 @@
contents->GetRenderProcessHost()->GetID());
}
+// Updates the location bar to reflect |contents| Instant support state.
+void UpdateLocationBar(content::WebContents* contents) {
+// iOS and Android doesn't use the Instant framework.
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+ if (!contents)
+ return;
+
+ Browser* browser = chrome::FindBrowserWithWebContents(contents);
+ if (!browser)
+ return;
+ browser->OnWebContentsInstantSupportDisabled(contents);
+#endif
+}
+
} // namespace
SearchTabHelper::SearchTabHelper(content::WebContents* web_contents)
@@ -107,8 +124,18 @@
if (!is_search_enabled_)
return;
- model_.SetInstantSupportState(instant_support ? INSTANT_SUPPORT_YES :
- INSTANT_SUPPORT_NO);
+ InstantSupportState new_state = instant_support ? INSTANT_SUPPORT_YES :
+ INSTANT_SUPPORT_NO;
+
+ model_.SetInstantSupportState(new_state);
+
+ content::NavigationEntry* entry =
+ web_contents_->GetController().GetVisibleEntry();
+ if (entry) {
+ chrome::SetInstantSupportStateInNavigationEntry(new_state, entry);
+ if (!instant_support)
+ UpdateLocationBar(web_contents_);
+ }
}
bool SearchTabHelper::SupportsInstant() const {
@@ -127,6 +154,10 @@
UpdateMode(true, false);
+ content::NavigationEntry* entry =
+ web_contents_->GetController().GetVisibleEntry();
+ DCHECK(entry);
+
// Already determined the instant support state for this page, do not reset
// the instant support state.
//
@@ -139,11 +170,22 @@
// crbug.com/251330 for more details.
if (load_details->is_in_page ||
load_details->type == content::NAVIGATION_TYPE_IN_PAGE) {
+ // When an "in-page" navigation happens, we will not receive a
+ // DidFinishLoad() event. Therefore, we will not determine the Instant
+ // support for the navigated page. So, copy over the Instant support from
+ // the previous entry. If the page does not support Instant, update the
+ // location bar from here to turn off search terms replacement.
+ chrome::SetInstantSupportStateInNavigationEntry(model_.instant_support(),
+ entry);
+ if (model_.instant_support() == INSTANT_SUPPORT_NO)
+ UpdateLocationBar(web_contents_);
return;
}
model_.SetInstantSupportState(INSTANT_SUPPORT_UNKNOWN);
model_.SetVoiceSearchSupported(false);
+ chrome::SetInstantSupportStateInNavigationEntry(model_.instant_support(),
+ entry);
}
void SearchTabHelper::DidNavigateMainFrame(
diff --git a/chrome/browser/ui/sync/one_click_signin_helper.cc b/chrome/browser/ui/sync/one_click_signin_helper.cc
index 17f2519..46f030d 100644
--- a/chrome/browser/ui/sync/one_click_signin_helper.cc
+++ b/chrome/browser/ui/sync/one_click_signin_helper.cc
@@ -93,7 +93,7 @@
const std::string& session_index,
const std::string& email,
const std::string& password,
- bool force_same_tab_navigation,
+ content::WebContents* web_contents,
bool untrusted_confirmation_required,
signin::Source source,
OneClickSigninSyncStarter::Callback callback);
@@ -104,7 +104,11 @@
std::string session_index;
std::string email;
std::string password;
- bool force_same_tab_navigation;
+
+ // Web contents in which the sync setup page should be displayed,
+ // if necessary. Can be NULL.
+ content::WebContents* web_contents;
+
OneClickSigninSyncStarter::ConfirmationRequired confirmation_required;
signin::Source source;
OneClickSigninSyncStarter::Callback callback;
@@ -116,7 +120,7 @@
const std::string& session_index,
const std::string& email,
const std::string& password,
- bool force_same_tab_navigation,
+ content::WebContents* web_contents,
bool untrusted_confirmation_required,
signin::Source source,
OneClickSigninSyncStarter::Callback callback)
@@ -126,7 +130,7 @@
session_index(session_index),
email(email),
password(password),
- force_same_tab_navigation(force_same_tab_navigation),
+ web_contents(web_contents),
source(source),
callback(callback) {
if (untrusted_confirmation_required) {
@@ -243,7 +247,7 @@
// The starter deletes itself once its done.
new OneClickSigninSyncStarter(args.profile, args.browser, args.session_index,
args.email, args.password, start_mode,
- args.force_same_tab_navigation,
+ args.web_contents,
args.confirmation_required,
args.source,
args.callback);
@@ -258,8 +262,6 @@
one_click_signin::HISTOGRAM_AUTO_WITH_DEFAULTS :
one_click_signin::HISTOGRAM_AUTO_WITH_ADVANCED;
break;
- action = one_click_signin::HISTOGRAM_AUTO_WITH_DEFAULTS;
- break;
case OneClickSigninHelper::AUTO_ACCEPT_CONFIGURE:
DCHECK(start_mode == OneClickSigninSyncStarter::CONFIGURE_SYNC_FIRST);
action = one_click_signin::HISTOGRAM_AUTO_WITH_ADVANCED;
@@ -1052,9 +1054,9 @@
void OneClickSigninHelper::DidNavigateMainFrame(
const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) {
- // If we navigate to a non-sign-in URL, make sure that the renderer process
- // is no longer considered the trusted sign-in process.
if (!SigninManager::IsWebBasedSigninFlowURL(params.url)) {
+ // Make sure the renderer process is no longer considered the trusted
+ // sign-in process when a navigation to a non-sign-in URL occurs.
Profile* profile =
Profile::FromBrowserContext(web_contents()->GetBrowserContext());
SigninManager* manager = profile ?
@@ -1062,6 +1064,14 @@
int process_id = web_contents()->GetRenderProcessHost()->GetID();
if (manager && manager->IsSigninProcess(process_id))
manager->ClearSigninProcess();
+
+ // If the navigation to a non-sign-in URL hasn't been triggered by the web
+ // contents, the sign in flow has been aborted and the state must be
+ // cleaned (crbug.com/269421).
+ if (!content::PageTransitionIsWebTriggerable(params.transition) &&
+ auto_accept_ != AUTO_ACCEPT_NONE) {
+ CleanTransientState();
+ }
}
}
@@ -1145,8 +1155,9 @@
// checked, the source parameter will indicate settings. This will only be
// communicated back to chrome when Gaia redirects to the continue URL, and
// this is considered here a last minute change to the source. See a little
- // further below for when this variable is set to true.
- bool force_same_tab_navigation = false;
+ // further below for when this variable is set to a web contents that must be
+ // used to show the sync setup page.
+ content::WebContents* sync_setup_contents = NULL;
if (!continue_url_match && IsValidGaiaSigninRedirectOrResponseURL(url))
return;
@@ -1182,8 +1193,10 @@
signin::Source source = signin::GetSourceForPromoURL(url);
if (source != source_) {
source_ = source;
- force_same_tab_navigation = source == signin::SOURCE_SETTINGS;
- switched_to_advanced_ = source == signin::SOURCE_SETTINGS;
+ if (source == signin::SOURCE_SETTINGS) {
+ sync_setup_contents = web_contents();
+ switched_to_advanced_ = true;
+ }
}
}
@@ -1204,12 +1217,13 @@
SigninManager::DisableOneClickSignIn(profile);
// Start syncing with the default settings - prompt the user to sign in
// first.
- StartSync(StartSyncArgs(profile, browser, auto_accept_,
- session_index_, email_, password_,
- false /* force_same_tab_navigation */,
- true /* confirmation_required */, source_,
- CreateSyncStarterCallback()),
- OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS);
+ StartSync(
+ StartSyncArgs(profile, browser, auto_accept_,
+ session_index_, email_, password_,
+ NULL /* don't force to show sync setup in same tab */,
+ true /* confirmation_required */, source_,
+ CreateSyncStarterCallback()),
+ OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS);
break;
case AUTO_ACCEPT_CONFIGURE:
LogOneClickHistogramValue(one_click_signin::HISTOGRAM_ACCEPTED);
@@ -1218,8 +1232,9 @@
// Display the extra confirmation (even in the SAML case) in case this
// was an untrusted renderer.
StartSync(
- StartSyncArgs(profile, browser, auto_accept_, session_index_, email_,
- password_, false /* force_same_tab_navigation */,
+ StartSyncArgs(profile, browser, auto_accept_,
+ session_index_, email_, password_,
+ NULL /* don't force to show sync setup in same tab */,
true /* confirmation_required */, source_,
CreateSyncStarterCallback()),
OneClickSigninSyncStarter::CONFIGURE_SYNC_FIRST);
@@ -1259,6 +1274,8 @@
// No need to display a second confirmation so pass false below.
// TODO(atwilson): Move this into OneClickSigninSyncStarter.
+ // If |sync_setup_contents| is deleted before the callback execution,
+ // the tab modal dialog is closed and the callback is never executed.
ConfirmEmailDialogDelegate::AskForConfirmation(
contents,
last_email,
@@ -1267,7 +1284,7 @@
&StartExplicitSync,
StartSyncArgs(profile, browser, auto_accept_,
session_index_, email_, password_,
- force_same_tab_navigation,
+ sync_setup_contents,
false /* confirmation_required */, source_,
CreateSyncStarterCallback()),
contents,
@@ -1275,7 +1292,7 @@
} else {
StartSync(
StartSyncArgs(profile, browser, auto_accept_, session_index_,
- email_, password_, force_same_tab_navigation,
+ email_, password_, sync_setup_contents,
untrusted_confirmation_required_, source_,
CreateSyncStarterCallback()),
start_mode);
diff --git a/chrome/browser/ui/sync/one_click_signin_helper.h b/chrome/browser/ui/sync/one_click_signin_helper.h
index 79d9086..46f7765 100644
--- a/chrome/browser/ui/sync/one_click_signin_helper.h
+++ b/chrome/browser/ui/sync/one_click_signin_helper.h
@@ -52,7 +52,7 @@
AUTO_ACCEPT_ACCEPTED,
// User has explicitly accepted to sign in, but wants to configure sync
- // settings before turing it on.
+ // settings before turning it on.
AUTO_ACCEPT_CONFIGURE,
// User has explicitly rejected to sign in. Furthermore, the user does
@@ -133,6 +133,8 @@
ShowSigninBubbleAfterSigninComplete);
FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperTest, SigninCancelled);
FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperTest, SigninFailed);
+ FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperTest,
+ CleanTransientStateOnNavigate);
FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest, CanOfferOnIOThread);
FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest,
CanOfferOnIOThreadIncognito);
diff --git a/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc b/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc
index aebcbfa..1406217 100644
--- a/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc
+++ b/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc
@@ -28,7 +28,9 @@
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/navigation_details.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/frame_navigate_params.h"
#include "content/public/common/password_form.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/mock_render_process_host.h"
@@ -670,6 +672,27 @@
EXPECT_EQ("user@gmail.com", signin_manager_->GetAuthenticatedUsername());
}
+// Checks that the state of OneClickSigninHelper is cleaned when there is a
+// navigation away from the sign in flow that is not triggered by the
+// web contents.
+TEST_F(OneClickSigninHelperTest, CleanTransientStateOnNavigate) {
+ content::WebContents* contents = web_contents();
+
+ OneClickSigninHelper::CreateForWebContents(contents);
+ OneClickSigninHelper* helper =
+ OneClickSigninHelper::FromWebContents(contents);
+ helper->SetDoNotClearPendingEmailForTesting();
+ helper->auto_accept_ = OneClickSigninHelper::AUTO_ACCEPT_EXPLICIT;
+
+ content::LoadCommittedDetails details;
+ content::FrameNavigateParams params;
+ params.url = GURL("http://crbug.com");
+ params.transition = content::PAGE_TRANSITION_TYPED;
+ helper->DidNavigateMainFrame(details, params);
+
+ EXPECT_EQ(OneClickSigninHelper::AUTO_ACCEPT_NONE, helper->auto_accept_);
+}
+
// I/O thread tests
TEST_F(OneClickSigninHelperIOTest, CanOfferOnIOThread) {
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
index d037dab..884c09d 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
@@ -48,12 +48,12 @@
const std::string& email,
const std::string& password,
StartSyncMode start_mode,
- bool force_same_tab_navigation,
+ content::WebContents* web_contents,
ConfirmationRequired confirmation_required,
signin::Source source,
Callback sync_setup_completed_callback)
- : start_mode_(start_mode),
- force_same_tab_navigation_(force_same_tab_navigation),
+ : content::WebContentsObserver(web_contents),
+ start_mode_(start_mode),
confirmation_required_(confirmation_required),
source_(source),
sync_setup_completed_callback_(sync_setup_completed_callback),
@@ -424,8 +424,8 @@
EnsureBrowser();
if (profile_sync_service) {
// Need to navigate to the settings page and display the sync UI.
- if (force_same_tab_navigation_) {
- ShowSyncSettingsPageOnSameTab();
+ if (web_contents()) {
+ ShowSyncSettingsPageInWebContents(web_contents());
} else {
// If the user is setting up sync for the first time, let them configure
// advanced sync settings. However, in the case of re-authentication,
@@ -459,12 +459,21 @@
service->SetSetupInProgress(false);
}
-void OneClickSigninSyncStarter::ShowSyncSettingsPageOnSameTab() {
+void OneClickSigninSyncStarter::ShowSyncSettingsPageInWebContents(
+ content::WebContents* contents) {
std::string url = std::string(chrome::kChromeUISettingsURL) +
chrome::kSyncSetupSubPage;
- chrome::NavigateParams params(
- browser_, GURL(url), content::PAGE_TRANSITION_AUTO_TOPLEVEL);
- params.disposition = CURRENT_TAB;
- params.window_action = chrome::NavigateParams::SHOW_WINDOW;
- chrome::Navigate(¶ms);
+ content::OpenURLParams params(GURL(url),
+ content::Referrer(),
+ CURRENT_TAB,
+ content::PAGE_TRANSITION_AUTO_TOPLEVEL,
+ false);
+ contents->OpenURL(params);
+
+ // Activate the tab.
+ Browser* browser = chrome::FindBrowserWithWebContents(contents);
+ int content_index =
+ browser->tab_strip_model()->GetIndexOfWebContents(contents);
+ browser->tab_strip_model()->ActivateTabAt(content_index,
+ false /* user_gesture */);
}
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.h b/chrome/browser/ui/sync/one_click_signin_sync_starter.h
index 3fc359e..11c3ce5 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.h
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.h
@@ -17,10 +17,15 @@
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h"
+#include "content/public/browser/web_contents_observer.h"
class Browser;
class ProfileSyncService;
+namespace content {
+class WebContents;
+} // namespace content
+
namespace policy {
class CloudPolicyClient;
}
@@ -29,7 +34,8 @@
// starts the sync machine. Instances of this class delete themselves once
// the job is done.
class OneClickSigninSyncStarter : public SigninTracker::Observer,
- public chrome::BrowserListObserver {
+ public chrome::BrowserListObserver,
+ public content::WebContentsObserver {
public:
enum StartSyncMode {
// Starts the process of signing the user in with the SigninManager, and
@@ -75,6 +81,9 @@
// OneClickSigninSyncStarter from a browser, provide both.
// If |display_confirmation| is true, the user will be prompted to confirm the
// signin before signin completes.
+ // |web_contents| is used to show the sync setup page, if necessary. If NULL,
+ // the sync setup page will be loaded in either a new tab or a tab that is
+ // already showing it.
// |callback| is always executed before OneClickSigninSyncStarter is deleted.
// It can be empty.
OneClickSigninSyncStarter(Profile* profile,
@@ -83,7 +92,7 @@
const std::string& email,
const std::string& password,
StartSyncMode start_mode,
- bool force_same_tab_navigation,
+ content::WebContents* web_contents,
ConfirmationRequired display_confirmation,
signin::Source source,
Callback callback);
@@ -178,8 +187,8 @@
// dialog if |configure_sync| is true.
void ShowSettingsPageInNewTab(bool configure_sync);
- // Displays the sync configuration UI in the same tab.
- void ShowSyncSettingsPageOnSameTab();
+ // Displays the sync configuration UI in the provided web contents.
+ void ShowSyncSettingsPageInWebContents(content::WebContents* contents);
// Shows the post-signin confirmation bubble. If |custom_message| is empty,
// the default "You are signed in" message is displayed.
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter_unittest.cc b/chrome/browser/ui/sync/one_click_signin_sync_starter_unittest.cc
index 2d12642..57820cb 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter_unittest.cc
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter_unittest.cc
@@ -60,7 +60,7 @@
kTestingUsername,
std::string(),
OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS,
- false,
+ NULL,
OneClickSigninSyncStarter::NO_CONFIRMATION,
signin::SOURCE_UNKNOWN,
callback
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.cc b/chrome/browser/ui/toolbar/wrench_menu_model.cc
index ab5998f..38118fa 100644
--- a/chrome/browser/ui/toolbar/wrench_menu_model.cc
+++ b/chrome/browser/ui/toolbar/wrench_menu_model.cc
@@ -468,6 +468,44 @@
tab_strip_model_(NULL) {
}
+bool WrenchMenuModel::ShouldShowNewIncognitoWindowMenuItem() {
+ if (browser_->profile()->IsManaged())
+ return false;
+
+#if defined(OS_WIN)
+ if (win8::IsSingleWindowMetroMode() &&
+ browser_->profile()->HasOffTheRecordProfile()) {
+ return false;
+ }
+#endif
+
+#if defined(OS_CHROMEOS)
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ chromeos::switches::kGuestSession)) {
+ return false;
+ }
+#endif
+
+ return true;
+}
+
+bool WrenchMenuModel::ShouldShowNewWindowMenuItem() {
+#if defined(OS_WIN)
+ if (!win8::IsSingleWindowMetroMode())
+ return true;
+
+ // In Win8's single window Metro mode, we only show the New Window options
+ // if there isn't already a window of the requested type (incognito or not)
+ // that is available.
+ return browser_->profile()->IsOffTheRecord() &&
+ !chrome::FindBrowserWithProfile(
+ browser_->profile()->GetOriginalProfile(),
+ browser_->host_desktop_type());
+#else
+ return true;
+#endif
+}
+
void WrenchMenuModel::Build(bool is_new_menu) {
#if defined(OS_WIN)
AddItem(IDC_VIEW_INCOMPATIBILITIES,
@@ -480,25 +518,13 @@
#endif
AddItemWithStringId(IDC_NEW_TAB, IDS_NEW_TAB);
-#if defined(OS_WIN)
- if (win8::IsSingleWindowMetroMode()) {
- // In Win8's single window Metro mode, we only show the New Window options
- // if there isn't already a window of the requested type (incognito or not)
- // that is available.
- if (browser_->profile()->IsOffTheRecord()) {
- if (chrome::FindBrowserWithProfile(
- browser_->profile()->GetOriginalProfile(),
- browser_->host_desktop_type()) == NULL) {
- AddItemWithStringId(IDC_NEW_WINDOW, IDS_NEW_WINDOW);
- }
- } else if (!browser_->profile()->HasOffTheRecordProfile()) {
- AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW, IDS_NEW_INCOGNITO_WINDOW);
- }
- } else {
- AddItemWithStringId(IDC_NEW_WINDOW, IDS_NEW_WINDOW);
+ if (ShouldShowNewIncognitoWindowMenuItem())
AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW, IDS_NEW_INCOGNITO_WINDOW);
- }
-#if !defined(NDEBUG) && defined(USE_ASH)
+
+ if (ShouldShowNewWindowMenuItem())
+ AddItemWithStringId(IDC_NEW_WINDOW, IDS_NEW_WINDOW);
+
+#if defined(OS_WIN) && !defined(NDEBUG) && defined(USE_ASH)
if (base::win::GetVersion() < base::win::VERSION_WIN8 &&
chrome::HOST_DESKTOP_TYPE_NATIVE != chrome::HOST_DESKTOP_TYPE_ASH) {
AddItemWithStringId(IDC_TOGGLE_ASH_DESKTOP,
@@ -506,17 +532,6 @@
IDS_OPEN_ASH_DESKTOP);
}
#endif
-#else // defined(OS_WIN)
- AddItemWithStringId(IDC_NEW_WINDOW, IDS_NEW_WINDOW);
-#if defined(OS_CHROMEOS)
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- chromeos::switches::kGuestSession))
- AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW, IDS_NEW_INCOGNITO_WINDOW);
-#else
- AddItemWithStringId(IDC_NEW_INCOGNITO_WINDOW, IDS_NEW_INCOGNITO_WINDOW);
-#endif
-
-#endif // else of defined(OS_WIN)
bookmark_sub_menu_model_.reset(new BookmarkSubMenuModel(this, browser_));
AddSubMenuWithStringId(IDC_BOOKMARKS_MENU, IDS_BOOKMARKS_MENU,
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.h b/chrome/browser/ui/toolbar/wrench_menu_model.h
index cf9df0d..417e023 100644
--- a/chrome/browser/ui/toolbar/wrench_menu_model.h
+++ b/chrome/browser/ui/toolbar/wrench_menu_model.h
@@ -149,6 +149,9 @@
void OnZoomLevelChanged(const content::HostZoomMap::ZoomLevelChange& change);
+ bool ShouldShowNewIncognitoWindowMenuItem();
+ bool ShouldShowNewWindowMenuItem();
+
// Models for the special menu items with buttons.
scoped_ptr<ui::ButtonMenuItemModel> edit_menu_item_model_;
scoped_ptr<ui::ButtonMenuItemModel> zoom_menu_item_model_;
diff --git a/chrome/browser/ui/uma_browsing_activity_observer.cc b/chrome/browser/ui/uma_browsing_activity_observer.cc
index 1db2777..046da4f 100644
--- a/chrome/browser/ui/uma_browsing_activity_observer.cc
+++ b/chrome/browser/ui/uma_browsing_activity_observer.cc
@@ -6,14 +6,19 @@
#include "base/metrics/histogram.h"
#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/search_engines/template_url_service.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_iterator.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "content/public/browser/navigation_controller.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/render_process_host.h"
+#include "content/public/browser/user_metrics.h"
namespace chrome {
namespace {
@@ -47,6 +52,20 @@
if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) {
const content::LoadCommittedDetails& load =
*content::Details<content::LoadCommittedDetails>(details).ptr();
+
+ content::NavigationController* controller =
+ content::Source<content::NavigationController>(source).ptr();
+ // Track whether the page loaded is a search results page (SRP). Track
+ // the non-SRP navigations as well so there is a control.
+ content::RecordAction(content::UserMetricsAction("NavEntryCommitted"));
+ if (TemplateURLServiceFactory::GetForProfile(
+ Profile::FromBrowserContext(controller->GetBrowserContext()))->
+ IsSearchResultsPageFromDefaultSearchProvider(
+ load.entry->GetURL())) {
+ content::RecordAction(
+ content::UserMetricsAction("NavEntryCommitted.SRP"));
+ }
+
if (!load.is_navigation_to_different_page())
return; // Don't log for subframes or other trivial types.
diff --git a/chrome/browser/ui/views/app_list/app_list_controller_win.cc b/chrome/browser/ui/views/app_list/app_list_controller_win.cc
index b87598a..46bdc93 100644
--- a/chrome/browser/ui/views/app_list/app_list_controller_win.cc
+++ b/chrome/browser/ui/views/app_list/app_list_controller_win.cc
@@ -281,6 +281,138 @@
DISALLOW_COPY_AND_ASSIGN(ScopedKeepAlive);
};
+class ActivationTracker {
+ public:
+ ActivationTracker(app_list::AppListView* view,
+ const base::Closure& on_active_lost)
+ : view_(view),
+ on_active_lost_(on_active_lost),
+ regain_next_lost_focus_(false),
+ preserving_focus_for_taskbar_menu_(false) {
+ }
+
+ void RegainNextLostFocus() {
+ regain_next_lost_focus_ = true;
+ }
+
+ void OnActivationChanged(bool active) {
+ const int kFocusCheckIntervalMS = 250;
+ if (active) {
+ timer_.Stop();
+ return;
+ }
+
+ preserving_focus_for_taskbar_menu_ = false;
+ timer_.Start(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kFocusCheckIntervalMS), this,
+ &ActivationTracker::CheckTaskbarOrViewHasFocus);
+ }
+
+ void OnViewHidden() {
+ timer_.Stop();
+ }
+
+ void CheckTaskbarOrViewHasFocus() {
+ // Remember if the taskbar had focus without the right mouse button being
+ // down.
+ bool was_preserving_focus = preserving_focus_for_taskbar_menu_;
+ preserving_focus_for_taskbar_menu_ = false;
+
+ // First get the taskbar and jump lists windows (the jump list is the
+ // context menu which the taskbar uses).
+ HWND jump_list_hwnd = FindWindow(L"DV2ControlHost", NULL);
+ HWND taskbar_hwnd = FindWindow(kTrayClassName, NULL);
+
+ // This code is designed to hide the app launcher when it loses focus,
+ // except for the cases necessary to allow the launcher to be pinned or
+ // closed via the taskbar context menu.
+ // First work out if the left or right button is currently down.
+ int swapped = GetSystemMetrics(SM_SWAPBUTTON);
+ int left_button = swapped ? VK_RBUTTON : VK_LBUTTON;
+ bool left_button_down = GetAsyncKeyState(left_button) < 0;
+ int right_button = swapped ? VK_LBUTTON : VK_RBUTTON;
+ bool right_button_down = GetAsyncKeyState(right_button) < 0;
+
+ // Now get the window that currently has focus.
+ HWND focused_hwnd = GetForegroundWindow();
+ if (!focused_hwnd) {
+ // Sometimes the focused window is NULL. This can happen when the focus is
+ // changing due to a mouse button press. If the button is still being
+ // pressed the launcher should not be hidden.
+ if (right_button_down || left_button_down)
+ return;
+
+ // If the focused window is NULL, and the mouse button is not being
+ // pressed, then the launcher no longer has focus.
+ on_active_lost_.Run();
+ return;
+ }
+
+ while (focused_hwnd) {
+ // If the focused window is the right click menu (called a jump list) or
+ // the app list, don't hide the launcher.
+ if (focused_hwnd == jump_list_hwnd ||
+ focused_hwnd == view_->GetHWND()) {
+ return;
+ }
+
+ if (focused_hwnd == taskbar_hwnd) {
+ // If the focused window is the taskbar, and the right button is down,
+ // don't hide the launcher as the user might be bringing up the menu.
+ if (right_button_down)
+ return;
+
+ // There is a short period between the right mouse button being down
+ // and the menu gaining focus, where the taskbar has focus and no button
+ // is down. If the taskbar is observed in this state once the launcher
+ // is not dismissed. If it happens twice in a row it is dismissed.
+ if (!was_preserving_focus) {
+ preserving_focus_for_taskbar_menu_ = true;
+ return;
+ }
+
+ break;
+ }
+ focused_hwnd = GetParent(focused_hwnd);
+ }
+
+ if (regain_next_lost_focus_) {
+ regain_next_lost_focus_ = false;
+ view_->GetWidget()->Activate();
+ return;
+ }
+
+ // If we get here, the focused window is not the taskbar, it's context menu,
+ // or the app list.
+ on_active_lost_.Run();
+ }
+
+ private:
+ // The window to track the active state of.
+ app_list::AppListView* view_;
+
+ // Called to request |view_| be closed.
+ base::Closure on_active_lost_;
+
+ // True if we are anticipating that the app list will lose focus, and we want
+ // to take it back. This is used when switching out of Metro mode, and the
+ // browser regains focus after showing the app list.
+ bool regain_next_lost_focus_;
+
+ // When the context menu on the app list's taskbar icon is brought up the
+ // app list should not be hidden, but it should be if the taskbar is clicked
+ // on. There can be a period of time when the taskbar gets focus between a
+ // right mouse click and the menu showing; to prevent hiding the app launcher
+ // when this happens it is kept visible if the taskbar is seen briefly without
+ // the right mouse button down, but not if this happens twice in a row.
+ bool preserving_focus_for_taskbar_menu_;
+
+ // Timer used to check if the taskbar or app list is active. Using a timer
+ // means we don't need to hook Windows, which is apparently not possible
+ // since Vista (and is not nice at any time).
+ base::RepeatingTimer<ActivationTracker> timer_;
+};
+
// The AppListController class manages global resources needed for the app
// list to operate, and controls when the app list is opened and closed.
// TODO(tapted): Rename this class to AppListServiceWin and move entire file to
@@ -307,6 +439,7 @@
// AppListService overrides:
virtual void HandleFirstRun() OVERRIDE;
virtual void Init(Profile* initial_profile) OVERRIDE;
+ virtual void CreateForProfile(Profile* requested_profile) OVERRIDE;
virtual void ShowForProfile(Profile* requested_profile) OVERRIDE;
virtual void DismissAppList() OVERRIDE;
virtual bool IsAppListVisible() const OVERRIDE;
@@ -332,9 +465,12 @@
void LoadProfileForWarmup();
void OnLoadProfileForWarmup(Profile* initial_profile);
- // Create or recreate, and initialize |current_view_| from
- // |requested_profile|.
- void PopulateViewFromProfile(Profile* requested_profile);
+ // Creates an AppListView.
+ app_list::AppListView* CreateAppListView();
+
+ // Customizes the app list |hwnd| for Windows (eg: disable aero peek, set up
+ // restart params).
+ void SetWindowAttributes(HWND hwnd);
// Utility methods for showing the app list.
gfx::Point FindAnchorPoint(const gfx::Display& display,
@@ -348,9 +484,6 @@
// periodically whenever the app list does not have focus.
void CheckTaskbarOrViewHasFocus();
- // Returns the underlying HWND for the AppList.
- HWND GetAppListHWND() const;
-
// Utilities to manage browser process keep alive for the view itself. Note
// keep alives are also used when asynchronously loading profiles.
void EnsureHaveKeepAliveForView();
@@ -359,13 +492,7 @@
// Weak pointer. The view manages its own lifetime.
app_list::AppListView* current_view_;
- // Weak pointer. The view owns the view delegate.
- AppListViewDelegate* view_delegate_;
-
- // Timer used to check if the taskbar or app list is active. Using a timer
- // means we don't need to hook Windows, which is apparently not possible
- // since Vista (and is not nice at any time).
- base::RepeatingTimer<AppListController> timer_;
+ scoped_ptr<ActivationTracker> activation_tracker_;
app_list::PaginationModel pagination_model_;
@@ -375,19 +502,6 @@
// Used to keep the browser process alive while the app list is visible.
scoped_ptr<ScopedKeepAlive> keep_alive_;
- // True if we are anticipating that the app list will lose focus, and we want
- // to take it back. This is used when switching out of Metro mode, and the
- // browser regains focus after showing the app list.
- bool regain_first_lost_focus_;
-
- // When the context menu on the app list's taskbar icon is brought up the
- // app list should not be hidden, but it should be if the taskbar is clicked
- // on. There can be a period of time when the taskbar gets focus between a
- // right mouse click and the menu showing; to prevent hiding the app launcher
- // when this happens it is kept visible if the taskbar is seen briefly without
- // the right mouse button down, but not if this happens twice in a row.
- bool preserving_focus_for_taskbar_menu_;
-
bool enable_app_list_on_next_init_;
base::WeakPtrFactory<AppListController> weak_factory_;
@@ -482,10 +596,7 @@
AppListController::AppListController()
: current_view_(NULL),
- view_delegate_(NULL),
can_close_app_list_(true),
- regain_first_lost_focus_(false),
- preserving_focus_for_taskbar_menu_(false),
enable_app_list_on_next_init_(false),
weak_factory_(this) {}
@@ -536,7 +647,7 @@
SetProfilePath(requested_profile->GetPath());
DismissAppList();
- PopulateViewFromProfile(requested_profile);
+ CreateForProfile(requested_profile);
DCHECK(current_view_);
EnsureHaveKeepAliveForView();
@@ -550,32 +661,45 @@
void AppListController::ShowAppListDuringModeSwitch(
Profile* requested_profile) {
- regain_first_lost_focus_ = true;
ShowForProfile(requested_profile);
+ activation_tracker_->RegainNextLostFocus();
}
-void AppListController::PopulateViewFromProfile(Profile* requested_profile) {
+void AppListController::CreateForProfile(Profile* requested_profile) {
+ // Aura has problems with layered windows and bubble delegates. The app
+ // launcher has a trick where it only hides the window when it is dismissed,
+ // reshowing it again later. This does not work with win aura for some
+ // reason. This change temporarily makes it always get recreated, only on win
+ // aura. See http://crbug.com/176186.
#if !defined(USE_AURA)
if (requested_profile == profile())
return;
#endif
SetProfile(requested_profile);
+ current_view_ = CreateAppListView();
+ activation_tracker_.reset(new ActivationTracker(current_view_,
+ base::Bind(&AppListController::DismissAppList, base::Unretained(this))));
+}
+app_list::AppListView* AppListController::CreateAppListView() {
// The controller will be owned by the view delegate, and the delegate is
// owned by the app list view. The app list view manages it's own lifetime.
- view_delegate_ = new AppListViewDelegate(CreateControllerDelegate(),
- profile());
- current_view_ = new app_list::AppListView(view_delegate_);
+ AppListViewDelegate* view_delegate =
+ new AppListViewDelegate(CreateControllerDelegate(), profile());
+ app_list::AppListView* view = new app_list::AppListView(view_delegate);
gfx::Point cursor = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
- current_view_->InitAsBubble(NULL,
- &pagination_model_,
- NULL,
- cursor,
- views::BubbleBorder::FLOAT,
- false /* border_accepts_events */);
- HWND hwnd = GetAppListHWND();
+ view->InitAsBubble(NULL,
+ &pagination_model_,
+ NULL,
+ cursor,
+ views::BubbleBorder::FLOAT,
+ false /* border_accepts_events */);
+ SetWindowAttributes(view->GetHWND());
+ return view;
+}
+void AppListController::SetWindowAttributes(HWND hwnd) {
// Vista and lower do not offer pinning to the taskbar, which makes any
// presence on the taskbar useless. So, hide the window on the taskbar
// for these versions of Windows.
@@ -609,7 +733,7 @@
void AppListController::DismissAppList() {
if (IsAppListVisible() && can_close_app_list_) {
current_view_->GetWidget()->Hide();
- timer_.Stop();
+ activation_tracker_->OnViewHidden();
FreeAnyKeepAliveForView();
}
}
@@ -617,22 +741,12 @@
void AppListController::AppListClosing() {
FreeAnyKeepAliveForView();
current_view_ = NULL;
- view_delegate_ = NULL;
+ activation_tracker_.reset();
SetProfile(NULL);
- timer_.Stop();
}
void AppListController::AppListActivationChanged(bool active) {
- const int kFocusCheckIntervalMS = 250;
- if (active) {
- timer_.Stop();
- return;
- }
-
- preserving_focus_for_taskbar_menu_ = false;
- timer_.Start(FROM_HERE,
- base::TimeDelta::FromMilliseconds(kFocusCheckIntervalMS), this,
- &AppListController::CheckTaskbarOrViewHasFocus);
+ activation_tracker_->OnActivationChanged(active);
}
// Attempts to find the bounds of the Windows taskbar. Returns true on success.
@@ -748,97 +862,6 @@
return result;
}
-void AppListController::CheckTaskbarOrViewHasFocus() {
- // Remember if the taskbar had focus without the right mouse button being
- // down.
- bool was_preserving_focus = preserving_focus_for_taskbar_menu_;
- preserving_focus_for_taskbar_menu_ = false;
-
- // Don't bother checking if the view has been closed.
- if (!current_view_)
- return;
-
- // First get the taskbar and jump lists windows (the jump list is the
- // context menu which the taskbar uses).
- HWND jump_list_hwnd = FindWindow(L"DV2ControlHost", NULL);
- HWND taskbar_hwnd = FindWindow(kTrayClassName, NULL);
-
- HWND app_list_hwnd = GetAppListHWND();
-
- // This code is designed to hide the app launcher when it loses focus, except
- // for the cases necessary to allow the launcher to be pinned or closed via
- // the taskbar context menu.
- // First work out if the left or right button is currently down.
- int swapped = GetSystemMetrics(SM_SWAPBUTTON);
- int left_button = swapped ? VK_RBUTTON : VK_LBUTTON;
- bool left_button_down = GetAsyncKeyState(left_button) < 0;
- int right_button = swapped ? VK_LBUTTON : VK_RBUTTON;
- bool right_button_down = GetAsyncKeyState(right_button) < 0;
-
- // Now get the window that currently has focus.
- HWND focused_hwnd = GetForegroundWindow();
- if (!focused_hwnd) {
- // Sometimes the focused window is NULL. This can happen when the focus is
- // changing due to a mouse button press. If the button is still being
- // pressed the launcher should not be hidden.
- if (right_button_down || left_button_down)
- return;
-
- // If the focused window is NULL, and the mouse button is not being pressed,
- // then the launcher no longer has focus so hide it.
- DismissAppList();
- return;
- }
-
- while (focused_hwnd) {
- // If the focused window is the right click menu (called a jump list) or
- // the app list, don't hide the launcher.
- if (focused_hwnd == jump_list_hwnd ||
- focused_hwnd == app_list_hwnd) {
- return;
- }
-
- if (focused_hwnd == taskbar_hwnd) {
- // If the focused window is the taskbar, and the right button is down,
- // don't hide the launcher as the user might be bringing up the menu.
- if (right_button_down)
- return;
-
- // There is a short period between the right mouse button being down
- // and the menu gaining focus, where the taskbar has focus and no button
- // is down. If the taskbar is observed in this state once the launcher
- // is not dismissed. If it happens twice in a row it is dismissed.
- if (!was_preserving_focus) {
- preserving_focus_for_taskbar_menu_ = true;
- return;
- }
-
- break;
- }
- focused_hwnd = GetParent(focused_hwnd);
- }
-
- if (regain_first_lost_focus_) {
- regain_first_lost_focus_ = false;
- current_view_->GetWidget()->Activate();
- return;
- }
-
- // If we get here, the focused window is not the taskbar, it's context menu,
- // or the app list, so close the app list.
- DismissAppList();
-}
-
-HWND AppListController::GetAppListHWND() const {
-#if defined(USE_AURA)
- gfx::NativeWindow window =
- current_view_->GetWidget()->GetTopLevelWidget()->GetNativeWindow();
- return window->GetRootWindow()->GetAcceleratedWidget();
-#else
- return current_view_->GetWidget()->GetTopLevelWidget()->GetNativeWindow();
-#endif
-}
-
void AppListController::EnsureHaveKeepAliveForView() {
if (!keep_alive_)
keep_alive_.reset(new ScopedKeepAlive());
@@ -853,7 +876,7 @@
if (!IsWarmupNeeded())
return;
- PopulateViewFromProfile(initial_profile);
+ CreateForProfile(initial_profile);
current_view_->Prerender();
}
@@ -877,6 +900,7 @@
if (enable_app_list_on_next_init_) {
enable_app_list_on_next_init_ = false;
EnableAppList(initial_profile);
+ CreateShortcut();
}
PrefService* prefs = g_browser_process->local_state();
@@ -906,6 +930,7 @@
chrome_launcher_support::USER_LEVEL_INSTALLATION);
}
EnableAppList(initial_profile);
+ CreateShortcut();
}
#endif
diff --git a/chrome/browser/ui/views/apps/native_app_window_views.cc b/chrome/browser/ui/views/apps/native_app_window_views.cc
index 31b52a7..3ceb272 100644
--- a/chrome/browser/ui/views/apps/native_app_window_views.cc
+++ b/chrome/browser/ui/views/apps/native_app_window_views.cc
@@ -317,12 +317,26 @@
// On Ash, restore fullscreen.
if (IsFullscreen())
return ui::SHOW_STATE_FULLSCREEN;
+
// Use kRestoreShowStateKey in case a window is minimized/hidden.
ui::WindowShowState restore_state =
window_->GetNativeWindow()->GetProperty(
aura::client::kRestoreShowStateKey);
- if (restore_state != ui::SHOW_STATE_MINIMIZED)
- return restore_state;
+ // Whitelist states to return so that invalid and transient states
+ // are not saved and used to restore windows when they are recreated.
+ switch (restore_state) {
+ case ui::SHOW_STATE_NORMAL:
+ case ui::SHOW_STATE_MAXIMIZED:
+ case ui::SHOW_STATE_FULLSCREEN:
+ case ui::SHOW_STATE_DETACHED:
+ return restore_state;
+
+ case ui::SHOW_STATE_DEFAULT:
+ case ui::SHOW_STATE_MINIMIZED:
+ case ui::SHOW_STATE_INACTIVE:
+ case ui::SHOW_STATE_END:
+ return ui::SHOW_STATE_NORMAL;
+ }
#endif
return ui::SHOW_STATE_NORMAL;
}
diff --git a/chrome/browser/ui/views/autofill/autofill_credit_card_bubble_views.cc b/chrome/browser/ui/views/autofill/autofill_credit_card_bubble_views.cc
deleted file mode 100644
index 48f7167..0000000
--- a/chrome/browser/ui/views/autofill/autofill_credit_card_bubble_views.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/views/autofill/autofill_credit_card_bubble_views.h"
-
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-#include "ui/gfx/font.h"
-#include "ui/gfx/insets.h"
-#include "ui/gfx/size.h"
-#include "ui/views/bubble/bubble_frame_view.h"
-#include "ui/views/controls/link.h"
-#include "ui/views/controls/styled_label.h"
-#include "ui/views/layout/box_layout.h"
-#include "ui/views/layout/layout_constants.h"
-#include "ui/views/view.h"
-#include "ui/views/widget/widget.h"
-
-namespace autofill {
-
-namespace {
-
-// Get the view this bubble will be anchored to via |controller|.
-views::View* GetAnchor(
- const base::WeakPtr<AutofillCreditCardBubbleController>& controller) {
- Browser* browser =
- chrome::FindBrowserWithWebContents(controller->web_contents());
- BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
- return browser_view->GetLocationBarView()->autofill_credit_card_view();
-}
-
-} // namespace
-
-AutofillCreditCardBubbleViews::~AutofillCreditCardBubbleViews() {}
-
-void AutofillCreditCardBubbleViews::Show() {
- // TODO(dbeam): investigate why this steals focus from the web contents.
- views::BubbleDelegateView::CreateBubble(this);
-
- GetWidget()->Show();
-
- // This bubble doesn't render correctly on Windows without calling
- // |SizeToContents()|. This must be called after showing the widget.
- SizeToContents();
-}
-
-void AutofillCreditCardBubbleViews::Hide() {
- GetWidget()->Close();
-}
-
-bool AutofillCreditCardBubbleViews::IsHiding() const {
- return GetWidget() && GetWidget()->IsClosed();
-}
-
-string16 AutofillCreditCardBubbleViews::GetWindowTitle() const {
- return controller_->BubbleTitle();
-}
-
-void AutofillCreditCardBubbleViews::Init() {
- SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
- views::kRelatedControlVerticalSpacing));
-
- views::StyledLabel::RangeStyleInfo bold;
- bold.font_style = gfx::Font::BOLD;
- const std::vector<ui::Range>& ranges = controller_->BubbleTextRanges();
-
- views::StyledLabel* contents =
- new views::StyledLabel(controller_->BubbleText(), NULL);
- for (size_t i = 0; i < ranges.size(); ++i) {
- contents->AddStyleRange(ranges[i], bold);
- }
- AddChildView(contents);
-
- views::Link* link = new views::Link();
- link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- link->SetText(controller_->LinkText());
- link->set_listener(this);
- AddChildView(link);
-}
-
-gfx::Size AutofillCreditCardBubbleViews::GetPreferredSize() {
- return gfx::Size(
- AutofillCreditCardBubbleViews::kContentWidth,
- GetHeightForWidth(AutofillCreditCardBubble::kContentWidth));
-}
-
-void AutofillCreditCardBubbleViews::LinkClicked(views::Link* source,
- int event_flags) {
- if (controller_)
- controller_->OnLinkClicked();
-}
-
-// static
-base::WeakPtr<AutofillCreditCardBubble> AutofillCreditCardBubble::Create(
- const base::WeakPtr<AutofillCreditCardBubbleController>& controller) {
- AutofillCreditCardBubbleViews* bubble =
- new AutofillCreditCardBubbleViews(controller);
- return bubble->weak_ptr_factory_.GetWeakPtr();
-}
-
-AutofillCreditCardBubbleViews::AutofillCreditCardBubbleViews(
- const base::WeakPtr<AutofillCreditCardBubbleController>& controller)
- : BubbleDelegateView(GetAnchor(controller), views::BubbleBorder::TOP_RIGHT),
- controller_(controller),
- weak_ptr_factory_(this) {
- // Match bookmarks bubble view's anchor view insets and margins.
- set_anchor_view_insets(gfx::Insets(7, 0, 7, 0));
- set_margins(gfx::Insets(0, 19, 18, 18));
- set_move_with_anchor(true);
-}
-
-} // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/autofill_credit_card_bubble_views.h b/chrome/browser/ui/views/autofill/autofill_credit_card_bubble_views.h
deleted file mode 100644
index 9d8e8f1..0000000
--- a/chrome/browser/ui/views/autofill/autofill_credit_card_bubble_views.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_VIEWS_H_
-#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_VIEWS_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble.h"
-#include "ui/views/bubble/bubble_delegate.h"
-#include "ui/views/controls/link_listener.h"
-
-namespace autofill {
-
-class AutofillCreditCardBubbleController;
-
-// Views toolkit implementation of AutofillCreditCard bubble (an educational
-// bubble shown after a successful submission of the Autofill dialog).
-class AutofillCreditCardBubbleViews : public AutofillCreditCardBubble,
- public views::BubbleDelegateView,
- public views::LinkListener {
- public:
- virtual ~AutofillCreditCardBubbleViews();
-
- // AutofillCreditCardBubble:
- virtual void Show() OVERRIDE;
- virtual void Hide() OVERRIDE;
- virtual bool IsHiding() const OVERRIDE;
-
- // views::BubbleDelegateView:
- virtual string16 GetWindowTitle() const OVERRIDE;
- virtual void Init() OVERRIDE;
- virtual gfx::Size GetPreferredSize() OVERRIDE;
-
- // views::LinkListener:
- virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
-
- private:
- friend base::WeakPtr<AutofillCreditCardBubble>
- AutofillCreditCardBubble::Create(
- const base::WeakPtr<AutofillCreditCardBubbleController>& controller);
-
- explicit AutofillCreditCardBubbleViews(
- const base::WeakPtr<AutofillCreditCardBubbleController>& controller);
-
- // Controller that drives this bubble. Invalid when hiding.
- base::WeakPtr<AutofillCreditCardBubbleController> controller_;
-
- base::WeakPtrFactory<AutofillCreditCardBubble> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(AutofillCreditCardBubbleViews);
-};
-
-} // namespace autofill
-
-#endif // CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_CREDIT_CARD_BUBBLE_VIEWS_H_
diff --git a/chrome/browser/ui/views/autofill/generated_credit_card_bubble_views.cc b/chrome/browser/ui/views/autofill/generated_credit_card_bubble_views.cc
new file mode 100644
index 0000000..8bc4766
--- /dev/null
+++ b/chrome/browser/ui/views/autofill/generated_credit_card_bubble_views.cc
@@ -0,0 +1,108 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/autofill/generated_credit_card_bubble_views.h"
+
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/size.h"
+#include "ui/views/bubble/bubble_frame_view.h"
+#include "ui/views/controls/styled_label.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/layout_constants.h"
+#include "ui/views/widget/widget.h"
+
+namespace autofill {
+
+namespace {
+
+// Get the view this bubble will be anchored to via |controller|.
+views::View* GetAnchor(
+ const base::WeakPtr<GeneratedCreditCardBubbleController>& controller) {
+ BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(
+ chrome::FindBrowserWithWebContents(controller->web_contents()));
+ return browser_view->GetLocationBarView()->generated_credit_card_view();
+}
+
+} // namespace
+
+GeneratedCreditCardBubbleViews::~GeneratedCreditCardBubbleViews() {}
+
+void GeneratedCreditCardBubbleViews::Show() {
+ // TODO(dbeam): investigate why this steals focus from the web contents.
+ views::BubbleDelegateView::CreateBubble(this)->Show();
+
+ // This bubble doesn't render correctly on Windows without calling
+ // |SizeToContents()|. This must be called after showing the widget.
+ SizeToContents();
+}
+
+void GeneratedCreditCardBubbleViews::Hide() {
+ GetWidget()->Close();
+}
+
+bool GeneratedCreditCardBubbleViews::IsHiding() const {
+ return GetWidget() && GetWidget()->IsClosed();
+}
+
+gfx::Size GeneratedCreditCardBubbleViews::GetPreferredSize() {
+ return gfx::Size(
+ GeneratedCreditCardBubbleView::kContentsWidth,
+ GetHeightForWidth(GeneratedCreditCardBubbleViews::kContentsWidth));
+}
+
+base::string16 GeneratedCreditCardBubbleViews::GetWindowTitle() const {
+ return controller_ ? controller_->TitleText() : base::string16();
+}
+
+void GeneratedCreditCardBubbleViews::Init() {
+ SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
+ views::kRelatedControlVerticalSpacing));
+
+ const base::string16& contents_text = controller_->ContentsText();
+ views::StyledLabel* contents = new views::StyledLabel(contents_text, this);
+
+ const std::vector<TextRange>& text_ranges = controller_->ContentsTextRanges();
+ for (size_t i = 0; i < text_ranges.size(); ++i) {
+ views::StyledLabel::RangeStyleInfo style;
+
+ if (text_ranges[i].is_link)
+ style = views::StyledLabel::RangeStyleInfo::CreateForLink();
+ else
+ style.font_style = gfx::Font::BOLD;
+
+ contents->AddStyleRange(text_ranges[i].range, style);
+ }
+
+ AddChildView(contents);
+}
+
+void GeneratedCreditCardBubbleViews::StyledLabelLinkClicked(const ui::Range& r,
+ int event_flags) {
+ if (controller_)
+ controller_->OnLinkClicked();
+}
+
+// static
+base::WeakPtr<GeneratedCreditCardBubbleView>
+ GeneratedCreditCardBubbleView::Create(
+ const base::WeakPtr<GeneratedCreditCardBubbleController>& controller) {
+ return (new GeneratedCreditCardBubbleViews(controller))->weak_ptr_factory_.
+ GetWeakPtr();
+}
+
+GeneratedCreditCardBubbleViews::GeneratedCreditCardBubbleViews(
+ const base::WeakPtr<GeneratedCreditCardBubbleController>& controller)
+ : BubbleDelegateView(GetAnchor(controller), views::BubbleBorder::TOP_RIGHT),
+ controller_(controller),
+ weak_ptr_factory_(this) {
+ gfx::Insets insets = views::BubbleFrameView::GetTitleInsets();
+ set_margins(gfx::Insets(0, insets.left(), insets.top(), insets.left()));
+}
+
+} // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/generated_credit_card_bubble_views.h b/chrome/browser/ui/views/autofill/generated_credit_card_bubble_views.h
new file mode 100644
index 0000000..5ee786a
--- /dev/null
+++ b/chrome/browser/ui/views/autofill/generated_credit_card_bubble_views.h
@@ -0,0 +1,60 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_VIEWS_H_
+#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_VIEWS_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_view.h"
+#include "ui/views/bubble/bubble_delegate.h"
+#include "ui/views/controls/styled_label_listener.h"
+
+namespace autofill {
+
+class GeneratedCreditCardBubbleController;
+
+// Views toolkit implementation of the GeneratedCreditCardBubbleView (an
+// educational bubble shown after a successful generation of a new credit card
+// number).
+class GeneratedCreditCardBubbleViews : public GeneratedCreditCardBubbleView,
+ public views::BubbleDelegateView,
+ public views::StyledLabelListener {
+ public:
+ virtual ~GeneratedCreditCardBubbleViews();
+
+ // GeneratedCreditCardBubbleView:
+ virtual void Show() OVERRIDE;
+ virtual void Hide() OVERRIDE;
+ virtual bool IsHiding() const OVERRIDE;
+
+ // views::BubbleDelegateView:
+ virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual base::string16 GetWindowTitle() const OVERRIDE;
+ virtual void Init() OVERRIDE;
+
+ // views::StyledLabelListener:
+ virtual void StyledLabelLinkClicked(const ui::Range& range, int event_flags)
+ OVERRIDE;
+
+ private:
+ friend base::WeakPtr<GeneratedCreditCardBubbleView>
+ GeneratedCreditCardBubbleView::Create(
+ const base::WeakPtr<GeneratedCreditCardBubbleController>& controller);
+
+ explicit GeneratedCreditCardBubbleViews(
+ const base::WeakPtr<GeneratedCreditCardBubbleController>& controller);
+
+ // Controller that drives this bubble. May be invalid when hiding.
+ base::WeakPtr<GeneratedCreditCardBubbleController> controller_;
+
+ base::WeakPtrFactory<GeneratedCreditCardBubbleView> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeneratedCreditCardBubbleViews);
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_VIEWS_AUTOFILL_GENERATED_CREDIT_CARD_BUBBLE_VIEWS_H_
diff --git a/chrome/browser/ui/views/autofill/new_credit_card_bubble_views.cc b/chrome/browser/ui/views/autofill/new_credit_card_bubble_views.cc
new file mode 100644
index 0000000..496860c
--- /dev/null
+++ b/chrome/browser/ui/views/autofill/new_credit_card_bubble_views.cc
@@ -0,0 +1,121 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/autofill/new_credit_card_bubble_views.h"
+
+#include "chrome/browser/ui/autofill/new_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/host_desktop.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/toolbar_view.h"
+#include "ui/gfx/insets.h"
+#include "ui/gfx/size.h"
+#include "ui/views/bubble/bubble_frame_view.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/link.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/layout_constants.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+
+namespace autofill {
+
+namespace {
+
+// Get the view this bubble will be anchored to via |controller|.
+views::View* GetAnchor(NewCreditCardBubbleController* controller) {
+ Browser* browser = chrome::FindTabbedBrowser(controller->profile(), false,
+ chrome::GetActiveDesktop());
+ if (!browser)
+ return NULL;
+ BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
+ return browser_view->GetToolbarView()->app_menu();
+}
+
+} // namespace
+
+NewCreditCardBubbleViews::~NewCreditCardBubbleViews() {
+ controller_->OnBubbleDestroyed();
+}
+
+void NewCreditCardBubbleViews::Show() {
+ // TODO(dbeam): investigate why this steals focus from the web contents.
+ views::BubbleDelegateView::CreateBubble(this)->Show();
+
+ // This bubble doesn't render correctly on Windows without calling
+ // |SizeToContents()|. This must be called after showing the widget.
+ SizeToContents();
+}
+
+void NewCreditCardBubbleViews::Hide() {
+ GetWidget()->Close();
+}
+
+gfx::Size NewCreditCardBubbleViews::GetPreferredSize() {
+ return gfx::Size(
+ NewCreditCardBubbleView::kContentsWidth,
+ GetHeightForWidth(NewCreditCardBubbleView::kContentsWidth));
+}
+
+void NewCreditCardBubbleViews::Init() {
+ SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
+ views::kRelatedControlVerticalSpacing));
+
+ views::View* card_container = new views::View();
+ card_container->SetLayoutManager(
+ new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 10));
+
+ views::View* card_desc_view = new views::View();
+ card_desc_view->SetLayoutManager(
+ new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 10));
+
+ views::ImageView* card_icon = new views::ImageView();
+ const CreditCardDescription& card_desc = controller_->CardDescription();
+ card_icon->SetImage(card_desc.icon.AsImageSkia());
+ card_desc_view->AddChildView(card_icon);
+
+ views::Label* card_name = new views::Label(card_desc.name);
+ card_name->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ card_desc_view->AddChildView(card_name);
+ card_container->AddChildView(card_desc_view);
+
+ views::Label* desc = new views::Label(card_desc.description);
+ desc->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ desc->SetMultiLine(true);
+ card_container->AddChildView(desc);
+
+ AddChildView(card_container);
+
+ views::Link* link = new views::Link(controller_->LinkText());
+ link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ link->set_listener(this);
+ AddChildView(link);
+}
+
+base::string16 NewCreditCardBubbleViews::GetWindowTitle() const {
+ return controller_->TitleText();
+}
+
+void NewCreditCardBubbleViews::LinkClicked(views::Link* source,
+ int event_flags) {
+ controller_->OnLinkClicked();
+}
+
+// static
+base::WeakPtr<NewCreditCardBubbleView> NewCreditCardBubbleView::Create(
+ NewCreditCardBubbleController* controller) {
+ NewCreditCardBubbleViews* bubble = new NewCreditCardBubbleViews(controller);
+ return bubble->weak_ptr_factory_.GetWeakPtr();
+}
+
+NewCreditCardBubbleViews::NewCreditCardBubbleViews(
+ NewCreditCardBubbleController* controller)
+ : BubbleDelegateView(GetAnchor(controller), views::BubbleBorder::TOP_RIGHT),
+ controller_(controller),
+ weak_ptr_factory_(this) {
+ gfx::Insets insets = views::BubbleFrameView::GetTitleInsets();
+ set_margins(gfx::Insets(0, insets.left(), insets.top(), insets.left()));
+}
+
+} // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/new_credit_card_bubble_views.h b/chrome/browser/ui/views/autofill/new_credit_card_bubble_views.h
new file mode 100644
index 0000000..fe57246
--- /dev/null
+++ b/chrome/browser/ui/views/autofill/new_credit_card_bubble_views.h
@@ -0,0 +1,56 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_VIEWS_H_
+#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_VIEWS_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/autofill/new_credit_card_bubble_view.h"
+#include "ui/views/bubble/bubble_delegate.h"
+#include "ui/views/controls/link_listener.h"
+
+namespace autofill {
+
+class NewCreditCardBubbleController;
+
+// Views toolkit implementation of NewCreditCardBubbleView (a bubble shown after
+// a user saved a new card locally in Chrome).
+class NewCreditCardBubbleViews : public NewCreditCardBubbleView,
+ public views::BubbleDelegateView,
+ public views::LinkListener {
+ public:
+ virtual ~NewCreditCardBubbleViews();
+
+ // NewCreditCardBubbleView:
+ virtual void Show() OVERRIDE;
+ virtual void Hide() OVERRIDE;
+
+ // views::BubbleDelegateView:
+ virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual base::string16 GetWindowTitle() const OVERRIDE;
+ virtual void Init() OVERRIDE;
+
+ // views::LinkListener:
+ virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
+
+ private:
+ friend base::WeakPtr<NewCreditCardBubbleView> NewCreditCardBubbleView::Create(
+ NewCreditCardBubbleController* controller);
+
+ explicit NewCreditCardBubbleViews(
+ NewCreditCardBubbleController* controller);
+
+ // Controller that drives this bubble. Never NULL; outlives this class.
+ NewCreditCardBubbleController* controller_;
+
+ base::WeakPtrFactory<NewCreditCardBubbleView> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(NewCreditCardBubbleViews);
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_VIEWS_AUTOFILL_NEW_CREDIT_CARD_BUBBLE_VIEWS_H_
diff --git a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
index 9a4fdfa..6270e8f 100644
--- a/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
+++ b/chrome/browser/ui/views/avatar_menu_button_browsertest.cc
@@ -193,7 +193,7 @@
EXPECT_EQ(starting_tab_count + 1, final_tab_count);
GURL tab_url = browser()->tab_strip_model()->GetActiveWebContents()->GetURL();
- EXPECT_EQ(std::string(chrome::kChromeUIUserChooserURL), tab_url.spec());
+ EXPECT_EQ(std::string(chrome::kChromeUIUserManagerURL), tab_url.spec());
}
INSTANTIATE_TEST_CASE_P(Old, AvatarMenuButtonTest, testing::Values(false));
diff --git a/chrome/browser/ui/views/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_media_picker_views.cc
index 685c155..b21ea7f 100644
--- a/chrome/browser/ui/views/desktop_media_picker_views.cc
+++ b/chrome/browser/ui/views/desktop_media_picker_views.cc
@@ -23,6 +23,8 @@
#include "ui/views/window/dialog_client_view.h"
#include "ui/views/window/dialog_delegate.h"
+using content::DesktopMediaID;
+
namespace {
const int kThumbnailWidth = 160;
@@ -49,7 +51,7 @@
class DesktopMediaSourceView : public views::View {
public:
DesktopMediaSourceView(DesktopMediaListView* parent,
- DesktopMediaPickerModel::SourceId source_id);
+ DesktopMediaID source_id);
virtual ~DesktopMediaSourceView();
// Updates thumbnail and title from |source|.
@@ -57,7 +59,7 @@
void SetThumbnail(const gfx::ImageSkia& thumbnail);
// Id for the source shown by this View.
- const DesktopMediaPickerModel::SourceId& source_id() const {
+ const DesktopMediaID& source_id() const {
return source_id_;
}
@@ -79,8 +81,7 @@
private:
DesktopMediaListView* parent_;
-
- DesktopMediaPickerModel::SourceId source_id_;
+ DesktopMediaID source_id_;
views::ImageView* image_view_;
views::Label* label_;
@@ -166,7 +167,7 @@
DesktopMediaPickerViews();
virtual ~DesktopMediaPickerViews();
- void NotifyDialogResult(DesktopMediaPickerModel::SourceId source);
+ void NotifyDialogResult(DesktopMediaID source);
// DesktopMediaPicker overrides.
virtual void Show(gfx::NativeWindow context,
@@ -188,7 +189,7 @@
DesktopMediaSourceView::DesktopMediaSourceView(
DesktopMediaListView* parent,
- DesktopMediaPickerModel::SourceId source_id)
+ DesktopMediaID source_id)
: parent_(parent),
source_id_(source_id),
image_view_(new views::ImageView()),
@@ -491,7 +492,7 @@
// Ok button should only be enabled when a source is selected.
DCHECK(selection);
- DesktopMediaPickerModel::SourceId source;
+ DesktopMediaID source;
if (selection)
source = selection->source_id();
@@ -504,10 +505,8 @@
void DesktopMediaPickerDialogView::DeleteDelegate() {
// If the dialog is being closed then notify the parent about it.
- if (parent_) {
- parent_->NotifyDialogResult(
- DesktopMediaPickerModel::SourceId(content::MEDIA_NO_SERVICE, 0));
- }
+ if (parent_)
+ parent_->NotifyDialogResult(DesktopMediaID());
delete this;
}
@@ -537,7 +536,7 @@
}
void DesktopMediaPickerViews::NotifyDialogResult(
- DesktopMediaPickerModel::SourceId source) {
+ DesktopMediaID source) {
// Once this method is called the |dialog_| will close and destroy itself.
dialog_->DetachParent();
dialog_ = NULL;
diff --git a/chrome/browser/ui/views/download/download_shelf_view.cc b/chrome/browser/ui/views/download/download_shelf_view.cc
index c737a85..e16536f 100644
--- a/chrome/browser/ui/views/download/download_shelf_view.cc
+++ b/chrome/browser/ui/views/download/download_shelf_view.cc
@@ -10,7 +10,7 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/download/download_item_model.h"
-#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/download/download_stats.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/chrome_pages.h"
@@ -406,9 +406,8 @@
if (download_views_[i]->download()->GetState() == DownloadItem::IN_PROGRESS)
++num_in_progress;
}
- download_util::RecordShelfClose(download_views_.size(),
- num_in_progress,
- reason == AUTOMATIC);
+ RecordDownloadShelfClose(
+ download_views_.size(), num_in_progress, reason == AUTOMATIC);
parent_->SetDownloadShelfVisible(false);
shelf_animation_->Hide();
}
diff --git a/chrome/browser/ui/views/frame/OWNERS b/chrome/browser/ui/views/frame/OWNERS
index 3ef69af..14b3d0e 100644
--- a/chrome/browser/ui/views/frame/OWNERS
+++ b/chrome/browser/ui/views/frame/OWNERS
@@ -4,3 +4,5 @@
# For Ash or other non-Windows-specific changes
jamescook@chromium.org
+
+per-file immersive_mode_controller*=pkotwicz@chromium.org
diff --git a/chrome/browser/ui/views/frame/global_menu_bar_x11.cc b/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
index e6ccb3e..9b0f1a7 100644
--- a/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
+++ b/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
@@ -9,27 +9,45 @@
#include "base/logging.h"
#include "base/prefs/pref_service.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/history/top_sites.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sessions/tab_restore_service.h"
+#include "chrome/browser/sessions/tab_restore_service_factory.h"
+#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
#include "chrome/browser/ui/views/frame/browser_desktop_root_window_host_x11.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h"
#include "chrome/common/pref_names.h"
+#include "content/public/browser/notification_source.h"
#include "grit/generated_resources.h"
#include "ui/base/accelerators/menu_label_accelerator_util_linux.h"
#include "ui/base/keycodes/keyboard_code_conversion_x.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/text/text_elider.h"
// libdbusmenu-glib types
typedef struct _DbusmenuMenuitem DbusmenuMenuitem;
typedef DbusmenuMenuitem* (*dbusmenu_menuitem_new_func)();
-typedef DbusmenuMenuitem* (*dbusmenu_menuitem_new_with_id_func)(int id);
-
-typedef int (*dbusmenu_menuitem_get_id_func)(DbusmenuMenuitem* item);
+typedef bool (*dbusmenu_menuitem_child_add_position_func)(
+ DbusmenuMenuitem* parent,
+ DbusmenuMenuitem* child,
+ unsigned int position);
typedef DbusmenuMenuitem* (*dbusmenu_menuitem_child_append_func)(
DbusmenuMenuitem* parent,
DbusmenuMenuitem* child);
+typedef bool (*dbusmenu_menuitem_child_delete_func)(
+ DbusmenuMenuitem* parent,
+ DbusmenuMenuitem* child);
+typedef GList* (*dbusmenu_menuitem_get_children_func)(
+ DbusmenuMenuitem* item);
typedef DbusmenuMenuitem* (*dbusmenu_menuitem_property_set_func)(
DbusmenuMenuitem* item,
const char* property,
@@ -65,9 +83,10 @@
// DbusmenuMenuItem methods:
dbusmenu_menuitem_new_func menuitem_new = NULL;
-dbusmenu_menuitem_new_with_id_func menuitem_new_with_id = NULL;
-dbusmenu_menuitem_get_id_func menuitem_get_id = NULL;
+dbusmenu_menuitem_get_children_func menuitem_get_children = NULL;
+dbusmenu_menuitem_child_add_position_func menuitem_child_add_position = NULL;
dbusmenu_menuitem_child_append_func menuitem_child_append = NULL;
+dbusmenu_menuitem_child_delete_func menuitem_child_delete = NULL;
dbusmenu_menuitem_property_set_func menuitem_property_set = NULL;
dbusmenu_menuitem_property_set_variant_func menuitem_property_set_variant =
NULL;
@@ -90,10 +109,30 @@
const char kTypeCheckmark[] = "checkmark";
const char kTypeSeparator[] = "separator";
-// Constants used in menu definitions
+// Data set on GObjectgs.
+const char kTypeTag[] = "type-tag";
+const char kHistoryItem[] = "history-item";
+
+// The maximum number of most visited items to display.
+const unsigned int kMostVisitedCount = 8;
+
+// The number of recently closed items to get.
+const unsigned int kRecentlyClosedCount = 8;
+
+// Menus more than this many chars long will get trimmed.
+const int kMaximumMenuWidthInChars = 50;
+
+// Constants used in menu definitions.
const int MENU_SEPARATOR =-1;
const int MENU_END = -2;
-const int MENU_DISABLED_LABEL = -3;
+const int MENU_DISABLED_ID = -3;
+
+// These tag values are used to refer to menu itesm.
+const int TAG_NORMAL = 0;
+const int TAG_MOST_VISITED = 1;
+const int TAG_RECENTLY_CLOSED = 2;
+const int TAG_MOST_VISITED_HEADER = 3;
+const int TAG_RECENTLY_CLOSED_HEADER = 4;
GlobalMenuBarCommand file_menu[] = {
{ IDS_NEW_TAB, IDC_NEW_TAB },
@@ -136,7 +175,6 @@
{ MENU_END, MENU_END }
};
-
GlobalMenuBarCommand view_menu[] = {
{ IDS_SHOW_BOOKMARK_BAR, IDC_SHOW_BOOKMARK_BAR },
@@ -155,7 +193,25 @@
{ MENU_END, MENU_END }
};
-// TODO(erg): History menu.
+GlobalMenuBarCommand history_menu[] = {
+ { IDS_HISTORY_HOME_LINUX, IDC_HOME },
+ { IDS_HISTORY_BACK_LINUX, IDC_BACK },
+ { IDS_HISTORY_FORWARD_LINUX, IDC_FORWARD },
+
+ { MENU_SEPARATOR, MENU_SEPARATOR },
+
+ { IDS_HISTORY_VISITED_LINUX, MENU_DISABLED_ID, TAG_MOST_VISITED_HEADER },
+
+ { MENU_SEPARATOR, MENU_SEPARATOR },
+
+ { IDS_HISTORY_CLOSED_LINUX, MENU_DISABLED_ID, TAG_RECENTLY_CLOSED_HEADER },
+
+ { MENU_SEPARATOR, MENU_SEPARATOR },
+
+ { IDS_SHOWFULLHISTORY_LINK, IDC_SHOW_HISTORY },
+
+ { MENU_END, MENU_END }
+};
GlobalMenuBarCommand tools_menu[] = {
{ IDS_SHOW_DOWNLOADS, IDC_SHOW_DOWNLOADS },
@@ -182,7 +238,6 @@
{ MENU_END, MENU_END }
};
-
void EnsureMethodsLoaded() {
static bool attempted_load = false;
if (attempted_load)
@@ -196,12 +251,15 @@
// DbusmenuMenuItem methods.
menuitem_new = reinterpret_cast<dbusmenu_menuitem_new_func>(
dlsym(dbusmenu_lib, "dbusmenu_menuitem_new"));
- menuitem_new_with_id = reinterpret_cast<dbusmenu_menuitem_new_with_id_func>(
- dlsym(dbusmenu_lib, "dbusmenu_menuitem_new_with_id"));
- menuitem_get_id = reinterpret_cast<dbusmenu_menuitem_get_id_func>(
- dlsym(dbusmenu_lib, "dbusmenu_menuitem_get_id"));
+ menuitem_child_add_position =
+ reinterpret_cast<dbusmenu_menuitem_child_add_position_func>(
+ dlsym(dbusmenu_lib, "dbusmenu_menuitem_child_add_position"));
menuitem_child_append = reinterpret_cast<dbusmenu_menuitem_child_append_func>(
dlsym(dbusmenu_lib, "dbusmenu_menuitem_child_append"));
+ menuitem_child_delete = reinterpret_cast<dbusmenu_menuitem_child_delete_func>(
+ dlsym(dbusmenu_lib, "dbusmenu_menuitem_child_delete"));
+ menuitem_get_children = reinterpret_cast<dbusmenu_menuitem_get_children_func>(
+ dlsym(dbusmenu_lib, "dbusmenu_menuitem_get_children"));
menuitem_property_set = reinterpret_cast<dbusmenu_menuitem_property_set_func>(
dlsym(dbusmenu_lib, "dbusmenu_menuitem_property_set"));
menuitem_property_set_variant =
@@ -223,13 +281,43 @@
} // namespace
+struct GlobalMenuBarX11::HistoryItem {
+ HistoryItem() : session_id(0) {}
+
+ // The title for the menu item.
+ string16 title;
+ // The URL that will be navigated to if the user selects this item.
+ GURL url;
+
+ // This ID is unique for a browser session and can be passed to the
+ // TabRestoreService to re-open the closed window or tab that this
+ // references. A non-0 session ID indicates that this is an entry can be
+ // restored that way. Otherwise, the URL will be used to open the item and
+ // this ID will be 0.
+ SessionID::id_type session_id;
+
+ // If the HistoryItem is a window, this will be the vector of tabs. Note
+ // that this is a list of weak references. The |menu_item_map_| is the owner
+ // of all items. If it is not a window, then the entry is a single page and
+ // the vector will be empty.
+ std::vector<HistoryItem*> tabs;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HistoryItem);
+};
+
GlobalMenuBarX11::GlobalMenuBarX11(BrowserView* browser_view,
BrowserDesktopRootWindowHostX11* host)
: browser_(browser_view->browser()),
+ profile_(browser_->profile()),
browser_view_(browser_view),
host_(host),
server_(NULL),
- root_item_(NULL) {
+ root_item_(NULL),
+ history_menu_(NULL),
+ top_sites_(NULL),
+ tab_restore_service_(NULL),
+ weak_ptr_factory_(this) {
EnsureMethodsLoaded();
if (server_new)
@@ -239,6 +327,10 @@
GlobalMenuBarX11::~GlobalMenuBarX11() {
if (server_) {
Disable();
+
+ if (tab_restore_service_)
+ tab_restore_service_->RemoveObserver(this);
+
g_object_unref(server_);
host_->RemoveObserver(this);
}
@@ -249,6 +341,26 @@
return base::StringPrintf("/com/canonical/menu/%lX", xid);
}
+DbusmenuMenuitem* GlobalMenuBarX11::BuildSeparator() {
+ DbusmenuMenuitem* item = menuitem_new();
+ menuitem_property_set(item, kPropertyType, kTypeSeparator);
+ menuitem_property_set_bool(item, kPropertyVisible, true);
+ return item;
+}
+
+DbusmenuMenuitem* GlobalMenuBarX11::BuildMenuItem(
+ const std::string& label,
+ int tag_id) {
+ DbusmenuMenuitem* item = menuitem_new();
+ menuitem_property_set(item, kPropertyLabel, label.c_str());
+ menuitem_property_set_bool(item, kPropertyVisible, true);
+
+ if (tag_id)
+ g_object_set_data(G_OBJECT(item), kTypeTag, GINT_TO_POINTER(tag_id));
+
+ return item;
+}
+
void GlobalMenuBarX11::InitServer(unsigned long xid) {
std::string path = GetPathForWindow(xid);
server_ = server_new(path.c_str());
@@ -257,13 +369,20 @@
menuitem_property_set(root_item_, kPropertyLabel, "Root");
menuitem_property_set_bool(root_item_, kPropertyVisible, true);
- BuildMenuFrom(root_item_, IDS_FILE_MENU_LINUX, &id_to_menu_item_, file_menu);
- BuildMenuFrom(root_item_, IDS_EDIT_MENU_LINUX, &id_to_menu_item_, edit_menu);
- BuildMenuFrom(root_item_, IDS_VIEW_MENU_LINUX, &id_to_menu_item_, view_menu);
- // TODO(erg): History menu.
- BuildMenuFrom(root_item_, IDS_TOOLS_MENU_LINUX, &id_to_menu_item_,
- tools_menu);
- BuildMenuFrom(root_item_, IDS_HELP_MENU_LINUX, &id_to_menu_item_, help_menu);
+ // First build static menu content.
+ BuildStaticMenu(root_item_, IDS_FILE_MENU_LINUX, file_menu);
+ BuildStaticMenu(root_item_, IDS_EDIT_MENU_LINUX, edit_menu);
+ BuildStaticMenu(root_item_, IDS_VIEW_MENU_LINUX, view_menu);
+ history_menu_ = BuildStaticMenu(
+ root_item_, IDS_HISTORY_MENU_LINUX, history_menu);
+ BuildStaticMenu(root_item_, IDS_TOOLS_MENU_LINUX, tools_menu);
+ BuildStaticMenu(root_item_, IDS_HELP_MENU_LINUX, help_menu);
+
+ // We have to connect to |history_menu_item|'s "activate" signal instead of
+ // |history_menu|'s "show" signal because we are not supposed to modify the
+ // menu during "show"
+ g_signal_connect(history_menu_, "about-to-show",
+ G_CALLBACK(OnHistoryMenuAboutToShowThunk), this);
for (CommandIDMenuItemMap::const_iterator it = id_to_menu_item_.begin();
it != id_to_menu_item_.end(); ++it) {
@@ -284,6 +403,16 @@
base::Unretained(this)));
OnBookmarkBarVisibilityChanged();
+ top_sites_ = profile_->GetTopSites();
+ if (top_sites_) {
+ GetTopSitesData();
+
+ // Register for notification when TopSites changes so that we can update
+ // ourself.
+ registrar_.Add(this, chrome::NOTIFICATION_TOP_SITES_CHANGED,
+ content::Source<history::TopSites>(top_sites_));
+ }
+
server_set_root(server_, root_item_);
}
@@ -297,10 +426,9 @@
pref_change_registrar_.RemoveAll();
}
-void GlobalMenuBarX11::BuildMenuFrom(
+DbusmenuMenuitem* GlobalMenuBarX11::BuildStaticMenu(
DbusmenuMenuitem* parent,
int menu_str_id,
- std::map<int, DbusmenuMenuitem*>* id_to_menu_item,
GlobalMenuBarCommand* commands) {
DbusmenuMenuitem* top = menuitem_new();
menuitem_property_set(
@@ -310,48 +438,37 @@
menuitem_property_set_bool(top, kPropertyVisible, true);
for (int i = 0; commands[i].str_id != MENU_END; ++i) {
- DbusmenuMenuitem* menu_item = BuildMenuItem(
- commands[i].str_id, commands[i].command, commands[i].tag,
- id_to_menu_item);
+ DbusmenuMenuitem* menu_item = NULL;
+ int command_id = commands[i].command;
+ if (commands[i].str_id == MENU_SEPARATOR) {
+ menu_item = BuildSeparator();
+ } else {
+ std::string label = ui::ConvertAcceleratorsFromWindowsStyle(
+ l10n_util::GetStringUTF8(commands[i].str_id));
+
+ menu_item = BuildMenuItem(label, commands[i].tag);
+
+ if (command_id == MENU_DISABLED_ID) {
+ menuitem_property_set_bool(menu_item, kPropertyEnabled, false);
+ } else {
+ if (command_id == IDC_SHOW_BOOKMARK_BAR)
+ menuitem_property_set(menu_item, kPropertyToggleType, kTypeCheckmark);
+
+ id_to_menu_item_.insert(std::make_pair(command_id, menu_item));
+ g_object_set_data(G_OBJECT(menu_item), "command-id",
+ GINT_TO_POINTER(command_id));
+ g_signal_connect(menu_item, "item-activated",
+ G_CALLBACK(OnItemActivatedThunk), this);
+ }
+ }
+
menuitem_child_append(top, menu_item);
+ g_object_unref(menu_item);
}
menuitem_child_append(parent, top);
-}
-
-DbusmenuMenuitem* GlobalMenuBarX11::BuildMenuItem(
- int string_id,
- int command_id,
- int tag_id,
- std::map<int, DbusmenuMenuitem*>* id_to_menu_item) {
- DbusmenuMenuitem* item = menuitem_new();
-
- if (string_id == MENU_SEPARATOR) {
- menuitem_property_set(item, kPropertyType, kTypeSeparator);
- } else {
- std::string label = ui::ConvertAcceleratorsFromWindowsStyle(
- l10n_util::GetStringUTF8(string_id));
- menuitem_property_set(item, kPropertyLabel, label.c_str());
-
- if (command_id == IDC_SHOW_BOOKMARK_BAR)
- menuitem_property_set(item, kPropertyToggleType, kTypeCheckmark);
-
- if (tag_id)
- g_object_set_data(G_OBJECT(item), "type-tag", GINT_TO_POINTER(tag_id));
-
- if (command_id == MENU_DISABLED_LABEL) {
- menuitem_property_set_bool(item, kPropertyEnabled, false);
- } else {
- id_to_menu_item->insert(std::make_pair(command_id, item));
- g_object_set_data(G_OBJECT(item), "command-id",
- GINT_TO_POINTER(command_id));
- g_signal_connect(item, "item-activated",
- G_CALLBACK(OnItemActivatedThunk), this);
- }
- }
-
- menuitem_property_set_bool(item, kPropertyVisible, true);
- return item;
+ g_object_unref(top);
+ return top;
}
void GlobalMenuBarX11::RegisterAccelerator(DbusmenuMenuitem* item,
@@ -384,6 +501,70 @@
menuitem_property_set_variant(item, kPropertyShortcut, outside_array);
}
+GlobalMenuBarX11::HistoryItem* GlobalMenuBarX11::HistoryItemForTab(
+ const TabRestoreService::Tab& entry) {
+ const sessions::SerializedNavigationEntry& current_navigation =
+ entry.navigations.at(entry.current_navigation_index);
+ HistoryItem* item = new HistoryItem();
+ item->title = current_navigation.title();
+ item->url = current_navigation.virtual_url();
+ item->session_id = entry.id;
+
+ return item;
+}
+
+void GlobalMenuBarX11::AddHistoryItemToMenu(HistoryItem* item,
+ DbusmenuMenuitem* menu,
+ int tag,
+ int index) {
+ string16 title = item->title;
+ std::string url_string = item->url.possibly_invalid_spec();
+
+ if (title.empty())
+ title = UTF8ToUTF16(url_string);
+ ui::ElideString(title, kMaximumMenuWidthInChars, &title);
+
+ DbusmenuMenuitem* menu_item = BuildMenuItem(UTF16ToUTF8(title), tag);
+ g_signal_connect(menu_item, "item-activated",
+ G_CALLBACK(OnHistoryItemActivatedThunk), this);
+
+ g_object_set_data_full(G_OBJECT(menu_item), kHistoryItem, item,
+ DeleteHistoryItem);
+ menuitem_child_add_position(menu, menu_item, index);
+ g_object_unref(menu_item);
+}
+
+void GlobalMenuBarX11::GetTopSitesData() {
+ DCHECK(top_sites_);
+
+ top_sites_->GetMostVisitedURLs(
+ base::Bind(&GlobalMenuBarX11::OnTopSitesReceived,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void GlobalMenuBarX11::OnTopSitesReceived(
+ const history::MostVisitedURLList& visited_list) {
+ ClearMenuSection(history_menu_, TAG_MOST_VISITED);
+
+ int index = GetIndexOfMenuItemWithTag(history_menu_,
+ TAG_MOST_VISITED_HEADER) + 1;
+
+ for (size_t i = 0; i < visited_list.size() && i < kMostVisitedCount; ++i) {
+ const history::MostVisitedURL& visited = visited_list[i];
+ if (visited.url.spec().empty())
+ break; // This is the signal that there are no more real visited sites.
+
+ HistoryItem* item = new HistoryItem();
+ item->title = visited.title;
+ item->url = visited.url;
+
+ AddHistoryItemToMenu(item,
+ history_menu_,
+ TAG_MOST_VISITED,
+ index++);
+ }
+}
+
void GlobalMenuBarX11::OnBookmarkBarVisibilityChanged() {
CommandIDMenuItemMap::iterator it =
id_to_menu_item_.find(IDC_SHOW_BOOKMARK_BAR);
@@ -396,12 +577,152 @@
}
}
+int GlobalMenuBarX11::GetIndexOfMenuItemWithTag(DbusmenuMenuitem* menu,
+ int tag_id) {
+ GList* childs = menuitem_get_children(menu);
+ int i = 0;
+ for (; childs != NULL; childs = childs->next, i++) {
+ int tag =
+ GPOINTER_TO_INT(g_object_get_data(G_OBJECT(childs->data), kTypeTag));
+ if (tag == tag_id)
+ return i;
+ }
+
+ NOTREACHED();
+ return -1;
+}
+
+void GlobalMenuBarX11::ClearMenuSection(DbusmenuMenuitem* menu, int tag_id) {
+ std::vector<DbusmenuMenuitem*> menuitems_to_delete;
+
+ GList* childs = menuitem_get_children(menu);
+ for (; childs != NULL; childs = childs->next) {
+ DbusmenuMenuitem* current_item = reinterpret_cast<DbusmenuMenuitem*>(
+ childs->data);
+ ClearMenuSection(current_item, tag_id);
+
+ int tag =
+ GPOINTER_TO_INT(g_object_get_data(G_OBJECT(childs->data), kTypeTag));
+ if (tag == tag_id)
+ menuitems_to_delete.push_back(current_item);
+ }
+
+ for (std::vector<DbusmenuMenuitem*>::const_iterator it =
+ menuitems_to_delete.begin(); it != menuitems_to_delete.end(); ++it) {
+ menuitem_child_delete(menu, *it);
+ }
+}
+
+// static
+void GlobalMenuBarX11::DeleteHistoryItem(void* void_item) {
+ HistoryItem* item =
+ reinterpret_cast<GlobalMenuBarX11::HistoryItem*>(void_item);
+ delete item;
+}
+
void GlobalMenuBarX11::EnabledStateChangedForCommand(int id, bool enabled) {
CommandIDMenuItemMap::iterator it = id_to_menu_item_.find(id);
if (it != id_to_menu_item_.end())
menuitem_property_set_bool(it->second, kPropertyEnabled, enabled);
}
+void GlobalMenuBarX11::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type == chrome::NOTIFICATION_TOP_SITES_CHANGED) {
+ GetTopSitesData();
+ } else {
+ NOTREACHED();
+ }
+}
+
+void GlobalMenuBarX11::TabRestoreServiceChanged(TabRestoreService* service) {
+ const TabRestoreService::Entries& entries = service->entries();
+
+ ClearMenuSection(history_menu_, TAG_RECENTLY_CLOSED);
+
+ // We'll get the index the "Recently Closed" header. (This can vary depending
+ // on the number of "Most Visited" items.
+ int index = GetIndexOfMenuItemWithTag(history_menu_,
+ TAG_RECENTLY_CLOSED_HEADER) + 1;
+
+ unsigned int added_count = 0;
+ for (TabRestoreService::Entries::const_iterator it = entries.begin();
+ it != entries.end() && added_count < kRecentlyClosedCount; ++it) {
+ TabRestoreService::Entry* entry = *it;
+
+ if (entry->type == TabRestoreService::WINDOW) {
+ TabRestoreService::Window* entry_win =
+ static_cast<TabRestoreService::Window*>(entry);
+ std::vector<TabRestoreService::Tab>& tabs = entry_win->tabs;
+ if (tabs.empty())
+ continue;
+
+ // Create the item for the parent/window.
+ HistoryItem* item = new HistoryItem();
+ item->session_id = entry_win->id;
+
+ std::string title = item->tabs.size() == 1 ?
+ l10n_util::GetStringUTF8(
+ IDS_NEW_TAB_RECENTLY_CLOSED_WINDOW_SINGLE) :
+ l10n_util::GetStringFUTF8(
+ IDS_NEW_TAB_RECENTLY_CLOSED_WINDOW_MULTIPLE,
+ base::IntToString16(item->tabs.size()));
+ DbusmenuMenuitem* parent_item = BuildMenuItem(
+ title, TAG_RECENTLY_CLOSED);
+ menuitem_child_add_position(history_menu_, parent_item, index++);
+ g_object_unref(parent_item);
+
+ // The mac version of this code allows the user to click on the parent
+ // menu item to have the same effect as clicking the restore window
+ // submenu item. GTK+ helpfully activates a menu item when it shows a
+ // submenu so toss that feature out.
+ DbusmenuMenuitem* restore_item = BuildMenuItem(
+ l10n_util::GetStringUTF8(
+ IDS_HISTORY_CLOSED_RESTORE_WINDOW_LINUX).c_str(),
+ TAG_RECENTLY_CLOSED);
+ g_signal_connect(restore_item, "item-activated",
+ G_CALLBACK(OnHistoryItemActivatedThunk), this);
+ g_object_set_data_full(G_OBJECT(restore_item), kHistoryItem, item,
+ DeleteHistoryItem);
+ menuitem_child_append(parent_item, restore_item);
+ g_object_unref(restore_item);
+
+ DbusmenuMenuitem* separator = BuildSeparator();
+ menuitem_child_append(parent_item, separator);
+ g_object_unref(separator);
+
+ // Loop over the window's tabs and add them to the submenu.
+ int subindex = 2;
+ std::vector<TabRestoreService::Tab>::const_iterator iter;
+ for (iter = tabs.begin(); iter != tabs.end(); ++iter) {
+ TabRestoreService::Tab tab = *iter;
+ HistoryItem* tab_item = HistoryItemForTab(tab);
+ item->tabs.push_back(tab_item);
+ AddHistoryItemToMenu(tab_item,
+ parent_item,
+ TAG_RECENTLY_CLOSED,
+ subindex++);
+ }
+
+ ++added_count;
+ } else if (entry->type == TabRestoreService::TAB) {
+ TabRestoreService::Tab* tab = static_cast<TabRestoreService::Tab*>(entry);
+ HistoryItem* item = HistoryItemForTab(*tab);
+ AddHistoryItemToMenu(item,
+ history_menu_,
+ TAG_RECENTLY_CLOSED,
+ index++);
+ ++added_count;
+ }
+ }
+}
+
+void GlobalMenuBarX11::TabRestoreServiceDestroyed(
+ TabRestoreService* service) {
+ tab_restore_service_ = NULL;
+}
+
void GlobalMenuBarX11::OnWindowMapped(unsigned long xid) {
if (!server_)
InitServer(xid);
@@ -418,3 +739,44 @@
int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item), "command-id"));
chrome::ExecuteCommand(browser_, id);
}
+
+void GlobalMenuBarX11::OnHistoryItemActivated(DbusmenuMenuitem* sender,
+ unsigned int timestamp) {
+ // Note: We don't have access to the event modifiers used to click the menu
+ // item since that happens in a different process.
+ HistoryItem* item = reinterpret_cast<HistoryItem*>(
+ g_object_get_data(G_OBJECT(sender), kHistoryItem));
+
+ // If this item can be restored using TabRestoreService, do so. Otherwise,
+ // just load the URL.
+ TabRestoreService* service =
+ TabRestoreServiceFactory::GetForProfile(profile_);
+ if (item->session_id && service) {
+ service->RestoreEntryById(browser_->tab_restore_service_delegate(),
+ item->session_id, browser_->host_desktop_type(),
+ UNKNOWN);
+ } else {
+ DCHECK(item->url.is_valid());
+ browser_->OpenURL(content::OpenURLParams(
+ item->url,
+ content::Referrer(),
+ NEW_FOREGROUND_TAB,
+ content::PAGE_TRANSITION_AUTO_BOOKMARK,
+ false));
+ }
+}
+
+void GlobalMenuBarX11::OnHistoryMenuAboutToShow(DbusmenuMenuitem* item) {
+ if (!tab_restore_service_) {
+ tab_restore_service_ = TabRestoreServiceFactory::GetForProfile(profile_);
+ if (tab_restore_service_) {
+ tab_restore_service_->LoadTabsFromLastSession();
+ tab_restore_service_->AddObserver(this);
+
+ // If LoadTabsFromLastSession doesn't load tabs, it won't call
+ // TabRestoreServiceChanged(). This ensures that all new windows after
+ // the first one will have their menus populated correctly.
+ TabRestoreServiceChanged(tab_restore_service_);
+ }
+ }
+}
diff --git a/chrome/browser/ui/views/frame/global_menu_bar_x11.h b/chrome/browser/ui/views/frame/global_menu_bar_x11.h
index 46f8cf3..269153e 100644
--- a/chrome/browser/ui/views/frame/global_menu_bar_x11.h
+++ b/chrome/browser/ui/views/frame/global_menu_bar_x11.h
@@ -11,18 +11,29 @@
#include "base/compiler_specific.h"
#include "base/prefs/pref_change_registrar.h"
#include "chrome/browser/command_observer.h"
+#include "chrome/browser/common/cancelable_request.h"
+#include "chrome/browser/history/history_types.h"
+#include "chrome/browser/sessions/tab_restore_service.h"
+#include "chrome/browser/sessions/tab_restore_service_observer.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
#include "ui/base/glib/glib_signal.h"
#include "ui/views/widget/desktop_aura/desktop_root_window_host_observer_x11.h"
typedef struct _DbusmenuMenuitem DbusmenuMenuitem;
typedef struct _DbusmenuServer DbusmenuServer;
+namespace history {
+class TopSites;
+}
+
namespace ui {
class Accelerator;
}
class Browser;
class BrowserView;
+class Profile;
class BrowserDesktopRootWindowHostX11;
struct GlobalMenuBarCommand;
@@ -36,6 +47,8 @@
// interface directly with the lower level libdbusmenu-glib, which we
// opportunistically dlopen() since not everyone is running Ubuntu.
class GlobalMenuBarX11 : public CommandObserver,
+ public content::NotificationObserver,
+ public TabRestoreServiceObserver,
public views::DesktopRootWindowHostObserverX11 {
public:
GlobalMenuBarX11(BrowserView* browser_view,
@@ -46,8 +59,16 @@
static std::string GetPathForWindow(unsigned long xid);
private:
+ struct HistoryItem;
typedef std::map<int, DbusmenuMenuitem*> CommandIDMenuItemMap;
+ // Builds a separator.
+ DbusmenuMenuitem* BuildSeparator();
+
+ // Creates an individual menu item from a title and command, and subscribes
+ // to the activation signal.
+ DbusmenuMenuitem* BuildMenuItem(const std::string& label, int tag_id);
+
// Creates a DbusmenuServer, and attaches all the menu items.
void InitServer(unsigned long xid);
@@ -56,37 +77,68 @@
// Creates a whole menu defined with |commands| and titled with the string
// |menu_str_id|. Then appends it to |parent|.
- void BuildMenuFrom(DbusmenuMenuitem* parent,
- int menu_str_id,
- CommandIDMenuItemMap* id_to_menu_item,
- GlobalMenuBarCommand* commands);
-
- // Creates an individual menu item from a title and command, and subscribes
- // to the activation signal.
- DbusmenuMenuitem* BuildMenuItem(
- int string_id,
- int command_id,
- int tag_id,
- CommandIDMenuItemMap* id_to_menu_item);
+ DbusmenuMenuitem* BuildStaticMenu(DbusmenuMenuitem* parent,
+ int menu_str_id,
+ GlobalMenuBarCommand* commands);
// Sets the accelerator for |item|.
void RegisterAccelerator(DbusmenuMenuitem* item,
const ui::Accelerator& accelerator);
+ // Creates a HistoryItem from the data in |entry|.
+ HistoryItem* HistoryItemForTab(const TabRestoreService::Tab& entry);
+
+ // Creates a menu item form |item| and inserts it in |menu| at |index|.
+ void AddHistoryItemToMenu(HistoryItem* item,
+ DbusmenuMenuitem* menu,
+ int tag,
+ int index);
+
+ // Sends a message off to History for data.
+ void GetTopSitesData();
+
+ // Callback to receive data requested from GetTopSitesData().
+ void OnTopSitesReceived(const history::MostVisitedURLList& visited_list);
+
// Updates the visibility of the bookmark bar on pref changes.
void OnBookmarkBarVisibilityChanged();
+ // Find the first index of the item in |menu| with the tag |tag_id|.
+ int GetIndexOfMenuItemWithTag(DbusmenuMenuitem* menu, int tag_id);
+
+ // This will remove all menu items in |menu| with |tag| as their tag. This
+ // clears state about HistoryItems* that we keep to prevent that data from
+ // going stale. That's why this method recurses into its child menus.
+ void ClearMenuSection(DbusmenuMenuitem* menu, int tag_id);
+
+ // Deleter function for HistoryItem implementation detail.
+ static void DeleteHistoryItem(void* void_item);
+
// Overridden from CommandObserver:
virtual void EnabledStateChangedForCommand(int id, bool enabled) OVERRIDE;
- // Overridden from DesktopRootWindowHostObserverX11:
+ // Overridden from content::NotificationObserver:
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ // Overridden from TabRestoreServiceObserver:
+ virtual void TabRestoreServiceChanged(TabRestoreService* service) OVERRIDE;
+ virtual void TabRestoreServiceDestroyed(TabRestoreService* service) OVERRIDE;
+
+ // Overridden from views::DesktopRootWindowHostObserverX11:
virtual void OnWindowMapped(unsigned long xid) OVERRIDE;
virtual void OnWindowUnmapped(unsigned long xid) OVERRIDE;
CHROMEG_CALLBACK_1(GlobalMenuBarX11, void, OnItemActivated, DbusmenuMenuitem*,
unsigned int);
+ CHROMEG_CALLBACK_1(GlobalMenuBarX11, void, OnHistoryItemActivated,
+ DbusmenuMenuitem*, unsigned int);
+ CHROMEG_CALLBACK_0(GlobalMenuBarX11, void, OnHistoryMenuAboutToShow,
+ DbusmenuMenuitem*);
Browser* browser_;
+ Profile* profile_;
BrowserView* browser_view_;
BrowserDesktopRootWindowHostX11* host_;
@@ -96,10 +148,20 @@
DbusmenuServer* server_;
DbusmenuMenuitem* root_item_;
+ DbusmenuMenuitem* history_menu_;
// Tracks value of the kShowBookmarkBar preference.
PrefChangeRegistrar pref_change_registrar_;
+ history::TopSites* top_sites_;
+
+ TabRestoreService* tab_restore_service_; // weak
+
+ content::NotificationRegistrar registrar_;
+
+ // For callbacks may be run after destruction.
+ base::WeakPtrFactory<GlobalMenuBarX11> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(GlobalMenuBarX11);
};
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 e469a3c..37ab716 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
@@ -353,7 +353,7 @@
if (reveal_state_ == REVEALED) {
// Reveal was unsuccessful. Reacquire the revealed locks if appropriate.
- UpdateLocatedEventRevealedLock(NULL);
+ UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_NO);
UpdateFocusRevealedLock();
}
} else {
@@ -440,7 +440,7 @@
return;
if (IsRevealed())
- UpdateLocatedEventRevealedLock(event);
+ UpdateLocatedEventRevealedLock(event, ALLOW_REVEAL_WHILE_CLOSING_NO);
// Trigger a reveal if the cursor pauses at the top of the screen for a
// while.
@@ -452,7 +452,7 @@
if (!enabled_ || event->type() != ui::ET_TOUCH_PRESSED)
return;
- UpdateLocatedEventRevealedLock(event);
+ UpdateLocatedEventRevealedLock(event, ALLOW_REVEAL_WHILE_CLOSING_NO);
}
void ImmersiveModeControllerAsh::OnGestureEvent(ui::GestureEvent* event) {
@@ -493,15 +493,6 @@
void ImmersiveModeControllerAsh::OnDidChangeFocus(views::View* focused_before,
views::View* focused_now) {
- scoped_ptr<ImmersiveRevealedLock> lock;
- if (reveal_state_ == REVEALED || reveal_state_ == SLIDING_OPEN) {
- // Acquire a lock so that if UpdateLocatedEventRevealedLock() or
- // UpdateFocusRevealedLock() ends the reveal, it occurs after the
- // function terminates. This is useful in tests.
- lock.reset(GetRevealedLock(ANIMATE_REVEAL_YES));
- }
-
- UpdateLocatedEventRevealedLock(NULL);
UpdateFocusRevealedLock();
}
@@ -517,20 +508,21 @@
void ImmersiveModeControllerAsh::OnWidgetActivationChanged(
views::Widget* widget,
bool active) {
- scoped_ptr<ImmersiveRevealedLock> lock;
- if (reveal_state_ == REVEALED || reveal_state_ == SLIDING_OPEN) {
- // Acquire a lock so that if UpdateLocatedEventRevealedLock() or
- // UpdateFocusRevealedLock() ends the reveal, it occurs after the
- // function terminates. This is useful in tests.
- lock.reset(GetRevealedLock(ANIMATE_REVEAL_YES));
- }
-
// Mouse hover should not initiate revealing the top-of-window views while
// |native_window_| is inactive.
top_edge_hover_timer_.Stop();
- UpdateLocatedEventRevealedLock(NULL);
UpdateFocusRevealedLock();
+
+ // Allow the top-of-window views to stay revealed if all of the revealed locks
+ // were released in the process of activating |widget| but the mouse is still
+ // hovered above the top-of-window views. For instance, if the bubble which
+ // has been keeping the top-of-window views revealed is hidden but the mouse
+ // is hovered above the top-of-window views, the top-of-window views should
+ // stay revealed. We cannot call UpdateLocatedEventRevealedLock() from
+ // BubbleManager::UpdateRevealedLock() because |widget| is not yet active
+ // at that time.
+ UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_YES);
}
////////////////////////////////////////////////////////////////////////////////
@@ -623,12 +615,12 @@
void ImmersiveModeControllerAsh::StartRevealForTest(bool hovered) {
MaybeStartReveal(ANIMATE_NO);
MoveMouse(top_container_, hovered);
- UpdateLocatedEventRevealedLock(NULL);
+ UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_NO);
}
void ImmersiveModeControllerAsh::SetMouseHoveredForTest(bool hovered) {
MoveMouse(top_container_, hovered);
- UpdateLocatedEventRevealedLock(NULL);
+ UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_NO);
}
void ImmersiveModeControllerAsh::DisableAnimationsForTest() {
@@ -746,7 +738,8 @@
}
void ImmersiveModeControllerAsh::UpdateLocatedEventRevealedLock(
- ui::LocatedEvent* event) {
+ ui::LocatedEvent* event,
+ AllowRevealWhileClosing allow_reveal_while_closing) {
if (!enabled_)
return;
DCHECK(!event || event->IsMouseEvent() || event->IsTouchEvent());
@@ -755,8 +748,11 @@
// views are sliding closed or are closed with the following exceptions:
// - Hovering at y = 0 which is handled in OnMouseEvent().
// - Doing a SWIPE_OPEN edge gesture which is handled in OnGestureEvent().
- if (reveal_state_ == SLIDING_CLOSED || reveal_state_ == CLOSED)
+ if (reveal_state_ == CLOSED ||
+ (reveal_state_ == SLIDING_CLOSED &&
+ allow_reveal_while_closing == ALLOW_REVEAL_WHILE_CLOSING_NO)) {
return;
+ }
// Neither the mouse nor touch should keep the top-of-window views revealed if
// |native_window_| is not active.
@@ -895,7 +891,7 @@
return true;
// Ending the reveal was unsuccessful. Reaquire the locks if appropriate.
- UpdateLocatedEventRevealedLock(NULL);
+ UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_NO);
UpdateFocusRevealedLock();
}
}
@@ -1031,7 +1027,7 @@
// The user may not have moved the mouse since the reveal was initiated.
// Update the revealed lock to reflect the mouse's current state.
- UpdateLocatedEventRevealedLock(NULL);
+ UpdateLocatedEventRevealedLock(NULL, ALLOW_REVEAL_WHILE_CLOSING_NO);
}
void ImmersiveModeControllerAsh::MaybeEndReveal(Animate animate) {
@@ -1123,19 +1119,31 @@
bool ImmersiveModeControllerAsh::ShouldHandleGestureEvent(
const gfx::Point& location) const {
+ gfx::Rect top_container_bounds_in_screen =
+ top_container_->GetBoundsInScreen();
+
// All of the gestures that are of interest start in a region with left &
// right edges agreeing with |top_container_|. When CLOSED it is difficult to
// hit the bounds due to small size of the tab strip, so the hit target needs
- // to be extended on the bottom, thus the inset call. Finally there may be a
- // bezel sensor off screen logically above |top_container_| thus the test
- // needs to include gestures starting above.
- gfx::Rect near_bounds = top_container_->GetBoundsInScreen();
+ // to be extended on the bottom, thus the inset call.
+ gfx::Rect near_bounds = top_container_bounds_in_screen;
if (reveal_state_ == CLOSED)
near_bounds.Inset(gfx::Insets(0, 0, -kNearTopContainerDistance, 0));
- return near_bounds.Contains(location) ||
- ((location.y() < near_bounds.y()) &&
- (location.x() >= near_bounds.x()) &&
- (location.x() < near_bounds.right()));
+ if (near_bounds.Contains(location))
+ return true;
+
+ // There may be a bezel sensor off screen logically above |top_container_|
+ // thus the test needs to include gestures starting above, but this needs to
+ // be distinguished from events originating on another screen from
+ // (potentially) an extended desktop. The check for the event not contained by
+ // the closest screen ensures that the event is from a valid bezel and can be
+ // interpreted as such.
+ gfx::Rect screen_bounds =
+ ash::Shell::GetScreen()->GetDisplayNearestPoint(location).bounds();
+ return (!screen_bounds.Contains(location) &&
+ location.y() < top_container_bounds_in_screen.y() &&
+ location.x() >= top_container_bounds_in_screen.x() &&
+ location.x() < top_container_bounds_in_screen.right());
}
void ImmersiveModeControllerAsh::SetRenderWindowTopInsetsForTouch(
@@ -1143,10 +1151,13 @@
content::WebContents* contents = delegate_->GetWebContents();
if (contents) {
aura::Window* window = contents->GetView()->GetContentNativeView();
- gfx::Insets inset(top_inset, 0, 0, 0);
- window->SetHitTestBoundsOverrideOuter(
- window->hit_test_bounds_override_outer_mouse(),
- inset);
+ // |window| is NULL if the renderer crashed.
+ if (window) {
+ gfx::Insets inset(top_inset, 0, 0, 0);
+ window->SetHitTestBoundsOverrideOuter(
+ window->hit_test_bounds_override_outer_mouse(),
+ inset);
+ }
}
}
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h
index 482c5b2..c904f05 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h
@@ -118,6 +118,10 @@
private:
friend class ImmersiveModeControllerAshTest;
+ enum AllowRevealWhileClosing {
+ ALLOW_REVEAL_WHILE_CLOSING_YES,
+ ALLOW_REVEAL_WHILE_CLOSING_NO
+ };
enum Animate {
ANIMATE_NO,
ANIMATE_SLOW,
@@ -156,7 +160,12 @@
// Updates |located_event_revealed_lock_| based on the current mouse state and
// the current touch state.
// |event| is NULL if the source event is not known.
- void UpdateLocatedEventRevealedLock(ui::LocatedEvent* event);
+ // |allow_reveal_while_closing| indicates whether the mouse and touch
+ // are allowed to initiate a reveal while the top-of-window views are sliding
+ // closed.
+ void UpdateLocatedEventRevealedLock(
+ ui::LocatedEvent* event,
+ AllowRevealWhileClosing allow_reveal_while_closing);
// Acquires |located_event_revealed_lock_| if it is not already held.
void AcquireLocatedEventRevealedLock();
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 d91bbd8..c983c9a 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
@@ -13,6 +13,7 @@
#include "ui/aura/root_window.h"
#include "ui/aura/test/event_generator.h"
#include "ui/aura/window.h"
+#include "ui/base/animation/slide_animation.h"
#include "ui/views/bubble/bubble_delegate.h"
// For now, immersive fullscreen is Chrome OS only.
@@ -96,7 +97,21 @@
widget_->GetContentsView()->AddChildView(top_container_);
controller_->Init(delegate_.get(), widget_, top_container_);
- controller_->DisableAnimationsForTest();
+ SetAnimationsDisabled(true);
+ }
+
+ // Enable or disable the immersive mode controller's animations. When the
+ // immersive mode controller's animations are disabled, some behavior is
+ // slightly different. In particular, the behavior is different when there
+ // is a transfer in which lock keeps the top-of-window views revealed (eg
+ // bubble keeps top-of-window views revealed -> mouse keeps top-of-window
+ // views revealed). It is necessary to temparily enable the immersive
+ // controller's animations to get the correct behavior in tests.
+ void SetAnimationsDisabled(bool disabled) {
+ controller_->animations_disabled_for_test_ = disabled;
+ // Force any in progress animations to finish.
+ if (disabled)
+ controller_->animation_->End();
}
// Attempt to reveal the top-of-window views via |modality|.
@@ -654,14 +669,25 @@
bubble_widget2->Close();
EXPECT_FALSE(controller()->IsRevealed());
- // 2) Test that the top-of-window views stay revealed as long as at least one
- // bubble anchored to a child of the top container is visible.
- views::BubbleDelegateView* bubble_delegate3(new views::BubbleDelegateView(
- child_view, views::BubbleBorder::NONE));
- bubble_delegate3->set_use_focusless(true);
- views::Widget* bubble_widget3(views::BubbleDelegateView::CreateBubble(
- bubble_delegate3));
+ // 2) Test that transitioning from keeping the top-of-window views revealed
+ // because of a bubble to keeping the top-of-window views revealed because of
+ // mouse hover by activating |top_container_widget| works.
+ views::Widget* bubble_widget3 = views::BubbleDelegateView::CreateBubble(
+ new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE));
bubble_widget3->Show();
+ SetHovered(true);
+ EXPECT_TRUE(controller()->IsRevealed());
+
+ SetAnimationsDisabled(false);
+ // Activating |top_container_widget| will close |bubble_widget3|.
+ top_container_widget->Activate();
+ SetAnimationsDisabled(true);
+ EXPECT_TRUE(controller()->IsRevealed());
+
+ // 3) Test that the top-of-window views stay revealed as long as at least one
+ // bubble anchored to a child of the top container is visible.
+ SetHovered(false);
+ EXPECT_FALSE(controller()->IsRevealed());
views::BubbleDelegateView* bubble_delegate4(new views::BubbleDelegateView(
child_view, views::BubbleBorder::NONE));
@@ -670,44 +696,51 @@
bubble_delegate4));
bubble_widget4->Show();
- EXPECT_TRUE(controller()->IsRevealed());
- bubble_widget3->Hide();
+ views::BubbleDelegateView* bubble_delegate5(new views::BubbleDelegateView(
+ child_view, views::BubbleBorder::NONE));
+ bubble_delegate5->set_use_focusless(true);
+ views::Widget* bubble_widget5(views::BubbleDelegateView::CreateBubble(
+ bubble_delegate5));
+ bubble_widget5->Show();
+
EXPECT_TRUE(controller()->IsRevealed());
bubble_widget4->Hide();
+ EXPECT_TRUE(controller()->IsRevealed());
+ bubble_widget5->Hide();
EXPECT_FALSE(controller()->IsRevealed());
- bubble_widget4->Show();
+ bubble_widget5->Show();
EXPECT_TRUE(controller()->IsRevealed());
- // 3) Test that visibility changes which occur while immersive fullscreen is
+ // 4) Test that visibility changes which occur while immersive fullscreen is
// disabled are handled upon reenabling immersive fullscreen.
controller()->SetEnabled(false);
- bubble_widget4->Hide();
+ bubble_widget5->Hide();
controller()->SetEnabled(true);
EXPECT_FALSE(controller()->IsRevealed());
- // We do not need |bubble_widget3| or |bubble_widget4| anymore, close them.
- bubble_widget3->Close();
+ // We do not need |bubble_widget4| or |bubble_widget5| anymore, close them.
bubble_widget4->Close();
+ bubble_widget5->Close();
- // 4) Test that a bubble added while immersive fullscreen is disabled is
+ // 5) Test that a bubble added while immersive fullscreen is disabled is
// handled upon reenabling immersive fullscreen.
controller()->SetEnabled(false);
- views::Widget* bubble_widget5 = views::BubbleDelegateView::CreateBubble(
+ views::Widget* bubble_widget6 = views::BubbleDelegateView::CreateBubble(
new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE));
- bubble_widget5->Show();
+ bubble_widget6->Show();
controller()->SetEnabled(true);
EXPECT_TRUE(controller()->IsRevealed());
- bubble_widget5->Close();
+ bubble_widget6->Close();
- // 5) Test that a bubble which is not anchored to a child of the
+ // 6) Test that a bubble which is not anchored to a child of the
// TopContainerView does not trigger a reveal or keep the
// top-of-window views revealed if they are already revealed.
- views::Widget* bubble_widget6 = views::BubbleDelegateView::CreateBubble(
+ views::Widget* bubble_widget7 = views::BubbleDelegateView::CreateBubble(
new views::BubbleDelegateView(unrelated_view, views::BubbleBorder::NONE));
- bubble_widget6->Show();
+ bubble_widget7->Show();
EXPECT_FALSE(controller()->IsRevealed());
// Activating |top_container_widget| will close |bubble_widget6|.
@@ -715,12 +748,12 @@
AttemptReveal(MODALITY_MOUSE);
EXPECT_TRUE(controller()->IsRevealed());
- views::Widget* bubble_widget7 = views::BubbleDelegateView::CreateBubble(
+ views::Widget* bubble_widget8 = views::BubbleDelegateView::CreateBubble(
new views::BubbleDelegateView(unrelated_view, views::BubbleBorder::NONE));
- bubble_widget7->Show();
+ bubble_widget8->Show();
SetHovered(false);
EXPECT_FALSE(controller()->IsRevealed());
- bubble_widget7->Close();
+ bubble_widget8->Close();
}
#endif // defined(OS_WIN)
diff --git a/chrome/browser/ui/views/location_bar/autofill_credit_card_view.cc b/chrome/browser/ui/views/location_bar/autofill_credit_card_view.cc
deleted file mode 100644
index 21e7208..0000000
--- a/chrome/browser/ui/views/location_bar/autofill_credit_card_view.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/views/location_bar/autofill_credit_card_view.h"
-
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h"
-#include "chrome/browser/ui/toolbar/toolbar_model.h"
-#include "ui/gfx/image/image.h"
-
-AutofillCreditCardView::AutofillCreditCardView(
- ToolbarModel* toolbar_model,
- LocationBarView::Delegate* delegate)
- : toolbar_model_(toolbar_model),
- delegate_(delegate) {
- Update();
-}
-
-AutofillCreditCardView::~AutofillCreditCardView() {}
-
-void AutofillCreditCardView::Update() {
- autofill::AutofillCreditCardBubbleController* controller = GetController();
- if (controller && !controller->AnchorIcon().IsEmpty()) {
- SetVisible(true);
- SetImage(controller->AnchorIcon().AsImageSkia());
- } else {
- SetVisible(false);
- SetImage(NULL);
- }
-}
-
-// TODO(dbeam): figure out what to do for a tooltip and accessibility.
-
-bool AutofillCreditCardView::CanHandleClick() const {
- autofill::AutofillCreditCardBubbleController* controller = GetController();
- return controller && !controller->IsHiding();
-}
-
-void AutofillCreditCardView::OnClick() {
- autofill::AutofillCreditCardBubbleController* controller = GetController();
- if (controller)
- controller->OnAnchorClicked();
-}
-
-autofill::AutofillCreditCardBubbleController* AutofillCreditCardView::
- GetController() const {
- content::WebContents* wc = delegate_->GetWebContents();
- if (!wc || toolbar_model_->GetInputInProgress())
- return NULL;
-
- return autofill::AutofillCreditCardBubbleController::FromWebContents(wc);
-}
diff --git a/chrome/browser/ui/views/location_bar/autofill_credit_card_view.h b/chrome/browser/ui/views/location_bar/autofill_credit_card_view.h
deleted file mode 100644
index 169c5f2..0000000
--- a/chrome/browser/ui/views/location_bar/autofill_credit_card_view.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_AUTOFILL_CREDIT_CARD_VIEW_H_
-#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_AUTOFILL_CREDIT_CARD_VIEW_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "chrome/browser/ui/autofill/autofill_credit_card_bubble_controller.h"
-#include "chrome/browser/ui/views/location_bar/location_bar_decoration_view.h"
-#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-#include "ui/views/controls/image_view.h"
-
-class ToolbarModel;
-
-namespace autofill {
-class AutofillCreditCardBubbleController;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// AutofillCreditCardView
-//
-// An icon that shows up in the omnibox after successfully submitting the
-// Autofill dialog. Used as an anchor and click target to show the associated
-// bubble with more details about the credit cards saved or used.
-//
-////////////////////////////////////////////////////////////////////////////////
-class AutofillCreditCardView : public LocationBarDecorationView {
- public:
- AutofillCreditCardView(ToolbarModel* toolbar_model,
- LocationBarView::Delegate* delegate);
- virtual ~AutofillCreditCardView();
-
- void Update();
-
- protected:
- // LocationBarDecorationView:
- virtual bool CanHandleClick() const OVERRIDE;
- virtual void OnClick() OVERRIDE;
-
- private:
- // Helper to get the AutofillCreditCardBubbleController associated with the
- // current web contents.
- autofill::AutofillCreditCardBubbleController* GetController() const;
-
- ToolbarModel* toolbar_model_; // weak; outlives us.
- LocationBarView::Delegate* delegate_; // weak; outlives us.
-
- DISALLOW_COPY_AND_ASSIGN(AutofillCreditCardView);
-};
-
-#endif // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_AUTOFILL_CREDIT_CARD_VIEW_H_
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 014c3da..6d05e4f 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
@@ -83,7 +83,7 @@
text_label_->SetElideBehavior(views::Label::NO_ELIDE);
AddChildView(text_label_);
- TouchableLocationBarView::Init(this);
+ LocationBarView::InitTouchableLocationBarChildView(this);
slide_animator_.SetSlideDuration(kAnimationDurationMS);
slide_animator_.SetTweenType(ui::Tween::LINEAR);
@@ -94,10 +94,6 @@
bubble_widget_->RemoveObserver(this);
}
-int ContentSettingImageView::GetBuiltInHorizontalPadding() const {
- return GetBuiltInHorizontalPaddingImpl();
-}
-
void ContentSettingImageView::Update(content::WebContents* web_contents) {
// Note: We explicitly want to call this even if |web_contents| is NULL, so we
// get hidden properly while the user is editing the omnibox.
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 4d59678..350b3fd 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
@@ -6,7 +6,6 @@
#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_CONTENT_SETTING_IMAGE_VIEW_H_
#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
#include "chrome/common/content_settings_types.h"
#include "ui/base/animation/animation_delegate.h"
#include "ui/base/animation/slide_animation.h"
@@ -30,8 +29,7 @@
// The ContentSettingImageView displays an icon and optional text label for
// various content settings affordances in the location bar (i.e. plugin
// blocking, geolocation).
-class ContentSettingImageView : public TouchableLocationBarView,
- public ui::AnimationDelegate,
+class ContentSettingImageView : public ui::AnimationDelegate,
public views::View,
public views::WidgetObserver {
public:
@@ -43,9 +41,6 @@
SkColor parent_background_color);
virtual ~ContentSettingImageView();
- // TouchableLocationBarView:
- virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
// Update the decoration from the shown WebContents.
void Update(content::WebContents* web_contents);
diff --git a/chrome/browser/ui/views/location_bar/generated_credit_card_view.cc b/chrome/browser/ui/views/location_bar/generated_credit_card_view.cc
new file mode 100644
index 0000000..ff914b6
--- /dev/null
+++ b/chrome/browser/ui/views/location_bar/generated_credit_card_view.cc
@@ -0,0 +1,52 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/location_bar/generated_credit_card_view.h"
+
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/toolbar/toolbar_model.h"
+#include "ui/gfx/image/image.h"
+
+GeneratedCreditCardView::GeneratedCreditCardView(
+ ToolbarModel* toolbar_model,
+ LocationBarView::Delegate* delegate)
+ : toolbar_model_(toolbar_model),
+ delegate_(delegate) {
+ Update();
+}
+
+GeneratedCreditCardView::~GeneratedCreditCardView() {}
+
+void GeneratedCreditCardView::Update() {
+ autofill::GeneratedCreditCardBubbleController* controller = GetController();
+ if (controller && !controller->AnchorIcon().IsEmpty()) {
+ SetVisible(true);
+ SetImage(controller->AnchorIcon().AsImageSkia());
+ } else {
+ SetVisible(false);
+ SetImage(NULL);
+ }
+}
+
+// TODO(dbeam): figure out what to do for a tooltip and accessibility.
+
+bool GeneratedCreditCardView::CanHandleClick() const {
+ autofill::GeneratedCreditCardBubbleController* controller = GetController();
+ return controller && !controller->IsHiding();
+}
+
+void GeneratedCreditCardView::OnClick() {
+ autofill::GeneratedCreditCardBubbleController* controller = GetController();
+ if (controller)
+ controller->OnAnchorClicked();
+}
+
+autofill::GeneratedCreditCardBubbleController* GeneratedCreditCardView::
+ GetController() const {
+ content::WebContents* wc = delegate_->GetWebContents();
+ if (!wc || toolbar_model_->GetInputInProgress())
+ return NULL;
+
+ return autofill::GeneratedCreditCardBubbleController::FromWebContents(wc);
+}
diff --git a/chrome/browser/ui/views/location_bar/generated_credit_card_view.h b/chrome/browser/ui/views/location_bar/generated_credit_card_view.h
new file mode 100644
index 0000000..c741985
--- /dev/null
+++ b/chrome/browser/ui/views/location_bar/generated_credit_card_view.h
@@ -0,0 +1,54 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_GENERATED_CREDIT_CARD_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_GENERATED_CREDIT_CARD_VIEW_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "chrome/browser/ui/autofill/generated_credit_card_bubble_controller.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_decoration_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "ui/views/controls/image_view.h"
+
+class ToolbarModel;
+
+namespace autofill {
+class GeneratedCreditCardBubbleController;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// GeneratedCreditCardView
+//
+// An icon that shows up in the omnibox after successfully generating a credit
+// card number. Used as an anchor and click target to show the associated
+// bubble with more details about the credit cards saved or used.
+//
+////////////////////////////////////////////////////////////////////////////////
+class GeneratedCreditCardView : public LocationBarDecorationView {
+ public:
+ GeneratedCreditCardView(ToolbarModel* toolbar_model,
+ LocationBarView::Delegate* delegate);
+ virtual ~GeneratedCreditCardView();
+
+ void Update();
+
+ protected:
+ // LocationBarDecorationView:
+ virtual bool CanHandleClick() const OVERRIDE;
+ virtual void OnClick() OVERRIDE;
+
+ private:
+ // Helper to get the GeneratedCreditCardBubbleController associated with the
+ // current web contents.
+ autofill::GeneratedCreditCardBubbleController* GetController() const;
+
+ ToolbarModel* toolbar_model_; // weak; outlives us.
+ LocationBarView::Delegate* delegate_; // weak; outlives us.
+
+ DISALLOW_COPY_AND_ASSIGN(GeneratedCreditCardView);
+};
+
+#endif // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_GENERATED_CREDIT_CARD_VIEW_H_
diff --git a/chrome/browser/ui/views/location_bar/location_bar_decoration_view.cc b/chrome/browser/ui/views/location_bar/location_bar_decoration_view.cc
index 443e368..c0bf64c 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_decoration_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_decoration_view.cc
@@ -4,12 +4,13 @@
#include "chrome/browser/ui/views/location_bar/location_bar_decoration_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "ui/base/events/event.h"
LocationBarDecorationView::LocationBarDecorationView()
: could_handle_click_(true) {
set_accessibility_focusable(true);
- TouchableLocationBarView::Init(this);
+ LocationBarView::InitTouchableLocationBarChildView(this);
}
LocationBarDecorationView::~LocationBarDecorationView() {}
@@ -48,10 +49,6 @@
}
}
-int LocationBarDecorationView::GetBuiltInHorizontalPadding() const {
- return GetBuiltInHorizontalPaddingImpl();
-}
-
bool LocationBarDecorationView::CanHandleClick() const {
return true;
}
diff --git a/chrome/browser/ui/views/location_bar/location_bar_decoration_view.h b/chrome/browser/ui/views/location_bar/location_bar_decoration_view.h
index 58e69db..117417b 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_decoration_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_decoration_view.h
@@ -7,7 +7,6 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
#include "ui/views/controls/image_view.h"
////////////////////////////////////////////////////////////////////////////////
@@ -18,8 +17,7 @@
// in the omnibox (like the bookmarks star or SSL lock).
//
////////////////////////////////////////////////////////////////////////////////
-class LocationBarDecorationView : public views::ImageView,
- public TouchableLocationBarView {
+class LocationBarDecorationView : public views::ImageView {
public:
LocationBarDecorationView();
virtual ~LocationBarDecorationView();
@@ -30,9 +28,6 @@
virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
- // TouchableLocationBarView:
- virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
protected:
// Whether this icon should currently be able to process a mouse click. Called
// both on mouse up and mouse down; must return true both times to for
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 72a84ce..64bdc85 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -38,13 +38,12 @@
#include "chrome/browser/ui/views/bookmarks/bookmark_prompt_view.h"
#include "chrome/browser/ui/views/browser_dialogs.h"
#include "chrome/browser/ui/views/extensions/extension_popup.h"
-#include "chrome/browser/ui/views/location_bar/autofill_credit_card_view.h"
#include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
#include "chrome/browser/ui/views/location_bar/ev_bubble_view.h"
+#include "chrome/browser/ui/views/location_bar/generated_credit_card_view.h"
#include "chrome/browser/ui/views/location_bar/keyword_hint_view.h"
#include "chrome/browser/ui/views/location_bar/location_bar_layout.h"
#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
-#include "chrome/browser/ui/views/location_bar/mic_search_view.h"
#include "chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.h"
#include "chrome/browser/ui/views/location_bar/page_action_image_view.h"
#include "chrome/browser/ui/views/location_bar/page_action_with_badge_view.h"
@@ -79,6 +78,7 @@
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/button_drag_utils.h"
+#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/widget/widget.h"
@@ -185,7 +185,7 @@
keyword_hint_view_(NULL),
mic_search_view_(NULL),
zoom_view_(NULL),
- autofill_credit_card_view_(NULL),
+ generated_credit_card_view_(NULL),
open_pdf_in_reader_view_(NULL),
script_bubble_icon_view_(NULL),
star_view_(NULL),
@@ -227,6 +227,15 @@
browser_->search_model()->RemoveObserver(this);
}
+// static
+void LocationBarView::InitTouchableLocationBarChildView(views::View* view) {
+ int horizontal_padding = GetBuiltInHorizontalPaddingForChildViews();
+ if (horizontal_padding != 0) {
+ view->set_border(views::Border::CreateEmptyBorder(
+ 3, horizontal_padding, 3, horizontal_padding));
+ }
+}
+
void LocationBarView::Init() {
// We need to be in a Widget, otherwise GetNativeTheme() may change and we're
// not prepared for that.
@@ -314,8 +323,19 @@
background_color);
AddChildView(keyword_hint_view_);
- mic_search_view_ = new MicSearchView(this);
+ mic_search_view_ = new views::ImageButton(this);
+ mic_search_view_->set_id(VIEW_ID_MIC_SEARCH_BUTTON);
+ mic_search_view_->set_accessibility_focusable(true);
+ mic_search_view_->SetTooltipText(
+ l10n_util::GetStringUTF16(IDS_TOOLTIP_MIC_SEARCH));
+ mic_search_view_->SetImage(
+ views::Button::STATE_NORMAL,
+ ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+ IDR_OMNIBOX_MIC_SEARCH));
+ mic_search_view_->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
+ views::ImageButton::ALIGN_MIDDLE);
mic_search_view_->SetVisible(false);
+ InitTouchableLocationBarChildView(mic_search_view_);
AddChildView(mic_search_view_);
for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
@@ -328,8 +348,8 @@
AddChildView(content_blocked_view);
}
- autofill_credit_card_view_ = new AutofillCreditCardView(model_, delegate_);
- AddChildView(autofill_credit_card_view_);
+ generated_credit_card_view_ = new GeneratedCreditCardView(model_, delegate_);
+ AddChildView(generated_credit_card_view_);
zoom_view_ = new ZoomView(model_, delegate_);
zoom_view_->set_id(VIEW_ID_ZOOM_BUTTON);
@@ -467,7 +487,7 @@
!model_->GetInputInProgress() && browser_ &&
browser_->search_model()->voice_search_supported());
RefreshContentSettingViews();
- autofill_credit_card_view_->Update();
+ generated_credit_card_view_->Update();
ZoomBubbleView::CloseBubble();
RefreshZoomView();
RefreshPageActionViews();
@@ -530,8 +550,8 @@
SchedulePaint();
}
-void LocationBarView::UpdateAutofillCreditCardView() {
- autofill_credit_card_view_->Update();
+void LocationBarView::UpdateGeneratedCreditCardView() {
+ generated_credit_card_view_->Update();
Layout();
SchedulePaint();
}
@@ -716,25 +736,25 @@
} else {
leading_decorations.AddDecoration(
vertical_edge_thickness(), location_height,
- location_icon_view_->GetBuiltInHorizontalPadding(),
+ GetBuiltInHorizontalPaddingForChildViews(),
location_icon_view_);
}
if (star_view_ && star_view_->visible()) {
trailing_decorations.AddDecoration(
vertical_edge_thickness(), location_height,
- star_view_->GetBuiltInHorizontalPadding(), star_view_);
+ GetBuiltInHorizontalPaddingForChildViews(), star_view_);
}
if (script_bubble_icon_view_ && script_bubble_icon_view_->visible()) {
trailing_decorations.AddDecoration(
vertical_edge_thickness(), location_height,
- script_bubble_icon_view_->GetBuiltInHorizontalPadding(),
+ GetBuiltInHorizontalPaddingForChildViews(),
script_bubble_icon_view_);
}
if (open_pdf_in_reader_view_ && open_pdf_in_reader_view_->visible()) {
trailing_decorations.AddDecoration(
vertical_edge_thickness(), location_height,
- open_pdf_in_reader_view_->GetBuiltInHorizontalPadding(),
+ GetBuiltInHorizontalPaddingForChildViews(),
open_pdf_in_reader_view_);
}
for (PageActionViews::const_iterator i(page_action_views_.begin());
@@ -742,7 +762,7 @@
if ((*i)->visible()) {
trailing_decorations.AddDecoration(
vertical_edge_thickness(), location_height,
- (*i)->GetBuiltInHorizontalPadding(), (*i));
+ GetBuiltInHorizontalPaddingForChildViews(), (*i));
}
}
if (zoom_view_->visible()) {
@@ -755,13 +775,13 @@
if ((*i)->visible()) {
trailing_decorations.AddDecoration(
bubble_location_y, bubble_height, false, 0, item_padding,
- item_padding, (*i)->GetBuiltInHorizontalPadding(), (*i));
+ item_padding, GetBuiltInHorizontalPaddingForChildViews(), (*i));
}
}
- if (autofill_credit_card_view_->visible()) {
+ if (generated_credit_card_view_->visible()) {
trailing_decorations.AddDecoration(vertical_edge_thickness(),
location_height, 0,
- autofill_credit_card_view_);
+ generated_credit_card_view_);
}
if (mic_search_view_->visible()) {
trailing_decorations.AddDecoration(vertical_edge_thickness(),
@@ -993,8 +1013,8 @@
}
#endif
-views::View* LocationBarView::autofill_credit_card_view() {
- return autofill_credit_card_view_;
+views::View* LocationBarView::generated_credit_card_view() {
+ return generated_credit_card_view_;
}
void LocationBarView::OnAutocompleteAccept(
@@ -1078,8 +1098,10 @@
return delegate_->GetWebContents();
}
-gfx::Rect LocationBarView::GetOmniboxBounds() const {
- return bounds();
+// static
+int LocationBarView::GetBuiltInHorizontalPaddingForChildViews() {
+ return (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH) ?
+ GetItemPadding() / 2 : 0;
}
int LocationBarView::GetHorizontalEdgeThickness() const {
@@ -1237,8 +1259,8 @@
page_action_view != page_action_views_.end();
++page_action_view) {
gfx::Rect bounds = (*page_action_view)->bounds();
- int horizontal_padding = GetItemPadding() -
- (*page_action_view)->GetBuiltInHorizontalPadding();
+ int horizontal_padding =
+ GetItemPadding() - GetBuiltInHorizontalPaddingForChildViews();
// Make the bounding rectangle include the whole vertical range of the
// location bar, and the mid-point pixels between adjacent page actions.
//
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h
index 96151da..2c14ff7 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -32,17 +32,16 @@
#endif
class ActionBoxButtonView;
-class AutofillCreditCardView;
class CommandUpdater;
class ContentSettingBubbleModelDelegate;
class ContentSettingImageView;
class EVBubbleView;
class ExtensionAction;
class GURL;
+class GeneratedCreditCardView;
class InstantController;
class KeywordHintView;
class LocationIconView;
-class MicSearchView;
class OpenPDFInReaderView;
class PageActionWithBadgeView;
class PageActionImageView;
@@ -55,6 +54,7 @@
namespace views {
class BubbleDelegateView;
+class ImageButton;
class Label;
class Widget;
}
@@ -140,6 +140,12 @@
virtual ~LocationBarView();
+ // Uses GetBuiltInHorizontalPaddingForChildViews() to optionally add
+ // additional padding (via an empty border) to |view|. This should be called
+ // during creation on all child views which are potentially touchable so that
+ // when touch is enabled they will have sufficient padding.
+ static void InitTouchableLocationBarChildView(views::View* view);
+
// Initializes the LocationBarView.
void Init();
@@ -245,7 +251,7 @@
views::View* location_entry_view() const { return location_entry_view_; }
- views::View* autofill_credit_card_view();
+ views::View* generated_credit_card_view();
// OmniboxEditController:
virtual void OnAutocompleteAccept(const GURL& url,
@@ -261,7 +267,6 @@
virtual string16 GetTitle() const OVERRIDE;
virtual InstantController* GetInstant() OVERRIDE;
virtual content::WebContents* GetWebContents() const OVERRIDE;
- virtual gfx::Rect GetOmniboxBounds() const OVERRIDE;
// views::View:
virtual const char* GetClassName() const OVERRIDE;
@@ -297,7 +302,7 @@
virtual void UpdatePageActions() OVERRIDE;
virtual void InvalidatePageActions() OVERRIDE;
virtual void UpdateOpenPDFInReaderPrompt() OVERRIDE;
- virtual void UpdateAutofillCreditCardView() OVERRIDE;
+ virtual void UpdateGeneratedCreditCardView() OVERRIDE;
virtual void SaveStateToContents(content::WebContents* contents) OVERRIDE;
virtual void Revert() OVERRIDE;
virtual const OmniboxView* GetLocationEntry() const OVERRIDE;
@@ -333,11 +338,10 @@
// Returns the position and width that the popup should be, and also the left
// edge that the results should align themselves to (which will leave some
// border on the left of the popup).
- void GetOmniboxPopupPositioningInfo(
- gfx::Point* top_left_screen_coord,
- int* popup_width,
- int* left_margin,
- int* right_margin);
+ void GetOmniboxPopupPositioningInfo(gfx::Point* top_left_screen_coord,
+ int* popup_width,
+ int* left_margin,
+ int* right_margin);
// Space between items in the location bar, as well as between items and the
// edges.
@@ -362,6 +366,11 @@
friend class PageActionWithBadgeView;
typedef std::vector<PageActionWithBadgeView*> PageActionViews;
+ // Returns the number of pixels of built-in padding to the left and right for
+ // child views. This is nonzero when touch UI is enabled so as to space out
+ // child views for easier targeting. See InitTouchableLocationBarChildView().
+ static int GetBuiltInHorizontalPaddingForChildViews();
+
// Returns the thickness of any visible left and right edge, in pixels.
int GetHorizontalEdgeThickness() const;
@@ -475,7 +484,7 @@
KeywordHintView* keyword_hint_view_;
// The voice search icon.
- MicSearchView* mic_search_view_;
+ views::ImageButton* mic_search_view_;
// The content setting views.
ContentSettingViews content_setting_views_;
@@ -483,8 +492,8 @@
// The zoom icon.
ZoomView* zoom_view_;
- // A bubble that shows after successful submission of the Autofill dialog.
- AutofillCreditCardView* autofill_credit_card_view_;
+ // A bubble that shows after successfully generating a new credit card number.
+ GeneratedCreditCardView* generated_credit_card_view_;
// The icon to open a PDF in Reader.
OpenPDFInReaderView* open_pdf_in_reader_view_;
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view.cc b/chrome/browser/ui/views/location_bar/location_icon_view.cc
index 1772e91..0526b6a 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_icon_view.cc
@@ -5,13 +5,14 @@
#include "chrome/browser/ui/views/location_bar/location_icon_view.h"
#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
LocationIconView::LocationIconView(LocationBarView* location_bar)
: page_info_helper_(this, location_bar) {
SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_LOCATION_ICON));
- TouchableLocationBarView::Init(this);
+ LocationBarView::InitTouchableLocationBarChildView(this);
}
LocationIconView::~LocationIconView() {
@@ -34,14 +35,7 @@
}
}
-int LocationIconView::GetBuiltInHorizontalPadding() const {
- return GetBuiltInHorizontalPaddingImpl();
-}
-
void LocationIconView::ShowTooltip(bool show) {
- if (show) {
- SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_LOCATION_ICON));
- } else {
- SetTooltipText(string16());
- }
+ SetTooltipText(show ?
+ l10n_util::GetStringUTF16(IDS_TOOLTIP_LOCATION_ICON) : base::string16());
}
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view.h b/chrome/browser/ui/views/location_bar/location_icon_view.h
index ba12c5f..2d6ad0c 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view.h
+++ b/chrome/browser/ui/views/location_bar/location_icon_view.h
@@ -6,7 +6,6 @@
#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_LOCATION_ICON_VIEW_H_
#include "chrome/browser/ui/views/location_bar/page_info_helper.h"
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
#include "ui/views/controls/image_view.h"
class LocationBarView;
@@ -14,22 +13,18 @@
// LocationIconView is used to display an icon to the left of the edit field.
// This shows the user's current action while editing, the page security
// status on https pages, or a globe for other URLs.
-class LocationIconView : public views::ImageView,
- public TouchableLocationBarView {
+class LocationIconView : public views::ImageView {
public:
explicit LocationIconView(LocationBarView* location_bar);
virtual ~LocationIconView();
- // Overridden from views::ImageView:
+ // views::ImageView:
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
- // Overridden from ui::EventHandler:
+ // ui::EventHandler:
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
- // TouchableLocationBarView.
- virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
// Whether we should show the tooltip for this icon or not.
void ShowTooltip(bool show);
diff --git a/chrome/browser/ui/views/location_bar/mic_search_view.cc b/chrome/browser/ui/views/location_bar/mic_search_view.cc
deleted file mode 100644
index 31f67d6..0000000
--- a/chrome/browser/ui/views/location_bar/mic_search_view.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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 "chrome/browser/ui/views/location_bar/mic_search_view.h"
-
-#include "chrome/browser/ui/view_ids.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "ui/base/accessibility/accessible_view_state.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-
-MicSearchView::MicSearchView(views::ButtonListener* button_listener)
- : views::ImageButton(button_listener) {
- set_id(VIEW_ID_MIC_SEARCH_BUTTON);
- set_accessibility_focusable(true);
- SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_MIC_SEARCH));
- SetImage(STATE_NORMAL,
- ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
- IDR_OMNIBOX_MIC_SEARCH));
- SetImageAlignment(ALIGN_CENTER, ALIGN_MIDDLE);
- TouchableLocationBarView::Init(this);
-}
-
-MicSearchView::~MicSearchView() {
-}
-
-int MicSearchView::GetBuiltInHorizontalPadding() const {
- return GetBuiltInHorizontalPaddingImpl();
-}
diff --git a/chrome/browser/ui/views/location_bar/mic_search_view.h b/chrome/browser/ui/views/location_bar/mic_search_view.h
deleted file mode 100644
index 30159a7..0000000
--- a/chrome/browser/ui/views/location_bar/mic_search_view.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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 CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_MIC_SEARCH_VIEW_H_
-#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_MIC_SEARCH_VIEW_H_
-
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
-#include "ui/views/controls/button/image_button.h"
-
-class CommandUpdater;
-
-class MicSearchView : public views::ImageButton,
- public TouchableLocationBarView {
- public:
- explicit MicSearchView(views::ButtonListener* button_listener);
- virtual ~MicSearchView();
-
- // TouchableLocationBarView:
- virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MicSearchView);
-};
-
-#endif // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_MIC_SEARCH_VIEW_H_
diff --git a/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.cc b/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.cc
index dc3a005..33607ad 100644
--- a/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.cc
+++ b/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.h"
#include "chrome/browser/ui/pdf/pdf_tab_helper.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "chrome/browser/ui/views/open_pdf_in_reader_bubble_view.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
@@ -18,12 +19,10 @@
bubble_(NULL),
model_(NULL) {
set_accessibility_focusable(true);
- SetImage(
- ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
- IDR_OMNIBOX_PDF_ICON));
- SetTooltipText(
- l10n_util::GetStringUTF16(IDS_PDF_BUBBLE_OPEN_IN_READER_LINK));
- TouchableLocationBarView::Init(this);
+ SetImage(ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+ IDR_OMNIBOX_PDF_ICON));
+ SetTooltipText(l10n_util::GetStringUTF16(IDS_PDF_BUBBLE_OPEN_IN_READER_LINK));
+ LocationBarView::InitTouchableLocationBarChildView(this);
}
OpenPDFInReaderView::~OpenPDFInReaderView() {
@@ -41,10 +40,6 @@
SetVisible(!!model_);
}
-int OpenPDFInReaderView::GetBuiltInHorizontalPadding() const {
- return GetBuiltInHorizontalPaddingImpl();
-}
-
void OpenPDFInReaderView::ShowBubble() {
if (bubble_)
return;
diff --git a/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.h b/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.h
index da90fbc..867e8d8 100644
--- a/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.h
+++ b/chrome/browser/ui/views/location_bar/open_pdf_in_reader_view.h
@@ -5,7 +5,6 @@
#ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_OPEN_PDF_IN_READER_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_OPEN_PDF_IN_READER_VIEW_H_
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/widget/widget_observer.h"
@@ -19,27 +18,23 @@
// A Page Action image view for the "Open PDF in Reader" bubble.
class OpenPDFInReaderView : public views::ImageView,
- public TouchableLocationBarView,
- views::WidgetObserver {
+ public views::WidgetObserver {
public:
explicit OpenPDFInReaderView(LocationBarView* location_bar_view);
virtual ~OpenPDFInReaderView();
void Update(content::WebContents* web_contents);
- // TouchableLocationBarView overrides:
- virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
private:
void ShowBubble();
- // views::ImageView overrides:
+ // views::ImageView:
virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
- // views::WidgetObserver override:
+ // views::WidgetObserver:
virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE;
// The LocationBarView hosting this view.
@@ -50,7 +45,7 @@
// Weak pointer; owned by the PDFTabHelper of the currently active tab.
OpenPDFInReaderPromptDelegate* model_;
- DISALLOW_IMPLICIT_CONSTRUCTORS(OpenPDFInReaderView);
+ DISALLOW_COPY_AND_ASSIGN(OpenPDFInReaderView);
};
#endif // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_OPEN_PDF_IN_READER_VIEW_H_
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 b148c8e..4bb9cca 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
@@ -4,6 +4,7 @@
#include "chrome/browser/ui/views/location_bar/page_action_with_badge_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "chrome/browser/ui/views/location_bar/page_action_image_view.h"
#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
#include "ui/base/accessibility/accessible_view_state.h"
@@ -14,7 +15,7 @@
PageActionImageView* image_view) {
image_view_ = image_view;
AddChildView(image_view_);
- TouchableLocationBarView::Init(this);
+ LocationBarView::InitTouchableLocationBarChildView(this);
}
void PageActionWithBadgeView::GetAccessibleState(
@@ -27,10 +28,6 @@
extensions::IconsInfo::kPageActionIconMaxSize);
}
-int PageActionWithBadgeView::GetBuiltInHorizontalPadding() const {
- return GetBuiltInHorizontalPaddingImpl();
-}
-
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
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 7118b98..82cf0e0 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
@@ -6,7 +6,6 @@
#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_PAGE_ACTION_WITH_BADGE_VIEW_H_
#include "base/compiler_specific.h"
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
#include "ui/gfx/size.h"
#include "ui/views/view.h"
@@ -18,21 +17,16 @@
}
// A container for the PageActionImageView plus its badge.
-class PageActionWithBadgeView
- : public views::View,
- public TouchableLocationBarView {
+class PageActionWithBadgeView : public views::View {
public:
explicit PageActionWithBadgeView(PageActionImageView* image_view);
PageActionImageView* image_view() { return image_view_; }
- // View overrides:
+ // views::View:
virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
virtual gfx::Size GetPreferredSize() OVERRIDE;
- // TouchableLocationBarView.
- virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
void UpdateVisibility(content::WebContents* contents, const GURL& url);
private:
diff --git a/chrome/browser/ui/views/location_bar/script_bubble_icon_view.cc b/chrome/browser/ui/views/location_bar/script_bubble_icon_view.cc
index 92a8411..82952c5 100644
--- a/chrome/browser/ui/views/location_bar/script_bubble_icon_view.cc
+++ b/chrome/browser/ui/views/location_bar/script_bubble_icon_view.cc
@@ -25,16 +25,12 @@
set_id(VIEW_ID_SCRIPT_BUBBLE);
SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_SCRIPT_BUBBLE));
set_accessibility_focusable(true);
- TouchableLocationBarView::Init(this);
+ LocationBarView::InitTouchableLocationBarChildView(this);
}
ScriptBubbleIconView::~ScriptBubbleIconView() {
}
-int ScriptBubbleIconView::GetBuiltInHorizontalPadding() const {
- return GetBuiltInHorizontalPaddingImpl();
-}
-
void ScriptBubbleIconView::SetScriptCount(size_t script_count) {
script_count_ = script_count;
gfx::ImageSkia* icon =
diff --git a/chrome/browser/ui/views/location_bar/script_bubble_icon_view.h b/chrome/browser/ui/views/location_bar/script_bubble_icon_view.h
index 2b72463..8e04e9e 100644
--- a/chrome/browser/ui/views/location_bar/script_bubble_icon_view.h
+++ b/chrome/browser/ui/views/location_bar/script_bubble_icon_view.h
@@ -6,38 +6,31 @@
#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_SCRIPT_BUBBLE_ICON_VIEW_H_
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
#include "ui/views/controls/image_view.h"
-class CommandUpdater;
-
// The ScriptBubbleIconView is the code behind the script bubble icon
// that we show in the Omnibox badged with a number to represent how many
// extensions are running content_scripts in the current page.
-class ScriptBubbleIconView : public views::ImageView,
- public TouchableLocationBarView {
+class ScriptBubbleIconView : public views::ImageView {
public:
explicit ScriptBubbleIconView(
LocationBarView::Delegate* location_bar_delegate);
virtual ~ScriptBubbleIconView();
- // TouchableLocationBarView methods.
- virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
// Updates the number shown on the script bubble icon.
void SetScriptCount(size_t script_count);
private:
- // views::View methods.
+ // views::View:
virtual void Layout() OVERRIDE;
- // views::ImageView methods.
+ // views::ImageView:
virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
- // ui::EventHandler overrides:
+ // ui::EventHandler:
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
// Shows the script bubble, anchored to anchor_view.
@@ -50,7 +43,7 @@
// The last reported script count.
size_t script_count_;
- DISALLOW_IMPLICIT_CONSTRUCTORS(ScriptBubbleIconView);
+ DISALLOW_COPY_AND_ASSIGN(ScriptBubbleIconView);
};
#endif // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_SCRIPT_BUBBLE_ICON_VIEW_H_
diff --git a/chrome/browser/ui/views/location_bar/star_view.cc b/chrome/browser/ui/views/location_bar/star_view.cc
index d07328e..1bf0b70 100644
--- a/chrome/browser/ui/views/location_bar/star_view.cc
+++ b/chrome/browser/ui/views/location_bar/star_view.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/command_updater.h"
#include "chrome/browser/ui/view_ids.h"
#include "chrome/browser/ui/views/browser_dialogs.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/accessibility/accessible_view_state.h"
@@ -24,16 +25,12 @@
set_id(VIEW_ID_STAR_BUTTON);
SetToggled(false);
set_accessibility_focusable(true);
- TouchableLocationBarView::Init(this);
+ LocationBarView::InitTouchableLocationBarChildView(this);
}
StarView::~StarView() {
}
-int StarView::GetBuiltInHorizontalPadding() const {
- return GetBuiltInHorizontalPaddingImpl();
-}
-
void StarView::SetToggled(bool on) {
SetTooltipText(l10n_util::GetStringUTF16(
on ? IDS_TOOLTIP_STARRED : IDS_TOOLTIP_STAR));
diff --git a/chrome/browser/ui/views/location_bar/star_view.h b/chrome/browser/ui/views/location_bar/star_view.h
index bac32f0..a2c7b95 100644
--- a/chrome/browser/ui/views/location_bar/star_view.h
+++ b/chrome/browser/ui/views/location_bar/star_view.h
@@ -5,19 +5,15 @@
#ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_STAR_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_STAR_VIEW_H_
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
#include "ui/views/controls/image_view.h"
class CommandUpdater;
-class StarView : public views::ImageView, public TouchableLocationBarView {
+class StarView : public views::ImageView {
public:
explicit StarView(CommandUpdater* command_updater);
virtual ~StarView();
- // TouchableLocationBarView:
- virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
// Toggles the star on or off.
void SetToggled(bool on);
@@ -30,7 +26,7 @@
virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
- // ui::EventHandler overrides:
+ // ui::EventHandler:
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
// The CommandUpdater for the Browser object that owns the location bar.
diff --git a/chrome/browser/ui/views/location_bar/touchable_location_bar_view.cc b/chrome/browser/ui/views/location_bar/touchable_location_bar_view.cc
deleted file mode 100644
index 26c222e..0000000
--- a/chrome/browser/ui/views/location_bar/touchable_location_bar_view.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
-
-#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-#include "ui/base/layout.h"
-#include "ui/views/border.h"
-
-// static
-void TouchableLocationBarView::Init(views::View* view) {
- int horizontal_padding = GetBuiltInHorizontalPaddingImpl();
- if (horizontal_padding != 0) {
- view->set_border(views::Border::CreateEmptyBorder(
- 3, horizontal_padding, 3, horizontal_padding));
- }
-}
-
-// static
-int TouchableLocationBarView::GetBuiltInHorizontalPaddingImpl() {
- return ui::GetDisplayLayout() == ui::LAYOUT_TOUCH ?
- LocationBarView::GetItemPadding() / 2 : 0;
-}
diff --git a/chrome/browser/ui/views/location_bar/touchable_location_bar_view.h b/chrome/browser/ui/views/location_bar/touchable_location_bar_view.h
deleted file mode 100644
index aaba2b9..0000000
--- a/chrome/browser/ui/views/location_bar/touchable_location_bar_view.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_TOUCHABLE_LOCATION_BAR_VIEW_H_
-#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_TOUCHABLE_LOCATION_BAR_VIEW_H_
-
-#include "ui/views/view.h"
-
-// An interface for a View in within the LocationBar that knows how to
-// increase its size (without affecting visual layout) in a touch
-// layout, to increase the size of the touch target. Its border
-// extends a few pixels up and down, which doesn't affect layout, and
-// extends half of the padding used between items in the location bar
-// to the left and right.
-//
-// To make your location bar View extend itself into the padding
-// around it to get an enlarged touch target, inherit from
-// TouchableLocationBarView interface, implement its
-// GetBuiltInHorizontalPadding method by calling
-// GetBuiltInHorizontalPaddingImpl, and call
-// TouchableLocationBarView::Init() from your constructor.
-class TouchableLocationBarView {
- public:
- // Returns the number of pixels of built-in padding to the left and
- // right of the image for this view.
- virtual int GetBuiltInHorizontalPadding() const = 0;
-
- protected:
- // Call this from the constructor (or during early initialization)
- // of a class that inherits from TouchableLocationBarView.
- static void Init(views::View* view);
-
- // Use this to implement GetBuiltInHorizontalPadding().
- static int GetBuiltInHorizontalPaddingImpl();
-};
-
-#endif // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_TOUCHABLE_LOCATION_BAR_VIEW_H_
diff --git a/chrome/browser/ui/views/location_bar/zoom_view.cc b/chrome/browser/ui/views/location_bar/zoom_view.cc
index 2a1c39d..34b432a 100644
--- a/chrome/browser/ui/views/location_bar/zoom_view.cc
+++ b/chrome/browser/ui/views/location_bar/zoom_view.cc
@@ -22,7 +22,7 @@
location_bar_delegate_(location_bar_delegate) {
set_accessibility_focusable(true);
Update(NULL);
- TouchableLocationBarView::Init(this);
+ LocationBarView::InitTouchableLocationBarChildView(this);
}
ZoomView::~ZoomView() {
@@ -80,10 +80,6 @@
}
}
-int ZoomView::GetBuiltInHorizontalPadding() const {
- return GetBuiltInHorizontalPaddingImpl();
-}
-
void ZoomView::ActivateBubble() {
ZoomBubbleView::ShowBubble(location_bar_delegate_->GetWebContents(), false);
}
diff --git a/chrome/browser/ui/views/location_bar/zoom_view.h b/chrome/browser/ui/views/location_bar/zoom_view.h
index 4610f81..bc3876d 100644
--- a/chrome/browser/ui/views/location_bar/zoom_view.h
+++ b/chrome/browser/ui/views/location_bar/zoom_view.h
@@ -8,15 +8,13 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-#include "chrome/browser/ui/views/location_bar/touchable_location_bar_view.h"
#include "ui/views/controls/image_view.h"
class ToolbarModel;
class ZoomController;
// View for the zoom icon in the Omnibox.
-class ZoomView : public views::ImageView,
- public TouchableLocationBarView {
+class ZoomView : public views::ImageView {
public:
// Clicking on the ZoomView shows a ZoomBubbleView, which requires the current
// WebContents. Because the current WebContents changes as the user switches
@@ -43,9 +41,6 @@
// ui::EventHandler:
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
- // TouchableLocationBarView.
- virtual int GetBuiltInHorizontalPadding() const OVERRIDE;
-
// Helper method to show and focus the zoom bubble associated with this
// widget.
void ActivateBubble();
diff --git a/chrome/browser/ui/views/message_center/web_notification_tray.cc b/chrome/browser/ui/views/message_center/web_notification_tray.cc
index b3faf1a..5fcf10a 100644
--- a/chrome/browser/ui/views/message_center/web_notification_tray.cc
+++ b/chrome/browser/ui/views/message_center/web_notification_tray.cc
@@ -132,7 +132,6 @@
should_update_tray_content_(true) {
message_center_tray_.reset(
new MessageCenterTray(this, g_browser_process->message_center()));
- OnMessageCenterTrayChanged();
}
WebNotificationTray::~WebNotificationTray() {
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 c5dfb4b..2d9094d 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -6,7 +6,6 @@
#include "chrome/browser/search/search.h"
#include "chrome/browser/themes/theme_properties.h"
-#include "chrome/browser/ui/omnibox/omnibox_popup_non_view.h"
#include "chrome/browser/ui/omnibox/omnibox_view.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "chrome/browser/ui/views/omnibox/omnibox_result_view.h"
@@ -57,11 +56,6 @@
OmniboxView* omnibox_view,
OmniboxEditModel* edit_model,
LocationBarView* location_bar_view) {
-#if defined(HTML_INSTANT_EXTENDED_POPUP)
- if (chrome::IsInstantExtendedAPIEnabled())
- return new OmniboxPopupNonView(edit_model);
-#endif
-
OmniboxPopupContentsView* view = NULL;
if (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH) {
view = new TouchOmniboxPopupContentsView(
@@ -165,7 +159,8 @@
}
void OmniboxPopupContentsView::UpdatePopupAppearance() {
- if (model_->result().empty() ||
+ const size_t hidden_matches = model_->result().ShouldHideTopMatch() ? 1 : 0;
+ if (model_->result().size() <= hidden_matches ||
omnibox_view_->IsImeShowingPopup()) {
// No matches or the IME is showing a popup window which may overlap
// the omnibox popup window. Close any existing popup.
@@ -188,7 +183,7 @@
for (size_t i = 0; i < result_size; ++i) {
OmniboxResultView* view = result_view_at(i);
view->SetMatch(GetMatchAtIndex(i));
- view->SetVisible(true);
+ view->SetVisible(i >= hidden_matches);
}
for (size_t i = result_size; i < AutocompleteResult::kMaxMatches; ++i)
child_at(i)->SetVisible(false);
@@ -393,7 +388,8 @@
int OmniboxPopupContentsView::CalculatePopupHeight() {
DCHECK_GE(static_cast<size_t>(child_count()), model_->result().size());
int popup_height = 0;
- for (size_t i = 0; i < model_->result().size(); ++i)
+ for (size_t i = model_->result().ShouldHideTopMatch() ? 1 : 0;
+ i < model_->result().size(); ++i)
popup_height += child_at(i)->GetPreferredSize().height();
// Add enough space on the top and bottom so it looks like there is the same
@@ -488,7 +484,7 @@
views::View* child = child_at(i);
gfx::Point point_in_child_coords(point);
View::ConvertPointToTarget(this, child, &point_in_child_coords);
- if (child->HitTestPoint(point_in_child_coords))
+ if (child->visible() && child->HitTestPoint(point_in_child_coords))
return i;
}
return OmniboxPopupModel::kNoMatch;
diff --git a/chrome/browser/ui/views/profile_chooser_view.cc b/chrome/browser/ui/views/profile_chooser_view.cc
index afcd69f..af7ee91 100644
--- a/chrome/browser/ui/views/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profile_chooser_view.cc
@@ -119,7 +119,7 @@
if (sender == guest_button_view_) {
avatar_menu_model_->SwitchToGuestProfileWindow(browser_);
} else if (sender == users_button_view_) {
- chrome::ShowSingletonTab(browser_, GURL(chrome::kChromeUIUserChooserURL));
+ chrome::ShowSingletonTab(browser_, GURL(chrome::kChromeUIUserManagerURL));
} else {
DCHECK_EQ(sender, signout_current_profile_view_);
avatar_menu_model_->BeginSignOut();
diff --git a/chrome/browser/ui/views/select_file_dialog_extension.cc b/chrome/browser/ui/views/select_file_dialog_extension.cc
index 538dbed..e3324aa 100644
--- a/chrome/browser/ui/views/select_file_dialog_extension.cc
+++ b/chrome/browser/ui/views/select_file_dialog_extension.cc
@@ -6,6 +6,7 @@
#include "apps/native_app_window.h"
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
@@ -17,7 +18,6 @@
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/browser.h"
@@ -270,7 +270,7 @@
if (!owner_browser) {
// If an owner_window was supplied but we couldn't find a browser, this
// could be for a shell window.
- shell_window = extensions::ShellWindowRegistry::
+ shell_window = apps::ShellWindowRegistry::
GetShellWindowForNativeWindowAnyProfile(owner_window);
}
}
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index f556be5..fde9889 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -238,6 +238,10 @@
const SkColor kImmersiveActiveTabColor = SkColorSetRGB(235, 235, 235);
const SkColor kImmersiveInactiveTabColor = SkColorSetRGB(190, 190, 190);
+// The minimum opacity (out of 1) when a tab (either active or inactive) is
+// throbbing in the immersive mode light strip.
+const double kImmersiveTabMinThrobOpacity = 0.66;
+
// Number of steps in the immersive mode loading animation.
const int kImmersiveLoadingStepCount = 32;
@@ -1115,9 +1119,13 @@
void Tab::PaintImmersiveTab(gfx::Canvas* canvas) {
// Use transparency for the draw-attention animation.
- int alpha = (tab_animation_ && tab_animation_->is_animating())
- ? static_cast<int>(GetThrobValue() * 255)
- : 255;
+ int alpha = 255;
+ if (tab_animation_ &&
+ tab_animation_->is_animating() &&
+ !data().mini) {
+ alpha = tab_animation_->CurrentValueBetween(
+ 255, static_cast<int>(255 * kImmersiveTabMinThrobOpacity));
+ }
// Draw a gray rectangle to represent the tab. This works for mini-tabs as
// well as regular ones. The active tab has a brigher bar.
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index abcf5f5..560c344 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -46,7 +46,7 @@
#include "chrome/browser/ui/webui/profiler_ui.h"
#include "chrome/browser/ui/webui/quota_internals/quota_internals_ui.h"
#include "chrome/browser/ui/webui/signin/profile_signin_confirmation_ui.h"
-#include "chrome/browser/ui/webui/signin/user_chooser_ui.h"
+#include "chrome/browser/ui/webui/signin/user_manager_ui.h"
#include "chrome/browser/ui/webui/signin_internals_ui.h"
#include "chrome/browser/ui/webui/sync_internals_ui.h"
#include "chrome/browser/ui/webui/translate_internals/translate_internals_ui.h"
@@ -104,6 +104,7 @@
#include "chrome/browser/ui/webui/chromeos/proxy_settings_ui.h"
#include "chrome/browser/ui/webui/chromeos/salsa_ui.h"
#include "chrome/browser/ui/webui/chromeos/sim_unlock_ui.h"
+#include "chrome/browser/ui/webui/chromeos/slow_ui.h"
#include "chrome/browser/ui/webui/chromeos/system_info_ui.h"
#endif
@@ -361,6 +362,8 @@
return &NewWebUI<SalsaUI>;
if (url.host() == chrome::kChromeUISimUnlockHost)
return &NewWebUI<chromeos::SimUnlockUI>;
+ if (url.host() == chrome::kChromeUISlowHost)
+ return &NewWebUI<chromeos::SlowUI>;
if (url.host() == chrome::kChromeUISystemInfoHost)
return &NewWebUI<chromeos::SystemInfoUI>;
#endif // defined(OS_CHROMEOS)
@@ -393,10 +396,10 @@
#endif
#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_IOS)
- if (url.host() == chrome::kChromeUIUserChooserHost &&
+ if (url.host() == chrome::kChromeUIUserManagerHost &&
CommandLine::ForCurrentProcess()->HasSwitch(
switches::kNewProfileManagement))
- return &NewWebUI<UserChooserUI>;
+ return &NewWebUI<UserManagerUI>;
#endif
if (url.host() == chrome::kChromeUIChromeURLsHost ||
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 d07dd47..ef91bc0 100644
--- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
@@ -120,6 +120,8 @@
&CoreOobeHandler::HandleEnableSpokenFeedback);
AddCallback("setDeviceRequisition",
&CoreOobeHandler::HandleSetDeviceRequisition);
+ AddCallback("skipToLoginForTesting",
+ &CoreOobeHandler::HandleSkipToLoginForTesting);
}
void CoreOobeHandler::ShowSignInError(
@@ -222,6 +224,11 @@
SetDeviceRequisition(requisition);
}
+void CoreOobeHandler::HandleSkipToLoginForTesting() {
+ if (WizardController::default_controller())
+ WizardController::default_controller()->SkipToLoginForTesting();
+}
+
void CoreOobeHandler::ShowOobeUI(bool show) {
if (show == show_oobe_ui_)
return;
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 7ecd9e6..7b67f47 100644
--- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
@@ -85,6 +85,7 @@
void HandleSkipUpdateEnrollAfterEula();
void HandleUpdateCurrentScreen(const std::string& screen);
void HandleSetDeviceRequisition(const std::string& requisition);
+ void HandleSkipToLoginForTesting();
// Updates a11y menu state based on the current a11y features state(on/off).
void UpdateA11yState();
diff --git a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
index bc47831..40d0b1d 100644
--- a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
@@ -59,6 +59,7 @@
ShowScreen(OobeUI::kScreenErrorMessage, params);
NetworkErrorShown();
EnableLazyDetection();
+ LOG(WARNING) << "Offline message is displayed";
}
void ErrorScreenHandler::Hide() {
@@ -68,6 +69,7 @@
if (GetScreenName(parent_screen_, &screen_name))
ShowScreen(screen_name.c_str(), NULL);
DisableLazyDetection();
+ LOG(WARNING) << "Offline message is hidden";
}
void ErrorScreenHandler::FixCaptivePortal() {
diff --git a/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.cc
index 164a96c..bfaa5e4 100644
--- a/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.cc
@@ -51,6 +51,10 @@
"managedUserCreationFlowGotitButtonTitle",
IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_GOT_IT_BUTTON_TITLE);
+ builder->Add("createManagedUserIntroTextTitle",
+ IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_TITLE);
+ builder->Add("createManagedUserIntroAlternateText",
+ IDS_CREATE_LOCALLY_MANAGED_INTRO_ALTERNATE_TEXT);
builder->Add("createManagedUserIntroText1",
IDS_CREATE_LOCALLY_MANAGED_INTRO_TEXT_1);
builder->Add("createManagedUserIntroManagerItem1",
diff --git a/chrome/browser/ui/webui/chromeos/login/network_state_informer.cc b/chrome/browser/ui/webui/chromeos/login/network_state_informer.cc
index f090f56..8ec6ccb 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_state_informer.cc
+++ b/chrome/browser/ui/webui/chromeos/login/network_state_informer.cc
@@ -17,13 +17,6 @@
#include "net/proxy/proxy_config.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
-namespace {
-
-// Timeout to smooth temporary network state transitions for flaky networks.
-const int kNetworkStateCheckDelaySec = 3;
-
-} // namespace
-
namespace chromeos {
NetworkStateInformer::NetworkStateInformer()
@@ -71,50 +64,17 @@
}
void NetworkStateInformer::NetworkManagerChanged() {
- const NetworkState* default_network =
- NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
- State new_state = OFFLINE;
- std::string new_network_service_path;
- if (default_network) {
- new_state = GetNetworkState(default_network);
- new_network_service_path = default_network->path();
- }
- if ((state_ != ONLINE && (new_state == ONLINE || new_state == CONNECTING)) ||
- (state_ == ONLINE && (new_state == ONLINE || new_state == CONNECTING) &&
- new_network_service_path != last_online_service_path_) ||
- (new_state == CAPTIVE_PORTAL &&
- new_network_service_path == last_network_service_path_)) {
- last_network_service_path_ = new_network_service_path;
- if (new_state == ONLINE)
- last_online_service_path_ = new_network_service_path;
- // Transitions {OFFLINE, PORTAL} -> ONLINE and connections to
- // different network are processed without delay.
- // Transitions {OFFLINE, ONLINE} -> PORTAL in the same network are
- // also processed without delay.
- UpdateStateAndNotify();
- } else {
- check_state_.Cancel();
- check_state_.Reset(
- base::Bind(&NetworkStateInformer::UpdateStateAndNotify,
- weak_ptr_factory_.GetWeakPtr()));
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- check_state_.callback(),
- base::TimeDelta::FromSeconds(kNetworkStateCheckDelaySec));
- }
+ UpdateStateAndNotify();
}
void NetworkStateInformer::DefaultNetworkChanged(const NetworkState* network) {
- NetworkManagerChanged();
+ UpdateStateAndNotify();
}
void NetworkStateInformer::OnPortalDetectionCompleted(
const NetworkState* network,
const NetworkPortalDetector::CaptivePortalState& state) {
- if (NetworkHandler::IsInitialized() &&
- NetworkHandler::Get()->network_state_handler()->DefaultNetwork() ==
- network)
- NetworkManagerChanged();
+ UpdateStateAndNotify();
}
void NetworkStateInformer::Observe(
@@ -130,26 +90,27 @@
}
void NetworkStateInformer::OnPortalDetected() {
- SendStateToObservers(ErrorScreenActor::ERROR_REASON_PORTAL_DETECTED);
+ UpdateStateAndNotify();
}
bool NetworkStateInformer::UpdateState() {
- State new_state = OFFLINE;
-
const NetworkState* default_network =
NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
+ State new_state = OFFLINE;
+ std::string new_network_path;
+ std::string new_network_type;
if (default_network) {
new_state = GetNetworkState(default_network);
- last_network_service_path_ = default_network->path();
- last_network_type_ = default_network->type();
+ new_network_path = default_network->path();
+ new_network_type = default_network->type();
}
bool updated = (new_state != state_) ||
- (new_state != OFFLINE &&
- last_network_service_path_ != last_connected_service_path_);
+ (new_network_path != network_path_) ||
+ (new_network_type != network_type_);
state_ = new_state;
- if (state_ != OFFLINE)
- last_connected_service_path_ = last_network_service_path_;
+ network_path_ = new_network_path;
+ network_type_ = new_network_type;
if (updated && state_ == ONLINE) {
FOR_EACH_OBSERVER(NetworkStateInformerObserver, observers_,
@@ -160,9 +121,6 @@
}
void NetworkStateInformer::UpdateStateAndNotify() {
- // Cancel pending update request if any.
- check_state_.Cancel();
-
if (UpdateState())
SendStateToObservers(ErrorScreenActor::ERROR_REASON_NETWORK_STATE_CHANGED);
else
@@ -172,7 +130,7 @@
void NetworkStateInformer::SendStateToObservers(
ErrorScreenActor::ErrorReason reason) {
FOR_EACH_OBSERVER(NetworkStateInformerObserver, observers_,
- UpdateState(state_, reason));
+ UpdateState(reason));
}
NetworkStateInformer::State NetworkStateInformer::GetNetworkState(
diff --git a/chrome/browser/ui/webui/chromeos/login/network_state_informer.h b/chrome/browser/ui/webui/chromeos/login/network_state_informer.h
index 85710d8..69b2766 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_state_informer.h
+++ b/chrome/browser/ui/webui/chromeos/login/network_state_informer.h
@@ -49,8 +49,7 @@
NetworkStateInformerObserver() {}
virtual ~NetworkStateInformerObserver() {}
- virtual void UpdateState(State state,
- ErrorScreenActor::ErrorReason reason) = 0;
+ virtual void UpdateState(ErrorScreenActor::ErrorReason reason) = 0;
virtual void OnNetworkReady() {}
};
@@ -81,18 +80,9 @@
// CaptivePortalWindowProxyDelegate implementation:
virtual void OnPortalDetected() OVERRIDE;
- // Returns active network's service path. It can be used to uniquely
- // identify the network.
- std::string active_network_service_path() {
- return last_online_service_path_;
- }
-
- bool is_online() { return state_ == ONLINE; }
State state() const { return state_; }
- std::string last_network_service_path() const {
- return last_network_service_path_;
- }
- std::string last_network_type() const { return last_network_type_; }
+ std::string network_path() const { return network_path_; }
+ std::string network_type() const { return network_type_; }
private:
friend class base::RefCounted<NetworkStateInformer>;
@@ -108,14 +98,12 @@
State GetNetworkState(const NetworkState* network);
bool IsProxyConfigured(const NetworkState* network);
- content::NotificationRegistrar registrar_;
State state_;
+ std::string network_path_;
+ std::string network_type_;
+
ObserverList<NetworkStateInformerObserver> observers_;
- std::string last_online_service_path_;
- std::string last_connected_service_path_;
- std::string last_network_service_path_;
- std::string last_network_type_;
- base::CancelableClosure check_state_;
+ content::NotificationRegistrar registrar_;
base::WeakPtrFactory<NetworkStateInformer> weak_ptr_factory_;
};
diff --git a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
index 535842b..fb40ab3 100644
--- a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
@@ -70,7 +70,8 @@
IDS_RESET_SCREEN_WARNING_MSG,
IDS_SHORT_PRODUCT_NAME);
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kFirstBoot)) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kFirstExecAfterBoot)) {
builder->AddF("resetWarningDetails",
IDS_RESET_SCREEN_WARNING_DETAILS,
IDS_SHORT_PRODUCT_NAME);
@@ -104,7 +105,8 @@
}
void ResetScreenHandler::HandleOnReset() {
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kFirstBoot)) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kFirstExecAfterBoot)) {
chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->
StartDeviceWipe();
} else {
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 c3c4831..922a60d 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -238,15 +238,6 @@
return network->name();
}
-// Returns network unique id by service path.
-std::string GetNetworkUniqueId(const std::string& service_path) {
- const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
- GetNetworkState(service_path);
- if (!network)
- return std::string();
- return network->guid();
-}
-
// Returns captive portal state for a network by its service path.
NetworkPortalDetector::CaptivePortalState GetCaptivePortalState(
const std::string& service_path) {
@@ -560,9 +551,8 @@
MaybePreloadAuthExtension();
}
-void SigninScreenHandler::UpdateState(NetworkStateInformer::State state,
- ErrorScreenActor::ErrorReason reason) {
- UpdateStateInternal(state, reason, false);
+void SigninScreenHandler::UpdateState(ErrorScreenActor::ErrorReason reason) {
+ UpdateStateInternal(reason, false);
}
// SigninScreenHandler, private: -----------------------------------------------
@@ -586,7 +576,6 @@
// TODO (ygorshenin@): split this method into small parts.
void SigninScreenHandler::UpdateStateInternal(
- NetworkStateInformer::State state,
ErrorScreenActor::ErrorReason reason,
bool force_update) {
// Do nothing once user has signed in or sign in is in progress.
@@ -598,16 +587,15 @@
return;
}
- const std::string service_path =
- network_state_informer_->last_network_service_path();
- const std::string network_id =
- GetNetworkUniqueId(service_path);
+ NetworkStateInformer::State state = network_state_informer_->state();
+ const std::string network_path = network_state_informer_->network_path();
+ const std::string network_name = GetNetworkName(network_path);
// Skip "update" notification about OFFLINE state from
// NetworkStateInformer if previous notification already was
// delayed.
- if (state == NetworkStateInformer::OFFLINE &&
- reason == ErrorScreenActor::ERROR_REASON_UPDATE &&
+ if ((state == NetworkStateInformer::OFFLINE || has_pending_auth_ui_) &&
+ !force_update &&
!update_state_closure_.IsCancelled()) {
return;
}
@@ -616,31 +604,23 @@
// will be tested well.
LOG(WARNING) << "SigninScreenHandler::UpdateStateInternal(): "
<< "state=" << NetworkStateStatusString(state) << ", "
- << "network_id=" << network_id << ", "
+ << "network_name=" << network_name << ", "
<< "reason=" << ErrorReasonString(reason) << ", "
<< "force_update=" << force_update;
update_state_closure_.Cancel();
- // Delay UpdateStateInternal() call in the following cases:
- // 1. this is the first call and it's about offline state of the
- // current network. This can happen because device is just powered
- // up and network stack isn't ready now.
- // 2. proxy auth ui is displayed. UpdateStateCall() is delayed to
- // prevent screen change behind proxy auth ui.
- if ((state == NetworkStateInformer::OFFLINE && is_first_update_state_call_) ||
+ if ((state == NetworkStateInformer::OFFLINE && !force_update) ||
has_pending_auth_ui_) {
- is_first_update_state_call_ = false;
update_state_closure_.Reset(
base::Bind(
&SigninScreenHandler::UpdateStateInternal,
- weak_factory_.GetWeakPtr(), state, reason, force_update));
+ weak_factory_.GetWeakPtr(), reason, true));
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
update_state_closure_.callback(),
base::TimeDelta::FromSeconds(kOfflineTimeoutSec));
return;
}
- is_first_update_state_call_ = false;
// Don't show or hide error screen if we're in connecting state.
if (state == NetworkStateInformer::CONNECTING && !force_update) {
@@ -648,7 +628,7 @@
// First notification about CONNECTING state.
connecting_closure_.Reset(
base::Bind(&SigninScreenHandler::UpdateStateInternal,
- weak_factory_.GetWeakPtr(), state, reason, true));
+ weak_factory_.GetWeakPtr(), reason, true));
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
connecting_closure_.callback(),
@@ -715,19 +695,15 @@
void SigninScreenHandler::SetupAndShowOfflineMessage(
NetworkStateInformer:: State state,
ErrorScreenActor::ErrorReason reason) {
- const std::string service_path =
- network_state_informer_->last_network_service_path();
- const std::string network_id = GetNetworkUniqueId(service_path);
+ const std::string network_path = network_state_informer_->network_path();
const bool is_under_captive_portal = IsUnderCaptivePortal(state, reason);
const bool is_proxy_error = IsProxyError(state, reason, frame_error_);
const bool is_gaia_loading_timeout =
(reason == ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
- LOG(WARNING) << "Offline message is displayed";
-
// Record portal detection stats only if we're going to show or
// change state of the error screen.
- RecordNetworkPortalDetectorStats(service_path);
+ RecordNetworkPortalDetectorStats(network_path);
if (is_proxy_error) {
error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PROXY,
@@ -742,7 +718,7 @@
ErrorScreen::ERROR_STATE_PORTAL)) {
error_screen_actor_->FixCaptivePortal();
}
- const std::string network_name = GetNetworkName(service_path);
+ const std::string network_name = GetNetworkName(network_path);
error_screen_actor_->SetErrorState(ErrorScreen::ERROR_STATE_PORTAL,
network_name);
} else if (is_gaia_loading_timeout) {
@@ -765,9 +741,8 @@
if (GetCurrentScreen() != OobeUI::SCREEN_ERROR_MESSAGE) {
DictionaryValue params;
- const std::string connection_type =
- network_state_informer_->last_network_type();
- params.SetString("lastNetworkType", connection_type);
+ const std::string network_type = network_state_informer_->network_type();
+ params.SetString("lastNetworkType", network_type);
error_screen_actor_->SetUIState(ErrorScreen::UI_STATE_SIGNIN);
error_screen_actor_->Show(OobeUI::SCREEN_GAIA_SIGNIN, ¶ms);
}
@@ -779,7 +754,6 @@
if (!IsSigninScreenHiddenByError())
return;
- LOG(WARNING) << "Offline message is hidden";
error_screen_actor_->Hide();
// Forces a reload for Gaia screen on hiding error message.
@@ -855,9 +829,7 @@
&SigninScreenHandler::HandleAccountPickerReady);
AddCallback("wallpaperReady", &SigninScreenHandler::HandleWallpaperReady);
AddCallback("loginWebuiReady", &SigninScreenHandler::HandleLoginWebuiReady);
- AddCallback("demoWebuiReady", &SigninScreenHandler::HandleDemoWebuiReady);
AddCallback("signOutUser", &SigninScreenHandler::HandleSignOutUser);
- AddCallback("userImagesLoaded", &SigninScreenHandler::HandleUserImagesLoaded);
AddCallback("networkErrorShown",
&SigninScreenHandler::HandleNetworkErrorShown);
AddCallback("openProxySettings",
@@ -1074,11 +1046,10 @@
if (!dns_cleared_ || !cookies_cleared_ || !delegate_)
return;
- std::string active_network =
- network_state_informer_->active_network_service_path();
+ std::string active_network_path = network_state_informer_->network_path();
if (gaia_silent_load_ &&
- (!network_state_informer_->is_online() ||
- gaia_silent_load_network_ != active_network)) {
+ (network_state_informer_->state() != NetworkStateInformer::ONLINE ||
+ gaia_silent_load_network_ != active_network_path)) {
// Network has changed. Force Gaia reload.
gaia_silent_load_ = false;
// Gaia page will be realoded, so focus isn't stolen anymore.
@@ -1106,8 +1077,7 @@
HandleLoginWebuiReady();
}
- UpdateState(network_state_informer_->state(),
- ErrorScreenActor::ERROR_REASON_UPDATE);
+ UpdateState(ErrorScreenActor::ERROR_REASON_UPDATE);
}
@@ -1514,25 +1484,11 @@
SubmitLoginFormForTest();
}
-void SigninScreenHandler::HandleDemoWebuiReady() {
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_DEMO_WEBUI_LOADED,
- content::NotificationService::AllSources(),
- content::NotificationService::NoDetails());
-}
-
void SigninScreenHandler::HandleSignOutUser() {
if (delegate_)
delegate_->Signout();
}
-void SigninScreenHandler::HandleUserImagesLoaded() {
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_LOGIN_USER_IMAGES_LOADED,
- content::NotificationService::AllSources(),
- content::NotificationService::NoDetails());
-}
-
void SigninScreenHandler::HandleNetworkErrorShown() {
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN,
@@ -1634,18 +1590,14 @@
if (network_state_informer_->state() != NetworkStateInformer::ONLINE)
return;
- if (frame_state_ == FRAME_STATE_LOADED) {
- UpdateState(network_state_informer_->state(),
- ErrorScreenActor::ERROR_REASON_UPDATE);
- } else if (frame_state_ == FRAME_STATE_ERROR) {
- UpdateState(network_state_informer_->state(),
- ErrorScreenActor::ERROR_REASON_FRAME_ERROR);
- }
+ if (frame_state_ == FRAME_STATE_LOADED)
+ UpdateState(ErrorScreenActor::ERROR_REASON_UPDATE);
+ else if (frame_state_ == FRAME_STATE_ERROR)
+ UpdateState(ErrorScreenActor::ERROR_REASON_FRAME_ERROR);
}
void SigninScreenHandler::HandleShowLoadingTimeoutError() {
- UpdateState(network_state_informer_->state(),
- ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
+ UpdateState(ErrorScreenActor::ERROR_REASON_LOADING_TIMEOUT);
}
void SigninScreenHandler::HandleUpdateOfflineLogin(bool offline_login_active) {
@@ -1688,10 +1640,9 @@
!ScreenLocker::default_screen_locker() &&
!cookies_cleared_ &&
!dns_clear_task_running_ &&
- network_state_informer_->is_online()) {
+ network_state_informer_->state() == NetworkStateInformer::ONLINE) {
gaia_silent_load_ = true;
- gaia_silent_load_network_ =
- network_state_informer_->active_network_service_path();
+ gaia_silent_load_network_ = network_state_informer_->network_path();
LoadAuthExtension(true, true, false);
}
}
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
index f5fbd6b..1d51afc 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -191,9 +191,7 @@
// NetworkStateInformer::NetworkStateInformerObserver implementation:
virtual void OnNetworkReady() OVERRIDE;
-
- virtual void UpdateState(NetworkStateInformer::State state,
- ErrorScreenActor::ErrorReason reason) OVERRIDE;
+ virtual void UpdateState(ErrorScreenActor::ErrorReason reason) OVERRIDE;
// Required Local State preferences.
static void RegisterPrefs(PrefRegistrySimple* registry);
@@ -222,8 +220,7 @@
// |params| argument.
void UpdateUIState(UIState ui_state, DictionaryValue* params);
- void UpdateStateInternal(NetworkStateInformer::State state,
- ErrorScreenActor::ErrorReason reason,
+ void UpdateStateInternal(ErrorScreenActor::ErrorReason reason,
bool force_update);
void SetupAndShowOfflineMessage(NetworkStateInformer::State state,
ErrorScreenActor::ErrorReason reason);
@@ -314,9 +311,7 @@
void HandleAccountPickerReady();
void HandleWallpaperReady();
void HandleLoginWebuiReady();
- void HandleDemoWebuiReady();
void HandleSignOutUser();
- void HandleUserImagesLoaded();
void HandleNetworkErrorShown();
void HandleOpenProxySettings();
void HandleLoginVisible(const std::string& source);
diff --git a/chrome/browser/ui/webui/chromeos/sim_unlock_ui.cc b/chrome/browser/ui/webui/chromeos/sim_unlock_ui.cc
index 5da85d1..9fd266c 100644
--- a/chrome/browser/ui/webui/chromeos/sim_unlock_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/sim_unlock_ui.cc
@@ -151,7 +151,8 @@
class TaskProxy : public base::RefCountedThreadSafe<TaskProxy> {
public:
explicit TaskProxy(const base::WeakPtr<SimUnlockHandler>& handler)
- : handler_(handler) {
+ : handler_(handler),
+ code_type_() {
}
TaskProxy(const base::WeakPtr<SimUnlockHandler>& handler,
diff --git a/chrome/browser/ui/webui/chromeos/slow_ui.cc b/chrome/browser/ui/webui/chromeos/slow_ui.cc
new file mode 100644
index 0000000..ddf64c4
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/slow_ui.cc
@@ -0,0 +1,139 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/chromeos/slow_ui.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/prefs/pref_change_registrar.h"
+#include "base/prefs/pref_service.h"
+#include "base/values.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "content/public/browser/web_contents.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"
+#include "grit/browser_resources.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/webui/jstemplate_builder.h"
+#include "ui/webui/web_ui_util.h"
+
+using content::WebUIMessageHandler;
+
+namespace {
+
+// JS API callbacks names.
+const char kJsApiDisableTracing[] = "disableTracing";
+const char kJsApiEnableTracing[] = "enableTracing";
+const char kJsApiLoadComplete[] = "loadComplete";
+
+// Page JS API function names.
+const char kJsApiTracingPrefChanged[] = "options.Slow.tracingPrefChanged";
+
+} // namespace
+
+namespace chromeos {
+
+content::WebUIDataSource* CreateSlowUIHTMLSource() {
+ content::WebUIDataSource* source =
+ content::WebUIDataSource::Create(chrome::kChromeUISlowHost);
+
+ source->SetUseJsonJSFormatV2();
+ source->AddLocalizedString("slowDisable", IDS_SLOW_DISABLE);
+ source->AddLocalizedString("slowEnable", IDS_SLOW_ENABLE);
+ source->AddLocalizedString("slowDescription", IDS_SLOW_DESCRIPTION);
+ source->AddLocalizedString("slowWarning", IDS_SLOW_WARNING);
+
+ source->SetJsonPath("strings.js");
+ source->AddResourcePath("slow.js", IDR_SLOW_JS);
+ source->SetDefaultResource(IDR_SLOW_HTML);
+ return source;
+}
+
+// The handler for Javascript messages related to the "slow" view.
+class SlowHandler : public WebUIMessageHandler {
+ public:
+ explicit SlowHandler(Profile* profile);
+ virtual ~SlowHandler();
+
+ // WebUIMessageHandler implementation.
+ virtual void RegisterMessages() OVERRIDE;
+
+ private:
+ void UpdatePage();
+
+ // Handlers for JS WebUI messages.
+ void HandleDisable(const ListValue* args);
+ void HandleEnable(const ListValue* args);
+ void LoadComplete(const ListValue* args);
+
+ Profile* profile_;
+ scoped_ptr<PrefChangeRegistrar> user_pref_registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(SlowHandler);
+};
+
+// SlowHandler ------------------------------------------------------------
+
+SlowHandler::SlowHandler(Profile* profile) : profile_(profile) {
+}
+
+SlowHandler::~SlowHandler() {
+}
+
+void SlowHandler::RegisterMessages() {
+ web_ui()->RegisterMessageCallback(kJsApiDisableTracing,
+ base::Bind(&SlowHandler::HandleDisable, base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(kJsApiEnableTracing,
+ base::Bind(&SlowHandler::HandleEnable, base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(kJsApiLoadComplete,
+ base::Bind(&SlowHandler::LoadComplete, base::Unretained(this)));
+
+ user_pref_registrar_.reset(new PrefChangeRegistrar);
+ user_pref_registrar_->Init(profile_->GetPrefs());
+ user_pref_registrar_->Add(prefs::kPerformanceTracingEnabled,
+ base::Bind(&SlowHandler::UpdatePage,
+ base::Unretained(this)));
+}
+
+void SlowHandler::HandleDisable(const ListValue* args) {
+ PrefService* pref_service = profile_->GetPrefs();
+ pref_service->SetBoolean(prefs::kPerformanceTracingEnabled, false);
+}
+
+void SlowHandler::HandleEnable(const ListValue* args) {
+ PrefService* pref_service = profile_->GetPrefs();
+ pref_service->SetBoolean(prefs::kPerformanceTracingEnabled, true);
+}
+
+void SlowHandler::LoadComplete(const ListValue* args) {
+ UpdatePage();
+}
+
+void SlowHandler::UpdatePage() {
+ PrefService* pref_service = profile_->GetPrefs();
+ bool enabled = pref_service->GetBoolean(prefs::kPerformanceTracingEnabled);
+ base::FundamentalValue pref_value(enabled);
+ web_ui()->CallJavascriptFunction(kJsApiTracingPrefChanged, pref_value);
+}
+
+// SlowUI -----------------------------------------------------------------
+
+SlowUI::SlowUI(content::WebUI* web_ui) : WebUIController(web_ui) {
+ Profile* profile = Profile::FromWebUI(web_ui);
+
+ SlowHandler* handler = new SlowHandler(profile);
+ web_ui->AddMessageHandler(handler);
+
+ // Set up the chrome://slow/ source.
+ content::WebUIDataSource::Add(profile, CreateSlowUIHTMLSource());
+}
+
+} // namespace chromeos
+
diff --git a/chrome/browser/ui/webui/chromeos/slow_ui.h b/chrome/browser/ui/webui/chromeos/slow_ui.h
new file mode 100644
index 0000000..1a3e1b6
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/slow_ui.h
@@ -0,0 +1,25 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_SLOW_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_SLOW_UI_H_
+
+#include "content/public/browser/web_ui_controller.h"
+
+namespace chromeos {
+
+// A custom WebUI that allows users to enable and disable performance tracing
+// for feedback reports.
+class SlowUI : public content::WebUIController {
+ public:
+ explicit SlowUI(content::WebUI* web_ui);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SlowUI);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_SLOW_UI_H_
+
diff --git a/chrome/browser/ui/webui/chromeos/system_info_ui.cc b/chrome/browser/ui/webui/chromeos/system_info_ui.cc
index d711523..3040b9d 100644
--- a/chrome/browser/ui/webui/chromeos/system_info_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/system_info_ui.cc
@@ -18,7 +18,7 @@
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "base/values.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/about_system_logs_fetcher.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/url_constants.h"
@@ -110,7 +110,7 @@
path_ = path;
callback_ = callback;
- SystemLogsFetcher* fetcher = new SystemLogsFetcher();
+ AboutSystemLogsFetcher* fetcher = new AboutSystemLogsFetcher();
fetcher->Fetch(base::Bind(&SystemInfoUIHTMLSource::SysInfoComplete,
weak_ptr_factory_.GetWeakPtr()));
}
diff --git a/chrome/browser/ui/webui/downloads_dom_handler.cc b/chrome/browser/ui/webui/downloads_dom_handler.cc
index d9938b2..6415b54 100644
--- a/chrome/browser/ui/webui/downloads_dom_handler.cc
+++ b/chrome/browser/ui/webui/downloads_dom_handler.cc
@@ -13,6 +13,7 @@
#include "base/i18n/rtl.h"
#include "base/i18n/time_formatting.h"
#include "base/memory/singleton.h"
+#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_piece.h"
@@ -50,10 +51,6 @@
#include "ui/base/l10n/time_format.h"
#include "ui/gfx/image/image.h"
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
-#endif
-
using content::BrowserContext;
using content::BrowserThread;
using content::UserMetricsAction;
@@ -184,9 +181,23 @@
content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST ||
download_item->GetDangerType() ==
content::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED);
+ std::string trial_condition =
+ base::FieldTrialList::FindFullName(download_util::kFinchTrialName);
const char* danger_type_value =
GetDangerTypeString(download_item->GetDangerType());
file_value->SetString("danger_type", danger_type_value);
+ if (!trial_condition.empty()) {
+ base::string16 finch_string;
+ content::DownloadDangerType danger_type =
+ download_item->GetDangerType();
+ if (danger_type == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL ||
+ danger_type == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT ||
+ danger_type == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST) {
+ finch_string = download_util::AssembleMalwareFinchString(
+ trial_condition, file_name);
+ }
+ file_value->SetString("finch_string", finch_string);
+ }
} else if (download_item->IsPaused()) {
file_value->SetString("state", "PAUSED");
} else {
@@ -247,8 +258,7 @@
} // namespace
DownloadsDOMHandler::DownloadsDOMHandler(content::DownloadManager* dlm)
- : search_text_(),
- main_notifier_(dlm, this),
+ : main_notifier_(dlm, this),
update_scheduled_(false),
weak_ptr_factory_(this) {
// Create our fileicon data source.
@@ -323,16 +333,14 @@
content::DownloadManager* manager,
content::DownloadItem* download_item) {
if (IsDownloadDisplayable(*download_item)) {
- if (!search_text_.empty()) {
+ if (search_terms_ && !search_terms_->empty()) {
// Don't CallDownloadUpdated() if download_item doesn't match
- // search_text_.
+ // search_terms_.
// TODO(benjhayden): Consider splitting MatchesQuery() out to a function.
content::DownloadManager::DownloadVector all_items, filtered_items;
all_items.push_back(download_item);
DownloadQuery query;
- scoped_ptr<base::Value> query_text(base::Value::CreateStringValue(
- search_text_));
- query.AddFilter(DownloadQuery::FILTER_QUERY, *query_text.get());
+ query.AddFilter(DownloadQuery::FILTER_QUERY, *search_terms_.get());
query.Search(all_items.begin(), all_items.end(), &filtered_items);
if (filtered_items.empty())
return;
@@ -364,7 +372,7 @@
void DownloadsDOMHandler::HandleGetDownloads(const base::ListValue* args) {
CountDownloadsDOMEvents(DOWNLOADS_DOM_EVENT_GET_DOWNLOADS);
- search_text_ = ExtractStringValue(args);
+ search_terms_.reset((args && !args->empty()) ? args->DeepCopy() : NULL);
SendCurrentDownloads();
}
@@ -508,10 +516,8 @@
original_notifier_->GetManager()->CheckForHistoryFilesRemoval();
}
DownloadQuery query;
- if (!search_text_.empty()) {
- scoped_ptr<base::Value> query_text(base::Value::CreateStringValue(
- search_text_));
- query.AddFilter(DownloadQuery::FILTER_QUERY, *query_text.get());
+ if (search_terms_ && !search_terms_->empty()) {
+ query.AddFilter(DownloadQuery::FILTER_QUERY, *search_terms_.get());
}
query.AddFilter(base::Bind(&IsDownloadDisplayable));
query.AddSorter(DownloadQuery::SORT_START_TIME, DownloadQuery::DESCENDING);
diff --git a/chrome/browser/ui/webui/downloads_dom_handler.h b/chrome/browser/ui/webui/downloads_dom_handler.h
index aee7ed1..8b5d23c 100644
--- a/chrome/browser/ui/webui/downloads_dom_handler.h
+++ b/chrome/browser/ui/webui/downloads_dom_handler.h
@@ -130,8 +130,8 @@
// Returns the download that is referred to in a given value.
content::DownloadItem* GetDownloadByValue(const base::ListValue* args);
- // Current search text.
- string16 search_text_;
+ // Current search terms.
+ scoped_ptr<base::ListValue> search_terms_;
// Notifies OnDownload*() and provides safe access to the DownloadManager.
AllDownloadItemNotifier main_notifier_;
diff --git a/chrome/browser/ui/webui/downloads_dom_handler_browsertest.cc b/chrome/browser/ui/webui/downloads_dom_handler_browsertest.cc
index 9c445dc..34c5619 100644
--- a/chrome/browser/ui/webui/downloads_dom_handler_browsertest.cc
+++ b/chrome/browser/ui/webui/downloads_dom_handler_browsertest.cc
@@ -146,6 +146,8 @@
GURL(std::string()),
current,
current,
+ std::string(),
+ std::string(),
128,
128,
content::DownloadItem::COMPLETE,
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
index 37c1c1a..ac1482c 100644
--- a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
+++ b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
@@ -8,6 +8,7 @@
#include "apps/app_restore_service.h"
#include "apps/saved_files_service.h"
#include "apps/shell_window.h"
+#include "apps/shell_window_registry.h"
#include "base/auto_reset.h"
#include "base/base64.h"
#include "base/bind.h"
@@ -34,7 +35,6 @@
#include "chrome/browser/extensions/extension_warning_set.h"
#include "chrome/browser/extensions/lazy_background_task_queue.h"
#include "chrome/browser/extensions/management_policy.h"
-#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/extensions/unpacked_installer.h"
#include "chrome/browser/extensions/updater/extension_updater.h"
#include "chrome/browser/google/google_util.h"
@@ -1037,13 +1037,13 @@
const Extension* extension,
Profile* profile,
std::vector<ExtensionPage>* result) {
- ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile);
+ apps::ShellWindowRegistry* registry = apps::ShellWindowRegistry::Get(profile);
if (!registry) return;
- const ShellWindowRegistry::ShellWindowList windows =
+ const apps::ShellWindowRegistry::ShellWindowList windows =
registry->GetShellWindowsForApp(extension->id());
- for (ShellWindowRegistry::const_iterator it = windows.begin();
+ for (apps::ShellWindowRegistry::const_iterator it = windows.begin();
it != windows.end(); ++it) {
WebContents* web_contents = (*it)->web_contents();
RenderViewHost* host = web_contents->GetRenderViewHost();
diff --git a/chrome/browser/ui/webui/extensions/install_extension_handler.cc b/chrome/browser/ui/webui/extensions/install_extension_handler.cc
index 17e466d..72aa3e3 100644
--- a/chrome/browser/ui/webui/extensions/install_extension_handler.cc
+++ b/chrome/browser/ui/webui/extensions/install_extension_handler.cc
@@ -96,9 +96,11 @@
Profile* profile = Profile::FromBrowserContext(
web_ui()->GetWebContents()->GetBrowserContext());
+ scoped_ptr<ExtensionInstallPrompt> prompt(
+ new ExtensionInstallPrompt(web_ui()->GetWebContents()));
scoped_refptr<CrxInstaller> crx_installer(CrxInstaller::Create(
ExtensionSystem::Get(profile)->extension_service(),
- new ExtensionInstallPrompt(web_ui()->GetWebContents())));
+ prompt.Pass()));
crx_installer->set_error_on_unsupported_requirements(true);
crx_installer->set_off_store_install_allow_reason(
CrxInstaller::OffStoreInstallAllowedFromSettingsPage);
diff --git a/chrome/browser/ui/webui/feedback_ui.cc b/chrome/browser/ui/webui/feedback_ui.cc
index 0f58e2c..72863a6 100644
--- a/chrome/browser/ui/webui/feedback_ui.cc
+++ b/chrome/browser/ui/webui/feedback_ui.cc
@@ -24,6 +24,7 @@
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/feedback/feedback_data.h"
#include "chrome/browser/feedback/feedback_util.h"
+#include "chrome/browser/feedback/tracing_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/signin_manager.h"
@@ -65,7 +66,7 @@
#include "chrome/browser/chromeos/drive/file_system_interface.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
#include "chrome/browser/chromeos/login/user_manager.h"
-#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
+#include "chrome/browser/chromeos/system_logs/system_logs_fetcher_base.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#endif
@@ -86,6 +87,7 @@
#if defined(OS_CHROMEOS)
const char kTimestampParameter[] = "timestamp=";
+const char kTraceIdParameter[] = "traceId=";
const size_t kMaxSavedScreenshots = 2;
size_t kMaxNumScanFiles = 1000;
@@ -236,6 +238,13 @@
#if defined(OS_CHROMEOS)
feedback_url = feedback_url + "&" + kTimestampParameter +
net::EscapeUrlEncodedData(timestamp, false);
+
+ // The manager is only available if tracing is enabled.
+ if (TracingManager* manager = TracingManager::Get()) {
+ int trace_id = manager->RequestTrace();
+ feedback_url = feedback_url + "&" + kTraceIdParameter +
+ base::IntToString(trace_id);
+ }
#endif
chrome::ShowSingletonTab(browser, GURL(feedback_url));
}
@@ -307,6 +316,8 @@
source->AddLocalizedString("user-email", IDS_FEEDBACK_USER_EMAIL_LABEL);
#if defined(OS_CHROMEOS)
+ source->AddLocalizedString("performance-trace",
+ IDS_FEEDBACK_INCLUDE_PERFORMANCE_TRACE_CHECKBOX);
source->AddLocalizedString("sysinfo",
IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX);
source->AddLocalizedString("currentscreenshots",
@@ -608,6 +619,11 @@
(*i++)->GetAsString(&sys_info_checkbox);
bool send_sys_info = (sys_info_checkbox == "true");
+ std::string trace_id_str;
+ (*i++)->GetAsString(&trace_id_str);
+ int trace_id = 0;
+ base::StringToInt(trace_id_str, &trace_id);
+
std::string attached_filename;
scoped_ptr<std::string> attached_filedata;
// If we have an attached file, we'll still have more data in the list.
@@ -645,6 +661,7 @@
feedback_data_->set_attached_filename(attached_filename);
feedback_data_->set_send_sys_info(send_sys_info);
feedback_data_->set_timestamp(timestamp_);
+ feedback_data_->set_trace_id(trace_id);
#endif
// Signal the feedback object that the data from the feedback page has been
diff --git a/chrome/browser/ui/webui/flash_ui.cc b/chrome/browser/ui/webui/flash_ui.cc
index 52b70e3..bcd03e7 100644
--- a/chrome/browser/ui/webui/flash_ui.cc
+++ b/chrome/browser/ui/webui/flash_ui.cc
@@ -33,6 +33,7 @@
#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"
+#include "content/public/common/content_constants.h"
#include "content/public/common/webplugininfo.h"
#include "gpu/config/gpu_info.h"
#include "grit/browser_resources.h"
@@ -41,7 +42,6 @@
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
-#include "webkit/plugins/plugin_constants.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
@@ -268,7 +268,7 @@
// Obtain the version of the Flash plugins.
std::vector<content::WebPluginInfo> info_array;
PluginService::GetInstance()->GetPluginInfoArray(
- GURL(), kFlashPluginSwfMimeType, false, &info_array, NULL);
+ GURL(), content::kFlashPluginSwfMimeType, false, &info_array, NULL);
if (info_array.empty()) {
AddPair(list, ASCIIToUTF16(kFlashPlugin), "Not installed");
} else {
diff --git a/chrome/browser/ui/webui/history_ui.cc b/chrome/browser/ui/webui/history_ui.cc
index 7a3f570..2b1f49e 100644
--- a/chrome/browser/ui/webui/history_ui.cc
+++ b/chrome/browser/ui/webui/history_ui.cc
@@ -184,6 +184,7 @@
source->SetUseJsonJSFormatV2();
source->DisableDenyXFrameOptions();
source->AddBoolean("isManagedProfile", profile->IsManaged());
+ source->AddBoolean("showDeleteVisitUI", !profile->IsManaged());
return source;
}
diff --git a/chrome/browser/ui/webui/inline_login_ui.cc b/chrome/browser/ui/webui/inline_login_ui.cc
index 967d214..da5e138 100644
--- a/chrome/browser/ui/webui/inline_login_ui.cc
+++ b/chrome/browser/ui/webui/inline_login_ui.cc
@@ -132,7 +132,7 @@
profile_, NULL, "0" /* session_index 0 for the default user */,
UTF16ToASCII(email), UTF16ToASCII(password),
OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS,
- true /* force_same_tab_navigation */,
+ web_ui()->GetWebContents(),
OneClickSigninSyncStarter::NO_CONFIRMATION,
signin::SOURCE_UNKNOWN,
OneClickSigninSyncStarter::Callback());
diff --git a/chrome/browser/ui/webui/nacl_ui.cc b/chrome/browser/ui/webui/nacl_ui.cc
index b08affb..f38de6b 100644
--- a/chrome/browser/ui/webui/nacl_ui.cc
+++ b/chrome/browser/ui/webui/nacl_ui.cc
@@ -11,6 +11,7 @@
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/file_util.h"
+#include "base/json/json_file_value_serializer.h"
#include "base/memory/weak_ptr.h"
#include "base/path_service.h"
#include "base/strings/string16.h"
@@ -77,6 +78,7 @@
// WebUIMessageHandler implementation.
virtual void RegisterMessages() OVERRIDE;
+ private:
// Callback for the "requestNaClInfo" message.
void HandleRequestNaClInfo(const ListValue* args);
@@ -84,11 +86,10 @@
void OnGotPlugins(const std::vector<content::WebPluginInfo>& plugins);
// A helper callback that receives the result of checking if PNaCl path
- // exists. |is_valid| is true if the PNaCl path that was returned by
- // PathService is valid, and false otherwise.
- void DidValidatePnaclPath(bool* is_valid);
+ // exists and checking the PNaCl |version|. |is_valid| is true if the PNaCl
+ // path that was returned by PathService is valid, and false otherwise.
+ void DidCheckPathAndVersion(bool* is_valid, std::string* version);
- private:
// Called when enough information is gathered to return data back to the page.
void MaybeRespondToPage();
@@ -108,7 +109,8 @@
// Adds the list of plugins for NaCl to list.
void AddPluginList(ListValue* list);
- // Adds the information relevant to PNaCl (e.g., enablement, paths) to list.
+ // Adds the information relevant to PNaCl (e.g., enablement, paths, version)
+ // to the list.
void AddPnaclInfo(ListValue* list);
// Adds the information relevant to NaCl to list.
@@ -124,6 +126,7 @@
// that does not exists, so it needs to be validated.
bool pnacl_path_validated_;
bool pnacl_path_exists_;
+ std::string pnacl_version_string_;
DISALLOW_COPY_AND_ASSIGN(NaClDomHandler);
};
@@ -265,12 +268,9 @@
AddPair(list,
ASCIIToUTF16("PNaCl translator path"),
pnacl_path.LossyDisplayName());
- // Version string is part of the directory name:
- // pnacl/<version>/_platform_specific/<arch>/[files]
- // Keep in sync with pnacl_component_installer.cc.
AddPair(list,
ASCIIToUTF16("PNaCl translator version"),
- pnacl_path.DirName().DirName().BaseName().LossyDisplayName());
+ ASCIIToUTF16(pnacl_version_string_));
}
AddLineBreak(list);
}
@@ -289,7 +289,7 @@
void NaClDomHandler::HandleRequestNaClInfo(const ListValue* args) {
page_has_requested_data_ = true;
- // Force re-validation of pnacl's path in the next call to
+ // Force re-validation of PNaCl's path in the next call to
// MaybeRespondToPage(), in case PNaCl went from not-installed
// to installed since the request.
pnacl_path_validated_ = false;
@@ -318,16 +318,35 @@
naclInfo->Set("naclInfo", list.release());
}
-void NaClDomHandler::DidValidatePnaclPath(bool* is_valid) {
+void NaClDomHandler::DidCheckPathAndVersion(bool* is_valid,
+ std::string* version) {
pnacl_path_validated_ = true;
pnacl_path_exists_ = *is_valid;
+ pnacl_version_string_ = *version;
MaybeRespondToPage();
}
-void ValidatePnaclPath(bool* is_valid) {
+void CheckVersion(const base::FilePath& pnacl_path, std::string* version) {
+ base::FilePath pnacl_json_path =
+ pnacl_path.Append(FILE_PATH_LITERAL("pnacl_public_pnacl_json"));
+ JSONFileValueSerializer serializer(pnacl_json_path);
+ std::string error;
+ scoped_ptr<base::Value> root(serializer.Deserialize(NULL, &error));
+ if (!root || !root->IsType(base::Value::TYPE_DICTIONARY))
+ return;
+
+ // Now try to get the field. This may leave version empty if the
+ // the "get" fails (no key, or wrong type).
+ static_cast<base::DictionaryValue*>(root.get())->
+ GetStringASCII("pnacl-version", version);
+}
+
+void CheckPathAndVersion(bool* is_valid, std::string* version) {
base::FilePath pnacl_path;
bool got_path = PathService::Get(chrome::DIR_PNACL_COMPONENT, &pnacl_path);
*is_valid = got_path && !pnacl_path.empty() && base::PathExists(pnacl_path);
+ if (*is_valid)
+ CheckVersion(pnacl_path, version);
}
void NaClDomHandler::MaybeRespondToPage() {
@@ -338,12 +357,14 @@
if (!pnacl_path_validated_) {
bool* is_valid = new bool;
+ std::string* version_string = new std::string;
BrowserThread::PostBlockingPoolTaskAndReply(
FROM_HERE,
- base::Bind(&ValidatePnaclPath, is_valid),
- base::Bind(&NaClDomHandler::DidValidatePnaclPath,
+ base::Bind(&CheckPathAndVersion, is_valid, version_string),
+ base::Bind(&NaClDomHandler::DidCheckPathAndVersion,
weak_ptr_factory_.GetWeakPtr(),
- base::Owned(is_valid)));
+ base::Owned(is_valid),
+ base::Owned(version_string)));
return;
}
diff --git a/chrome/browser/ui/webui/ntp/android/new_tab_page_ready_handler.cc b/chrome/browser/ui/webui/ntp/android/new_tab_page_ready_handler.cc
index d81f34b..4e3f727 100644
--- a/chrome/browser/ui/webui/ntp/android/new_tab_page_ready_handler.cc
+++ b/chrome/browser/ui/webui/ntp/android/new_tab_page_ready_handler.cc
@@ -7,8 +7,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/values.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "content/public/browser/notification_service.h"
+#include "chrome/browser/android/tab_android.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
@@ -36,10 +35,10 @@
void NewTabPageReadyHandler::HandleNewTabPageReady(
const ListValue* args) {
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_NEW_TAB_READY,
- content::Source<content::WebContents>(web_ui()->GetWebContents()),
- content::NotificationService::NoDetails());
+ TabAndroid* tab = TabAndroid::FromWebContents(web_ui()->GetWebContents());
+ if (!tab)
+ return;
+ tab->OnNewTabPageReady();
}
void NewTabPageReadyHandler::HandleNewTabPageUnexpectedNavigation(
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index 6d7d9ee..4de0128 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -317,12 +317,6 @@
}
break;
}
- // The promo may not load until a couple seconds after the first NTP view,
- // so we listen for the load notification and notify the NTP when ready.
- case chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED:
- // TODO(estade): Try to get rid of this inefficient operation.
- HandleGetApps(NULL);
- break;
case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: {
CrxInstaller* crx_installer = content::Source<CrxInstaller>(source).ptr();
if (!Profile::FromWebUI(web_ui())->IsSameProfile(
@@ -454,8 +448,6 @@
registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LAUNCHER_REORDERED,
content::Source<ExtensionSorting>(
extension_service_->extension_prefs()->extension_sorting()));
- registrar_.Add(this, chrome::NOTIFICATION_WEB_STORE_PROMO_LOADED,
- content::Source<Profile>(profile));
registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
content::Source<CrxInstaller>(NULL));
registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOAD_ERROR,
@@ -727,7 +719,7 @@
}
scoped_refptr<CrxInstaller> installer(
- CrxInstaller::Create(extension_service_, NULL));
+ CrxInstaller::CreateSilent(extension_service_));
installer->set_error_on_unsupported_requirements(true);
installer->set_page_ordinal(install_info->page_ordinal);
installer->InstallWebApp(*web_app);
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.cc b/chrome/browser/ui/webui/options/browser_options_handler.cc
index bc9f5c1..7fc38bd 100644
--- a/chrome/browser/ui/webui/options/browser_options_handler.cc
+++ b/chrome/browser/ui/webui/options/browser_options_handler.cc
@@ -585,6 +585,10 @@
"themesReset",
base::Bind(&BrowserOptionsHandler::ThemesReset,
base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "requestProfilesInfo",
+ base::Bind(&BrowserOptionsHandler::HandleRequestProfilesInfo,
+ base::Unretained(this)));
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
web_ui()->RegisterMessageCallback(
"themesSetNative",
@@ -1484,6 +1488,10 @@
chrome::AttemptRestart();
}
+void BrowserOptionsHandler::HandleRequestProfilesInfo(const ListValue* args) {
+ SendProfilesInfo();
+}
+
#if !defined(OS_CHROMEOS)
void BrowserOptionsHandler::ShowNetworkProxySettings(const ListValue* args) {
content::RecordAction(UserMetricsAction("Options_ShowProxySettings"));
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.h b/chrome/browser/ui/webui/options/browser_options_handler.h
index 6dbc64d..b0ca806 100644
--- a/chrome/browser/ui/webui/options/browser_options_handler.h
+++ b/chrome/browser/ui/webui/options/browser_options_handler.h
@@ -228,6 +228,9 @@
// Callback for the "restartBrowser" message. Restores all tabs on restart.
void HandleRestartBrowser(const ListValue* args);
+ // Callback for "requestProfilesInfo" message.
+ void HandleRequestProfilesInfo(const ListValue* args);
+
#if !defined(OS_CHROMEOS)
// Callback for the "showNetworkProxySettings" message. This will invoke
// an appropriate dialog for configuring proxy settings.
diff --git a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
index 8861b50..d02c3b3 100644
--- a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
@@ -9,6 +9,7 @@
#include "ash/display/display_controller.h"
#include "ash/display/display_manager.h"
#include "ash/display/output_configurator_animation.h"
+#include "ash/display/resolution_notification_controller.h"
#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "base/bind.h"
@@ -19,6 +20,7 @@
#include "chrome/browser/chromeos/display/display_preferences.h"
#include "chromeos/display/output_configurator.h"
#include "content/public/browser/web_ui.h"
+#include "grit/ash_strings.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/display.h"
@@ -100,11 +102,11 @@
localized_strings->SetString("orientation0", l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_STANDARD_ORIENTATION));
localized_strings->SetString("orientation90", l10n_util::GetStringUTF16(
- IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION_90));
+ IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90));
localized_strings->SetString("orientation180", l10n_util::GetStringUTF16(
- IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION_180));
+ IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_180));
localized_strings->SetString("orientation270", l10n_util::GetStringUTF16(
- IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION_270));
+ IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_270));
localized_strings->SetString(
"startCalibratingOverscan", l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_CALIBRATING_OVERSCAN));
@@ -343,9 +345,34 @@
return;
}
- // TODO(mukai): creates a confirmation dialog.
- GetDisplayManager()->SetDisplayResolution(
- display_id, gfx::ToFlooredSize(gfx::SizeF(width, height)));
+ const ash::internal::DisplayInfo& display_info =
+ GetDisplayManager()->GetDisplayInfo(display_id);
+ gfx::Size new_resolution = gfx::ToFlooredSize(gfx::SizeF(width, height));
+ gfx::Size old_resolution = display_info.size_in_pixel();
+ bool has_new_resolution = false;
+ bool has_old_resolution = false;
+ for (size_t i = 0; i < display_info.resolutions().size(); ++i) {
+ ash::internal::Resolution resolution = display_info.resolutions()[i];
+ if (resolution.size == new_resolution)
+ has_new_resolution = true;
+ if (resolution.size == old_resolution)
+ has_old_resolution = true;
+ }
+ if (!has_new_resolution) {
+ LOG(ERROR) << "No new resolution " << new_resolution.ToString()
+ << " is found in the display info " << display_info.ToString();
+ return;
+ }
+ if (!has_old_resolution) {
+ LOG(ERROR) << "No old resolution " << old_resolution.ToString()
+ << " is found in the display info " << display_info.ToString();
+ return;
+ }
+
+ ash::Shell::GetInstance()->resolution_notification_controller()->
+ SetDisplayResolutionAndNotify(
+ display_id, old_resolution, new_resolution,
+ base::Bind(&StoreDisplayPrefs));
}
void DisplayOptionsHandler::HandleSetOrientation(const base::ListValue* args) {
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 7cb13218..6537a55 100644
--- a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
@@ -281,15 +281,6 @@
base::Bind(&ShillError, "SetNetworkProperty"));
}
-const base::DictionaryValue* FindPolicyForActiveUser(
- const NetworkState* network,
- onc::ONCSource* onc_source) {
- const User* user = UserManager::Get()->GetActiveUser();
- std::string username_hash = user ? user->username_hash() : std::string();
- return NetworkHandler::Get()->managed_network_configuration_handler()
- ->FindPolicyByGUID(username_hash, network->guid(), onc_source);
-}
-
std::string ActivationStateString(const std::string& activation_state) {
int id;
if (activation_state == flimflam::kActivationStateActivated)
@@ -656,7 +647,8 @@
dictionary->SetString(kTagUsername, username);
onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
- const base::DictionaryValue* onc = FindPolicyForActiveUser(vpn, &onc_source);
+ const base::DictionaryValue* onc =
+ network_connect::FindPolicyForActiveUser(vpn, &onc_source);
NetworkPropertyUIData hostname_ui_data;
hostname_ui_data.ParseOncProperty(
@@ -945,6 +937,7 @@
web_ui()->CallJavascriptFunction(kSetDefaultNetworkIconsFunction,
dictionary);
NetworkHandler::Get()->network_state_handler()->RequestScan();
+ RefreshNetworkData();
}
void InternetOptionsHandler::RegisterMessages() {
@@ -1164,7 +1157,7 @@
const NetworkState* network =
handler->FirstNetworkByType(flimflam::kTypeCellular);
if (network) {
- chromeos::network_connect::ActivateCellular(network->path());
+ ash::network_connect::ActivateCellular(network->path());
UpdateConnectionData(network->path());
}
}
@@ -1446,7 +1439,7 @@
onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
const base::DictionaryValue* onc =
- FindPolicyForActiveUser(network, &onc_source);
+ network_connect::FindPolicyForActiveUser(network, &onc_source);
const NetworkPropertyUIData property_ui_data(onc_source);
base::DictionaryValue dictionary;
@@ -1691,7 +1684,7 @@
// caching them (will be done for the new UI).
const base::DictionaryValue& device_properties = device->properties();
const NetworkPropertyUIData cellular_property_ui_data(
- cellular->onc_source());
+ cellular->ui_data().onc_source());
CopyStringFromDictionary(device_properties, flimflam::kManufacturerProperty,
kTagManufacturer, dictionary);
CopyStringFromDictionary(device_properties, flimflam::kModelIDProperty,
@@ -1849,17 +1842,16 @@
weak_factory_.GetWeakPtr()),
base::Bind(&ShillError, "NetworkCommand: " + command));
} else if (command == kTagConnect) {
- network_connect::ConnectToNetwork(
- service_path, GetNativeWindow());
+ ash::network_connect::ConnectToNetwork(service_path, GetNativeWindow());
} else if (command == kTagDisconnect) {
NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork(
service_path,
base::Bind(&base::DoNothing),
base::Bind(&ShillError, "NetworkCommand: " + command));
} else if (command == kTagConfigure) {
- NetworkConfigView::ShowForPath(service_path, GetNativeWindow());
+ NetworkConfigView::Show(service_path, GetNativeWindow());
} else if (command == kTagActivate && type == flimflam::kTypeCellular) {
- network_connect::ActivateCellular(service_path);
+ ash::network_connect::ActivateCellular(service_path);
// Activation may update network properties (e.g. ActivationState), so
// request them here in case they change.
UpdateConnectionData(service_path);
@@ -1871,9 +1863,9 @@
void InternetOptionsHandler::AddConnection(const std::string& type) {
if (type == flimflam::kTypeWifi)
- NetworkConfigView::ShowForType(chromeos::TYPE_WIFI, GetNativeWindow());
+ NetworkConfigView::ShowForType(flimflam::kTypeWifi, GetNativeWindow());
else if (type == flimflam::kTypeVPN)
- NetworkConfigView::ShowForType(chromeos::TYPE_VPN, GetNativeWindow());
+ NetworkConfigView::ShowForType(flimflam::kTypeVPN, GetNativeWindow());
else if (type == flimflam::kTypeCellular)
ChooseMobileNetworkDialog::ShowDialog(GetNativeWindow());
else
diff --git a/chrome/browser/ui/webui/options/clear_browser_data_handler.cc b/chrome/browser/ui/webui/options/clear_browser_data_handler.cc
index 3d11f05..0b578e0 100644
--- a/chrome/browser/ui/webui/options/clear_browser_data_handler.cc
+++ b/chrome/browser/ui/webui/options/clear_browser_data_handler.cc
@@ -133,6 +133,8 @@
time_list->Append(option);
}
localized_strings->Set("clearBrowserDataTimeList", time_list);
+ localized_strings->SetBoolean("showDeleteBrowsingHistoryCheckboxes",
+ !Profile::FromWebUI(web_ui())->IsManaged());
}
void ClearBrowserDataHandler::RegisterMessages() {
diff --git a/chrome/browser/ui/webui/options/import_data_handler.cc b/chrome/browser/ui/webui/options/import_data_handler.cc
index b456d25..cc12315 100644
--- a/chrome/browser/ui/webui/options/import_data_handler.cc
+++ b/chrome/browser/ui/webui/options/import_data_handler.cc
@@ -22,6 +22,8 @@
#include "chrome/browser/importer/importer_uma.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "content/public/browser/web_ui.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
@@ -34,11 +36,14 @@
}
ImportDataHandler::~ImportDataHandler() {
- if (importer_list_.get())
+ if (importer_list_)
importer_list_->set_observer(NULL);
if (importer_host_)
importer_host_->set_observer(NULL);
+
+ if (select_file_dialog_)
+ select_file_dialog_->ListenerDestroyed();
}
void ImportDataHandler::GetLocalizedValues(DictionaryValue* localized_strings) {
@@ -52,10 +57,12 @@
{ "importFavorites", IDS_IMPORT_FAVORITES_CHKBOX },
{ "importSearch", IDS_IMPORT_SEARCH_ENGINES_CHKBOX },
{ "importPasswords", IDS_IMPORT_PASSWORDS_CHKBOX },
+ { "importChooseFile", IDS_IMPORT_CHOOSE_FILE },
{ "importCommit", IDS_IMPORT_COMMIT },
{ "noProfileFound", IDS_IMPORT_NO_PROFILE_FOUND },
{ "importSucceeded", IDS_IMPORT_SUCCEEDED },
{ "findYourImportedBookmarks", IDS_IMPORT_FIND_YOUR_BOOKMARKS },
+ { "macPasswordKeychain", IDS_IMPORT_PASSWORD_KEYCHAIN_WARNING },
};
RegisterStrings(localized_strings, resources, arraysize(resources));
@@ -70,8 +77,13 @@
}
void ImportDataHandler::RegisterMessages() {
- web_ui()->RegisterMessageCallback("importData",
+ web_ui()->RegisterMessageCallback(
+ "importData",
base::Bind(&ImportDataHandler::ImportData, base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "chooseBookmarksFile",
+ base::Bind(&ImportDataHandler::HandleChooseBookmarksFile,
+ base::Unretained(this)));
}
void ImportDataHandler::ImportData(const ListValue* args) {
@@ -150,6 +162,13 @@
browser_profile->SetBoolean("search",
(browser_services & importer::SEARCH_ENGINES) != 0);
+ browser_profile->SetBoolean("show_bottom_bar",
+#if defined(OS_MACOSX)
+ source_profile.importer_type == importer::TYPE_SAFARI);
+#else
+ false);
+#endif
+
browser_profiles.Append(browser_profile);
}
@@ -183,4 +202,47 @@
}
}
+void ImportDataHandler::FileSelected(const base::FilePath& path,
+ int index,
+ void* params) {
+ base::FundamentalValue importing(true);
+ web_ui()->CallJavascriptFunction("ImportDataOverlay.setImportingState",
+ importing);
+ import_did_succeed_ = false;
+
+ importer_host_ = new ExternalProcessImporterHost();
+ importer_host_->set_observer(this);
+
+ importer::SourceProfile source_profile;
+ source_profile.importer_type = importer::TYPE_BOOKMARKS_FILE;
+ source_profile.source_path = path;
+
+ Profile* profile = Profile::FromWebUI(web_ui());
+
+ importer_host_->StartImportSettings(
+ source_profile, profile, importer::FAVORITES, new ProfileWriter(profile));
+}
+
+void ImportDataHandler::HandleChooseBookmarksFile(const base::ListValue* args) {
+ DCHECK(args && args->empty());
+ select_file_dialog_ = ui::SelectFileDialog::Create(
+ this, new ChromeSelectFilePolicy(web_ui()->GetWebContents()));
+
+ ui::SelectFileDialog::FileTypeInfo file_type_info;
+ file_type_info.extensions.resize(1);
+ file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("html"));
+
+ Browser* browser =
+ chrome::FindBrowserWithWebContents(web_ui()->GetWebContents());
+
+ select_file_dialog_->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE,
+ base::string16(),
+ base::FilePath(),
+ &file_type_info,
+ 0,
+ base::FilePath::StringType(),
+ browser->window()->GetNativeWindow(),
+ NULL);
+}
+
} // namespace options
diff --git a/chrome/browser/ui/webui/options/import_data_handler.h b/chrome/browser/ui/webui/options/import_data_handler.h
index 79bd035..08ca902 100644
--- a/chrome/browser/ui/webui/options/import_data_handler.h
+++ b/chrome/browser/ui/webui/options/import_data_handler.h
@@ -12,6 +12,7 @@
#include "chrome/browser/importer/importer_progress_observer.h"
#include "chrome/browser/ui/webui/options/options_ui.h"
#include "chrome/common/importer/importer_data_types.h"
+#include "ui/shell_dialogs/select_file_dialog.h"
class ExternalProcessImporterHost;
class ImporterList;
@@ -21,7 +22,8 @@
// Chrome personal stuff import data overlay UI handler.
class ImportDataHandler : public OptionsPageUIHandler,
public importer::ImporterListObserver,
- public importer::ImporterProgressObserver {
+ public importer::ImporterProgressObserver,
+ public ui::SelectFileDialog::Listener {
public:
ImportDataHandler();
virtual ~ImportDataHandler();
@@ -32,7 +34,7 @@
virtual void InitializeHandler() OVERRIDE;
virtual void InitializePage() OVERRIDE;
- // WebUIMessageHandler:
+ // content::WebUIMessageHandler:
virtual void RegisterMessages() OVERRIDE;
private:
@@ -47,6 +49,14 @@
virtual void ImportItemEnded(importer::ImportItem item) OVERRIDE;
virtual void ImportEnded() OVERRIDE;
+ // ui::SelectFileDialog::Listener:
+ virtual void FileSelected(const base::FilePath& path,
+ int index,
+ void* params) OVERRIDE;
+
+ // Opens a file selection dialog to choose the bookmarks HTML file.
+ void HandleChooseBookmarksFile(const base::ListValue* args);
+
scoped_refptr<ImporterList> importer_list_;
// If non-null it means importing is in progress. ImporterHost takes care
@@ -55,6 +65,8 @@
bool import_did_succeed_;
+ scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
+
DISALLOW_COPY_AND_ASSIGN(ImportDataHandler);
};
diff --git a/chrome/browser/ui/webui/options/manage_profile_handler.cc b/chrome/browser/ui/webui/options/manage_profile_handler.cc
index 4c78ff3..a7d0152 100644
--- a/chrome/browser/ui/webui/options/manage_profile_handler.cc
+++ b/chrome/browser/ui/webui/options/manage_profile_handler.cc
@@ -27,6 +27,8 @@
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/signin/signin_manager.h"
#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
@@ -65,11 +67,11 @@
Profile::CreateStatus status) {
if (status == Profile::CREATE_STATUS_INITIALIZED) {
profiles::FindOrCreateNewWindowForProfile(
- profile,
- chrome::startup::IS_PROCESS_STARTUP,
- chrome::startup::IS_FIRST_RUN,
- desktop_type,
- false);
+ profile,
+ chrome::startup::IS_PROCESS_STARTUP,
+ chrome::startup::IS_FIRST_RUN,
+ desktop_type,
+ false);
}
}
@@ -92,9 +94,13 @@
IDS_PROFILES_MANAGE_DUPLICATE_NAME_ERROR },
{ "manageProfilesIconLabel", IDS_PROFILES_MANAGE_ICON_LABEL },
{ "manageProfilesManagedSignedInLabel",
- IDS_PROFILES_CREATE_MANAGED_SIGNED_IN_LABEL },
+ IDS_PROFILES_CREATE_MANAGED_SIGNED_IN_LABEL },
{ "manageProfilesManagedNotSignedInLabel",
IDS_PROFILES_CREATE_MANAGED_NOT_SIGNED_IN_LABEL },
+ { "manageProfilesManagedAccountDetailsOutOfDate",
+ IDS_PROFILES_CREATE_MANAGED_ACCOUNT_DETAILS_OUT_OF_DATE_LABEL },
+ { "manageProfilesManagedSignInAgainLink",
+ IDS_PROFILES_CREATE_MANAGED_ACCOUNT_SIGN_IN_AGAIN_LINK },
{ "manageProfilesManagedNotSignedInLink",
IDS_PROFILES_CREATE_MANAGED_NOT_SIGNED_IN_LINK },
{ "manageProfilesSelectExistingManagedProfileLabel",
@@ -443,13 +449,20 @@
void ManageProfileHandler::RequestCreateProfileUpdate(
const base::ListValue* args) {
+ Profile* profile = Profile::FromWebUI(web_ui());
SigninManagerBase* manager =
- SigninManagerFactory::GetForProfile(Profile::FromWebUI(web_ui()));
+ SigninManagerFactory::GetForProfile(profile);
string16 username = UTF8ToUTF16(manager->GetAuthenticatedUsername());
- StringValue username_value(username);
+ ProfileSyncService* service =
+ ProfileSyncServiceFactory::GetForProfile(profile);
+ GoogleServiceAuthError::State state = service->GetAuthError().state();
+ bool has_error = (state == GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS ||
+ state == GoogleServiceAuthError::USER_NOT_SIGNED_UP ||
+ state == GoogleServiceAuthError::ACCOUNT_DELETED ||
+ state == GoogleServiceAuthError::ACCOUNT_DISABLED);
web_ui()->CallJavascriptFunction("CreateProfileOverlay.updateSignedInStatus",
- username_value);
-
+ base::StringValue(username),
+ base::FundamentalValue(has_error));
OnCreateManagedUserPrefChange();
}
diff --git a/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc b/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc
index 6222f91..a726a26 100644
--- a/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc
+++ b/chrome/browser/ui/webui/options/reset_profile_settings_handler.cc
@@ -95,7 +95,7 @@
ResettableSettingsSnapshot current_snapshot(profile);
int difference = setting_snapshot_->FindDifferentFields(current_snapshot);
if (difference) {
- setting_snapshot_->SubtractStartupURLs(current_snapshot);
+ setting_snapshot_->Subtract(current_snapshot);
std::string report = SerializeSettingsReport(*setting_snapshot_,
difference);
SendSettingsFeedback(report, profile);
diff --git a/chrome/browser/ui/webui/signin/user_chooser_ui.h b/chrome/browser/ui/webui/signin/user_chooser_ui.h
deleted file mode 100644
index 4799bd7..0000000
--- a/chrome/browser/ui/webui/signin/user_chooser_ui.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_CHOOSER_UI_H_
-#define CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_CHOOSER_UI_H_
-
-#include "content/public/browser/web_ui_controller.h"
-
-class UserChooserScreenHandler;
-
-namespace base {
-class DictionaryValue;
-}
-namespace content {
-class WebUIDataSource;
-}
-
-// A WebUI dialog to display available users.
-class UserChooserUI : public content::WebUIController {
- public:
- explicit UserChooserUI(content::WebUI* web_ui);
- virtual ~UserChooserUI();
-
- private:
- content::WebUIDataSource* CreateUIDataSource(
- const base::DictionaryValue& localized_strings);
- void GetLocalizedStrings(base::DictionaryValue* localized_strings);
-
- UserChooserScreenHandler* user_chooser_screen_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(UserChooserUI);
-};
-
-#endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_CHOOSER_UI_H_
diff --git a/chrome/browser/ui/webui/signin/user_chooser_screen_handler.cc b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
similarity index 83%
rename from chrome/browser/ui/webui/signin/user_chooser_screen_handler.cc
rename to chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
index c132816..3405777 100644
--- a/chrome/browser/ui/webui/signin/user_chooser_screen_handler.cc
+++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.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/ui/webui/signin/user_chooser_screen_handler.h"
+#include "chrome/browser/ui/webui/signin/user_manager_screen_handler.h"
#include "base/bind.h"
#include "base/value_conversions.h"
@@ -56,11 +56,11 @@
const char kSourceAccountPicker[] = "account-picker";
// JS API callback names.
-const char kJsApiUserChooserInitialize[] = "userChooserInitialize";
-const char kJsApiUserChooserAddUser[] = "addUser";
-const char kJsApiUserChooserLaunchGuest[] = "launchGuest";
-const char kJsApiUserChooserLaunchUser[] = "launchUser";
-const char kJsApiUserChooserRemoveUser[] = "removeUser";
+const char kJsApiUserManagerInitialize[] = "userManagerInitialize";
+const char kJsApiUserManagerAddUser[] = "addUser";
+const char kJsApiUserManagerLaunchGuest[] = "launchGuest";
+const char kJsApiUserManagerLaunchUser[] = "launchUser";
+const char kJsApiUserManagerRemoveUser[] = "removeUser";
const size_t kAvatarIconSize = 160;
@@ -99,15 +99,15 @@
// ProfileUpdateObserver ------------------------------------------------------
-class UserChooserScreenHandler::ProfileUpdateObserver
+class UserManagerScreenHandler::ProfileUpdateObserver
: public ProfileInfoCacheObserver {
public:
ProfileUpdateObserver(
- ProfileManager* profile_manager, UserChooserScreenHandler* handler)
+ ProfileManager* profile_manager, UserManagerScreenHandler* handler)
: profile_manager_(profile_manager),
- user_chooser_handler_(handler) {
+ user_manager_handler_(handler) {
DCHECK(profile_manager_);
- DCHECK(user_chooser_handler_);
+ DCHECK(user_manager_handler_);
profile_manager_->GetProfileInfoCache().AddObserver(this);
}
@@ -121,12 +121,12 @@
// If any change has been made to a profile, propagate it to all the
// visible user manager screens.
virtual void OnProfileAdded(const base::FilePath& profile_path) OVERRIDE {
- user_chooser_handler_->SendUserList();
+ user_manager_handler_->SendUserList();
}
virtual void OnProfileWasRemoved(const base::FilePath& profile_path,
const string16& profile_name) OVERRIDE {
- user_chooser_handler_->SendUserList();
+ user_manager_handler_->SendUserList();
}
virtual void OnProfileWillBeRemoved(
@@ -137,45 +137,45 @@
virtual void OnProfileNameChanged(const base::FilePath& profile_path,
const string16& old_profile_name) OVERRIDE {
- user_chooser_handler_->SendUserList();
+ user_manager_handler_->SendUserList();
}
virtual void OnProfileAvatarChanged(
const base::FilePath& profile_path) OVERRIDE {
- user_chooser_handler_->SendUserList();
+ user_manager_handler_->SendUserList();
}
ProfileManager* profile_manager_;
- UserChooserScreenHandler* user_chooser_handler_; // Weak; owns us.
+ UserManagerScreenHandler* user_manager_handler_; // Weak; owns us.
DISALLOW_COPY_AND_ASSIGN(ProfileUpdateObserver);
};
-// UserChooserScreenHandler ---------------------------------------------------
+// UserManagerScreenHandler ---------------------------------------------------
-UserChooserScreenHandler::UserChooserScreenHandler() {
+UserManagerScreenHandler::UserManagerScreenHandler() {
profileInfoCacheObserver_.reset(
- new UserChooserScreenHandler::ProfileUpdateObserver(
+ new UserManagerScreenHandler::ProfileUpdateObserver(
g_browser_process->profile_manager(), this));
}
-UserChooserScreenHandler::~UserChooserScreenHandler() {
+UserManagerScreenHandler::~UserManagerScreenHandler() {
}
-void UserChooserScreenHandler::HandleInitialize(const base::ListValue* args) {
+void UserManagerScreenHandler::HandleInitialize(const base::ListValue* args) {
SendUserList();
- web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserChooserScreen");
+ web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserManagerScreen");
}
-void UserChooserScreenHandler::HandleAddUser(const base::ListValue* args) {
+void UserManagerScreenHandler::HandleAddUser(const base::ListValue* args) {
// TODO(noms): Should redirect to a sign in page.
chrome::ShowSingletonTab(chrome::FindBrowserWithWebContents(
web_ui()->GetWebContents()),
GURL("chrome://settings/createProfile"));
}
-void UserChooserScreenHandler::HandleRemoveUser(const base::ListValue* args) {
+void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) {
DCHECK(args);
const Value* profile_path_value;
if (!args->Get(0, &profile_path_value))
@@ -203,12 +203,12 @@
base::Bind(&OpenNewWindowForProfile, desktop_type));
}
-void UserChooserScreenHandler::HandleLaunchGuest(const base::ListValue* args) {
+void UserManagerScreenHandler::HandleLaunchGuest(const base::ListValue* args) {
AvatarMenuModel::SwitchToGuestProfileWindow(
chrome::FindBrowserWithWebContents(web_ui()->GetWebContents()));
}
-void UserChooserScreenHandler::HandleLaunchUser(const base::ListValue* args) {
+void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) {
string16 emailAddress;
string16 displayName;
@@ -232,21 +232,21 @@
}
}
-void UserChooserScreenHandler::RegisterMessages() {
- web_ui()->RegisterMessageCallback(kJsApiUserChooserInitialize,
- base::Bind(&UserChooserScreenHandler::HandleInitialize,
+void UserManagerScreenHandler::RegisterMessages() {
+ web_ui()->RegisterMessageCallback(kJsApiUserManagerInitialize,
+ base::Bind(&UserManagerScreenHandler::HandleInitialize,
base::Unretained(this)));
- web_ui()->RegisterMessageCallback(kJsApiUserChooserAddUser,
- base::Bind(&UserChooserScreenHandler::HandleAddUser,
+ web_ui()->RegisterMessageCallback(kJsApiUserManagerAddUser,
+ base::Bind(&UserManagerScreenHandler::HandleAddUser,
base::Unretained(this)));
- web_ui()->RegisterMessageCallback(kJsApiUserChooserLaunchGuest,
- base::Bind(&UserChooserScreenHandler::HandleLaunchGuest,
+ web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchGuest,
+ base::Bind(&UserManagerScreenHandler::HandleLaunchGuest,
base::Unretained(this)));
- web_ui()->RegisterMessageCallback(kJsApiUserChooserLaunchUser,
- base::Bind(&UserChooserScreenHandler::HandleLaunchUser,
+ web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchUser,
+ base::Bind(&UserManagerScreenHandler::HandleLaunchUser,
base::Unretained(this)));
- web_ui()->RegisterMessageCallback(kJsApiUserChooserRemoveUser,
- base::Bind(&UserChooserScreenHandler::HandleRemoveUser,
+ web_ui()->RegisterMessageCallback(kJsApiUserManagerRemoveUser,
+ base::Bind(&UserManagerScreenHandler::HandleRemoveUser,
base::Unretained(this)));
const content::WebUI::MessageCallback& kDoNothingCallback =
@@ -261,11 +261,9 @@
web_ui()->RegisterMessageCallback("loadWallpaper", kDoNothingCallback);
web_ui()->RegisterMessageCallback("updateCurrentScreen", kDoNothingCallback);
web_ui()->RegisterMessageCallback("loginVisible", kDoNothingCallback);
- // Unused callbacks from user_pod_row.js
- web_ui()->RegisterMessageCallback("userImagesLoaded", kDoNothingCallback);
}
-void UserChooserScreenHandler::GetLocalizedValues(
+void UserManagerScreenHandler::GetLocalizedValues(
base::DictionaryValue* localized_strings) {
// For Control Bar.
localized_strings->SetString("signedIn",
@@ -283,7 +281,8 @@
// For AccountPickerScreen.
localized_strings->SetString("screenType", "login-add-user");
localized_strings->SetString("highlightStrength", "normal");
- localized_strings->SetString("title", "User Chooser");
+ localized_strings->SetString("title",
+ l10n_util::GetStringUTF16(IDS_USER_MANAGER_SCREEN_TITLE));
localized_strings->SetString("passwordHint",
l10n_util::GetStringUTF16(IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT));
localized_strings->SetString("podMenuButtonAccessibleName",
@@ -311,7 +310,7 @@
localized_strings->SetString("publicAccountEnterAccessibleName", string16());
}
-void UserChooserScreenHandler::SendUserList() {
+void UserManagerScreenHandler::SendUserList() {
ListValue users_list;
base::FilePath active_profile_path =
web_ui()->GetWebContents()->GetBrowserContext()->GetPath();
diff --git a/chrome/browser/ui/webui/signin/user_chooser_screen_handler.h b/chrome/browser/ui/webui/signin/user_manager_screen_handler.h
similarity index 77%
rename from chrome/browser/ui/webui/signin/user_chooser_screen_handler.h
rename to chrome/browser/ui/webui/signin/user_manager_screen_handler.h
index 8169d8c..4ac7297 100644
--- a/chrome/browser/ui/webui/signin/user_chooser_screen_handler.h
+++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.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_UI_WEBUI_SIGNIN_USER_CHOOSER_SCREEN_HANDLER_H_
-#define CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_CHOOSER_SCREEN_HANDLER_H_
+#ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_MANAGER_SCREEN_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_MANAGER_SCREEN_HANDLER_H_
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
@@ -15,10 +15,10 @@
class ListValue;
}
-class UserChooserScreenHandler : public content::WebUIMessageHandler {
+class UserManagerScreenHandler : public content::WebUIMessageHandler {
public:
- UserChooserScreenHandler();
- virtual ~UserChooserScreenHandler();
+ UserManagerScreenHandler();
+ virtual ~UserManagerScreenHandler();
// WebUIMessageHandler implementation.
virtual void RegisterMessages() OVERRIDE;
@@ -43,7 +43,7 @@
// modified, so that the displayed user pods can be updated.
scoped_ptr<ProfileUpdateObserver> profileInfoCacheObserver_;
- DISALLOW_COPY_AND_ASSIGN(UserChooserScreenHandler);
+ DISALLOW_COPY_AND_ASSIGN(UserManagerScreenHandler);
};
-#endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_CHOOSER_SCREEN_HANDLER_H_
+#endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_MANAGER_SCREEN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/signin/user_chooser_ui.cc b/chrome/browser/ui/webui/signin/user_manager_ui.cc
similarity index 71%
rename from chrome/browser/ui/webui/signin/user_chooser_ui.cc
rename to chrome/browser/ui/webui/signin/user_manager_ui.cc
index 0664716..67e8ed5 100644
--- a/chrome/browser/ui/webui/signin/user_chooser_ui.cc
+++ b/chrome/browser/ui/webui/signin/user_manager_ui.cc
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/ui/webui/signin/user_chooser_ui.h"
+#include "chrome/browser/ui/webui/signin/user_manager_ui.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/webui/signin/user_chooser_screen_handler.h"
+#include "chrome/browser/ui/webui/signin/user_manager_screen_handler.h"
#include "chrome/browser/ui/webui/theme_source.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/web_ui.h"
@@ -18,17 +18,17 @@
namespace {
// JS file names.
const char kStringsJSPath[] = "strings.js";
- const char kUserChooserJSPath[] = "user_chooser.js";
+ const char kUserManagerJSPath[] = "user_manager.js";
const char kHeaderBarJSPath[] = "header_bar.js";
const char kAccountPickerJSPath[] = "screen_account_picker.js";
}
-UserChooserUI::UserChooserUI(content::WebUI* web_ui)
+UserManagerUI::UserManagerUI(content::WebUI* web_ui)
: WebUIController(web_ui) {
// The web_ui object takes ownership of the handler, and will
// destroy it when it (the WebUI) is destroyed.
- user_chooser_screen_handler_ = new UserChooserScreenHandler();
- web_ui->AddMessageHandler(user_chooser_screen_handler_);
+ user_manager_screen_handler_ = new UserManagerScreenHandler();
+ web_ui->AddMessageHandler(user_manager_screen_handler_);
base::DictionaryValue localized_strings;
GetLocalizedStrings(&localized_strings);
@@ -44,26 +44,26 @@
#endif
}
-UserChooserUI::~UserChooserUI() {
+UserManagerUI::~UserManagerUI() {
}
-content::WebUIDataSource* UserChooserUI::CreateUIDataSource(
+content::WebUIDataSource* UserManagerUI::CreateUIDataSource(
const base::DictionaryValue& localized_strings) {
content::WebUIDataSource* source =
- content::WebUIDataSource::Create(chrome::kChromeUIUserChooserHost);
+ content::WebUIDataSource::Create(chrome::kChromeUIUserManagerHost);
source->SetUseJsonJSFormatV2();
source->AddLocalizedStrings(localized_strings);
source->SetJsonPath(kStringsJSPath);
- source->SetDefaultResource(IDR_USER_CHOOSER_HTML);
- source->AddResourcePath(kUserChooserJSPath, IDR_USER_CHOOSER_JS);
+ source->SetDefaultResource(IDR_USER_MANAGER_HTML);
+ source->AddResourcePath(kUserManagerJSPath, IDR_USER_MANAGER_JS);
return source;
}
-void UserChooserUI::GetLocalizedStrings(
+void UserManagerUI::GetLocalizedStrings(
base::DictionaryValue* localized_strings) {
- user_chooser_screen_handler_->GetLocalizedValues(localized_strings);
+ user_manager_screen_handler_->GetLocalizedValues(localized_strings);
webui::SetFontAndTextDirection(localized_strings);
#if defined(GOOGLE_CHROME_BUILD)
diff --git a/chrome/browser/ui/webui/signin/user_manager_ui.h b/chrome/browser/ui/webui/signin/user_manager_ui.h
new file mode 100644
index 0000000..0e5ab3d
--- /dev/null
+++ b/chrome/browser/ui/webui/signin/user_manager_ui.h
@@ -0,0 +1,35 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_MANAGER_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_MANAGER_UI_H_
+
+#include "content/public/browser/web_ui_controller.h"
+
+class UserManagerScreenHandler;
+
+namespace base {
+class DictionaryValue;
+}
+namespace content {
+class WebUIDataSource;
+}
+
+// A WebUI dialog to display available users.
+class UserManagerUI : public content::WebUIController {
+ public:
+ explicit UserManagerUI(content::WebUI* web_ui);
+ virtual ~UserManagerUI();
+
+ private:
+ content::WebUIDataSource* CreateUIDataSource(
+ const base::DictionaryValue& localized_strings);
+ void GetLocalizedStrings(base::DictionaryValue* localized_strings);
+
+ UserManagerScreenHandler* user_manager_screen_handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(UserManagerUI);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_USER_MANAGER_UI_H_
diff --git a/chrome/browser/ui/webui/task_manager/task_manager_handler.cc b/chrome/browser/ui/webui/task_manager/task_manager_handler.cc
index 8ce0d82..8ba6cef 100644
--- a/chrome/browser/ui/webui/task_manager/task_manager_handler.cc
+++ b/chrome/browser/ui/webui/task_manager/task_manager_handler.cc
@@ -11,12 +11,9 @@
#include "base/bind_helpers.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
-#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/task_manager/task_manager.h"
#include "chrome/browser/ui/host_desktop.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
@@ -184,11 +181,6 @@
model_->AddObserver(this);
model_->StartUpdating();
-
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_TASK_MANAGER_WINDOW_READY,
- content::Source<TaskManagerModel>(model_),
- content::NotificationService::NoDetails());
}
void TaskManagerHandler::OpenAboutMemory(const ListValue* indexes) {
diff --git a/chrome/browser/ui/webui/version_handler.cc b/chrome/browser/ui/webui/version_handler.cc
index 065b4f2..91c5fa3 100644
--- a/chrome/browser/ui/webui/version_handler.cc
+++ b/chrome/browser/ui/webui/version_handler.cc
@@ -14,10 +14,10 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/web_ui.h"
+#include "content/public/common/content_constants.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"
-#include "webkit/plugins/plugin_constants.h"
namespace {
@@ -133,7 +133,7 @@
// Obtain the version of the first enabled Flash plugin.
std::vector<content::WebPluginInfo> info_array;
content::PluginService::GetInstance()->GetPluginInfoArray(
- GURL(), kFlashPluginSwfMimeType, false, &info_array, NULL);
+ GURL(), content::kFlashPluginSwfMimeType, false, &info_array, NULL);
string16 flash_version =
l10n_util::GetStringUTF16(IDS_PLUGINS_DISABLED_PLUGIN);
PluginPrefs* plugin_prefs =
diff --git a/chrome/browser/usb/usb_device.cc b/chrome/browser/usb/usb_device.cc
new file mode 100644
index 0000000..6041e68
--- /dev/null
+++ b/chrome/browser/usb/usb_device.cc
@@ -0,0 +1,98 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/usb/usb_device.h"
+
+#include <algorithm>
+
+#include "base/stl_util.h"
+#include "chrome/browser/usb/usb_context.h"
+#include "chrome/browser/usb/usb_device_handle.h"
+#include "content/public/browser/browser_thread.h"
+#include "third_party/libusb/src/libusb/libusb.h"
+
+using content::BrowserThread;
+
+UsbDevice::UsbDevice(
+ scoped_refptr<UsbContext> context,
+ PlatformUsbDevice platform_device,
+ uint16 vendor_id,
+ uint16 product_id)
+ : platform_device_(platform_device),
+ vendor_id_(vendor_id),
+ product_id_(product_id),
+ context_(context) {
+ CHECK(platform_device) << "platform_device cannot be NULL";
+ libusb_ref_device(platform_device);
+}
+
+UsbDevice::UsbDevice()
+ : platform_device_(NULL),
+ vendor_id_(0),
+ product_id_(0),
+ context_(NULL) {
+}
+
+UsbDevice::~UsbDevice() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ for (HandlesVector::iterator it = handles_.begin();
+ it != handles_.end();
+ ++it) {
+ (*it)->InternalClose();
+ }
+ STLClearObject(&handles_);
+ libusb_unref_device(platform_device_);
+}
+
+scoped_refptr<UsbDeviceHandle> UsbDevice::Open() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ PlatformUsbDeviceHandle handle;
+ int rv = libusb_open(platform_device_, &handle);
+ if (LIBUSB_SUCCESS == rv) {
+ scoped_refptr<UsbDeviceHandle> device_handle =
+ new UsbDeviceHandle(context_, this, handle);
+ handles_.push_back(device_handle);
+ return device_handle;
+ }
+ return NULL;
+}
+
+bool UsbDevice::Close(scoped_refptr<UsbDeviceHandle> handle) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ for (HandlesVector::iterator it = handles_.begin();
+ it != handles_.end();
+ ++it) {
+ if (*it == handle) {
+ (*it)->InternalClose();
+ handles_.erase(it);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool UsbDevice::ListInterfaces(UsbConfigDescriptor* config) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ PlatformUsbConfigDescriptor platform_config;
+ const int list_result =
+ libusb_get_active_config_descriptor(platform_device_, &platform_config);
+ if (list_result == 0)
+ config->Reset(platform_config);
+
+ return list_result == 0;
+}
+
+void UsbDevice::OnDisconnect() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ HandlesVector handles;
+ swap(handles, handles_);
+ for (std::vector<scoped_refptr<UsbDeviceHandle> >::iterator it =
+ handles.begin();
+ it != handles.end();
+ ++it) {
+ (*it)->InternalClose();
+ }
+}
diff --git a/chrome/browser/usb/usb_device.h b/chrome/browser/usb/usb_device.h
new file mode 100644
index 0000000..524cee3
--- /dev/null
+++ b/chrome/browser/usb/usb_device.h
@@ -0,0 +1,81 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+#ifndef CHROME_BROWSER_USB_USB_DEVICE_H_
+#define CHROME_BROWSER_USB_USB_DEVICE_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
+#include "chrome/browser/usb/usb_interface.h"
+
+struct libusb_device;
+class UsbDeviceHandle;
+class UsbContext;
+
+typedef libusb_device* PlatformUsbDevice;
+
+// A UsbDevice object represents a detected USB device, providing basic
+// information about it. For further manipulation of the device, a
+// UsbDeviceHandle must be created from Open() method.
+class UsbDevice : public base::RefCountedThreadSafe<UsbDevice> {
+ public:
+ // Accessors to basic information.
+ PlatformUsbDevice platform_device() const { return platform_device_; }
+ uint16 vendor_id() const { return vendor_id_; }
+ uint16 product_id() const { return product_id_; }
+
+ // Creates a UsbDeviceHandle for further manipulation.
+ // Blocking method. Must be called on FILE thread.
+ virtual scoped_refptr<UsbDeviceHandle> Open();
+
+ // Explicitly closes a device handle. This method will be automatically called
+ // by the destructor of a UsbDeviceHandle as well.
+ // Closing a closed handle is a safe
+ // Blocking method. Must be called on FILE thread.
+ virtual bool Close(scoped_refptr<UsbDeviceHandle> handle);
+
+ // Lists the interfaces provided by the device and fills the given
+ // UsbConfigDescriptor.
+ // Blocking method. Must be called on FILE thread.
+ virtual bool ListInterfaces(UsbConfigDescriptor* config);
+
+ protected:
+ friend class UsbService;
+ friend class base::RefCountedThreadSafe<UsbDevice>;
+
+ // Called by UsbService only;
+ UsbDevice(scoped_refptr<UsbContext> context,
+ PlatformUsbDevice platform_device,
+ uint16 vendor_id,
+ uint16 product_id);
+
+ // Constructor called in test only.
+ UsbDevice();
+ virtual ~UsbDevice();
+
+ // Called only be UsbService.
+ virtual void OnDisconnect();
+
+ private:
+ PlatformUsbDevice platform_device_;
+ uint16 vendor_id_;
+ uint16 product_id_;
+
+ // Retain the context so that it will not be released before UsbDevice.
+ scoped_refptr<UsbContext> context_;
+
+ // Opened handles.
+ typedef std::vector<scoped_refptr<UsbDeviceHandle> > HandlesVector;
+ HandlesVector handles_;
+
+ base::ThreadChecker thread_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(UsbDevice);
+};
+
+#endif // CHROME_BROWSER_USB_USB_DEVICE_H_
diff --git a/chrome/browser/usb/usb_device_handle.cc b/chrome/browser/usb/usb_device_handle.cc
index 56c3dc7..32903ba 100644
--- a/chrome/browser/usb/usb_device_handle.cc
+++ b/chrome/browser/usb/usb_device_handle.cc
@@ -7,13 +7,20 @@
#include <algorithm>
#include <vector>
+#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/synchronization/lock.h"
+#include "chrome/browser/usb/usb_context.h"
+#include "chrome/browser/usb/usb_device.h"
#include "chrome/browser/usb/usb_interface.h"
#include "chrome/browser/usb/usb_service.h"
+#include "content/public/browser/browser_thread.h"
#include "third_party/libusb/src/libusb/libusb.h"
+using content::BrowserThread;
+void HandleTransferCompletion(PlatformUsbTransferHandle transfer);
+
namespace {
static uint8 ConvertTransferDirection(
@@ -90,61 +97,139 @@
}
}
-static void LIBUSB_CALL HandleTransferCompletion(
- struct libusb_transfer* transfer) {
- UsbDeviceHandle* const device =
- reinterpret_cast<UsbDeviceHandle*>(transfer->user_data);
- device->TransferComplete(transfer);
+static void LIBUSB_CALL PlatformTransferCompletionCallback(
+ PlatformUsbTransferHandle transfer) {
+ BrowserThread::PostTask(BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(HandleTransferCompletion, transfer));
}
} // namespace
-UsbDeviceHandle::Transfer::Transfer() : length(0) {}
+void HandleTransferCompletion(PlatformUsbTransferHandle transfer) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ UsbDeviceHandle* const device_handle =
+ reinterpret_cast<UsbDeviceHandle*>(transfer->user_data);
+ CHECK(device_handle) << "Device handle is closed before transfer finishes.";
+ device_handle->TransferComplete(transfer);
+ libusb_free_transfer(transfer);
+}
+
+
+class UsbDeviceHandle::InterfaceClaimer
+ : public base::RefCountedThreadSafe<UsbDeviceHandle::InterfaceClaimer> {
+ public:
+ InterfaceClaimer(const scoped_refptr<UsbDeviceHandle> handle,
+ const int interface_number);
+
+ bool Claim() const;
+
+ int alternate_setting() const { return alternate_setting_; }
+ void set_alternate_setting(const int alternate_setting) {
+ alternate_setting_ = alternate_setting;
+ }
+
+ private:
+ friend class UsbDevice;
+ friend class base::RefCountedThreadSafe<InterfaceClaimer>;
+ ~InterfaceClaimer();
+
+ const scoped_refptr<UsbDeviceHandle> handle_;
+ const int interface_number_;
+ int alternate_setting_;
+
+ DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer);
+};
+
+UsbDeviceHandle::InterfaceClaimer::InterfaceClaimer(
+ const scoped_refptr<UsbDeviceHandle> handle, const int interface_number)
+ : handle_(handle),
+ interface_number_(interface_number),
+ alternate_setting_(0) {
+}
+
+UsbDeviceHandle::InterfaceClaimer::~InterfaceClaimer() {
+ libusb_release_interface(handle_->handle(), interface_number_);
+}
+
+bool UsbDeviceHandle::InterfaceClaimer::Claim() const {
+ return libusb_claim_interface(handle_->handle(), interface_number_) == 0;
+}
+
+struct UsbDeviceHandle::Transfer {
+ Transfer();
+ ~Transfer();
+
+ UsbTransferType transfer_type;
+ scoped_refptr<net::IOBuffer> buffer;
+ scoped_refptr<UsbDeviceHandle::InterfaceClaimer> claimed_interface;
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy;
+ size_t length;
+ UsbTransferCallback callback;
+};
+
+UsbDeviceHandle::Transfer::Transfer()
+ : transfer_type(USB_TRANSFER_CONTROL),
+ length(0) {
+}
UsbDeviceHandle::Transfer::~Transfer() {}
UsbDeviceHandle::UsbDeviceHandle(
- UsbService* service,
+ scoped_refptr<UsbContext> context,
+ UsbDevice* device,
PlatformUsbDeviceHandle handle)
- : service_(service), handle_(handle) {
+ : device_(device), handle_(handle), context_(context) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(handle) << "Cannot create device with NULL handle.";
+ interfaces_ = new UsbConfigDescriptor();
+ device->ListInterfaces(interfaces_.get());
}
-UsbDeviceHandle::UsbDeviceHandle() : service_(NULL), handle_(NULL) {}
+UsbDeviceHandle::UsbDeviceHandle() : device_(NULL), handle_(NULL) {
+}
-UsbDeviceHandle::~UsbDeviceHandle() {}
+UsbDeviceHandle::~UsbDeviceHandle() {
+ DCHECK(thread_checker_.CalledOnValidThread());
-void UsbDeviceHandle::Close() {
- CheckDevice();
- service_->CloseDevice(this);
+ libusb_close(handle_);
handle_ = NULL;
}
-void UsbDeviceHandle::TransferComplete(PlatformUsbTransferHandle handle) {
- base::AutoLock lock(lock_);
+scoped_refptr<UsbDevice> UsbDeviceHandle::device() const {
+ return device_;
+}
- // TODO(gdk): Handle device disconnect.
+void UsbDeviceHandle::Close() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (device_)
+ device_->Close(this);
+}
+
+void UsbDeviceHandle::TransferComplete(PlatformUsbTransferHandle handle) {
DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed";
- Transfer* const transfer = &transfers_[handle];
+
+ Transfer transfer = transfers_[handle];
+ transfers_.erase(handle);
DCHECK_GE(handle->actual_length, 0) << "Negative actual length received";
size_t actual_length =
static_cast<size_t>(std::max(handle->actual_length, 0));
- DCHECK(transfer->length >= actual_length) <<
+ DCHECK(transfer.length >= actual_length) <<
"data too big for our buffer (libusb failure?)";
- scoped_refptr<net::IOBuffer> buffer = transfer->buffer;
- switch (transfer->transfer_type) {
+ scoped_refptr<net::IOBuffer> buffer = transfer.buffer;
+ switch (transfer.transfer_type) {
case USB_TRANSFER_CONTROL:
// If the transfer is a control transfer we do not expose the control
// setup header to the caller. This logic strips off the header if
// present before invoking the callback provided with the transfer.
if (actual_length > 0) {
- CHECK(transfer->length >= LIBUSB_CONTROL_SETUP_SIZE) <<
+ CHECK(transfer.length >= LIBUSB_CONTROL_SETUP_SIZE) <<
"buffer was not correctly set: too small for the control header";
- if (transfer->length >= actual_length &&
+ if (transfer.length >= actual_length &&
actual_length >= LIBUSB_CONTROL_SETUP_SIZE) {
// If the payload is zero bytes long, pad out the allocated buffer
// size to one byte so that an IOBuffer of that size can be allocated.
@@ -172,7 +257,7 @@
// all the data the packet can hold.
if (actual_length < packet_buffer_start) {
CHECK(packet_buffer_start + packet->actual_length <=
- transfer->length);
+ transfer.length);
memmove(buffer->data() + actual_length,
buffer->data() + packet_buffer_start,
packet->actual_length);
@@ -191,61 +276,81 @@
default:
NOTREACHED() << "Invalid usb transfer type";
+ break;
}
- transfer->callback.Run(ConvertTransferStatus(handle->status), buffer,
- actual_length);
+ transfer.message_loop_proxy->PostTask(
+ FROM_HERE,
+ base::Bind(transfer.callback,
+ ConvertTransferStatus(handle->status),
+ buffer,
+ actual_length));
- transfers_.erase(handle);
- libusb_free_transfer(handle);
-}
-
-bool UsbDeviceHandle::ListInterfaces(UsbConfigDescriptor* config) {
- CheckDevice();
-
- PlatformUsbDevice device = libusb_get_device(handle_);
-
- PlatformUsbConfigDescriptor platform_config;
- const int list_result = libusb_get_active_config_descriptor(device,
- &platform_config);
- if (list_result == 0) {
- config->Reset(platform_config);
- }
- return list_result == 0;
+ // Must release interface first before actually delete this.
+ transfer.claimed_interface = NULL;
}
bool UsbDeviceHandle::ClaimInterface(const int interface_number) {
- CheckDevice();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!device_) return false;
+ if (ContainsKey(claimed_interfaces_, interface_number)) return true;
- const int claim_result = libusb_claim_interface(handle_, interface_number);
- return claim_result == 0;
+ scoped_refptr<InterfaceClaimer> claimer =
+ new InterfaceClaimer(this, interface_number);
+
+ if (claimer->Claim()) {
+ claimed_interfaces_[interface_number]= claimer;
+ RefreshEndpointMap();
+ return true;
+ }
+ return false;
}
bool UsbDeviceHandle::ReleaseInterface(const int interface_number) {
- CheckDevice();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!device_) return false;
+ if (!ContainsKey(claimed_interfaces_, interface_number)) return false;
- const int release_result = libusb_release_interface(handle_,
- interface_number);
- return release_result == 0;
+ // Cancel all the transfers on that interface.
+ InterfaceClaimer* interface_claimer =
+ claimed_interfaces_[interface_number].get();
+ for (TransferMap::iterator it = transfers_.begin();
+ it != transfers_.end(); ++it) {
+ if (it->second.claimed_interface.get() == interface_claimer)
+ libusb_cancel_transfer(it->first);
+ }
+ claimed_interfaces_.erase(interface_number);
+
+ RefreshEndpointMap();
+ return true;
}
bool UsbDeviceHandle::SetInterfaceAlternateSetting(
const int interface_number,
const int alternate_setting) {
- CheckDevice();
-
- const int setting_result = libusb_set_interface_alt_setting(handle_,
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!device_) return false;
+ if (!ContainsKey(claimed_interfaces_, interface_number)) return false;
+ const int rv = libusb_set_interface_alt_setting(handle_,
interface_number, alternate_setting);
-
- return setting_result == 0;
+ if (rv == 0) {
+ claimed_interfaces_[interface_number]->
+ set_alternate_setting(alternate_setting);
+ RefreshEndpointMap();
+ return true;
+ }
+ return false;
}
bool UsbDeviceHandle::ResetDevice() {
- CheckDevice();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!device_) return false;
+
return libusb_reset_device(handle_) == 0;
}
bool UsbDeviceHandle::GetSerial(base::string16* serial) {
+ DCHECK(thread_checker_.CalledOnValidThread());
PlatformUsbDevice device = libusb_get_device(handle_);
libusb_device_descriptor desc;
@@ -291,7 +396,10 @@
const uint8 request, const uint16 value, const uint16 index,
net::IOBuffer* buffer, const size_t length, const unsigned int timeout,
const UsbTransferCallback& callback) {
- CheckDevice();
+ if (!device_) {
+ callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
+ return;
+ }
const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length;
scoped_refptr<net::IOBuffer> resized_buffer(new net::IOBufferWithSize(
@@ -299,84 +407,194 @@
memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(),
length);
- struct libusb_transfer* const transfer = libusb_alloc_transfer(0);
+ PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0);
const uint8 converted_type = CreateRequestType(direction, request_type,
recipient);
libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()),
converted_type, request, value, index, length);
- libusb_fill_control_transfer(transfer, handle_, reinterpret_cast<uint8*>(
- resized_buffer->data()), HandleTransferCompletion, this, timeout);
- SubmitTransfer(transfer,
+ libusb_fill_control_transfer(
+ transfer,
+ handle_,
+ reinterpret_cast<uint8*>(resized_buffer->data()),
+ PlatformTransferCompletionCallback,
+ this,
+ timeout);
+
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&UsbDeviceHandle::SubmitTransfer,
+ this,
+ transfer,
USB_TRANSFER_CONTROL,
- resized_buffer.get(),
+ resized_buffer,
resized_length,
- callback);
+ base::MessageLoopProxy::current(),
+ callback));
}
void UsbDeviceHandle::BulkTransfer(const UsbEndpointDirection direction,
const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
const unsigned int timeout, const UsbTransferCallback& callback) {
- CheckDevice();
+ if (!device_) {
+ callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
+ return;
+ }
- struct libusb_transfer* const transfer = libusb_alloc_transfer(0);
+ PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0);
const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
libusb_fill_bulk_transfer(transfer, handle_, new_endpoint,
reinterpret_cast<uint8*>(buffer->data()), length,
- HandleTransferCompletion, this, timeout);
- SubmitTransfer(transfer, USB_TRANSFER_BULK, buffer, length, callback);
+ PlatformTransferCompletionCallback, this, timeout);
+
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&UsbDeviceHandle::SubmitTransfer,
+ this,
+ transfer,
+ USB_TRANSFER_BULK,
+ make_scoped_refptr(buffer),
+ length,
+ base::MessageLoopProxy::current(),
+ callback));
}
void UsbDeviceHandle::InterruptTransfer(const UsbEndpointDirection direction,
const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
const unsigned int timeout, const UsbTransferCallback& callback) {
- CheckDevice();
+ if (!device_) {
+ callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
+ return;
+ }
- struct libusb_transfer* const transfer = libusb_alloc_transfer(0);
+ PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0);
const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
libusb_fill_interrupt_transfer(transfer, handle_, new_endpoint,
reinterpret_cast<uint8*>(buffer->data()), length,
- HandleTransferCompletion, this, timeout);
- SubmitTransfer(transfer, USB_TRANSFER_INTERRUPT, buffer, length, callback);
+ PlatformTransferCompletionCallback, this, timeout);
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&UsbDeviceHandle::SubmitTransfer,
+ this,
+ transfer,
+ USB_TRANSFER_INTERRUPT,
+ make_scoped_refptr(buffer),
+ length,
+ base::MessageLoopProxy::current(),
+ callback));
}
void UsbDeviceHandle::IsochronousTransfer(const UsbEndpointDirection direction,
const uint8 endpoint, net::IOBuffer* buffer, const size_t length,
const unsigned int packets, const unsigned int packet_length,
const unsigned int timeout, const UsbTransferCallback& callback) {
- CheckDevice();
+ if (!device_) {
+ callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
+ return;
+ }
const uint64 total_length = packets * packet_length;
CHECK(packets <= length && total_length <= length) <<
"transfer length is too small";
- struct libusb_transfer* const transfer = libusb_alloc_transfer(packets);
+ PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(packets);
const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
libusb_fill_iso_transfer(transfer, handle_, new_endpoint,
reinterpret_cast<uint8*>(buffer->data()), length, packets,
- HandleTransferCompletion, this, timeout);
+ PlatformTransferCompletionCallback, this, timeout);
libusb_set_iso_packet_lengths(transfer, packet_length);
- SubmitTransfer(transfer, USB_TRANSFER_ISOCHRONOUS, buffer, length, callback);
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&UsbDeviceHandle::SubmitTransfer,
+ this,
+ transfer,
+ USB_TRANSFER_ISOCHRONOUS,
+ make_scoped_refptr(buffer),
+ length,
+ base::MessageLoopProxy::current(),
+ callback));
}
-void UsbDeviceHandle::CheckDevice() {
- DCHECK(handle_) << "Device is already closed.";
+void UsbDeviceHandle::RefreshEndpointMap() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ endpoint_map_.clear();
+ for (ClaimedInterfaceMap::iterator it = claimed_interfaces_.begin();
+ it != claimed_interfaces_.end(); ++it) {
+ scoped_refptr<const UsbInterfaceDescriptor> interface_desc =
+ interfaces_->GetInterface(it->first)->GetAltSetting(
+ it->second->alternate_setting());
+ for (size_t i = 0; i < interface_desc->GetNumEndpoints(); i++) {
+ scoped_refptr<const UsbEndpointDescriptor> endpoint =
+ interface_desc->GetEndpoint(i);
+ endpoint_map_[endpoint->GetAddress()] = it->first;
+ }
+ }
}
-void UsbDeviceHandle::SubmitTransfer(PlatformUsbTransferHandle handle,
- UsbTransferType transfer_type,
- net::IOBuffer* buffer,
- const size_t length,
- const UsbTransferCallback& callback) {
+scoped_refptr<UsbDeviceHandle::InterfaceClaimer>
+ UsbDeviceHandle::GetClaimedInterfaceForEndpoint(unsigned char endpoint) {
+ unsigned char address = endpoint & LIBUSB_ENDPOINT_ADDRESS_MASK;
+ if (ContainsKey(endpoint_map_, address))
+ return claimed_interfaces_[endpoint_map_[address]];
+ return NULL;
+}
+
+void UsbDeviceHandle::SubmitTransfer(
+ PlatformUsbTransferHandle handle,
+ UsbTransferType transfer_type,
+ net::IOBuffer* buffer,
+ const size_t length,
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
+ const UsbTransferCallback& callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!device_) {
+ message_loop_proxy->PostTask(
+ FROM_HERE,
+ base::Bind(callback, USB_TRANSFER_DISCONNECT,
+ make_scoped_refptr(buffer), 0));
+ }
+
Transfer transfer;
transfer.transfer_type = transfer_type;
transfer.buffer = buffer;
transfer.length = length;
transfer.callback = callback;
+ transfer.message_loop_proxy = message_loop_proxy;
- {
- base::AutoLock lock(lock_);
+ // It's OK for this method to return NULL. libusb_submit_transfer will fail if
+ // it requires an interface we didn't claim.
+ transfer.claimed_interface = GetClaimedInterfaceForEndpoint(handle->endpoint);
+
+ if (libusb_submit_transfer(handle) == LIBUSB_SUCCESS) {
transfers_[handle] = transfer;
- libusb_submit_transfer(handle);
+ } else {
+ message_loop_proxy->PostTask(
+ FROM_HERE,
+ base::Bind(callback, USB_TRANSFER_ERROR,
+ make_scoped_refptr(buffer), 0));
}
}
+
+void UsbDeviceHandle::InternalClose() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!device_) return;
+
+ // Cancel all the transfers.
+ for (TransferMap::iterator it = transfers_.begin();
+ it != transfers_.end(); ++it) {
+ // The callback will be called some time later.
+ libusb_cancel_transfer(it->first);
+ }
+
+ // Attempt-release all the interfaces.
+ // It will be retained until the transfer cancellation is finished.
+ claimed_interfaces_.clear();
+
+ // Cannot close device handle here. Need to wait for libusb_cancel_transfer to
+ // finish.
+ device_ = NULL;
+}
diff --git a/chrome/browser/usb/usb_device_handle.h b/chrome/browser/usb/usb_device_handle.h
index 0659955..f7aa43f 100644
--- a/chrome/browser/usb/usb_device_handle.h
+++ b/chrome/browser/usb/usb_device_handle.h
@@ -11,21 +11,28 @@
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
#include "chrome/browser/usb/usb_interface.h"
+#include "content/public/browser/browser_thread.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
-struct libusb_device;
struct libusb_device_handle;
struct libusb_iso_packet_descriptor;
struct libusb_transfer;
-typedef libusb_device* PlatformUsbDevice;
typedef libusb_device_handle* PlatformUsbDeviceHandle;
typedef libusb_iso_packet_descriptor* PlatformUsbIsoPacketDescriptor;
typedef libusb_transfer* PlatformUsbTransferHandle;
-class UsbService;
+class UsbContext;
+class UsbConfigDescriptor;
+class UsbDevice;
+class UsbInterface;
+
+namespace base {
+ class MessageLoopProxy;
+} // namespace base
namespace net {
class IOBuffer;
@@ -45,35 +52,33 @@
typedef base::Callback<void(UsbTransferStatus, scoped_refptr<net::IOBuffer>,
size_t)> UsbTransferCallback;
-// A UsbDevice wraps the platform's underlying representation of what a USB
-// device actually is, and provides accessors for performing many of the
-// standard USB operations.
-class UsbDeviceHandle : public base::RefCounted<UsbDeviceHandle> {
+// UsbDeviceHandle class provides basic I/O related functionalities.
+class UsbDeviceHandle : public base::RefCountedThreadSafe<UsbDeviceHandle> {
public:
enum TransferRequestType { STANDARD, CLASS, VENDOR, RESERVED };
enum TransferRecipient { DEVICE, INTERFACE, ENDPOINT, OTHER };
- // Usually you will not want to directly create a UsbDevice, favoring to let
- // the UsbService take care of the logistics of getting a platform device
- // handle and handling events for it.
- UsbDeviceHandle(UsbService* service, PlatformUsbDeviceHandle handle);
+ scoped_refptr<UsbDevice> device() const;
+ PlatformUsbDeviceHandle handle() const { return handle_; }
- PlatformUsbDeviceHandle handle() { return handle_; }
-
- // Close the USB device and release the underlying platform device.
+ // Notifies UsbDevice to drop the reference of this object; cancels all the
+ // flying transfers.
+ // It is possible that the object has no other reference after this call. So
+ // if it is called using a raw pointer, it could be invalidated.
+ // The platform device handle will be closed when UsbDeviceHandle destructs.
virtual void Close();
- // Device manipulation operations. These methods are blocking.
- virtual bool ListInterfaces(UsbConfigDescriptor* config);
+ // Device manipulation operations. These methods are blocking and must be
+ // called on FILE thread.
virtual bool ClaimInterface(const int interface_number);
virtual bool ReleaseInterface(const int interface_number);
virtual bool SetInterfaceAlternateSetting(
const int interface_number,
const int alternate_setting);
virtual bool ResetDevice();
- bool GetSerial(base::string16* serial);
+ virtual bool GetSerial(base::string16* serial);
- // Async IO.
+ // Async IO. Can be called on any thread.
virtual void ControlTransfer(const UsbEndpointDirection direction,
const TransferRequestType request_type,
const TransferRecipient recipient,
@@ -108,32 +113,34 @@
const unsigned int timeout,
const UsbTransferCallback& callback);
- // Normal code should not call this function. It is called by the platform's
- // callback mechanism in such a way that it cannot be made private. Invokes
- // the callbacks associated with a given transfer, and removes it from the
- // in-flight transfer set.
- void TransferComplete(PlatformUsbTransferHandle transfer);
-
protected:
+ friend class base::RefCountedThreadSafe<UsbDeviceHandle>;
+ friend class UsbDevice;
+
+ // This constructor is called by UsbDevice.
+ UsbDeviceHandle(scoped_refptr<UsbContext> context,
+ UsbDevice* device, PlatformUsbDeviceHandle handle);
+
// This constructor variant is for use in testing only.
UsbDeviceHandle();
-
- friend class base::RefCounted<UsbDeviceHandle>;
virtual ~UsbDeviceHandle();
+ UsbDevice* device_;
+
private:
- struct Transfer {
- Transfer();
- ~Transfer();
+ friend void HandleTransferCompletion(PlatformUsbTransferHandle handle);
- UsbTransferType transfer_type;
- scoped_refptr<net::IOBuffer> buffer;
- size_t length;
- UsbTransferCallback callback;
- };
+ class InterfaceClaimer;
+ struct Transfer;
- // Checks that the device has not yet been closed.
- void CheckDevice();
+ // Refresh endpoint_map_ after ClaimInterface, ReleaseInterface and
+ // SetInterfaceAlternateSetting.
+ void RefreshEndpointMap();
+
+ // Look up the claimed interface by endpoint. Return NULL if the interface
+ // of the endpoint is not found.
+ scoped_refptr<InterfaceClaimer> GetClaimedInterfaceForEndpoint(
+ unsigned char endpoint);
// Submits a transfer and starts tracking it. Retains the buffer and copies
// the completion callback until the transfer finishes, whereupon it invokes
@@ -142,20 +149,35 @@
UsbTransferType transfer_type,
net::IOBuffer* buffer,
const size_t length,
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy,
const UsbTransferCallback& callback);
- // The UsbService isn't referenced here to prevent a dependency cycle between
- // the service and the devices. Since a service owns every device, and is
- // responsible for its destruction, there is no case where a UsbDevice can
- // have outlived its originating UsbService.
- UsbService* const service_;
+ // Invokes the callbacks associated with a given transfer, and removes it from
+ // the in-flight transfer set.
+ void TransferComplete(PlatformUsbTransferHandle transfer);
+
+ // Informs the object to drop internal references.
+ void InternalClose();
+
PlatformUsbDeviceHandle handle_;
- // transfers_ tracks all in-flight transfers associated with this device,
- // allowing the device to retain the buffer and callback associated with a
- // transfer until such time that it completes. It is protected by lock_.
- base::Lock lock_;
- std::map<PlatformUsbTransferHandle, Transfer> transfers_;
+ scoped_refptr<UsbConfigDescriptor> interfaces_;
+
+ typedef std::map<int, scoped_refptr<InterfaceClaimer> > ClaimedInterfaceMap;
+ ClaimedInterfaceMap claimed_interfaces_;
+
+ typedef std::map<PlatformUsbTransferHandle, Transfer> TransferMap;
+ TransferMap transfers_;
+
+ // A map from endpoints to interfaces
+ typedef std::map<int, int> EndpointMap;
+ EndpointMap endpoint_map_;
+
+ // Retain the UsbContext so that the platform context will not be destroyed
+ // before this handle.
+ scoped_refptr<UsbContext> context_;
+
+ base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(UsbDeviceHandle);
};
diff --git a/chrome/browser/usb/usb_service.cc b/chrome/browser/usb/usb_service.cc
index d850488..4425d9b 100644
--- a/chrome/browser/usb/usb_service.cc
+++ b/chrome/browser/usb/usb_service.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/usb/usb_service.h"
+#include <set>
#include <vector>
#include "base/bind.h"
@@ -60,15 +61,19 @@
} // namespace
-UsbService::UsbService() : context_(new UsbContext()) {
+using content::BrowserThread;
+
+UsbService::UsbService()
+ : context_(new UsbContext()) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
}
UsbService::~UsbService() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- // UsbDeviceHandle::Close removes itself from devices_.
- while (devices_.size())
- devices_.begin()->second->Close();
+ for (DeviceMap::iterator it = devices_.begin();
+ it != devices_.end(); ++it) {
+ it->second->OnDisconnect();
+ }
}
UsbService* UsbService::GetInstance() {
@@ -116,19 +121,14 @@
#endif // defined(OS_CHROMEOS)
}
-void UsbService::EnumerateDevices(
- vector<scoped_refptr<UsbDeviceHandle> >* devices) {
- devices->clear();
+void UsbService::GetDevices(std::vector<scoped_refptr<UsbDevice> >* devices) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ STLClearObject(devices);
+ RefreshDevices();
- DeviceVector enumerated_devices;
- EnumerateDevicesImpl(&enumerated_devices);
-
- for (DeviceVector::iterator it = enumerated_devices.begin();
- it != enumerated_devices.end(); ++it) {
- PlatformUsbDevice device = it->device();
- UsbDeviceHandle* const wrapper = LookupOrCreateDevice(device);
- if (wrapper)
- devices->push_back(wrapper);
+ for (DeviceMap::iterator it = devices_.begin();
+ it != devices_.end(); ++it) {
+ devices->push_back(it->second);
}
}
@@ -153,7 +153,8 @@
const uint16 product_id,
const base::Callback<void(ScopedDeviceVector vectors)>& callback,
bool success) {
- ScopedDeviceVector devices(new vector<scoped_refptr<UsbDeviceHandle> >());
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ ScopedDeviceVector devices(new vector<scoped_refptr<UsbDevice> >());
// If the permission broker was unable to obtain permission for the specified
// devices then there is no point in attempting to enumerate the devices. On
@@ -163,88 +164,64 @@
return;
}
- DeviceVector enumerated_devices;
- EnumerateDevicesImpl(&enumerated_devices);
+ RefreshDevices();
- for (DeviceVector::iterator it = enumerated_devices.begin();
- it != enumerated_devices.end(); ++it) {
- PlatformUsbDevice device = it->device();
- if (DeviceMatches(device, vendor_id, product_id)) {
- UsbDeviceHandle* const wrapper = LookupOrCreateDevice(device);
- if (wrapper)
- devices->push_back(make_scoped_refptr(wrapper));
- }
+ for (DeviceMap::iterator it = devices_.begin();
+ it != devices_.end(); ++it) {
+ if (DeviceMatches(it->second, vendor_id, product_id))
+ devices->push_back(it->second);
}
+
callback.Run(devices.Pass());
}
-void UsbService::CloseDevice(scoped_refptr<UsbDeviceHandle> device) {
- PlatformUsbDevice platform_device = libusb_get_device(device->handle());
- if (!ContainsKey(devices_, platform_device)) {
- LOG(WARNING) << "CloseDevice called for device we're not tracking!";
- return;
+void UsbService::RefreshDevices() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ libusb_device** platform_devices = NULL;
+ const ssize_t device_count =
+ libusb_get_device_list(context_->context(), &platform_devices);
+
+ std::set<UsbDevice*> connected_devices;
+ vector<PlatformUsbDevice> disconnected_devices;
+
+ // Populates new devices.
+ for (ssize_t i = 0; i < device_count; ++i) {
+ if (!ContainsKey(devices_, platform_devices[i])) {
+ libusb_device_descriptor descriptor;
+ // This test is needed. A valid vendor/produce pair is required.
+ if (0 != libusb_get_device_descriptor(platform_devices[i], &descriptor))
+ continue;
+ UsbDevice* new_device = new UsbDevice(context_,
+ platform_devices[i],
+ descriptor.idVendor,
+ descriptor.idProduct);
+ devices_[platform_devices[i]] = new_device;
+ connected_devices.insert(new_device);
+ } else {
+ connected_devices.insert(devices_[platform_devices[i]].get());
+ }
}
- devices_.erase(platform_device);
- libusb_close(device->handle());
-}
-
-UsbService::RefCountedPlatformUsbDevice::RefCountedPlatformUsbDevice(
- PlatformUsbDevice device) : device_(device) {
- libusb_ref_device(device_);
-}
-
-UsbService::RefCountedPlatformUsbDevice::RefCountedPlatformUsbDevice(
- const RefCountedPlatformUsbDevice& other) : device_(other.device_) {
- libusb_ref_device(device_);
-}
-
-UsbService::RefCountedPlatformUsbDevice::~RefCountedPlatformUsbDevice() {
- libusb_unref_device(device_);
-}
-
-PlatformUsbDevice UsbService::RefCountedPlatformUsbDevice::device() {
- return device_;
-}
-
-void UsbService::EnumerateDevicesImpl(DeviceVector* output) {
- STLClearObject(output);
-
- libusb_device** devices = NULL;
- const ssize_t device_count = libusb_get_device_list(
- context_->context(),
- &devices);
- if (device_count < 0)
- return;
-
- for (int i = 0; i < device_count; ++i) {
- libusb_device* device = devices[i];
- libusb_ref_device(device);
- output->push_back(RefCountedPlatformUsbDevice(device));
+ // Find disconnected devices.
+ for (DeviceMap::iterator it = devices_.begin(); it != devices_.end(); ++it) {
+ if (!ContainsKey(connected_devices, it->second)) {
+ disconnected_devices.push_back(it->first);
+ }
}
- libusb_free_device_list(devices, true);
+ // Remove disconnected devices from devices_.
+ for (size_t i = 0; i < disconnected_devices.size(); ++i) {
+ // UsbDevice will be destroyed after this. The corresponding
+ // PlatformUsbDevice will be unref'ed during this process.
+ devices_.erase(disconnected_devices[i]);
+ }
+
+ libusb_free_device_list(platform_devices, true);
}
-bool UsbService::DeviceMatches(PlatformUsbDevice device,
+bool UsbService::DeviceMatches(scoped_refptr<UsbDevice> device,
const uint16 vendor_id,
const uint16 product_id) {
- libusb_device_descriptor descriptor;
- if (libusb_get_device_descriptor(device, &descriptor))
- return false;
- return descriptor.idVendor == vendor_id && descriptor.idProduct == product_id;
-}
-
-UsbDeviceHandle* UsbService::LookupOrCreateDevice(PlatformUsbDevice device) {
- if (!ContainsKey(devices_, device)) {
- libusb_device_handle* handle = NULL;
- if (libusb_open(device, &handle)) {
- LOG(WARNING) << "Could not open device.";
- return NULL;
- }
-
- UsbDeviceHandle* wrapper = new UsbDeviceHandle(this, handle);
- devices_[device] = wrapper;
- }
- return devices_[device].get();
+ return device->vendor_id() == vendor_id && device->product_id() == product_id;
}
diff --git a/chrome/browser/usb/usb_service.h b/chrome/browser/usb/usb_service.h
index dcd6e28..e89eff9 100644
--- a/chrome/browser/usb/usb_service.h
+++ b/chrome/browser/usb/usb_service.h
@@ -11,7 +11,7 @@
#include "base/basictypes.h"
#include "base/memory/singleton.h"
-#include "chrome/browser/usb/usb_device_handle.h"
+#include "chrome/browser/usb/usb_device.h"
namespace base {
@@ -28,54 +28,38 @@
// competition for the same USB device.
class UsbService {
public:
- typedef scoped_ptr<std::vector<scoped_refptr<UsbDeviceHandle> > >
+ typedef scoped_ptr<std::vector<scoped_refptr<UsbDevice> > >
ScopedDeviceVector;
+
// Must be called on FILE thread.
static UsbService* GetInstance();
// Find all of the devices attached to the system that are identified by
// |vendor_id| and |product_id|, inserting them into |devices|. Clears
// |devices| before use. Calls |callback| once |devices| is populated.
+ // The result will be sorted by id in increasing order. Must be called on
+ // FILE thread.
void FindDevices(
const uint16 vendor_id,
const uint16 product_id,
int interface_id,
const base::Callback<void(ScopedDeviceVector vector)>& callback);
- // Find all of the devices attached to the system, inserting them into
- // |devices|. Clears |devices| before use.
- void EnumerateDevices(std::vector<scoped_refptr<UsbDeviceHandle> >* devices);
-
- // This function should not be called by normal code. It is invoked by a
- // UsbDevice's Close function and disposes of the associated platform handle.
- void CloseDevice(scoped_refptr<UsbDeviceHandle> device);
+ // Get all of the devices attached to the system, inserting them into
+ // |devices|. Clears |devices| before use. The result will be sorted by id
+ // in increasing order. Must be called on FILE thread.
+ void GetDevices(std::vector<scoped_refptr<UsbDevice> >* devices);
private:
- UsbService();
- virtual ~UsbService();
friend struct DefaultSingletonTraits<UsbService>;
friend class base::DeleteHelper<UsbService>;
- // RefCountedPlatformUsbDevice takes care of managing the underlying reference
- // count of a single PlatformUsbDevice. This allows us to construct things
- // like vectors of RefCountedPlatformUsbDevices and not worry about having to
- // explicitly unreference them after use.
- class RefCountedPlatformUsbDevice {
- public:
- explicit RefCountedPlatformUsbDevice(PlatformUsbDevice device);
- RefCountedPlatformUsbDevice(const RefCountedPlatformUsbDevice& other);
- virtual ~RefCountedPlatformUsbDevice();
- PlatformUsbDevice device();
-
- private:
- PlatformUsbDevice device_;
- };
-
- typedef std::vector<RefCountedPlatformUsbDevice> DeviceVector;
+ UsbService();
+ virtual ~UsbService();
// Return true if |device|'s vendor and product identifiers match |vendor_id|
// and |product_id|.
- static bool DeviceMatches(PlatformUsbDevice device,
+ static bool DeviceMatches(scoped_refptr<UsbDevice> device,
const uint16 vendor_id,
const uint16 product_id);
@@ -97,21 +81,13 @@
const base::Callback<void(ScopedDeviceVector vector)>& callback,
bool success);
- // Populates |output| with the result of enumerating all attached USB devices.
- void EnumerateDevicesImpl(DeviceVector* output);
-
- // If a UsbDevice wrapper corresponding to |device| has already been created,
- // returns it. Otherwise, opens the device, creates a wrapper, and associates
- // the wrapper with the device internally.
- UsbDeviceHandle* LookupOrCreateDevice(PlatformUsbDevice device);
+ // Enumerate USB devices from OS and Update devices_ map.
+ void RefreshDevices();
scoped_refptr<UsbContext> context_;
- // The devices_ map contains scoped_refptrs to all open devices, indicated by
- // their vendor and product id. This allows for reusing an open device without
- // creating another platform handle for it.
- typedef std::map<PlatformUsbDevice, scoped_refptr<UsbDeviceHandle> >
- DeviceMap;
+ // The map from PlatformUsbDevices to UsbDevices.
+ typedef std::map<PlatformUsbDevice, scoped_refptr<UsbDevice> > DeviceMap;
DeviceMap devices_;
DISALLOW_COPY_AND_ASSIGN(UsbService);
diff --git a/chrome/browser_tests.isolate b/chrome/browser_tests.isolate
index 9c9ad09..79ffdc0 100644
--- a/chrome/browser_tests.isolate
+++ b/chrome/browser_tests.isolate
@@ -39,6 +39,9 @@
['OS=="linux" or OS=="mac" or OS=="win"', {
'variables': {
'isolate_dependency_tracked': [
+ '../media/test/data/bear-320x240-multitrack.webm',
+ '../media/test/data/no_streams.webm',
+ '../media/test/data/sfx.ogg',
'../ppapi/tests/test_case.html',
'../ppapi/tests/test_page.css',
'../tools/swarm_client/run_isolated.py',
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index f9334b1..011c65d 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -252,6 +252,7 @@
'dependencies': [
'../base/base.gyp:base',
'../content/content.gyp:content_utility',
+ '../media/media.gyp:media',
'../skia/skia.gyp:skia',
'../third_party/libxml/libxml.gyp:libxml',
'common',
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index dc86b55..97546aa 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -410,6 +410,8 @@
'browser/component_updater/pnacl/pnacl_profile_observer.h',
'browser/component_updater/pnacl/pnacl_updater_observer.cc',
'browser/component_updater/pnacl/pnacl_updater_observer.h',
+ 'browser/component_updater/ppapi_utils.cc',
+ 'browser/component_updater/ppapi_utils.h',
'browser/component_updater/recovery_component_installer.cc',
'browser/component_updater/recovery_component_installer.h',
'browser/component_updater/swiftshader_component_installer.cc',
@@ -485,6 +487,8 @@
'browser/download/download_crx_util.cc',
'browser/download/download_crx_util.h',
'browser/download/download_crx_util_android.cc',
+ 'browser/download/download_danger_prompt.cc',
+ 'browser/download/download_danger_prompt.h',
'browser/download/download_extensions.cc',
'browser/download/download_extensions.h',
'browser/download/download_file_picker.cc',
@@ -493,6 +497,8 @@
'browser/download/download_history.h',
'browser/download/download_item_model.cc',
'browser/download/download_item_model.h',
+ 'browser/download/download_path_reservation_tracker.cc',
+ 'browser/download/download_path_reservation_tracker.h',
'browser/download/download_prefs.cc',
'browser/download/download_prefs.h',
'browser/download/download_query.cc',
@@ -501,21 +507,19 @@
'browser/download/download_request_infobar_delegate.h',
'browser/download/download_request_limiter.cc',
'browser/download/download_request_limiter.h',
- 'browser/download/download_path_reservation_tracker.cc',
- 'browser/download/download_path_reservation_tracker.h',
+ 'browser/download/download_resource_throttle.cc',
+ 'browser/download/download_resource_throttle.h',
'browser/download/download_service.cc',
'browser/download/download_service.h',
'browser/download/download_service_factory.cc',
'browser/download/download_service_factory.h',
- 'browser/download/download_danger_prompt.cc',
- 'browser/download/download_danger_prompt.h',
- 'browser/download/download_shelf.h',
'browser/download/download_shelf.cc',
+ 'browser/download/download_shelf.h',
'browser/download/download_shelf_context_menu.cc',
'browser/download/download_shelf_context_menu.h',
'browser/download/download_started_animation.h',
- 'browser/download/download_resource_throttle.cc',
- 'browser/download/download_resource_throttle.h',
+ 'browser/download/download_stats.cc',
+ 'browser/download/download_stats.h',
'browser/download/download_status_updater.cc',
'browser/download/download_status_updater.h',
'browser/download/download_status_updater_gtk.cc',
@@ -987,6 +991,8 @@
'browser/media/webrtc_logging_handler_host.h',
'browser/media_galleries/fileapi/av_scanning_file_validator.cc',
'browser/media_galleries/fileapi/av_scanning_file_validator.h',
+ 'browser/media_galleries/fileapi/device_media_async_file_util.cc',
+ 'browser/media_galleries/fileapi/device_media_async_file_util.h',
'browser/media_galleries/fileapi/itunes_finder.cc',
'browser/media_galleries/fileapi/itunes_finder.h',
'browser/media_galleries/fileapi/itunes_finder_mac.h',
@@ -999,12 +1005,19 @@
'browser/media_galleries/fileapi/media_file_validator_factory.cc',
'browser/media_galleries/fileapi/media_path_filter.cc',
'browser/media_galleries/fileapi/media_path_filter.h',
+ 'browser/media_galleries/fileapi/mtp_device_async_delegate.h',
+ 'browser/media_galleries/fileapi/mtp_device_map_service.cc',
+ 'browser/media_galleries/fileapi/mtp_device_map_service.h',
'browser/media_galleries/fileapi/native_media_file_util.cc',
'browser/media_galleries/fileapi/native_media_file_util.h',
'browser/media_galleries/fileapi/picasa/picasa_finder.cc',
'browser/media_galleries/fileapi/picasa/picasa_finder.h',
+ 'browser/media_galleries/fileapi/safe_audio_video_checker.cc',
+ 'browser/media_galleries/fileapi/safe_audio_video_checker.h',
'browser/media_galleries/fileapi/safe_itunes_pref_parser_win.cc',
'browser/media_galleries/fileapi/safe_itunes_pref_parser_win.h',
+ 'browser/media_galleries/fileapi/supported_audio_video_checker.cc',
+ 'browser/media_galleries/fileapi/supported_audio_video_checker.h',
'browser/media_galleries/fileapi/supported_image_type_validator.cc',
'browser/media_galleries/fileapi/supported_image_type_validator.h',
'browser/media_galleries/imported_media_gallery_registry.cc',
@@ -1513,6 +1526,9 @@
'browser/prefs/scoped_user_pref_update.h',
'browser/prefs/session_startup_pref.cc',
'browser/prefs/session_startup_pref.h',
+ 'browser/prefs/synced_pref_change_registrar.cc',
+ 'browser/prefs/synced_pref_change_registrar.h',
+ 'browser/prefs/synced_pref_observer.h',
'browser/prerender/prerender_condition.h',
'browser/prerender/prerender_config.cc',
'browser/prerender/prerender_config.h',
@@ -2012,6 +2028,8 @@
'browser/storage_monitor/udev_util_linux.h',
'browser/storage_monitor/volume_mount_watcher_win.cc',
'browser/storage_monitor/volume_mount_watcher_win.h',
+ 'browser/sxs_linux.cc',
+ 'browser/sxs_linux.h',
'browser/sync/about_sync_util.cc',
'browser/sync/about_sync_util.h',
'browser/sync/backend_migrator.cc',
@@ -2349,6 +2367,8 @@
'browser/upgrade_detector_impl.h',
'browser/upload_list.cc',
'browser/upload_list.h',
+ 'browser/usb/usb_device.cc',
+ 'browser/usb/usb_device.h',
'browser/usb/usb_device_handle.cc',
'browser/usb/usb_device_handle.h',
'browser/usb/usb_interface.cc',
@@ -2465,7 +2485,6 @@
'../ui/web_dialogs/web_dialogs.gyp:web_dialogs',
'../v8/tools/gyp/v8.gyp:v8',
'../webkit/common/webkit_common.gyp:webkit_common',
- '../webkit/plugins/webkit_plugins.gyp:plugins_common',
'../webkit/storage_browser.gyp:webkit_storage_browser',
'../webkit/storage_common.gyp:webkit_storage_common',
'../webkit/webkit_resources.gyp:webkit_resources',
@@ -2502,15 +2521,6 @@
'xcode_settings': {'OTHER_LDFLAGS': ['-weak_framework CoreImage']},
},
}],
- ['OS=="win" or OS=="mac" or OS=="linux" or chromeos==1', {
- 'sources': [
- 'browser/media_galleries/fileapi/device_media_async_file_util.cc',
- 'browser/media_galleries/fileapi/device_media_async_file_util.h',
- 'browser/media_galleries/fileapi/mtp_device_async_delegate.h',
- 'browser/media_galleries/fileapi/mtp_device_map_service.cc',
- 'browser/media_galleries/fileapi/mtp_device_map_service.h',
- ],
- }],
['OS=="win" or OS=="mac"', {
'sources': [
'browser/media_galleries/fileapi/itunes_data_provider.cc',
@@ -2780,6 +2790,8 @@
'browser/storage_monitor/mtab_watcher_linux.h',
'browser/storage_monitor/storage_monitor_linux.cc',
'browser/storage_monitor/storage_monitor_linux.h',
+ 'browser/sxs_linux.cc',
+ 'browser/sxs_linux.h',
'browser/themes/theme_service_aurax11.cc',
'browser/themes/theme_service_aurax11.h',
'browser/ui/webui/help/version_updater_basic.cc',
@@ -3377,6 +3389,8 @@
'type': 'none',
'sources': [
'android/java/src/org/chromium/chrome/browser/ApplicationLifetime.java',
+ 'android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogControllerAndroid.java',
+ 'android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogResult.java',
'android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupGlue.java',
'android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java',
'android/java/src/org/chromium/chrome/browser/CertificateViewer.java',
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index cd5fba8..1a8f105 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -248,6 +248,8 @@
'browser/chromeos/drive/file_system/create_file_operation.h',
'browser/chromeos/drive/file_system/download_operation.cc',
'browser/chromeos/drive/file_system/download_operation.h',
+ 'browser/chromeos/drive/file_system/get_file_for_saving_operation.cc',
+ 'browser/chromeos/drive/file_system/get_file_for_saving_operation.h',
'browser/chromeos/drive/file_system/move_operation.cc',
'browser/chromeos/drive/file_system/move_operation.h',
'browser/chromeos/drive/file_system/open_file_operation.cc',
@@ -321,12 +323,16 @@
'browser/chromeos/extensions/file_manager/desktop_notifications.h',
'browser/chromeos/extensions/file_manager/event_router.cc',
'browser/chromeos/extensions/file_manager/event_router.h',
+ 'browser/chromeos/extensions/file_manager/file_browser_handlers.cc',
+ 'browser/chromeos/extensions/file_manager/file_browser_handlers.h',
'browser/chromeos/extensions/file_manager/file_manager_util.cc',
'browser/chromeos/extensions/file_manager/file_manager_util.h',
'browser/chromeos/extensions/file_manager/file_tasks.cc',
'browser/chromeos/extensions/file_manager/file_tasks.h',
'browser/chromeos/extensions/file_manager/file_watcher.cc',
'browser/chromeos/extensions/file_manager/file_watcher.h',
+ 'browser/chromeos/extensions/file_manager/fileapi_util.cc',
+ 'browser/chromeos/extensions/file_manager/fileapi_util.h',
'browser/chromeos/extensions/file_manager/mounted_disk_monitor.cc',
'browser/chromeos/extensions/file_manager/mounted_disk_monitor.h',
'browser/chromeos/extensions/file_manager/zip_file_creator.cc',
@@ -592,13 +598,6 @@
'browser/chromeos/mobile/mobile_activator.h',
'browser/chromeos/mobile_config.cc',
'browser/chromeos/mobile_config.h',
- 'browser/chromeos/net/connectivity_state_helper.cc',
- 'browser/chromeos/net/connectivity_state_helper.h',
- 'browser/chromeos/net/connectivity_state_helper_observer.h',
- 'browser/chromeos/net/cros_network_change_notifier_factory.cc',
- 'browser/chromeos/net/cros_network_change_notifier_factory.h',
- 'browser/chromeos/net/network_change_notifier_network_library.cc',
- 'browser/chromeos/net/network_change_notifier_network_library.h',
'browser/chromeos/net/network_portal_detector.cc',
'browser/chromeos/net/network_portal_detector.h',
'browser/chromeos/net/network_portal_detector_impl.cc',
@@ -786,6 +785,8 @@
'browser/chromeos/system/timezone_settings.h',
'browser/chromeos/system_key_event_listener.cc',
'browser/chromeos/system_key_event_listener.h',
+ 'browser/chromeos/system_logs/about_system_logs_fetcher.cc',
+ 'browser/chromeos/system_logs/about_system_logs_fetcher.h',
'browser/chromeos/system_logs/chrome_internal_log_source.cc',
'browser/chromeos/system_logs/chrome_internal_log_source.h',
'browser/chromeos/system_logs/command_line_log_source.cc',
@@ -800,8 +801,10 @@
'browser/chromeos/system_logs/memory_details_log_source.h',
'browser/chromeos/system_logs/network_event_log_source.cc',
'browser/chromeos/system_logs/network_event_log_source.h',
- 'browser/chromeos/system_logs/system_logs_fetcher.cc',
- 'browser/chromeos/system_logs/system_logs_fetcher.h',
+ 'browser/chromeos/system_logs/scrubbed_system_logs_fetcher.cc',
+ 'browser/chromeos/system_logs/scrubbed_system_logs_fetcher.h',
+ 'browser/chromeos/system_logs/system_logs_fetcher_base.cc',
+ 'browser/chromeos/system_logs/system_logs_fetcher_base.h',
'browser/chromeos/system_logs/touch_log_source.cc',
'browser/chromeos/system_logs/touch_log_source.h',
'browser/chromeos/ui/app_launch_view.cc',
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index 6f7425d..e61183b 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -54,6 +54,8 @@
# All .cc, .h, .m, and .mm files under browser/extensions except for
# tests and mocks.
'../extensions/browser/extension_prefs_scope.h',
+ '../extensions/browser/extension_error.cc',
+ '../extensions/browser/extension_error.h',
'../extensions/browser/file_reader.cc',
'../extensions/browser/file_reader.h',
'../extensions/browser/pref_names.cc',
@@ -76,11 +78,12 @@
'browser/extensions/activity_log/activity_log.h',
'browser/extensions/activity_log/activity_log_policy.cc',
'browser/extensions/activity_log/activity_log_policy.h',
+ 'browser/extensions/activity_log/counting_policy.cc',
+ 'browser/extensions/activity_log/counting_policy.h',
+ 'browser/extensions/activity_log/database_string_table.cc',
+ 'browser/extensions/activity_log/database_string_table.h',
'browser/extensions/activity_log/fullstream_ui_policy.cc',
'browser/extensions/activity_log/fullstream_ui_policy.h',
- 'browser/extensions/activity_log/stream_noargs_ui_policy.cc',
- 'browser/extensions/activity_log/stream_noargs_ui_policy.h',
- 'browser/extensions/activity_log/api_name_constants.h',
'browser/extensions/activity_log/web_request_constants.cc',
'browser/extensions/activity_log/web_request_constants.h',
'browser/extensions/admin_policy.cc',
@@ -485,7 +488,6 @@
'browser/extensions/api/system_memory/memory_info_provider.h',
'browser/extensions/api/system_memory/system_memory_api.cc',
'browser/extensions/api/system_memory/system_memory_api.h',
- 'browser/extensions/api/system_storage/storage_free_space_observer.h',
'browser/extensions/api/system_storage/storage_info_provider.cc',
'browser/extensions/api/system_storage/storage_info_provider.h',
'browser/extensions/api/system_storage/system_storage_api.cc',
@@ -573,8 +575,6 @@
'browser/extensions/default_apps.h',
'browser/extensions/error_console/error_console.cc',
'browser/extensions/error_console/error_console.h',
- 'browser/extensions/error_console/extension_error.cc',
- 'browser/extensions/error_console/extension_error.h',
'browser/extensions/event_listener_map.cc',
'browser/extensions/event_listener_map.h',
'browser/extensions/event_names.cc',
@@ -745,8 +745,6 @@
'browser/extensions/script_bubble_controller.h',
'browser/extensions/script_executor.cc',
'browser/extensions/script_executor.h',
- 'browser/extensions/shell_window_registry.cc',
- 'browser/extensions/shell_window_registry.h',
'browser/extensions/standard_management_policy_provider.cc',
'browser/extensions/standard_management_policy_provider.h',
'browser/extensions/startup_helper.cc',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index ea97dd7..a2ccaca 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -71,6 +71,10 @@
'browser/ui/alternate_error_tab_observer.h',
'browser/ui/android/android_about_app_info.cc',
'browser/ui/android/android_about_app_info.h',
+ 'browser/ui/android/autofill/autofill_dialog_controller_android.cc',
+ 'browser/ui/android/autofill/autofill_dialog_controller_android.h',
+ 'browser/ui/android/autofill/autofill_dialog_result.cc',
+ 'browser/ui/android/autofill/autofill_dialog_result.h',
'browser/ui/android/autofill/autofill_popup_view_android.cc',
'browser/ui/android/autofill/autofill_popup_view_android.h',
'browser/ui/android/certificate_viewer_android.cc',
@@ -276,10 +280,10 @@
'browser/ui/autofill/autocheckout_bubble.cc',
'browser/ui/autofill/autocheckout_bubble_controller.cc',
'browser/ui/autofill/autocheckout_bubble_controller.h',
- 'browser/ui/autofill/autofill_credit_card_bubble.cc',
- 'browser/ui/autofill/autofill_credit_card_bubble.h',
- 'browser/ui/autofill/autofill_credit_card_bubble_controller.cc',
- 'browser/ui/autofill/autofill_credit_card_bubble_controller.h',
+ 'browser/ui/autofill/autofill_dialog_common.cc',
+ 'browser/ui/autofill/autofill_dialog_common.h',
+ 'browser/ui/autofill/autofill_dialog_controller.cc',
+ 'browser/ui/autofill/autofill_dialog_controller.h',
'browser/ui/autofill/autofill_dialog_controller_impl.cc',
'browser/ui/autofill/autofill_dialog_controller_impl.h',
'browser/ui/autofill/autofill_dialog_models.cc',
@@ -299,6 +303,14 @@
'browser/ui/autofill/country_combobox_model.h',
'browser/ui/autofill/data_model_wrapper.cc',
'browser/ui/autofill/data_model_wrapper.h',
+ 'browser/ui/autofill/generated_credit_card_bubble_view.cc',
+ 'browser/ui/autofill/generated_credit_card_bubble_view.h',
+ 'browser/ui/autofill/generated_credit_card_bubble_controller.cc',
+ 'browser/ui/autofill/generated_credit_card_bubble_controller.h',
+ 'browser/ui/autofill/new_credit_card_bubble_view.cc',
+ 'browser/ui/autofill/new_credit_card_bubble_view.h',
+ 'browser/ui/autofill/new_credit_card_bubble_controller.cc',
+ 'browser/ui/autofill/new_credit_card_bubble_controller.h',
'browser/ui/autofill/tab_autofill_manager_delegate.cc',
'browser/ui/autofill/tab_autofill_manager_delegate.h',
'browser/ui/auto_login_infobar_delegate.cc',
@@ -518,6 +530,8 @@
'browser/ui/cocoa/bookmarks/bookmark_tree_browser_cell.mm',
'browser/ui/cocoa/browser/avatar_button_controller.h',
'browser/ui/cocoa/browser/avatar_button_controller.mm',
+ 'browser/ui/cocoa/browser/avatar_label_button.h',
+ 'browser/ui/cocoa/browser/avatar_label_button.mm',
'browser/ui/cocoa/browser/avatar_menu_bubble_controller.h',
'browser/ui/cocoa/browser/avatar_menu_bubble_controller.mm',
'browser/ui/cocoa/browser/edit_search_engine_cocoa_controller.h',
@@ -779,6 +793,8 @@
'browser/ui/cocoa/multi_key_equivalent_button.mm',
'browser/ui/cocoa/new_tab_button.h',
'browser/ui/cocoa/new_tab_button.mm',
+ 'browser/ui/cocoa/nine_part_button_cell.h',
+ 'browser/ui/cocoa/nine_part_button_cell.mm',
'browser/ui/cocoa/notifications/balloon_collection_cocoa.mm',
'browser/ui/cocoa/notifications/balloon_controller.h',
'browser/ui/cocoa/notifications/balloon_controller.mm',
@@ -1302,8 +1318,6 @@
'browser/ui/omnibox/omnibox_popup_model.cc',
'browser/ui/omnibox/omnibox_popup_model.h',
'browser/ui/omnibox/omnibox_popup_model_observer.h',
- 'browser/ui/omnibox/omnibox_popup_non_view.cc',
- 'browser/ui/omnibox/omnibox_popup_non_view.h',
'browser/ui/omnibox/omnibox_popup_view.h',
'browser/ui/omnibox/omnibox_view.cc',
'browser/ui/omnibox/omnibox_view.h',
@@ -1539,12 +1553,14 @@
'browser/ui/views/ash/tab_scrubber.cc',
'browser/ui/views/autofill/autocheckout_bubble_views.cc',
'browser/ui/views/autofill/autocheckout_bubble_views.h',
- 'browser/ui/views/autofill/autofill_credit_card_bubble_views.cc',
- 'browser/ui/views/autofill/autofill_credit_card_bubble_views.h',
'browser/ui/views/autofill/autofill_dialog_views.cc',
'browser/ui/views/autofill/autofill_dialog_views.h',
'browser/ui/views/autofill/autofill_popup_view_views.cc',
'browser/ui/views/autofill/autofill_popup_view_views.h',
+ 'browser/ui/views/autofill/generated_credit_card_bubble_views.cc',
+ 'browser/ui/views/autofill/generated_credit_card_bubble_views.h',
+ 'browser/ui/views/autofill/new_credit_card_bubble_views.cc',
+ 'browser/ui/views/autofill/new_credit_card_bubble_views.h',
'browser/ui/views/autofill/decorated_textfield.cc',
'browser/ui/views/autofill/decorated_textfield.h',
'browser/ui/views/avatar_menu_bubble_view.cc',
@@ -1779,8 +1795,8 @@
'browser/ui/views/javascript_app_modal_dialog_views.h',
'browser/ui/views/load_complete_listener.cc',
'browser/ui/views/load_complete_listener.h',
- 'browser/ui/views/location_bar/autofill_credit_card_view.cc',
- 'browser/ui/views/location_bar/autofill_credit_card_view.h',
+ 'browser/ui/views/location_bar/generated_credit_card_view.cc',
+ 'browser/ui/views/location_bar/generated_credit_card_view.h',
'browser/ui/views/location_bar/content_setting_image_view.cc',
'browser/ui/views/location_bar/content_setting_image_view.h',
'browser/ui/views/location_bar/ev_bubble_view.cc',
@@ -1797,8 +1813,6 @@
'browser/ui/views/location_bar/location_bar_view.h',
'browser/ui/views/location_bar/location_icon_view.cc',
'browser/ui/views/location_bar/location_icon_view.h',
- 'browser/ui/views/location_bar/mic_search_view.cc',
- 'browser/ui/views/location_bar/mic_search_view.h',
'browser/ui/views/location_bar/open_pdf_in_reader_view.cc',
'browser/ui/views/location_bar/open_pdf_in_reader_view.h',
'browser/ui/views/location_bar/page_action_image_view.cc',
@@ -1813,8 +1827,6 @@
'browser/ui/views/location_bar/selected_keyword_view.h',
'browser/ui/views/location_bar/star_view.cc',
'browser/ui/views/location_bar/star_view.h',
- 'browser/ui/views/location_bar/touchable_location_bar_view.cc',
- 'browser/ui/views/location_bar/touchable_location_bar_view.h',
'browser/ui/views/location_bar/zoom_bubble_view.cc',
'browser/ui/views/location_bar/zoom_bubble_view.h',
'browser/ui/views/location_bar/zoom_view.cc',
@@ -2053,6 +2065,8 @@
'browser/ui/webui/chromeos/proxy_settings_ui.h',
'browser/ui/webui/chromeos/sim_unlock_ui.cc',
'browser/ui/webui/chromeos/sim_unlock_ui.h',
+ 'browser/ui/webui/chromeos/slow_ui.cc',
+ 'browser/ui/webui/chromeos/slow_ui.h',
'browser/ui/webui/chromeos/system_info_ui.cc',
'browser/ui/webui/chromeos/system_info_ui.h',
'browser/ui/webui/chromeos/ui_account_tweaks.cc',
@@ -2335,10 +2349,10 @@
'browser/ui/webui/signin/profile_signin_confirmation_dialog.cc',
'browser/ui/webui/signin/profile_signin_confirmation_ui.h',
'browser/ui/webui/signin/profile_signin_confirmation_ui.cc',
- 'browser/ui/webui/signin/user_chooser_screen_handler.h',
- 'browser/ui/webui/signin/user_chooser_screen_handler.cc',
- 'browser/ui/webui/signin/user_chooser_ui.h',
- 'browser/ui/webui/signin/user_chooser_ui.cc',
+ 'browser/ui/webui/signin/user_manager_screen_handler.h',
+ 'browser/ui/webui/signin/user_manager_screen_handler.cc',
+ 'browser/ui/webui/signin/user_manager_ui.h',
+ 'browser/ui/webui/signin/user_manager_ui.cc',
'browser/ui/webui/signin_internals_ui.cc',
'browser/ui/webui/signin_internals_ui.h',
'browser/ui/webui/suggestions_internals/suggestions_internals_ui.cc',
@@ -2593,6 +2607,10 @@
['exclude', 'browser/ui/views/screen_capture_notification_ui_views.cc'],
['exclude', 'browser/ui/webui/help/version_updater_basic.cc'],
['exclude', 'browser/ui/webui/help/version_updater_basic.h'],
+ ['exclude', 'browser/ui/webui/signin/user_manager_screen_handler.h'],
+ ['exclude', 'browser/ui/webui/signin/user_manager_screen_handler.cc'],
+ ['exclude', 'browser/ui/webui/signin/user_manager_ui.h'],
+ ['exclude', 'browser/ui/webui/signin/user_manager_ui.cc'],
['exclude', 'browser/upgrade_detector_impl.cc'],
['exclude', 'browser/upgrade_detector_impl.h'],
],
@@ -2782,8 +2800,6 @@
'chrome_browser_jni_headers',
],
'sources': [
- 'browser/ui/find_bar/find_match_rects_details.cc',
- 'browser/ui/find_bar/find_match_rects_details.h',
'browser/ui/webui/ntp/android/bookmarks_handler.cc',
'browser/ui/webui/ntp/android/bookmarks_handler.h',
'browser/ui/webui/ntp/android/context_menu_handler.cc',
@@ -2878,6 +2894,7 @@
'browser/ui/window_sizer/window_sizer.h',
],
'sources/': [
+ ['exclude', '^browser/ui/autofill/.*credit_card_bubble.*'],
['exclude', '^browser/ui/content_settings/'],
['exclude', '^browser/ui/omnibox/'],
['exclude', '^browser/ui/panels/'],
@@ -3081,6 +3098,15 @@
['include', '^browser/ui/app_list/app_list_service_disabled.cc'],
],
}],
+ ['enable_autofill_dialog!=1 or OS=="android"', {
+ 'sources!': [
+ 'browser/ui/autofill/autofill_dialog_controller_impl.cc',
+ 'browser/ui/autofill/autofill_dialog_controller_impl.h',
+ 'browser/ui/autofill/autofill_dialog_view.h',
+ 'browser/ui/autofill/autofill_dialog_view.cc',
+ 'browser/ui/autofill/autofill_dialog_view_delegate.h',
+ ],
+ }],
['enable_google_now==0', {
'sources!': [
'browser/ui/webui/options/geolocation_options_handler.cc',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index bf7f2ae..e5bdb52 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -70,6 +70,10 @@
'../extensions/common/extension_paths.h',
'../extensions/common/extension_resource.cc',
'../extensions/common/extension_resource.h',
+ '../extensions/common/extensions_client.cc',
+ '../extensions/common/extensions_client.h',
+ '../extensions/common/features/feature_provider.cc',
+ '../extensions/common/features/feature_provider.h',
'../extensions/common/id_util.cc',
'../extensions/common/id_util.h',
'../extensions/common/install_warning.cc',
@@ -90,6 +94,7 @@
'../extensions/common/matcher/url_matcher_helpers.h',
'../extensions/common/one_shot_event.cc',
'../extensions/common/one_shot_event.h',
+ '../extensions/common/permissions/permissions_provider.h',
'../extensions/common/switches.cc',
'../extensions/common/switches.h',
'../extensions/common/url_pattern.cc',
@@ -205,6 +210,8 @@
'common/extensions/api/system_indicator/system_indicator_handler.h',
'common/extensions/background_info.cc',
'common/extensions/background_info.h',
+ 'common/extensions/chrome_extensions_client.cc',
+ 'common/extensions/chrome_extensions_client.h',
'common/extensions/chrome_manifest_handlers.cc',
'common/extensions/chrome_manifest_handlers.h',
'common/extensions/command.cc',
@@ -242,7 +249,8 @@
'common/extensions/features/complex_feature.h',
'common/extensions/features/feature.cc',
'common/extensions/features/feature.h',
- 'common/extensions/features/feature_provider.h',
+ 'common/extensions/features/feature_channel.cc',
+ 'common/extensions/features/feature_channel.h',
'common/extensions/features/manifest_feature.cc',
'common/extensions/features/manifest_feature.h',
'common/extensions/features/permission_feature.cc',
diff --git a/chrome/chrome_dll.gypi b/chrome/chrome_dll.gypi
index 7c831d3..a64ad95 100644
--- a/chrome/chrome_dll.gypi
+++ b/chrome/chrome_dll.gypi
@@ -242,9 +242,12 @@
}, {
'dependencies': [
'<@(chromium_child_dependencies)',
- '../content/content.gyp:content_app_child',
+ '../content/content.gyp:content_app_both',
'../content/content.gyp:content_worker',
],
+ 'dependencies!': [
+ '../content/content.gyp:content_app_browser',
+ ],
}],
['OS=="mac" and component!="shared_library"', {
'includes': [ 'chrome_dll_bundle.gypi' ],
diff --git a/chrome/chrome_installer.gypi b/chrome/chrome_installer.gypi
index 8543946..f4c5f5d 100644
--- a/chrome/chrome_installer.gypi
+++ b/chrome/chrome_installer.gypi
@@ -279,6 +279,7 @@
'installer/setup/install_worker.cc',
'installer/setup/install_worker.h',
'installer/setup/setup_main.cc',
+ 'installer/setup/setup_main.h',
'installer/setup/setup.ico',
'installer/setup/setup.rc',
'installer/setup/setup_constants.cc',
diff --git a/chrome/chrome_nibs.gypi b/chrome/chrome_nibs.gypi
index f327c14..7c7aa33 100644
--- a/chrome/chrome_nibs.gypi
+++ b/chrome/chrome_nibs.gypi
@@ -18,6 +18,7 @@
'app/nibs/CollectedCookies.xib',
'app/nibs/ContentBlockedCookies.xib',
'app/nibs/ContentBlockedDownloads.xib',
+ 'app/nibs/ContentBlockedMIDISysEx.xib',
'app/nibs/ContentBlockedMedia.xib',
'app/nibs/ContentBlockedMixedScript.xib',
'app/nibs/ContentBlockedPlugins.xib',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index d7f0353..ed66398 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -31,7 +31,6 @@
'../webkit/support/webkit_support.gyp:glue_child',
'../webkit/renderer/webkit_renderer.gyp:webkit_renderer',
'../webkit/support/webkit_support.gyp:glue',
- '../webkit/support/webkit_support.gyp:plugins',
'../webkit/webkit_resources.gyp:webkit_resources',
],
'include_dirs': [
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 80199fe..8a257ce 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1337,6 +1337,8 @@
'browser/extensions/api/system_display/system_display_apitest.cc',
'browser/extensions/api/system_memory/system_memory_apitest.cc',
'browser/extensions/api/system_private/system_private_apitest.cc',
+ 'browser/extensions/api/system_storage/storage_api_test_util.cc',
+ 'browser/extensions/api/system_storage/storage_api_test_util.h',
'browser/extensions/api/system_storage/system_storage_apitest.cc',
'browser/extensions/api/system_storage/system_storage_eject_apitest.cc',
'browser/extensions/api/tab_capture/tab_capture_apitest.cc',
@@ -1444,12 +1446,13 @@
'browser/managed_mode/managed_user_service_browsertest.cc',
'browser/media/chrome_media_stream_infobar_browsertest.cc',
'browser/media/chrome_webrtc_browsertest.cc',
+ 'browser/media/chrome_webrtc_audio_quality_browsertest.cc',
'browser/media/chrome_webrtc_video_quality_browsertest.cc',
'browser/media/webrtc_browsertest_base.cc',
'browser/media/webrtc_browsertest_base.h',
'browser/media/webrtc_browsertest_common.cc',
'browser/media_galleries/fileapi/itunes_finder_win_browsertest.cc',
- 'browser/media_galleries/fileapi/media_file_validator_unittest.cc',
+ 'browser/media_galleries/fileapi/media_file_validator_browsertest.cc',
'browser/media_galleries/media_galleries_dialog_controller_mock.cc',
'browser/media_galleries/media_galleries_dialog_controller_mock.h',
'browser/metrics/metrics_service_browsertest.cc',
@@ -1482,6 +1485,7 @@
'browser/policy/test_utils.h',
'browser/prefs/pref_functional_browsertest.cc',
'browser/prefs/pref_service_browsertest.cc',
+ 'browser/prefs/synced_pref_change_registrar_browsertest.cc',
'browser/prerender/prefetch_browsertest.cc',
'browser/prerender/prerender_browsertest.cc',
'browser/printing/cloud_print/test/cloud_print_policy_browsertest.cc',
@@ -2069,7 +2073,7 @@
'dependencies': [
# Runtime dependency.
'../third_party/widevine/cdm/widevine_cdm.gyp:widevinecdmadapter',
- '../webkit/support/webkit_support.gyp:clearkeycdmadapter',
+ '../media/media.gyp:clearkeycdmadapter',
],
}],
], # conditions
@@ -3295,7 +3299,7 @@
'dependencies': [
'browser_tests',
'chrome',
- '../third_party/WebKit/Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp:copy_TestNetscapePlugIn',
+ '../third_party/WebKit/public/blink_test_plugin.gyp:blink_test_plugin',
],
'includes': [
'../build/isolate.gypi',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 79f7a73..c5c831c 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -11,7 +11,6 @@
'dependencies': [
# NOTE: New dependencies should generally be added in the OS!="ios"
# dependencies block below, rather than here.
- 'app/policy/cloud_policy_codegen.gyp:policy_test_support',
'browser',
'chrome_resources.gyp:chrome_resources',
'chrome_resources.gyp:chrome_strings',
@@ -33,7 +32,6 @@
'../ui/message_center/message_center.gyp:message_center_test_support',
],
'export_dependent_settings': [
- 'app/policy/cloud_policy_codegen.gyp:policy_test_support',
'../base/base.gyp:test_support_base',
],
'include_dirs': [
@@ -90,8 +88,6 @@
'browser/chromeos/login/mock_user_image_manager.h',
'browser/chromeos/login/mock_user_manager.cc',
'browser/chromeos/login/mock_user_manager.h',
- 'browser/chromeos/net/mock_connectivity_state_helper.cc',
- 'browser/chromeos/net/mock_connectivity_state_helper.h',
'browser/chromeos/policy/device_policy_builder.cc',
'browser/chromeos/policy/device_policy_builder.h',
'browser/chromeos/policy/stub_enterprise_install_attributes.cc',
@@ -113,8 +109,6 @@
'browser/drive/fake_drive_service.h',
'browser/extensions/api/messaging/native_messaging_test_util.cc',
'browser/extensions/api/messaging/native_messaging_test_util.h',
- 'browser/extensions/api/system_storage/test_storage_info_provider.cc',
- 'browser/extensions/api/system_storage/test_storage_info_provider.h',
'browser/extensions/extension_notification_observer.cc',
'browser/extensions/extension_notification_observer.h',
'browser/extensions/fake_safe_browsing_database_manager.cc',
@@ -195,8 +189,6 @@
'common/extensions/extension_builder.h',
'common/extensions/extension_test_util.cc',
'common/extensions/extension_test_util.h',
- 'common/extensions/permissions/scoped_testing_permissions_info.cc',
- 'common/extensions/permissions/scoped_testing_permissions_info.h',
'common/extensions/value_builder.cc',
'common/extensions/value_builder.h',
'renderer/chrome_mock_render_thread.cc',
@@ -342,6 +334,14 @@
['exclude', '^browser/policy'],
],
}],
+ ['configuration_policy==1', {
+ 'dependencies': [
+ 'app/policy/cloud_policy_codegen.gyp:policy_test_support',
+ ],
+ 'export_dependent_settings': [
+ 'app/policy/cloud_policy_codegen.gyp:policy_test_support',
+ ],
+ }],
['safe_browsing!=1', {
'sources/': [
['exclude', '^browser/extensions/blacklist_unittest.cc'],
@@ -618,6 +618,7 @@
'browser/chromeos/drive/file_system/create_directory_operation_unittest.cc',
'browser/chromeos/drive/file_system/create_file_operation_unittest.cc',
'browser/chromeos/drive/file_system/download_operation_unittest.cc',
+ 'browser/chromeos/drive/file_system/get_file_for_saving_operation_unittest.cc',
'browser/chromeos/drive/file_system/move_operation_unittest.cc',
'browser/chromeos/drive/file_system/open_file_operation_unittest.cc',
'browser/chromeos/drive/file_system/operation_test_base.cc',
@@ -646,6 +647,7 @@
'browser/chromeos/drive/webkit_file_stream_reader_impl_unittest.cc',
'browser/chromeos/extensions/default_app_order_unittest.cc',
'browser/chromeos/extensions/file_manager/desktop_notifications_unittest.cc',
+ 'browser/chromeos/extensions/file_manager/file_tasks_unittest.cc',
'browser/chromeos/extensions/file_manager/file_watcher_unittest.cc',
'browser/chromeos/extensions/wallpaper_private_api_unittest.cc',
'browser/chromeos/external_metrics_unittest.cc',
@@ -750,6 +752,7 @@
'browser/download/download_status_updater_unittest.cc',
'browser/download/download_target_determiner_unittest.cc',
'browser/download/download_ui_controller_unittest.cc',
+ 'browser/download/download_util_unittest.cc',
'browser/drive/drive_api_util_unittest.cc',
'browser/drive/drive_uploader_unittest.cc',
'browser/drive/event_logger_unittest.cc',
@@ -758,8 +761,10 @@
'browser/extensions/active_tab_unittest.cc',
'browser/extensions/activity_log/activity_database_unittest.cc',
'browser/extensions/activity_log/activity_log_unittest.cc',
+ 'browser/extensions/activity_log/activity_log_policy_unittest.cc',
+ 'browser/extensions/activity_log/counting_policy_unittest.cc',
+ 'browser/extensions/activity_log/database_string_table_unittest.cc',
'browser/extensions/activity_log/fullstream_ui_policy_unittest.cc',
- 'browser/extensions/activity_log/stream_noargs_ui_policy_unittest.cc',
'browser/extensions/admin_policy_unittest.cc',
'browser/extensions/api/activity_log_private/activity_log_private_api_unittest.cc',
'browser/extensions/api/alarms/alarms_api_unittest.cc',
@@ -817,7 +822,6 @@
'browser/extensions/api/storage/settings_test_util.h',
'browser/extensions/api/streams_private/streams_private_manifest_unittest.cc',
'browser/extensions/api/system_display/display_info_provider_chromeos_unittest.cc',
- 'browser/extensions/api/system_storage/storage_info_provider_unittest.cc',
'browser/extensions/api/web_navigation/frame_navigation_state_unittest.cc',
'browser/extensions/api/web_request/form_data_parser_unittest.cc',
'browser/extensions/api/web_request/upload_data_presenter_unittest.cc',
@@ -1346,16 +1350,18 @@
'browser/ui/ash/window_positioner_unittest.cc',
'browser/ui/autofill/account_chooser_model_unittest.cc',
'browser/ui/autofill/autocheckout_bubble_controller_unittest.cc',
- 'browser/ui/autofill/autofill_credit_card_bubble_controller_unittest.cc',
'browser/ui/autofill/autofill_dialog_controller_unittest.cc',
'browser/ui/autofill/autofill_dialog_models_unittest.cc',
'browser/ui/autofill/autofill_dialog_types_unittest.cc',
'browser/ui/autofill/autofill_popup_controller_unittest.cc',
'browser/ui/autofill/data_model_wrapper_unittest.cc',
+ 'browser/ui/autofill/generated_credit_card_bubble_controller_unittest.cc',
'browser/ui/autofill/mock_autofill_dialog_view_delegate.cc',
'browser/ui/autofill/mock_autofill_dialog_view_delegate.h',
- 'browser/ui/autofill/test_autofill_credit_card_bubble.cc',
- 'browser/ui/autofill/test_autofill_credit_card_bubble.h',
+ 'browser/ui/autofill/mock_new_credit_card_bubble_controller.cc',
+ 'browser/ui/autofill/mock_new_credit_card_bubble_controller.h',
+ 'browser/ui/autofill/test_generated_credit_card_bubble_view.cc',
+ 'browser/ui/autofill/test_generated_credit_card_bubble_view.h',
'browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc',
'browser/ui/bookmarks/bookmark_bubble_sign_in_delegate_unittest.cc',
'browser/ui/bookmarks/bookmark_editor_unittest.cc',
@@ -1420,6 +1426,7 @@
'browser/ui/cocoa/bookmarks/bookmark_sync_promo_controller_unittest.mm',
'browser/ui/cocoa/bookmarks/bookmark_tree_browser_cell_unittest.mm',
'browser/ui/cocoa/browser/avatar_button_controller_unittest.mm',
+ 'browser/ui/cocoa/browser/avatar_label_button_unittest.mm',
'browser/ui/cocoa/browser/avatar_menu_bubble_controller_unittest.mm',
'browser/ui/cocoa/browser/edit_search_engine_cocoa_controller_unittest.mm',
'browser/ui/cocoa/browser/password_generation_bubble_controller_unittest.mm',
@@ -1493,6 +1500,7 @@
'browser/ui/cocoa/location_bar/keyword_hint_decoration_unittest.mm',
'browser/ui/cocoa/location_bar/selected_keyword_decoration_unittest.mm',
'browser/ui/cocoa/menu_button_unittest.mm',
+ 'browser/ui/cocoa/nine_part_button_cell_unittest.mm',
'browser/ui/cocoa/notifications/balloon_controller_unittest.mm',
'browser/ui/cocoa/notifications/message_center_tray_bridge_unittest.mm',
'browser/ui/cocoa/nsmenuitem_additions_unittest.mm',
@@ -2147,6 +2155,18 @@
['exclude', '^renderer/safe_browsing/'],
],
}],
+ ['enable_autofill_dialog!=1 or OS=="android"', {
+ 'sources!': [
+ 'browser/ui/autofill/account_chooser_model_unittest.cc',
+ 'browser/ui/autofill/autocheckout_bubble_controller_unittest.cc',
+ 'browser/ui/autofill/autofill_credit_card_bubble_controller_unittest.cc',
+ 'browser/ui/autofill/autofill_dialog_controller_unittest.cc',
+ 'browser/ui/autofill/mock_autofill_dialog_view_delegate.cc',
+ 'browser/ui/autofill/mock_autofill_dialog_view_delegate.h',
+ 'browser/ui/autofill/test_autofill_credit_card_bubble.cc',
+ 'browser/ui/autofill/test_autofill_credit_card_bubble.h',
+ ],
+ }],
['enable_automation!=1', {
'sources/': [
['exclude', '^browser/automation/'],
@@ -2457,6 +2477,7 @@
'browser/sync/profile_sync_service_session_unittest.cc',
'browser/sync/sync_global_error_unittest.cc',
'browser/tab_contents/render_view_context_menu_unittest.cc',
+ 'browser/ui/autofill/autofill_dialog_controller_unittest.cc',
'browser/ui/bookmarks/bookmark_bubble_sign_in_delegate_unittest.cc',
'browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc',
'browser/ui/bookmarks/bookmark_prompt_controller_unittest.cc',
@@ -2521,6 +2542,7 @@
['exclude', '^browser/sync/glue/app_'],
['exclude', '^browser/sync/glue/extension_'],
['exclude', '^browser/themes/'],
+ ['exclude', '^browser/ui/autofill/.*credit_card_bubble.*'],
['exclude', '^browser/ui/content_settings/'],
['exclude', '^browser/ui/omnibox/'],
['exclude', '^browser/ui/panels'],
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc
index 874a039..40621f8 100644
--- a/chrome/common/chrome_constants.cc
+++ b/chrome/common/chrome_constants.cc
@@ -253,6 +253,12 @@
const char kProfileDirPrefix[] = "u-";
#endif
+// This GUID is associated with any 'don't ask me again' settings that the
+// user can select for different file types.
+// {2676A9A2-D919-4FEE-9187-152100393AB2}
+const char kApplicationClientIDStringForAVScanning[] =
+ "2676A9A2-D919-4FEE-9187-152100393AB2";
+
} // namespace chrome
#undef FPL
diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h
index 6775c80..cd97f7c 100644
--- a/chrome/common/chrome_constants.h
+++ b/chrome/common/chrome_constants.h
@@ -139,6 +139,9 @@
extern const char kProfileDirPrefix[];
#endif
+// Used to identify the application to the system AV function in Windows.
+extern const char kApplicationClientIDStringForAVScanning[];
+
} // namespace chrome
#endif // CHROME_COMMON_CHROME_CONSTANTS_H_
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc
index 79ef06c..77a54fa 100644
--- a/chrome/common/chrome_content_client.cc
+++ b/chrome/common/chrome_content_client.cc
@@ -22,6 +22,7 @@
#include "chrome/common/render_messages.h"
#include "chrome/common/url_constants.h"
#include "components/nacl/common/nacl_process_type.h"
+#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/pepper_plugin_info.h"
#include "content/public/common/url_constants.h"
@@ -33,8 +34,6 @@
#include "ui/base/layout.h"
#include "ui/base/resource/resource_bundle.h"
#include "webkit/common/user_agent/user_agent_util.h"
-#include "webkit/plugins/plugin_constants.h"
-#include "webkit/plugins/plugin_switches.h"
#include "flapper_version.h" // In SHARED_INTERMEDIATE_DIR.
#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
@@ -300,7 +299,7 @@
// for testing purposes.
plugin.is_out_of_process = !CommandLine::ForCurrentProcess()->HasSwitch(
switches::kPpapiFlashInProcess);
- plugin.name = kFlashPluginName;
+ plugin.name = content::kFlashPluginName;
plugin.path = path;
plugin.permissions = kPepperFlashPermissions;
@@ -321,13 +320,13 @@
plugin.description = plugin.name + " " + flash_version_numbers[0] + "." +
flash_version_numbers[1] + " r" + flash_version_numbers[2];
plugin.version = JoinString(flash_version_numbers, '.');
- content::WebPluginMimeType swf_mime_type(kFlashPluginSwfMimeType,
- kFlashPluginSwfExtension,
- kFlashPluginSwfDescription);
+ content::WebPluginMimeType swf_mime_type(content::kFlashPluginSwfMimeType,
+ content::kFlashPluginSwfExtension,
+ content::kFlashPluginSwfDescription);
plugin.mime_types.push_back(swf_mime_type);
- content::WebPluginMimeType spl_mime_type(kFlashPluginSplMimeType,
- kFlashPluginSplExtension,
- kFlashPluginSplDescription);
+ content::WebPluginMimeType spl_mime_type(content::kFlashPluginSplMimeType,
+ content::kFlashPluginSplExtension,
+ content::kFlashPluginSplDescription);
plugin.mime_types.push_back(spl_mime_type);
return plugin;
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 8119470..c802fd1 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -145,6 +145,10 @@
const char kAutomationReinitializeOnChannelError[] =
"automation-reinitialize-on-channel-error";
+// Similar to kNoFirstRun, but also drops the First Run beacon so that first run
+// will not occur in subsequent runs either.
+const char kCancelFirstRun[] = "cancel-first-run";
+
// How often (in seconds) to check for updates. Should only be used for testing
// purposes.
const char kCheckForUpdateIntervalSec[] = "check-for-update-interval";
@@ -809,7 +813,8 @@
const char kForceAppMode[] = "force-app-mode";
// Displays the First Run experience when the browser is started, regardless of
-// whether or not it's actually the First Run (this overrides kNoFirstRun).
+// whether or not it's actually the First Run (this overrides kNoFirstRun and
+// kCancelFirstRun).
const char kForceFirstRun[] = "force-first-run";
// Tries to load cloud policy for every signed in user, regardless of whether
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 3272ce5..17d203c 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -56,6 +56,7 @@
extern const char kAutoLaunchAtStartup[];
extern const char kAutomationClientChannelID[];
extern const char kAutomationReinitializeOnChannelError[];
+extern const char kCancelFirstRun[];
extern const char kCheckForUpdateIntervalSec[];
extern const char kCheckCloudPrintConnectorPolicy[];
extern const char kChromeFrame[];
diff --git a/chrome/common/chrome_utility_messages.h b/chrome/common/chrome_utility_messages.h
index 3534f60..d14def5 100644
--- a/chrome/common/chrome_utility_messages.h
+++ b/chrome/common/chrome_utility_messages.h
@@ -189,6 +189,16 @@
std::vector<picasa::FolderINIContents> /* folders_inis */)
#endif // defined(OS_WIN) || defined(OS_MACOSX)
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+// Tell the utility process to attempt to validate the passed media file. The
+// file will undergo basic sanity checks and will be decoded for up to
+// |milliseconds_of_decoding| wall clock time. It is still not safe to decode
+// the file in the browser process after this check.
+IPC_MESSAGE_CONTROL2(ChromeUtilityMsg_CheckMediaFile,
+ int64 /* milliseconds_of_decoding */,
+ IPC::PlatformFileForTransit /* Media file to parse */)
+#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
+
//------------------------------------------------------------------------------
// Utility process host messages:
// These are messages from the utility process to the browser.
@@ -312,3 +322,10 @@
IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_IndexPicasaAlbumsContents_Finished,
picasa::AlbumImagesMap /* albums_images */)
#endif // defined(OS_WIN) || defined(OS_MACOSX)
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+// Reply after checking the passed media file. A true result indicates that
+// the file appears to be a well formed media file.
+IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_CheckMediaFile_Finished,
+ bool /* passed_checks */)
+#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json
index d9075d7..3f1a46f 100644
--- a/chrome/common/extensions/api/_api_features.json
+++ b/chrome/common/extensions/api/_api_features.json
@@ -498,21 +498,6 @@
"dependencies": ["permission:system.storage"],
"contexts": ["blessed_extension"]
},
- "system.storage.addAvailableCapacityWatch": {
- "channel": "dev"
- },
- "system.storage.removeAvailableCapacityWatch": {
- "channel": "dev"
- },
- "system.storage.getAllAvailableCapacityWatches": {
- "channel": "dev"
- },
- "system.storage.removeAllAvailableCapacityWatches": {
- "channel": "dev"
- },
- "system.storage.onAvailableCapacityChanged": {
- "channel": "dev"
- },
"systemPrivate": {
"dependencies": ["permission:systemPrivate"],
"contexts": ["blessed_extension"]
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index 1c761cc..fbaf434 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -188,15 +188,15 @@
}
],
"downloads": {
- "channel": "beta",
+ "channel": "stable",
"extension_types": ["extension"]
},
"downloads.open": {
- "channel": "beta",
+ "channel": "stable",
"extension_types": ["extension"]
},
"downloads.shelf": {
- "channel": "beta",
+ "channel": "stable",
"extension_types": ["extension"]
},
"dial": {
diff --git a/chrome/common/extensions/api/experimental_input_virtual_keyboard.json b/chrome/common/extensions/api/experimental_input_virtual_keyboard.json
index 4bd2c81..eb44bef 100644
--- a/chrome/common/extensions/api/experimental_input_virtual_keyboard.json
+++ b/chrome/common/extensions/api/experimental_input_virtual_keyboard.json
@@ -23,6 +23,27 @@
"parameters": []
}
]
+ },
+ {
+ "name": "moveCursor",
+ "type": "function",
+ "description": "Move cursor on the current focused textfield by swipe.",
+ "parameters": [
+ { "name": "swipe_direction",
+ "type": "integer",
+ "discription": "The direction of the cursor movement."
+ },
+ { "name": "modifier_flags",
+ "type": "integer",
+ "description": "Bitmask representing the state of the system modifier keys."
+ },
+ { "type": "function",
+ "name": "callback",
+ "optional": true,
+ "decription": "called when the swipe movement is completed.",
+ "parameters": []
+ }
+ ]
}
]
}
diff --git a/chrome/common/extensions/api/extension_api.cc b/chrome/common/extensions/api/extension_api.cc
index 56c44b5..0805b7e 100644
--- a/chrome/common/extensions/api/extension_api.cc
+++ b/chrome/common/extensions/api/extension_api.cc
@@ -18,10 +18,10 @@
#include "base/values.h"
#include "chrome/common/extensions/api/generated_schemas.h"
#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/features/base_feature_provider.h"
-#include "chrome/common/extensions/features/simple_feature.h"
+#include "chrome/common/extensions/features/feature.h"
#include "chrome/common/extensions/permissions/permission_set.h"
#include "chrome/common/extensions/permissions/permissions_data.h"
+#include "extensions/common/features/feature_provider.h"
#include "grit/common_resources.h"
#include "grit/extensions_api_resources.h"
#include "ui/base/resource/resource_bundle.h"
@@ -225,11 +225,11 @@
void ExtensionAPI::InitDefaultConfiguration() {
RegisterDependencyProvider(
- "api", BaseFeatureProvider::GetByName("api"));
+ "api", FeatureProvider::GetByName("api"));
RegisterDependencyProvider(
- "manifest", BaseFeatureProvider::GetByName("manifest"));
+ "manifest", FeatureProvider::GetByName("manifest"));
RegisterDependencyProvider(
- "permission", BaseFeatureProvider::GetByName("permission"));
+ "permission", FeatureProvider::GetByName("permission"));
// Schemas to be loaded from resources.
CHECK(unloaded_schemas_.empty());
diff --git a/chrome/common/extensions/api/extension_api.h b/chrome/common/extensions/api/extension_api.h
index 2d5845b..e250419 100644
--- a/chrome/common/extensions/api/extension_api.h
+++ b/chrome/common/extensions/api/extension_api.h
@@ -16,7 +16,7 @@
#include "base/strings/string_piece.h"
#include "base/values.h"
#include "chrome/common/extensions/features/feature.h"
-#include "chrome/common/extensions/features/feature_provider.h"
+#include "extensions/common/features/feature_provider.h"
#include "extensions/common/url_pattern_set.h"
namespace base {
diff --git a/chrome/common/extensions/api/metrics_private.json b/chrome/common/extensions/api/metrics_private.json
index 627687c..06e5274 100644
--- a/chrome/common/extensions/api/metrics_private.json
+++ b/chrome/common/extensions/api/metrics_private.json
@@ -57,6 +57,26 @@
]
},
{
+ "name": "getVariationParams",
+ "description": "Returns variation parameters for the named trial if available, or undefined otherwise.",
+ "type": "function",
+ "parameters": [
+ {"name": "name", "type": "string"},
+ {
+ "name": "callback",
+ "type": "function",
+ "optional": "false",
+ "parameters": [
+ {
+ "name": "params",
+ "type": "object",
+ "additionalProperties": { "type": "string" }
+ }
+ ]
+ }
+ ]
+ },
+ {
"name": "recordUserAction",
"type": "function",
"description": "Records an action performed by the user.",
diff --git a/chrome/common/extensions/api/notifications.idl b/chrome/common/extensions/api/notifications.idl
index 5808bc4..2330c4d 100644
--- a/chrome/common/extensions/api/notifications.idl
+++ b/chrome/common/extensions/api/notifications.idl
@@ -61,7 +61,7 @@
// epoch (e.g. <code>Date.now() + n</code>).
double? eventTime;
- // Text and icons of notification action buttons.
+ // Text and icons for up to two notification action buttons.
NotificationButton[]? buttons;
// Secondary notification content.
diff --git a/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc b/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc
index 4a6b4d8..088a2d5 100644
--- a/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc
+++ b/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc
@@ -14,7 +14,7 @@
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_file_util.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/common/extensions/manifest.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -67,7 +67,7 @@
}
base::ScopedTempDir temp_dir_;
- Feature::ScopedCurrentChannel scoped_channel_;
+ ScopedCurrentChannel scoped_channel_;
base::DictionaryValue manifest_;
};
diff --git a/chrome/common/extensions/api/sync_file_system.idl b/chrome/common/extensions/api/sync_file_system.idl
index 72e2479..5eceabc 100644
--- a/chrome/common/extensions/api/sync_file_system.idl
+++ b/chrome/common/extensions/api/sync_file_system.idl
@@ -170,7 +170,7 @@
// Returns each $ref:FileStatus for the given <code>fileEntry</code> array.
// Typically called with the result from dirReader.readEntries().
- static void getFileStatuses([instanceOf=EntryArray] object fileEntries,
+ static void getFileStatuses(object[] fileEntries,
GetFileStatusesCallback callback);
};
diff --git a/chrome/common/extensions/api/system_storage.idl b/chrome/common/extensions/api/system_storage.idl
index 4ec51f6..33338d4 100644
--- a/chrome/common/extensions/api/system_storage.idl
+++ b/chrome/common/extensions/api/system_storage.idl
@@ -4,7 +4,7 @@
// Use the <code>chrome.system.storage</code> API to query storage device
// information and be notified when a removable storage device is attached and
-// detached or the available capacity changes.
+// detached.
namespace system.storage {
enum StorageUnitType {
@@ -30,20 +30,6 @@
double capacity;
};
- dictionary StorageFreeSpaceChangeInfo {
- // The transient id of the storage unit already changed.
- DOMString id;
- // The new value of the available capacity.
- double availableCapacity;
- };
-
- // A dictionary that describes the add particular storage device watch
- // request results.
- dictionary AddAvailableCapacityWatchResult {
- DOMString id;
- boolean success;
- };
-
[inline_doc] enum EjectDeviceResultCode {
// The ejection command is successful -- the application can prompt the user
// to remove the device.
@@ -58,12 +44,6 @@
failure
};
- callback AddAvailableCapacityWatchCallback = void (
- AddAvailableCapacityWatchResult info);
-
- callback GetAllAvailableCapacityWatchesCallback = void (
- DOMString[] storageIds);
-
callback EjectDeviceCallback = void (EjectDeviceResultCode result);
callback StorageInfoCallback = void (StorageUnitInfo[] info);
@@ -75,21 +55,6 @@
// Ejects a removable storage device.
static void ejectDevice(DOMString id, EjectDeviceCallback callback);
-
- // Monitor a particular storage device available change capacity.
- static void addAvailableCapacityWatch(
- DOMString id,
- AddAvailableCapacityWatchCallback callback);
-
- // Remove the monitor of a particular device.
- static void removeAvailableCapacityWatch(DOMString id);
-
- // Get all the watched storage devices.
- static void getAllAvailableCapacityWatches(
- GetAllAvailableCapacityWatchesCallback callback);
-
- // Remove all the storage devices monitors.
- static void removeAllAvailableCapacityWatches();
};
interface Events {
@@ -98,10 +63,6 @@
// Fired when a removable storage is detached from the system.
static void onDetached(DOMString id);
-
- // Fired when the storage device available capacity is changed.
- // |info|: The changed information for the specified storage unit.
- static void onAvailableCapacityChanged(StorageFreeSpaceChangeInfo info);
};
};
diff --git a/chrome/common/extensions/api/test.json b/chrome/common/extensions/api/test.json
index a06052d..94742b5 100644
--- a/chrome/common/extensions/api/test.json
+++ b/chrome/common/extensions/api/test.json
@@ -218,6 +218,22 @@
]
},
{
+ "name": "assertThrows",
+ "type": "function",
+ "nocompile": true,
+ "parameters": [
+ {"type": "function", "name": "fn"},
+ {
+ "type": "object",
+ "name": "self",
+ "additionalProperties": {"type": "any"},
+ "optional": true
+ },
+ {"type": "array", "items": {"type": "any"}, "name": "args"},
+ {"type": "string", "name": "message", "optional": true}
+ ]
+ },
+ {
"name": "callback",
"type": "function",
"nocompile": true,
diff --git a/chrome/common/extensions/chrome_extensions_client.cc b/chrome/common/extensions/chrome_extensions_client.cc
new file mode 100644
index 0000000..3fa2135
--- /dev/null
+++ b/chrome/common/extensions/chrome_extensions_client.cc
@@ -0,0 +1,41 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/extensions/chrome_extensions_client.h"
+
+#include "chrome/common/extensions/chrome_manifest_handlers.h"
+#include "chrome/common/extensions/features/base_feature_provider.h"
+
+namespace extensions {
+
+static base::LazyInstance<ChromeExtensionsClient> g_client =
+ LAZY_INSTANCE_INITIALIZER;
+
+ChromeExtensionsClient::ChromeExtensionsClient()
+ : chrome_api_permissions_(ChromeAPIPermissions()) {
+}
+
+ChromeExtensionsClient::~ChromeExtensionsClient() {
+}
+
+const PermissionsProvider&
+ChromeExtensionsClient::GetPermissionsProvider() const {
+ return chrome_api_permissions_;
+}
+
+FeatureProvider* ChromeExtensionsClient::GetFeatureProviderByName(
+ const std::string& name) const {
+ return BaseFeatureProvider::GetByName(name);
+}
+
+void ChromeExtensionsClient::RegisterManifestHandlers() const {
+ RegisterChromeManifestHandlers();
+}
+
+// static
+ChromeExtensionsClient* ChromeExtensionsClient::GetInstance() {
+ return g_client.Pointer();
+}
+
+} // namespace extensions
diff --git a/chrome/common/extensions/chrome_extensions_client.h b/chrome/common/extensions/chrome_extensions_client.h
new file mode 100644
index 0000000..a74a890
--- /dev/null
+++ b/chrome/common/extensions/chrome_extensions_client.h
@@ -0,0 +1,42 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_EXTENSIONS_CHROME_EXTENSIONS_CLIENT_H_
+#define CHROME_COMMON_EXTENSIONS_CHROME_EXTENSIONS_CLIENT_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/lazy_instance.h"
+#include "chrome/common/extensions/permissions/chrome_api_permissions.h"
+#include "extensions/common/extensions_client.h"
+#include "extensions/common/permissions/permissions_provider.h"
+
+namespace extensions {
+
+// The implementation of ExtensionsClient for Chrome, which encapsulates the
+// global knowledge of features, permissions, and manifest fields.
+class ChromeExtensionsClient : public ExtensionsClient {
+ public:
+ ChromeExtensionsClient();
+ virtual ~ChromeExtensionsClient();
+
+ virtual const PermissionsProvider& GetPermissionsProvider() const OVERRIDE;
+ virtual void RegisterManifestHandlers() const OVERRIDE;
+ virtual FeatureProvider* GetFeatureProviderByName(const std::string& name)
+ const OVERRIDE;
+
+ // Get the LazyInstance for ChromeExtensionsClient.
+ static ChromeExtensionsClient* GetInstance();
+
+ private:
+ const ChromeAPIPermissions chrome_api_permissions_;
+
+ friend struct base::DefaultLazyInstanceTraits<ChromeExtensionsClient>;
+
+ DISALLOW_COPY_AND_ASSIGN(ChromeExtensionsClient);
+};
+
+} // namespace extensions
+
+#endif // CHROME_COMMON_EXTENSIONS_CHROME_EXTENSIONS_CLIENT_H_
diff --git a/chrome/common/extensions/docs/OWNERS b/chrome/common/extensions/docs/OWNERS
index 6ce4d20..df34150 100644
--- a/chrome/common/extensions/docs/OWNERS
+++ b/chrome/common/extensions/docs/OWNERS
@@ -2,6 +2,7 @@
awatson@chromium.org
mkearney@chromium.org
mkwst@chromium.org
+scheib@chromium.org
# For server related things (Python, JavaScript, templates, etc).
kalman@chromium.org
diff --git a/chrome/common/extensions/docs/templates/articles/cloudMessaging.html b/chrome/common/extensions/docs/templates/articles/cloudMessaging.html
index ebb8402..d046041 100644
--- a/chrome/common/extensions/docs/templates/articles/cloudMessaging.html
+++ b/chrome/common/extensions/docs/templates/articles/cloudMessaging.html
@@ -12,14 +12,14 @@
even when their calendaring app isn't open.
</p>
-<p>This document describes how the service works and
-provides very basic examples on how to use the service.
-To learn more about GCM,
-read the API reference for the <a href="pushMessaging.html">pushMessaging Chrome API</a> and the
+<p>This document describes how to set up and use GCM.
+For additional information see the reference documentation
+for the <a href="pushMessaging.html">pushMessaging Chrome API</a> and the
<a href="gcm_server.html">GCM service</a>.
+To get help with GCM or to give us feedback, see <a href="#feedback">Feedback</a>.
</p>
-<h2 id="one">How it works</h2>
+<h2 id="one">How push messaging works</h2>
<p>
At a glance, push messaging works like this:
@@ -543,3 +543,10 @@
you need to remove the key because the Store does not currently allow manifests
with keys.
</p>
+
+<h2 id="feedback">Feedback</h2>
+
+<p>You can provide feedback about Google Cloud Messaging
+and the pushMessaging API through the Google Group
+<a target="_blank" href="https://groups.google.com/forum/#!forum/gcm-for-chrome-feedback">GCM for Chrome feedback</a>.
+Use this group to ask for help, file bug reports, and request features.</p>
diff --git a/chrome/common/extensions/docs/templates/articles/manifest/file_handlers.html b/chrome/common/extensions/docs/templates/articles/manifest/file_handlers.html
index e2ee9dc..fff645a 100644
--- a/chrome/common/extensions/docs/templates/articles/manifest/file_handlers.html
+++ b/chrome/common/extensions/docs/templates/articles/manifest/file_handlers.html
@@ -38,5 +38,5 @@
permission. Apps can then be passed files in the $ref:app.runtime.onLaunched
event - either from the system
file manager (currently supported on ChromeOS only) or by providing
-a path on the <a href="../apps/first_app.html#open">command line</a>.
+a path on the <a href="../first_app.html#open">command line</a>.
</p>
diff --git a/chrome/common/extensions/docs/templates/json/api_availabilities.json b/chrome/common/extensions/docs/templates/json/api_availabilities.json
index 3b6fc6b..9dbc4d6 100644
--- a/chrome/common/extensions/docs/templates/json/api_availabilities.json
+++ b/chrome/common/extensions/docs/templates/json/api_availabilities.json
@@ -19,6 +19,10 @@
"channel": "stable",
"version": 21
},
+ "notifications": {
+ "channel": "stable",
+ "version": 28
+ },
"storage": {
"channel": "stable",
"version": 20
diff --git a/chrome/common/extensions/features/base_feature_provider.h b/chrome/common/extensions/features/base_feature_provider.h
index c014852..8f7d325 100644
--- a/chrome/common/extensions/features/base_feature_provider.h
+++ b/chrome/common/extensions/features/base_feature_provider.h
@@ -11,8 +11,8 @@
#include "base/memory/linked_ptr.h"
#include "base/values.h"
-#include "chrome/common/extensions/features/feature_provider.h"
#include "chrome/common/extensions/features/simple_feature.h"
+#include "extensions/common/features/feature_provider.h"
namespace extensions {
@@ -30,10 +30,6 @@
// Gets a feature provider for a specific feature type, like "permission".
static FeatureProvider* GetByName(const std::string& name);
- static FeatureProvider* GetPermissionFeatures() {
- return GetByName("permission");
- }
-
// Gets the feature |feature_name|, if it exists.
virtual Feature* GetFeature(const std::string& feature_name) OVERRIDE;
virtual Feature* GetParent(Feature* feature) OVERRIDE;
diff --git a/chrome/common/extensions/features/base_feature_provider_unittest.cc b/chrome/common/extensions/features/base_feature_provider_unittest.cc
index d9f1b28..30f6abb 100644
--- a/chrome/common/extensions/features/base_feature_provider_unittest.cc
+++ b/chrome/common/extensions/features/base_feature_provider_unittest.cc
@@ -4,6 +4,7 @@
#include "chrome/common/extensions/features/base_feature_provider.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/common/extensions/features/permission_feature.h"
#include "chrome/common/extensions/value_builder.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -164,7 +165,7 @@
// Make sure both rules are applied correctly.
{
- Feature::ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_BETA);
+ ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_BETA);
EXPECT_EQ(Feature::IS_AVAILABLE, feature->IsAvailableToManifest(
"1",
Manifest::TYPE_EXTENSION,
@@ -177,7 +178,7 @@
Feature::UNSPECIFIED_PLATFORM).result());
}
{
- Feature::ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_STABLE);
+ ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_STABLE);
EXPECT_NE(Feature::IS_AVAILABLE, feature->IsAvailableToManifest(
"1",
Manifest::TYPE_EXTENSION,
diff --git a/chrome/common/extensions/features/complex_feature.cc b/chrome/common/extensions/features/complex_feature.cc
index 09eb426..57c9ad4 100644
--- a/chrome/common/extensions/features/complex_feature.cc
+++ b/chrome/common/extensions/features/complex_feature.cc
@@ -4,8 +4,6 @@
#include "chrome/common/extensions/features/complex_feature.h"
-#include "chrome/common/extensions/features/simple_feature.h"
-
namespace extensions {
ComplexFeature::ComplexFeature(scoped_ptr<FeatureList> features) {
diff --git a/chrome/common/extensions/features/complex_feature.h b/chrome/common/extensions/features/complex_feature.h
index b5b5e0c..8653d3d 100644
--- a/chrome/common/extensions/features/complex_feature.h
+++ b/chrome/common/extensions/features/complex_feature.h
@@ -14,8 +14,6 @@
namespace extensions {
-class SimpleFeature;
-
// A ComplexFeature is composed of one or many Features. A ComplexFeature
// is available if any Feature (i.e. permission rule) that composes it is
// available, but not if only some combination of Features is available.
diff --git a/chrome/common/extensions/features/complex_feature_unittest.cc b/chrome/common/extensions/features/complex_feature_unittest.cc
index be8fd34..6e7ed65 100644
--- a/chrome/common/extensions/features/complex_feature_unittest.cc
+++ b/chrome/common/extensions/features/complex_feature_unittest.cc
@@ -4,6 +4,7 @@
#include "chrome/common/extensions/features/complex_feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/common/extensions/features/simple_feature.h"
#include "chrome/common/extensions/value_builder.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -14,6 +15,7 @@
using extensions::Feature;
using extensions::ListBuilder;
using extensions::Manifest;
+using extensions::ScopedCurrentChannel;
using extensions::SimpleFeature;
namespace {
@@ -25,7 +27,7 @@
virtual ~ExtensionComplexFeatureTest() {}
private:
- Feature::ScopedCurrentChannel current_channel_;
+ ScopedCurrentChannel current_channel_;
};
TEST_F(ExtensionComplexFeatureTest, MultipleRulesWhitelist) {
@@ -108,7 +110,7 @@
// Test match 1st rule.
{
- Feature::ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_UNKNOWN);
+ ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_UNKNOWN);
EXPECT_EQ(Feature::IS_AVAILABLE, feature->IsAvailableToManifest(
"1",
Manifest::TYPE_EXTENSION,
@@ -119,7 +121,7 @@
// Test match 2nd rule.
{
- Feature::ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_BETA);
+ ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_BETA);
EXPECT_EQ(Feature::IS_AVAILABLE, feature->IsAvailableToManifest(
"2",
Manifest::TYPE_LEGACY_PACKAGED_APP,
@@ -130,7 +132,7 @@
// Test feature not available to extensions above channel unknown.
{
- Feature::ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_BETA);
+ ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_BETA);
EXPECT_NE(Feature::IS_AVAILABLE, feature->IsAvailableToManifest(
"1",
Manifest::TYPE_EXTENSION,
diff --git a/chrome/common/extensions/features/feature.cc b/chrome/common/extensions/features/feature.cc
index 40ea052..d1ae538 100644
--- a/chrome/common/extensions/features/feature.cc
+++ b/chrome/common/extensions/features/feature.cc
@@ -10,16 +10,6 @@
#include "base/lazy_instance.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "chrome/common/chrome_switches.h"
-
-using chrome::VersionInfo;
-
-namespace {
-
-const VersionInfo::Channel kDefaultChannel = VersionInfo::CHANNEL_STABLE;
-VersionInfo::Channel g_current_channel = kDefaultChannel;
-
-} // namespace
namespace extensions {
@@ -41,21 +31,6 @@
}
// static
-chrome::VersionInfo::Channel Feature::GetCurrentChannel() {
- return g_current_channel;
-}
-
-// static
-void Feature::SetCurrentChannel(VersionInfo::Channel channel) {
- g_current_channel = channel;
-}
-
-// static
-chrome::VersionInfo::Channel Feature::GetDefaultChannel() {
- return kDefaultChannel;
-}
-
-// static
Feature::Availability Feature::CreateAvailability(AvailabilityResult result,
const std::string& message) {
return Availability(result, message);
diff --git a/chrome/common/extensions/features/feature.h b/chrome/common/extensions/features/feature.h
index b43dd06..618da57 100644
--- a/chrome/common/extensions/features/feature.h
+++ b/chrome/common/extensions/features/feature.h
@@ -9,14 +9,14 @@
#include <string>
#include "base/values.h"
-#include "chrome/common/chrome_version_info.h"
-#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/manifest.h"
class GURL;
namespace extensions {
+class Extension;
+
// Represents a single feature accessible to an extension developer, such as a
// top-level manifest key, a permission, or a programmatic API. A feature can
// express requirements for where it can be accessed, and supports testing
@@ -95,34 +95,6 @@
static Availability CreateAvailability(AvailabilityResult result,
const std::string& message);
- // Gets the current channel as seen by the Feature system.
- static chrome::VersionInfo::Channel GetCurrentChannel();
-
- // Sets the current channel as seen by the Feature system. In the browser
- // process this should be chrome::VersionInfo::GetChannel(), and in the
- // renderer this will need to come from an IPC.
- static void SetCurrentChannel(chrome::VersionInfo::Channel channel);
-
- // Gets the default channel as seen by the Feature system.
- static chrome::VersionInfo::Channel GetDefaultChannel();
-
- // Scoped channel setter. Use for tests.
- class ScopedCurrentChannel {
- public:
- explicit ScopedCurrentChannel(chrome::VersionInfo::Channel channel)
- : original_channel_(chrome::VersionInfo::CHANNEL_UNKNOWN) {
- original_channel_ = GetCurrentChannel();
- SetCurrentChannel(channel);
- }
-
- ~ScopedCurrentChannel() {
- SetCurrentChannel(original_channel_);
- }
-
- private:
- chrome::VersionInfo::Channel original_channel_;
- };
-
const std::string& name() const { return name_; }
void set_name(const std::string& name) { name_ = name; }
const std::set<std::string>& dependencies() { return dependencies_; }
diff --git a/chrome/common/extensions/features/feature_channel.cc b/chrome/common/extensions/features/feature_channel.cc
new file mode 100644
index 0000000..98a178e
--- /dev/null
+++ b/chrome/common/extensions/features/feature_channel.cc
@@ -0,0 +1,30 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/extensions/features/feature_channel.h"
+
+using chrome::VersionInfo;
+
+namespace {
+
+const VersionInfo::Channel kDefaultChannel = VersionInfo::CHANNEL_STABLE;
+VersionInfo::Channel g_current_channel = kDefaultChannel;
+
+} // namespace
+
+namespace extensions {
+
+VersionInfo::Channel GetCurrentChannel() {
+ return g_current_channel;
+}
+
+void SetCurrentChannel(VersionInfo::Channel channel) {
+ g_current_channel = channel;
+}
+
+VersionInfo::Channel GetDefaultChannel() {
+ return kDefaultChannel;
+}
+
+} // namespace extensions
diff --git a/chrome/common/extensions/features/feature_channel.h b/chrome/common/extensions/features/feature_channel.h
new file mode 100644
index 0000000..e915aac
--- /dev/null
+++ b/chrome/common/extensions/features/feature_channel.h
@@ -0,0 +1,42 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_EXTENSIONS_FEATURES_FEATURE_CHANNEL_H_
+#define CHROME_COMMON_EXTENSIONS_FEATURES_FEATURE_CHANNEL_H_
+
+#include "chrome/common/chrome_version_info.h"
+
+namespace extensions {
+
+// Gets the current channel as seen by the Feature system.
+chrome::VersionInfo::Channel GetCurrentChannel();
+
+// Sets the current channel as seen by the Feature system. In the browser
+// process this should be chrome::VersionInfo::GetChannel(), and in the
+// renderer this will need to come from an IPC.
+void SetCurrentChannel(chrome::VersionInfo::Channel channel);
+
+// Gets the default channel as seen by the Feature system.
+chrome::VersionInfo::Channel GetDefaultChannel();
+
+// Scoped channel setter. Use for tests.
+class ScopedCurrentChannel {
+ public:
+ explicit ScopedCurrentChannel(chrome::VersionInfo::Channel channel)
+ : original_channel_(chrome::VersionInfo::CHANNEL_UNKNOWN) {
+ original_channel_ = GetCurrentChannel();
+ SetCurrentChannel(channel);
+ }
+
+ ~ScopedCurrentChannel() {
+ SetCurrentChannel(original_channel_);
+ }
+
+ private:
+ chrome::VersionInfo::Channel original_channel_;
+};
+
+} // namespace extensions
+
+#endif // CHROME_COMMON_EXTENSIONS_FEATURES_FEATURE_CHANNEL_H_
diff --git a/chrome/common/extensions/features/simple_feature.cc b/chrome/common/extensions/features/simple_feature.cc
index 676c0c6..e8ee3d5 100644
--- a/chrome/common/extensions/features/simple_feature.cc
+++ b/chrome/common/extensions/features/simple_feature.cc
@@ -14,6 +14,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/features/feature_channel.h"
using chrome::VersionInfo;
@@ -306,7 +307,7 @@
if (max_manifest_version_ != 0 && manifest_version > max_manifest_version_)
return CreateAvailability(INVALID_MAX_MANIFEST_VERSION, type);
- if (channel_has_been_set_ && channel_ < Feature::GetCurrentChannel())
+ if (channel_has_been_set_ && channel_ < GetCurrentChannel())
return CreateAvailability(UNSUPPORTED_CHANNEL, type);
return CreateAvailability(IS_AVAILABLE, type);
diff --git a/chrome/common/extensions/features/simple_feature_unittest.cc b/chrome/common/extensions/features/simple_feature_unittest.cc
index b50ddb2..fc7967f 100644
--- a/chrome/common/extensions/features/simple_feature_unittest.cc
+++ b/chrome/common/extensions/features/simple_feature_unittest.cc
@@ -4,6 +4,7 @@
#include "chrome/common/extensions/features/simple_feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/common/extensions/value_builder.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -13,6 +14,7 @@
using extensions::Feature;
using extensions::ListBuilder;
using extensions::Manifest;
+using extensions::ScopedCurrentChannel;
using extensions::SimpleFeature;
namespace {
@@ -33,7 +35,7 @@
virtual ~ExtensionSimpleFeatureTest() {}
private:
- Feature::ScopedCurrentChannel current_channel_;
+ ScopedCurrentChannel current_channel_;
};
TEST_F(ExtensionSimpleFeatureTest, IsAvailableNullCase) {
@@ -534,7 +536,7 @@
Feature::AvailabilityResult IsAvailableInChannel(
const std::string& channel, VersionInfo::Channel channel_for_testing) {
- Feature::ScopedCurrentChannel current_channel(channel_for_testing);
+ ScopedCurrentChannel current_channel(channel_for_testing);
SimpleFeature feature;
if (!channel.empty()) {
diff --git a/chrome/common/extensions/manifest.cc b/chrome/common/extensions/manifest.cc
index c8cedf1..008912a 100644
--- a/chrome/common/extensions/manifest.cc
+++ b/chrome/common/extensions/manifest.cc
@@ -11,8 +11,9 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/extensions/extension_manifest_constants.h"
-#include "chrome/common/extensions/features/base_feature_provider.h"
+#include "chrome/common/extensions/features/feature.h"
#include "extensions/common/error_utils.h"
+#include "extensions/common/features/feature_provider.h"
#include "extensions/common/install_warning.h"
namespace errors = extension_manifest_errors;
@@ -141,7 +142,7 @@
// TODO(aa): Consider having an error here in the case of strict error
// checking to let developers know when they screw up.
- FeatureProvider* provider = BaseFeatureProvider::GetByName("manifest");
+ FeatureProvider* provider = FeatureProvider::GetByName("manifest");
const std::vector<std::string>& feature_names =
provider->GetAllFeatureNames();
for (std::vector<std::string>::const_iterator feature_name =
@@ -250,8 +251,7 @@
}
bool Manifest::CanAccessKey(const std::string& key) const {
- Feature* feature =
- BaseFeatureProvider::GetByName("manifest")->GetFeature(key);
+ Feature* feature = FeatureProvider::GetByName("manifest")->GetFeature(key);
if (!feature)
return true;
diff --git a/chrome/common/extensions/manifest_handlers/externally_connectable_unittest.cc b/chrome/common/extensions/manifest_handlers/externally_connectable_unittest.cc
index feea601..78857c2 100644
--- a/chrome/common/extensions/manifest_handlers/externally_connectable_unittest.cc
+++ b/chrome/common/extensions/manifest_handlers/externally_connectable_unittest.cc
@@ -5,7 +5,7 @@
#include <algorithm>
#include "chrome/common/extensions/extension_manifest_constants.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/common/extensions/manifest_handlers/externally_connectable.h"
#include "chrome/common/extensions/manifest_tests/extension_manifest_test.h"
#include "extensions/common/error_utils.h"
@@ -30,7 +30,7 @@
}
private:
- Feature::ScopedCurrentChannel channel_;
+ ScopedCurrentChannel channel_;
};
TEST_F(ExternallyConnectableTest, IDsAndMatches) {
diff --git a/chrome/common/extensions/manifest_tests/extension_manifest_test.h b/chrome/common/extensions/manifest_tests/extension_manifest_test.h
index d91fc9f..7694e15 100644
--- a/chrome/common/extensions/manifest_tests/extension_manifest_test.h
+++ b/chrome/common/extensions/manifest_tests/extension_manifest_test.h
@@ -10,7 +10,7 @@
#include "base/values.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_manifest_constants.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/common/extensions/manifest.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -149,7 +149,7 @@
//
// These objects nest, so if a test wants to explicitly test the behaviour
// on stable or beta, declare it inside that test.
- extensions::Feature::ScopedCurrentChannel current_channel_;
+ extensions::ScopedCurrentChannel current_channel_;
};
#endif // CHROME_COMMON_EXTENSIONS_MANIFEST_TESTS_EXTENSION_MANIFEST_TEST_H_
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc
index 10ddbe3..d2d4fc7 100644
--- a/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc
+++ b/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc
@@ -10,8 +10,7 @@
#include "chrome/common/extensions/background_info.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_manifest_constants.h"
-#include "chrome/common/extensions/features/base_feature_provider.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "extensions/common/constants.h"
#include "extensions/common/error_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -89,8 +88,7 @@
}
TEST_F(ExtensionManifestBackgroundTest, BackgroundPageWebRequest) {
- Feature::ScopedCurrentChannel current_channel(
- chrome::VersionInfo::CHANNEL_DEV);
+ ScopedCurrentChannel current_channel(chrome::VersionInfo::CHANNEL_DEV);
std::string error;
scoped_ptr<base::DictionaryValue> manifest(
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc
index 0b368f8..2850d13 100644
--- a/chrome/common/extensions/permissions/chrome_api_permissions.cc
+++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -317,13 +317,13 @@
return permissions;
}
-std::vector<PermissionsInfo::AliasInfo> ChromeAPIPermissions::GetAllAliases()
- const {
+std::vector<PermissionsProvider::AliasInfo>
+ChromeAPIPermissions::GetAllAliases() const {
// Register aliases.
- std::vector<PermissionsInfo::AliasInfo> aliases;
- aliases.push_back(PermissionsInfo::AliasInfo(
+ std::vector<PermissionsProvider::AliasInfo> aliases;
+ aliases.push_back(PermissionsProvider::AliasInfo(
"unlimitedStorage", kOldUnlimitedStoragePermission));
- aliases.push_back(PermissionsInfo::AliasInfo(
+ aliases.push_back(PermissionsProvider::AliasInfo(
"tabs", kWindowsPermission));
return aliases;
}
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.h b/chrome/common/extensions/permissions/chrome_api_permissions.h
index ec5283c..9341a66 100644
--- a/chrome/common/extensions/permissions/chrome_api_permissions.h
+++ b/chrome/common/extensions/permissions/chrome_api_permissions.h
@@ -7,15 +7,16 @@
#include <vector>
-#include "chrome/common/extensions/permissions/permissions_info.h"
+#include "base/compiler_specific.h"
+#include "extensions/common/permissions/permissions_provider.h"
namespace extensions {
// Registers the permissions used in Chrome with the PermissionsInfo global.
-class ChromeAPIPermissions : public PermissionsInfo::Delegate {
+class ChromeAPIPermissions : public PermissionsProvider {
public:
virtual std::vector<APIPermissionInfo*> GetAllPermissions() const OVERRIDE;
- virtual std::vector<PermissionsInfo::AliasInfo> GetAllAliases() const
+ virtual std::vector<PermissionsProvider::AliasInfo> GetAllAliases() const
OVERRIDE;
};
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc
index f5adabd..637fb54 100644
--- a/chrome/common/extensions/permissions/permission_set_unittest.cc
+++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -11,7 +11,7 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_test_util.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/common/extensions/permissions/permission_set.h"
#include "chrome/common/extensions/permissions/permissions_data.h"
#include "chrome/common/extensions/permissions/permissions_info.h"
@@ -835,7 +835,7 @@
}
TEST(PermissionsTest, GetWarningMessages_Socket_AnyHost) {
- Feature::ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
+ ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
scoped_refptr<Extension> extension =
LoadManifest("permissions", "socket_any_host.json");
@@ -849,7 +849,7 @@
}
TEST(PermissionsTest, GetWarningMessages_Socket_OneDomainTwoHostnames) {
- Feature::ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
+ ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
scoped_refptr<Extension> extension =
LoadManifest("permissions", "socket_one_domain_two_hostnames.json");
@@ -875,7 +875,7 @@
}
TEST(PermissionsTest, GetWarningMessages_Socket_TwoDomainsOneHostname) {
- Feature::ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
+ ScopedCurrentChannel channel(chrome::VersionInfo::CHANNEL_DEV);
scoped_refptr<Extension> extension =
LoadManifest("permissions", "socket_two_domains_one_hostname.json");
diff --git a/chrome/common/extensions/permissions/permissions_data_unittest.cc b/chrome/common/extensions/permissions/permissions_data_unittest.cc
index a4d1cda..0127ce6 100644
--- a/chrome/common/extensions/permissions/permissions_data_unittest.cc
+++ b/chrome/common/extensions/permissions/permissions_data_unittest.cc
@@ -12,7 +12,7 @@
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_manifest_constants.h"
#include "chrome/common/extensions/extension_test_util.h"
-#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/common/extensions/permissions/api_permission.h"
#include "chrome/common/extensions/permissions/permission_set.h"
#include "chrome/common/extensions/permissions/permissions_data.h"
@@ -117,8 +117,7 @@
TEST(ExtensionPermissionsTest, SocketPermissions) {
// Set feature current channel to appropriate value.
- Feature::ScopedCurrentChannel scoped_channel(
- chrome::VersionInfo::CHANNEL_DEV);
+ ScopedCurrentChannel scoped_channel(chrome::VersionInfo::CHANNEL_DEV);
scoped_refptr<Extension> extension;
std::string error;
diff --git a/chrome/common/extensions/permissions/permissions_info.cc b/chrome/common/extensions/permissions/permissions_info.cc
index 818bc4f..ec251e8 100644
--- a/chrome/common/extensions/permissions/permissions_info.cc
+++ b/chrome/common/extensions/permissions/permissions_info.cc
@@ -8,47 +8,22 @@
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
+#include "extensions/common/extensions_client.h"
namespace extensions {
static base::LazyInstance<PermissionsInfo> g_permissions_info =
LAZY_INSTANCE_INITIALIZER;
-// ScopedTestingPermissionsInfo can override the global instance for testing.
-static PermissionsInfo* g_permissions_info_override = NULL;
// static
PermissionsInfo* PermissionsInfo::GetInstance() {
- if (!g_permissions_info_override)
- g_permissions_info_override = g_permissions_info.Pointer();
- return g_permissions_info_override;
-}
-
-// static
-void PermissionsInfo::SetForTesting(PermissionsInfo* info) {
- g_permissions_info_override = info;
+ return g_permissions_info.Pointer();
}
PermissionsInfo::~PermissionsInfo() {
STLDeleteContainerPairSecondPointers(id_map_.begin(), id_map_.end());
}
-void PermissionsInfo::InitializeWithDelegate(
- const PermissionsInfo::Delegate& delegate) {
- // TODO(yoz): Change into a DCHECK once StartupHelper browser tests
- // are changed to unit tests.
- if (initialized_)
- return;
- std::vector<APIPermissionInfo*> permissions = delegate.GetAllPermissions();
- std::vector<AliasInfo> aliases = delegate.GetAllAliases();
-
- for (size_t i = 0; i < permissions.size(); ++i)
- RegisterPermission(permissions[i]);
- for (size_t i = 0; i < aliases.size(); ++i)
- RegisterAlias(aliases[i].name, aliases[i].alias);
-
- initialized_ = true;
-}
-
const APIPermissionInfo* PermissionsInfo::GetByID(
APIPermission::ID id) const {
IDMap::const_iterator i = id_map_.find(id);
@@ -88,8 +63,21 @@
PermissionsInfo::PermissionsInfo()
: hosted_app_permission_count_(0),
- permission_count_(0),
- initialized_(false) {
+ permission_count_(0) {
+ DCHECK(ExtensionsClient::Get());
+ InitializeWithProvider(ExtensionsClient::Get()->GetPermissionsProvider());
+}
+
+void PermissionsInfo::InitializeWithProvider(
+ const PermissionsProvider& provider) {
+ std::vector<APIPermissionInfo*> permissions = provider.GetAllPermissions();
+ std::vector<PermissionsProvider::AliasInfo> aliases =
+ provider.GetAllAliases();
+
+ for (size_t i = 0; i < permissions.size(); ++i)
+ RegisterPermission(permissions[i]);
+ for (size_t i = 0; i < aliases.size(); ++i)
+ RegisterAlias(aliases[i].name, aliases[i].alias);
}
void PermissionsInfo::RegisterAlias(
diff --git a/chrome/common/extensions/permissions/permissions_info.h b/chrome/common/extensions/permissions/permissions_info.h
index 238c8ae..6261362 100644
--- a/chrome/common/extensions/permissions/permissions_info.h
+++ b/chrome/common/extensions/permissions/permissions_info.h
@@ -14,6 +14,7 @@
#include "chrome/common/extensions/permissions/api_permission.h"
#include "chrome/common/extensions/permissions/api_permission_set.h"
#include "chrome/common/extensions/permissions/permission_message.h"
+#include "extensions/common/permissions/permissions_provider.h"
namespace extensions {
@@ -21,35 +22,10 @@
// methods for accessing them.
class PermissionsInfo {
public:
- // An alias for a given permission |name|.
- struct AliasInfo {
- const char* name;
- const char* alias;
-
- AliasInfo(const char* name, const char* alias)
- : name(name), alias(alias) {
- }
- };
-
- // The delegate creates the APIPermissions instances. It is only
- // needed at startup time.
- class Delegate {
- public:
- // Returns all the known permissions. The caller, PermissionsInfo,
- // takes ownership of the APIPermissionInfos.
- virtual std::vector<APIPermissionInfo*> GetAllPermissions() const = 0;
-
- // Returns all the known permission aliases.
- virtual std::vector<AliasInfo> GetAllAliases() const = 0;
- };
-
static PermissionsInfo* GetInstance();
virtual ~PermissionsInfo();
- // Initializes the permissions from the delegate.
- void InitializeWithDelegate(const Delegate& delegate);
-
// Returns the permission with the given |id|, and NULL if it doesn't exist.
const APIPermissionInfo* GetByID(APIPermission::ID id) const;
@@ -72,14 +48,12 @@
size_t get_permission_count() const { return permission_count_; }
private:
- friend class ScopedTestingPermissionsInfo;
friend struct base::DefaultLazyInstanceTraits<PermissionsInfo>;
PermissionsInfo();
- // Overrides the global PermissionsInfo for unit tests. Should only be
- // called from ScopedTestingPermissionsInfo.
- static void SetForTesting(PermissionsInfo* info);
+ // Initializes the permissions from the provider.
+ void InitializeWithProvider(const PermissionsProvider& provider);
// Registers an |alias| for a given permission |name|.
void RegisterAlias(const char* name, const char* alias);
@@ -99,9 +73,6 @@
size_t hosted_app_permission_count_;
size_t permission_count_;
- // Set to true after the delegate has created the known permissions.
- bool initialized_;
-
DISALLOW_COPY_AND_ASSIGN(PermissionsInfo);
};
diff --git a/chrome/common/extensions/permissions/scoped_testing_permissions_info.cc b/chrome/common/extensions/permissions/scoped_testing_permissions_info.cc
deleted file mode 100644
index 81919e0..0000000
--- a/chrome/common/extensions/permissions/scoped_testing_permissions_info.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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 "chrome/common/extensions/permissions/scoped_testing_permissions_info.h"
-
-namespace extensions {
-
-ScopedTestingPermissionsInfo::ScopedTestingPermissionsInfo()
- : info_(new PermissionsInfo),
- old_info_(PermissionsInfo::GetInstance()) {
- PermissionsInfo::SetForTesting(info_.get());
-}
-
-ScopedTestingPermissionsInfo::ScopedTestingPermissionsInfo(
- const PermissionsInfo::Delegate& delegate)
- : info_(new PermissionsInfo),
- old_info_(PermissionsInfo::GetInstance()) {
- PermissionsInfo::SetForTesting(info_.get());
- PermissionsInfo::GetInstance()->InitializeWithDelegate(delegate);
-}
-
-ScopedTestingPermissionsInfo::~ScopedTestingPermissionsInfo() {
- PermissionsInfo::SetForTesting(old_info_);
-}
-
-} // namespace extensions
diff --git a/chrome/common/extensions/permissions/scoped_testing_permissions_info.h b/chrome/common/extensions/permissions/scoped_testing_permissions_info.h
deleted file mode 100644
index a1d84cd..0000000
--- a/chrome/common/extensions/permissions/scoped_testing_permissions_info.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// 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 CHROME_COMMON_EXTENSIONS_PERMISSIONS_SCOPED_TESTING_PERMISSIONS_INFO_H_
-#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_SCOPED_TESTING_PERMISSIONS_INFO_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "chrome/common/extensions/permissions/permissions_info.h"
-
-namespace extensions {
-
-// Overrides the global PermissionsInfo on construction and restores it
-// on destruction.
-class ScopedTestingPermissionsInfo {
- public:
- ScopedTestingPermissionsInfo();
- explicit ScopedTestingPermissionsInfo(
- const PermissionsInfo::Delegate& delegate);
- ~ScopedTestingPermissionsInfo();
-
- private:
- scoped_ptr<PermissionsInfo> info_;
- PermissionsInfo* old_info_;
-};
-
-} // namespace extensions
-
-#endif // CHROME_COMMON_EXTENSIONS_PERMISSIONS_SCOPED_TESTING_PERMISSIONS_INFO_H_
diff --git a/chrome/common/extensions/permissions/usb_device_permission_unittest.cc b/chrome/common/extensions/permissions/usb_device_permission_unittest.cc
index a590288..3f7e0b8 100644
--- a/chrome/common/extensions/permissions/usb_device_permission_unittest.cc
+++ b/chrome/common/extensions/permissions/usb_device_permission_unittest.cc
@@ -10,7 +10,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/common/extensions/permissions/api_permission.h"
-#include "chrome/common/extensions/permissions/chrome_api_permissions.h"
+#include "chrome/common/extensions/permissions/permissions_info.h"
#include "chrome/common/extensions/permissions/usb_device_permission.h"
#include "chrome/common/extensions/permissions/usb_device_permission_data.h"
#include "ipc/ipc_message.h"
diff --git a/chrome/common/metrics/proto/omnibox_event.proto b/chrome/common/metrics/proto/omnibox_event.proto
index 4bd5dd1..ebe0ab6 100644
--- a/chrome/common/metrics/proto/omnibox_event.proto
+++ b/chrome/common/metrics/proto/omnibox_event.proto
@@ -85,6 +85,10 @@
// The new tab page in which this omnibox interaction first started
// with the user having focus in the fakebox.
INSTANT_NEW_TAB_PAGE_WITH_FAKEBOX_AS_STARTING_FOCUS = 8;
+ // The user is on a search result page that's not doing search term
+ // replacement, meaning the URL of the page should've appeared in the
+ // omnibox before the user started editing it, not the search terms.
+ SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT = 9;
}
optional PageClassification current_page_classification = 10;
diff --git a/chrome/common/metrics/variations/variation_ids.h b/chrome/common/metrics/variations/variation_ids.h
index 299f9c3..8ce3617 100644
--- a/chrome/common/metrics/variations/variation_ids.h
+++ b/chrome/common/metrics/variations/variation_ids.h
@@ -227,10 +227,14 @@
SHOW_APP_LAUNCHER_PROMO_UNTIL_DISMISSED = 3310366,
SHOW_APP_LAUNCHER_PROMO_RESET_PREF = 3310367,
+ // CookieRetentionPriorityStudy field trial.
+ COOKIE_RETENTION_PRIORITY_STUDY_EXPERIMENT_OFF = 3310869,
+ COOKIE_RETENTION_PRIORITY_STUDY_EXPERIMENT_ON = 3310870,
+
// NEXT ID: When adding new IDs, please add them above this section, starting
// with the value of NEXT_ID, and updating NEXT_ID to (end of your reserved
// range) + 1.
- NEXT_ID = 3310869,
+ NEXT_ID = 3310871,
// USABLE IDs END HERE.
//
diff --git a/chrome/common/metrics/variations/variations_associated_data.cc b/chrome/common/metrics/variations/variations_associated_data.cc
index f74bc85..9a1a56e 100644
--- a/chrome/common/metrics/variations/variations_associated_data.cc
+++ b/chrome/common/metrics/variations/variations_associated_data.cc
@@ -132,6 +132,11 @@
return true;
}
+ void ClearAllParamsForTesting() {
+ base::AutoLock scoped_lock(lock_);
+ variation_params_.clear();
+ }
+
private:
friend struct DefaultSingletonTraits<VariationsParamAssociator>;
@@ -222,6 +227,10 @@
GroupMapAccessor::GetInstance()->ClearAllMapsForTesting();
}
+void ClearAllVariationParams() {
+ VariationsParamAssociator::GetInstance()->ClearAllParamsForTesting();
+}
+
} // namespace testing
} // namespace chrome_variations
diff --git a/chrome/common/metrics/variations/variations_associated_data.h b/chrome/common/metrics/variations/variations_associated_data.h
index 182b66b..d191d38 100644
--- a/chrome/common/metrics/variations/variations_associated_data.h
+++ b/chrome/common/metrics/variations/variations_associated_data.h
@@ -137,13 +137,15 @@
std::string GetVariationParamValue(const std::string& trial_name,
const std::string& param_name);
-// Expose some functions for testing. These functions just wrap functionality
-// that is implemented above.
+// Expose some functions for testing.
namespace testing {
// Clears all of the mapped associations.
void ClearAllVariationIDs();
+// Clears all of the associated params.
+void ClearAllVariationParams();
+
} // namespace testing
} // namespace chrome_variations
diff --git a/chrome/common/net/url_util.cc b/chrome/common/net/url_util.cc
index 1047e91..442e599 100644
--- a/chrome/common/net/url_util.cc
+++ b/chrome/common/net/url_util.cc
@@ -5,7 +5,7 @@
#include "chrome/common/net/url_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "chrome/common/url_constants.h"
+#include "content/public/common/url_constants.h"
#include "net/base/escape.h"
#include "net/base/net_util.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
@@ -21,7 +21,7 @@
// Unescaping path and query is not a good idea because other applications
// may not encode non-ASCII characters in UTF-8. See crbug.com/2820.
- string16 text = url.SchemeIs(chrome::kMailToScheme) ?
+ string16 text = url.SchemeIs(content::kMailToScheme) ?
ASCIIToUTF16(url.path()) :
net::FormatUrl(url, languages, net::kFormatUrlOmitNothing,
net::UnescapeRule::NONE, NULL, NULL, NULL);
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index bdbb346..65b4c93 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1157,6 +1157,10 @@
const char kAutofillGeneratedCardBubbleTimesShown[] =
"autofill.generated_card_bubble_times_shown";
+// A dictionary that tracks the defaults to be set on the next invocation
+// of the requestAutocomplete/Autocheckout dialog.
+const char kAutofillDialogDefaults[] = "autofill.rac_dialog_defaults";
+
// Modifying bookmarks is completely disabled when this is set to false.
const char kEditBookmarksEnabled[] = "bookmarks.editing_enabled";
@@ -2489,6 +2493,10 @@
"overscroll.horizontal_resist_threshold";
const char kOverscrollVerticalResistThreshold[] =
"overscroll.vertical_resist_threshold";
+// TODO(mohsen): Remove following pref in M32. By then, gesture prefs will have
+// been cleared for majority of the users: crbug.com/269292.
+// A temporary pref to do a one-time wipe of gesture preferences.
+const char kGestureConfigIsTrustworthy[] = "gesture.config_is_trustworthy";
#endif
// Counts how many more times the 'profile on a network share' warning should be
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index d6d79b2..d1bfbe7 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -401,6 +401,7 @@
extern const char kAutofillDialogPayWithoutWallet[];
extern const char kAutofillDialogShowCount[];
extern const char kAutofillGeneratedCardBubbleTimesShown[];
+extern const char kAutofillDialogDefaults[];
extern const char kEditBookmarksEnabled[];
extern const char kEnableTranslate[];
@@ -907,6 +908,7 @@
extern const char kOverscrollVerticalThresholdStart[];
extern const char kOverscrollHorizontalResistThreshold[];
extern const char kOverscrollVerticalResistThreshold[];
+extern const char kGestureConfigIsTrustworthy[];
#endif
extern const char kNetworkProfileWarningsLeft[];
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 547057c..e75e566 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -672,6 +672,13 @@
int /* page_id */,
OmniboxFocusState /* state */)
+// Tells InstantExtended to paste text into the omnibox. If text is empty,
+// the clipboard contents will be pasted. This causes the omnibox dropdown to
+// open.
+IPC_MESSAGE_ROUTED2(ChromeViewHostMsg_PasteAndOpenDropdown,
+ int /* page_id */,
+ string16 /* text to be pasted */)
+
// Tells InstantExtended whether the embedded search API is supported.
// See http://dev.chromium.org/embeddedsearch
IPC_MESSAGE_ROUTED2(ChromeViewHostMsg_InstantSupportDetermined,
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index efc63bc..5f1c7a0 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -69,7 +69,7 @@
const char kChromeUIPolicyURL[] = "chrome://policy/";
const char kChromeUIProfileSigninConfirmationURL[] =
"chrome://profile-signin-confirmation/";
-const char kChromeUIUserChooserURL[] = "chrome://user-chooser/";
+const char kChromeUIUserManagerURL[] = "chrome://user-manager/";
const char kChromeUIPrintURL[] = "chrome://print/";
const char kChromeUIRestartURL[] = "chrome://restart/";
const char kChromeUISettingsURL[] = "chrome://settings/";
@@ -109,6 +109,7 @@
const char kChromeUIProxySettingsURL[] = "chrome://proxy-settings/";
const char kChromeUISimUnlockURL[] = "chrome://sim-unlock/";
const char kChromeUISlideshowURL[] = "chrome://slideshow/";
+const char kChromeUISlowURL[] = "chrome://slow/";
const char kChromeUISystemInfoURL[] = "chrome://system/";
const char kChromeUITermsOemURL[] = "chrome://terms/oem";
const char kChromeUIUserImageURL[] = "chrome://userimage/";
@@ -198,7 +199,7 @@
const char kChromeUIPolicyHost[] = "policy";
const char kChromeUIProfileSigninConfirmationHost[] =
"profile-signin-confirmation";
-const char kChromeUIUserChooserHost[] = "user-chooser";
+const char kChromeUIUserManagerHost[] = "user-manager";
const char kChromeUIPredictorsHost[] = "predictors";
const char kChromeUIPrintHost[] = "print";
const char kChromeUIProfilerHost[] = "profiler";
@@ -262,6 +263,7 @@
const char kChromeUIRotateHost[] = "rotate";
const char kChromeUISimUnlockHost[] = "sim-unlock";
const char kChromeUISlideshowHost[] = "slideshow";
+const char kChromeUISlowHost[] = "slow";
const char kChromeUISystemInfoHost[] = "system";
const char kChromeUIUserImageHost[] = "userimage";
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index c3ff8fc..dc878ed 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -64,7 +64,7 @@
extern const char kChromeUIPluginsURL[];
extern const char kChromeUIPolicyURL[];
extern const char kChromeUIProfileSigninConfirmationURL[];
-extern const char kChromeUIUserChooserURL[];
+extern const char kChromeUIUserManagerURL[];
extern const char kChromeUIPrintURL[];
extern const char kChromeUIRestartURL[];
extern const char kChromeUISessionFaviconURL[];
@@ -103,6 +103,7 @@
extern const char kChromeUIProxySettingsURL[];
extern const char kChromeUISimUnlockURL[];
extern const char kChromeUISlideshowURL[];
+extern const char kChromeUISlowURL[];
extern const char kChromeUISystemInfoURL[];
extern const char kChromeUITermsOemURL[];
extern const char kChromeUIUserImageURL[];
@@ -189,7 +190,7 @@
extern const char kChromeUIPluginsHost[];
extern const char kChromeUIPolicyHost[];
extern const char kChromeUIProfileSigninConfirmationHost[];
-extern const char kChromeUIUserChooserHost[];
+extern const char kChromeUIUserManagerHost[];
extern const char kChromeUIPredictorsHost[];
extern const char kChromeUIPrintHost[];
extern const char kChromeUIProfilerHost[];
@@ -254,6 +255,7 @@
extern const char kChromeUIRotateHost[];
extern const char kChromeUISimUnlockHost[];
extern const char kChromeUISlideshowHost[];
+extern const char kChromeUISlowHost[];
extern const char kChromeUISystemInfoHost[];
extern const char kChromeUIUserImageHost[];
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index dc96a5b..b02fb4e 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "chrome/installer/setup/setup_main.h"
+
#include <windows.h>
#include <msi.h>
#include <shellapi.h>
@@ -63,7 +65,6 @@
#include "chrome/installer/util/self_cleaning_temp_dir.h"
#include "chrome/installer/util/shell_util.h"
#include "chrome/installer/util/user_experiment.h"
-#include "chrome/installer/util/util_constants.h"
#include "installer_util_strings.h" // NOLINT
@@ -686,311 +687,6 @@
return true;
}
-installer::InstallStatus InstallProductsHelper(
- const InstallationState& original_state,
- const CommandLine& cmd_line,
- const MasterPreferences& prefs,
- const InstallerState& installer_state,
- installer::ArchiveType* archive_type,
- bool* delegated_to_existing) {
- DCHECK(archive_type);
- DCHECK(delegated_to_existing);
- const bool system_install = installer_state.system_install();
- installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
-
- // Drop to background processing mode if the process was started below the
- // normal process priority class.
- bool entered_background_mode = installer::AdjustProcessPriority();
- VLOG_IF(1, entered_background_mode) << "Entered background processing mode.";
-
- // Create a temp folder where we will unpack Chrome archive. If it fails,
- // then we are doomed, so return immediately and no cleanup is required.
- installer::SelfCleaningTempDir temp_path;
- base::FilePath unpack_path;
- if (!CreateTemporaryAndUnpackDirectories(installer_state, &temp_path,
- &unpack_path)) {
- installer_state.WriteInstallerResult(installer::TEMP_DIR_FAILED,
- IDS_INSTALL_TEMP_DIR_FAILED_BASE,
- NULL);
- return installer::TEMP_DIR_FAILED;
- }
-
- // Uncompress and optionally patch the archive if an uncompressed archive was
- // not specified on the command line and a compressed archive is found.
- *archive_type = installer::UNKNOWN_ARCHIVE_TYPE;
- base::FilePath uncompressed_archive(cmd_line.GetSwitchValuePath(
- installer::switches::kUncompressedArchive));
- if (uncompressed_archive.empty()) {
- scoped_ptr<installer::ArchivePatchHelper> archive_helper(
- CreateChromeArchiveHelper(cmd_line, installer_state, unpack_path));
- if (archive_helper) {
- VLOG(1) << "Installing Chrome from compressed archive "
- << archive_helper->compressed_archive().value();
- if (!UncompressAndPatchChromeArchive(original_state,
- installer_state,
- archive_helper.get(),
- archive_type,
- &install_status)) {
- DCHECK_NE(install_status, installer::UNKNOWN_STATUS);
- return install_status;
- }
- uncompressed_archive = archive_helper->target();
- DCHECK(!uncompressed_archive.empty());
- }
- }
-
- // Check for an uncompressed archive alongside the current executable if one
- // was not given or generated.
- if (uncompressed_archive.empty()) {
- uncompressed_archive =
- cmd_line.GetProgram().DirName().Append(installer::kChromeArchive);
- }
-
- if (*archive_type == installer::UNKNOWN_ARCHIVE_TYPE) {
- // An archive was not uncompressed or patched above.
- if (uncompressed_archive.empty() ||
- !base::PathExists(uncompressed_archive)) {
- LOG(ERROR) << "Cannot install Chrome without an uncompressed archive.";
- installer_state.WriteInstallerResult(
- installer::INVALID_ARCHIVE, IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL);
- return installer::INVALID_ARCHIVE;
- }
- *archive_type = installer::FULL_ARCHIVE_TYPE;
- }
-
- // Unpack the uncompressed archive.
- if (LzmaUtil::UnPackArchive(uncompressed_archive.value(),
- unpack_path.value(),
- NULL)) {
- installer_state.WriteInstallerResult(
- installer::UNCOMPRESSION_FAILED,
- IDS_INSTALL_UNCOMPRESSION_FAILED_BASE,
- NULL);
- return installer::UNCOMPRESSION_FAILED;
- }
-
- VLOG(1) << "unpacked to " << unpack_path.value();
- base::FilePath src_path(
- unpack_path.Append(installer::kInstallSourceChromeDir));
- scoped_ptr<Version>
- installer_version(installer::GetMaxVersionFromArchiveDir(src_path));
- if (!installer_version.get()) {
- LOG(ERROR) << "Did not find any valid version in installer.";
- install_status = installer::INVALID_ARCHIVE;
- installer_state.WriteInstallerResult(install_status,
- IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL);
- } else {
- VLOG(1) << "version to install: " << installer_version->GetString();
- bool proceed_with_installation = true;
-
- if (installer_state.operation() == InstallerState::MULTI_INSTALL) {
- // This is a new install of a multi-install product. Rather than give up
- // in case a higher version of the binaries (including a single-install
- // of Chrome, which can safely be migrated to multi-install by way of
- // CheckMultiInstallConditions) is already installed, delegate to the
- // installed setup.exe to install the product at hand.
- base::FilePath setup_exe;
- if (GetExistingHigherInstaller(original_state, system_install,
- *installer_version, &setup_exe)) {
- VLOG(1) << "Deferring to existing installer.";
- installer_state.UpdateStage(installer::DEFERRING_TO_HIGHER_VERSION);
- if (DeferToExistingInstall(setup_exe, cmd_line, installer_state,
- temp_path.path(), &install_status)) {
- *delegated_to_existing = true;
- return install_status;
- }
- }
- }
-
- uint32 higher_products = 0;
- COMPILE_ASSERT(
- sizeof(higher_products) * 8 > BrowserDistribution::NUM_TYPES,
- too_many_distribution_types_);
- const Products& products = installer_state.products();
- for (Products::const_iterator it = products.begin(); it < products.end();
- ++it) {
- const Product& product = **it;
- const ProductState* product_state =
- original_state.GetProductState(system_install,
- product.distribution()->GetType());
- if (product_state != NULL &&
- (product_state->version().CompareTo(*installer_version) > 0)) {
- LOG(ERROR) << "Higher version of "
- << product.distribution()->GetAppShortCutName()
- << " is already installed.";
- higher_products |= (1 << product.distribution()->GetType());
- }
- }
-
- if (higher_products != 0) {
- COMPILE_ASSERT(BrowserDistribution::NUM_TYPES == 4,
- add_support_for_new_products_here_);
- const uint32 kBrowserBit = 1 << BrowserDistribution::CHROME_BROWSER;
- const uint32 kGCFBit = 1 << BrowserDistribution::CHROME_FRAME;
- const uint32 kAppHostBit = 1 << BrowserDistribution::CHROME_APP_HOST;
- int message_id = 0;
-
- proceed_with_installation = false;
- install_status = installer::HIGHER_VERSION_EXISTS;
- switch (higher_products) {
- case kBrowserBit:
- message_id = IDS_INSTALL_HIGHER_VERSION_BASE;
- break;
- case kGCFBit:
- message_id = IDS_INSTALL_HIGHER_VERSION_CF_BASE;
- break;
- case kGCFBit | kBrowserBit:
- message_id = IDS_INSTALL_HIGHER_VERSION_CB_CF_BASE;
- break;
- default:
- message_id = IDS_INSTALL_HIGHER_VERSION_APP_LAUNCHER_BASE;
- break;
- }
-
- installer_state.WriteInstallerResult(install_status, message_id, NULL);
- }
-
- proceed_with_installation =
- proceed_with_installation &&
- CheckGroupPolicySettings(original_state, installer_state,
- *installer_version, &install_status);
-
- if (proceed_with_installation) {
- // If Google Update is absent at user-level, install it using the
- // Google Update installer from an existing system-level installation.
- // This is for quick-enable App Host install from a system-level
- // Chrome Binaries installation.
- if (!system_install && installer_state.ensure_google_update_present()) {
- if (!google_update::EnsureUserLevelGoogleUpdatePresent()) {
- LOG(ERROR) << "Failed to install Google Update";
- proceed_with_installation = false;
- install_status = installer::INSTALL_OF_GOOGLE_UPDATE_FAILED;
- installer_state.WriteInstallerResult(install_status, 0, NULL);
- }
- }
- }
-
- if (proceed_with_installation) {
- base::FilePath prefs_source_path(cmd_line.GetSwitchValueNative(
- installer::switches::kInstallerData));
- install_status = installer::InstallOrUpdateProduct(
- original_state, installer_state, cmd_line.GetProgram(),
- uncompressed_archive, temp_path.path(), src_path, prefs_source_path,
- prefs, *installer_version);
-
- int install_msg_base = IDS_INSTALL_FAILED_BASE;
- string16 chrome_exe;
- string16 quoted_chrome_exe;
- if (install_status == installer::SAME_VERSION_REPAIR_FAILED) {
- if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) {
- install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_CF_BASE;
- } else {
- install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_BASE;
- }
- } else if (install_status != installer::INSTALL_FAILED) {
- if (installer_state.target_path().empty()) {
- // If we failed to construct install path, it means the OS call to
- // get %ProgramFiles% or %AppData% failed. Report this as failure.
- install_msg_base = IDS_INSTALL_OS_ERROR_BASE;
- install_status = installer::OS_ERROR;
- } else {
- chrome_exe = installer_state.target_path()
- .Append(installer::kChromeExe).value();
- quoted_chrome_exe = L"\"" + chrome_exe + L"\"";
- install_msg_base = 0;
- }
- }
-
- installer_state.UpdateStage(installer::FINISHING);
-
- // Only do Chrome-specific stuff (like launching the browser) if
- // Chrome was specifically requested (rather than being upgraded as
- // part of a multi-install).
- const Product* chrome_install = prefs.install_chrome() ?
- installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER) :
- NULL;
-
- bool do_not_register_for_update_launch = false;
- if (chrome_install) {
- prefs.GetBool(
- installer::master_preferences::kDoNotRegisterForUpdateLaunch,
- &do_not_register_for_update_launch);
- } else {
- do_not_register_for_update_launch = true; // Never register.
- }
-
- bool write_chrome_launch_string =
- (!do_not_register_for_update_launch &&
- install_status != installer::IN_USE_UPDATED);
-
- installer_state.WriteInstallerResult(install_status, install_msg_base,
- write_chrome_launch_string ? "ed_chrome_exe : NULL);
-
- if (install_status == installer::FIRST_INSTALL_SUCCESS) {
- VLOG(1) << "First install successful.";
- if (chrome_install) {
- // We never want to launch Chrome in system level install mode.
- bool do_not_launch_chrome = false;
- prefs.GetBool(
- installer::master_preferences::kDoNotLaunchChrome,
- &do_not_launch_chrome);
- if (!system_install && !do_not_launch_chrome)
- chrome_install->LaunchChrome(installer_state.target_path());
- }
- } else if ((install_status == installer::NEW_VERSION_UPDATED) ||
- (install_status == installer::IN_USE_UPDATED)) {
- const Product* chrome = installer_state.FindProduct(
- BrowserDistribution::CHROME_BROWSER);
- if (chrome != NULL) {
- DCHECK_NE(chrome_exe, string16());
- installer::RemoveChromeLegacyRegistryKeys(chrome->distribution(),
- chrome_exe);
- }
- }
-
- if (prefs.install_chrome_app_launcher() &&
- InstallUtil::GetInstallReturnCode(install_status) == 0) {
- std::string webstore_item(google_update::GetUntrustedDataValue(
- installer::kInstallFromWebstore));
- if (!webstore_item.empty()) {
- bool success = installer::InstallFromWebstore(webstore_item);
- VLOG_IF(1, !success) << "Failed to launch app installation.";
- }
- }
- }
- }
-
- // There might be an experiment (for upgrade usually) that needs to happen.
- // An experiment's outcome can include chrome's uninstallation. If that is
- // the case we would not do that directly at this point but in another
- // instance of setup.exe
- //
- // There is another way to reach this same function if this is a system
- // level install. See HandleNonInstallCmdLineOptions().
- {
- // If installation failed, use the path to the currently running setup.
- // If installation succeeded, use the path to setup in the installer dir.
- base::FilePath setup_path(cmd_line.GetProgram());
- if (InstallUtil::GetInstallReturnCode(install_status) == 0) {
- setup_path = installer_state.GetInstallerDirectory(*installer_version)
- .Append(setup_path.BaseName());
- }
- const Products& products = installer_state.products();
- for (Products::const_iterator it = products.begin(); it < products.end();
- ++it) {
- const Product& product = **it;
- product.LaunchUserExperiment(setup_path, install_status,
- system_install);
- }
- }
-
- // temp_path's dtor will take care of deleting or scheduling itself for
- // deletion at reboot when this scope closes.
- VLOG(1) << "Deleting temporary directory " << temp_path.path().value();
-
- return install_status;
-}
-
installer::InstallStatus InstallProducts(
const InstallationState& original_state,
const CommandLine& cmd_line,
@@ -1111,7 +807,7 @@
// trigger Active Setup and make sure the system-level Chrome doesn't go
// through first run.
trigger_active_setup = true;
- system_level_cmd.AppendSwitch(::switches::kNoFirstRun);
+ system_level_cmd.AppendSwitch(::switches::kCancelFirstRun);
}
}
}
@@ -1703,6 +1399,315 @@
} // namespace
+namespace installer {
+
+installer::InstallStatus InstallProductsHelper(
+ const InstallationState& original_state,
+ const CommandLine& cmd_line,
+ const MasterPreferences& prefs,
+ const InstallerState& installer_state,
+ installer::ArchiveType* archive_type,
+ bool* delegated_to_existing) {
+ DCHECK(archive_type);
+ DCHECK(delegated_to_existing);
+ const bool system_install = installer_state.system_install();
+ installer::InstallStatus install_status = installer::UNKNOWN_STATUS;
+
+ // Drop to background processing mode if the process was started below the
+ // normal process priority class.
+ bool entered_background_mode = installer::AdjustProcessPriority();
+ VLOG_IF(1, entered_background_mode) << "Entered background processing mode.";
+
+ // Create a temp folder where we will unpack Chrome archive. If it fails,
+ // then we are doomed, so return immediately and no cleanup is required.
+ installer::SelfCleaningTempDir temp_path;
+ base::FilePath unpack_path;
+ if (!CreateTemporaryAndUnpackDirectories(installer_state, &temp_path,
+ &unpack_path)) {
+ installer_state.WriteInstallerResult(installer::TEMP_DIR_FAILED,
+ IDS_INSTALL_TEMP_DIR_FAILED_BASE,
+ NULL);
+ return installer::TEMP_DIR_FAILED;
+ }
+
+ // Uncompress and optionally patch the archive if an uncompressed archive was
+ // not specified on the command line and a compressed archive is found.
+ *archive_type = installer::UNKNOWN_ARCHIVE_TYPE;
+ base::FilePath uncompressed_archive(cmd_line.GetSwitchValuePath(
+ installer::switches::kUncompressedArchive));
+ if (uncompressed_archive.empty()) {
+ scoped_ptr<installer::ArchivePatchHelper> archive_helper(
+ CreateChromeArchiveHelper(cmd_line, installer_state, unpack_path));
+ if (archive_helper) {
+ VLOG(1) << "Installing Chrome from compressed archive "
+ << archive_helper->compressed_archive().value();
+ if (!UncompressAndPatchChromeArchive(original_state,
+ installer_state,
+ archive_helper.get(),
+ archive_type,
+ &install_status)) {
+ DCHECK_NE(install_status, installer::UNKNOWN_STATUS);
+ return install_status;
+ }
+ uncompressed_archive = archive_helper->target();
+ DCHECK(!uncompressed_archive.empty());
+ }
+ }
+
+ // Check for an uncompressed archive alongside the current executable if one
+ // was not given or generated.
+ if (uncompressed_archive.empty()) {
+ uncompressed_archive =
+ cmd_line.GetProgram().DirName().Append(installer::kChromeArchive);
+ }
+
+ if (*archive_type == installer::UNKNOWN_ARCHIVE_TYPE) {
+ // An archive was not uncompressed or patched above.
+ if (uncompressed_archive.empty() ||
+ !base::PathExists(uncompressed_archive)) {
+ LOG(ERROR) << "Cannot install Chrome without an uncompressed archive.";
+ installer_state.WriteInstallerResult(
+ installer::INVALID_ARCHIVE, IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL);
+ return installer::INVALID_ARCHIVE;
+ }
+ *archive_type = installer::FULL_ARCHIVE_TYPE;
+ }
+
+ // Unpack the uncompressed archive.
+ if (LzmaUtil::UnPackArchive(uncompressed_archive.value(),
+ unpack_path.value(),
+ NULL)) {
+ installer_state.WriteInstallerResult(
+ installer::UNCOMPRESSION_FAILED,
+ IDS_INSTALL_UNCOMPRESSION_FAILED_BASE,
+ NULL);
+ return installer::UNCOMPRESSION_FAILED;
+ }
+
+ VLOG(1) << "unpacked to " << unpack_path.value();
+ base::FilePath src_path(
+ unpack_path.Append(installer::kInstallSourceChromeDir));
+ scoped_ptr<Version>
+ installer_version(installer::GetMaxVersionFromArchiveDir(src_path));
+ if (!installer_version.get()) {
+ LOG(ERROR) << "Did not find any valid version in installer.";
+ install_status = installer::INVALID_ARCHIVE;
+ installer_state.WriteInstallerResult(install_status,
+ IDS_INSTALL_INVALID_ARCHIVE_BASE, NULL);
+ } else {
+ VLOG(1) << "version to install: " << installer_version->GetString();
+ bool proceed_with_installation = true;
+
+ if (installer_state.operation() == InstallerState::MULTI_INSTALL) {
+ // This is a new install of a multi-install product. Rather than give up
+ // in case a higher version of the binaries (including a single-install
+ // of Chrome, which can safely be migrated to multi-install by way of
+ // CheckMultiInstallConditions) is already installed, delegate to the
+ // installed setup.exe to install the product at hand.
+ base::FilePath setup_exe;
+ if (GetExistingHigherInstaller(original_state, system_install,
+ *installer_version, &setup_exe)) {
+ VLOG(1) << "Deferring to existing installer.";
+ installer_state.UpdateStage(installer::DEFERRING_TO_HIGHER_VERSION);
+ if (DeferToExistingInstall(setup_exe, cmd_line, installer_state,
+ temp_path.path(), &install_status)) {
+ *delegated_to_existing = true;
+ return install_status;
+ }
+ }
+ }
+
+ uint32 higher_products = 0;
+ COMPILE_ASSERT(
+ sizeof(higher_products) * 8 > BrowserDistribution::NUM_TYPES,
+ too_many_distribution_types_);
+ const Products& products = installer_state.products();
+ for (Products::const_iterator it = products.begin(); it < products.end();
+ ++it) {
+ const Product& product = **it;
+ const ProductState* product_state =
+ original_state.GetProductState(system_install,
+ product.distribution()->GetType());
+ if (product_state != NULL &&
+ (product_state->version().CompareTo(*installer_version) > 0)) {
+ LOG(ERROR) << "Higher version of "
+ << product.distribution()->GetAppShortCutName()
+ << " is already installed.";
+ higher_products |= (1 << product.distribution()->GetType());
+ }
+ }
+
+ if (higher_products != 0) {
+ COMPILE_ASSERT(BrowserDistribution::NUM_TYPES == 4,
+ add_support_for_new_products_here_);
+ const uint32 kBrowserBit = 1 << BrowserDistribution::CHROME_BROWSER;
+ const uint32 kGCFBit = 1 << BrowserDistribution::CHROME_FRAME;
+ const uint32 kAppHostBit = 1 << BrowserDistribution::CHROME_APP_HOST;
+ int message_id = 0;
+
+ proceed_with_installation = false;
+ install_status = installer::HIGHER_VERSION_EXISTS;
+ switch (higher_products) {
+ case kBrowserBit:
+ message_id = IDS_INSTALL_HIGHER_VERSION_BASE;
+ break;
+ case kGCFBit:
+ message_id = IDS_INSTALL_HIGHER_VERSION_CF_BASE;
+ break;
+ case kGCFBit | kBrowserBit:
+ message_id = IDS_INSTALL_HIGHER_VERSION_CB_CF_BASE;
+ break;
+ default:
+ message_id = IDS_INSTALL_HIGHER_VERSION_APP_LAUNCHER_BASE;
+ break;
+ }
+
+ installer_state.WriteInstallerResult(install_status, message_id, NULL);
+ }
+
+ proceed_with_installation =
+ proceed_with_installation &&
+ CheckGroupPolicySettings(original_state, installer_state,
+ *installer_version, &install_status);
+
+ if (proceed_with_installation) {
+ // If Google Update is absent at user-level, install it using the
+ // Google Update installer from an existing system-level installation.
+ // This is for quick-enable App Host install from a system-level
+ // Chrome Binaries installation.
+ if (!system_install && installer_state.ensure_google_update_present()) {
+ if (!google_update::EnsureUserLevelGoogleUpdatePresent()) {
+ LOG(ERROR) << "Failed to install Google Update";
+ proceed_with_installation = false;
+ install_status = installer::INSTALL_OF_GOOGLE_UPDATE_FAILED;
+ installer_state.WriteInstallerResult(install_status, 0, NULL);
+ }
+ }
+ }
+
+ if (proceed_with_installation) {
+ base::FilePath prefs_source_path(cmd_line.GetSwitchValueNative(
+ installer::switches::kInstallerData));
+ install_status = installer::InstallOrUpdateProduct(
+ original_state, installer_state, cmd_line.GetProgram(),
+ uncompressed_archive, temp_path.path(), src_path, prefs_source_path,
+ prefs, *installer_version);
+
+ int install_msg_base = IDS_INSTALL_FAILED_BASE;
+ string16 chrome_exe;
+ string16 quoted_chrome_exe;
+ if (install_status == installer::SAME_VERSION_REPAIR_FAILED) {
+ if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) {
+ install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_CF_BASE;
+ } else {
+ install_msg_base = IDS_SAME_VERSION_REPAIR_FAILED_BASE;
+ }
+ } else if (install_status != installer::INSTALL_FAILED) {
+ if (installer_state.target_path().empty()) {
+ // If we failed to construct install path, it means the OS call to
+ // get %ProgramFiles% or %AppData% failed. Report this as failure.
+ install_msg_base = IDS_INSTALL_OS_ERROR_BASE;
+ install_status = installer::OS_ERROR;
+ } else {
+ chrome_exe = installer_state.target_path()
+ .Append(installer::kChromeExe).value();
+ quoted_chrome_exe = L"\"" + chrome_exe + L"\"";
+ install_msg_base = 0;
+ }
+ }
+
+ installer_state.UpdateStage(installer::FINISHING);
+
+ // Only do Chrome-specific stuff (like launching the browser) if
+ // Chrome was specifically requested (rather than being upgraded as
+ // part of a multi-install).
+ const Product* chrome_install = prefs.install_chrome() ?
+ installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER) :
+ NULL;
+
+ bool do_not_register_for_update_launch = false;
+ if (chrome_install) {
+ prefs.GetBool(
+ installer::master_preferences::kDoNotRegisterForUpdateLaunch,
+ &do_not_register_for_update_launch);
+ } else {
+ do_not_register_for_update_launch = true; // Never register.
+ }
+
+ bool write_chrome_launch_string =
+ (!do_not_register_for_update_launch &&
+ install_status != installer::IN_USE_UPDATED);
+
+ installer_state.WriteInstallerResult(install_status, install_msg_base,
+ write_chrome_launch_string ? "ed_chrome_exe : NULL);
+
+ if (install_status == installer::FIRST_INSTALL_SUCCESS) {
+ VLOG(1) << "First install successful.";
+ if (chrome_install) {
+ // We never want to launch Chrome in system level install mode.
+ bool do_not_launch_chrome = false;
+ prefs.GetBool(
+ installer::master_preferences::kDoNotLaunchChrome,
+ &do_not_launch_chrome);
+ if (!system_install && !do_not_launch_chrome)
+ chrome_install->LaunchChrome(installer_state.target_path());
+ }
+ } else if ((install_status == installer::NEW_VERSION_UPDATED) ||
+ (install_status == installer::IN_USE_UPDATED)) {
+ const Product* chrome = installer_state.FindProduct(
+ BrowserDistribution::CHROME_BROWSER);
+ if (chrome != NULL) {
+ DCHECK_NE(chrome_exe, string16());
+ installer::RemoveChromeLegacyRegistryKeys(chrome->distribution(),
+ chrome_exe);
+ }
+ }
+
+ if (prefs.install_chrome_app_launcher() &&
+ InstallUtil::GetInstallReturnCode(install_status) == 0) {
+ std::string webstore_item(google_update::GetUntrustedDataValue(
+ installer::kInstallFromWebstore));
+ if (!webstore_item.empty()) {
+ bool success = installer::InstallFromWebstore(webstore_item);
+ VLOG_IF(1, !success) << "Failed to launch app installation.";
+ }
+ }
+ }
+ }
+
+ // There might be an experiment (for upgrade usually) that needs to happen.
+ // An experiment's outcome can include chrome's uninstallation. If that is
+ // the case we would not do that directly at this point but in another
+ // instance of setup.exe
+ //
+ // There is another way to reach this same function if this is a system
+ // level install. See HandleNonInstallCmdLineOptions().
+ {
+ // If installation failed, use the path to the currently running setup.
+ // If installation succeeded, use the path to setup in the installer dir.
+ base::FilePath setup_path(cmd_line.GetProgram());
+ if (InstallUtil::GetInstallReturnCode(install_status) == 0) {
+ setup_path = installer_state.GetInstallerDirectory(*installer_version)
+ .Append(setup_path.BaseName());
+ }
+ const Products& products = installer_state.products();
+ for (Products::const_iterator it = products.begin(); it < products.end();
+ ++it) {
+ const Product& product = **it;
+ product.LaunchUserExperiment(setup_path, install_status,
+ system_install);
+ }
+ }
+
+ // temp_path's dtor will take care of deleting or scheduling itself for
+ // deletion at reboot when this scope closes.
+ VLOG(1) << "Deleting temporary directory " << temp_path.path().value();
+
+ return install_status;
+}
+
+} // namespace installer
+
int WINAPI wWinMain(HINSTANCE instance, HINSTANCE prev_instance,
wchar_t* command_line, int show_command) {
// The exit manager is in charge of calling the dtors of singletons.
diff --git a/chrome/installer/setup/setup_main.h b/chrome/installer/setup/setup_main.h
new file mode 100644
index 0000000..f39e742
--- /dev/null
+++ b/chrome/installer/setup/setup_main.h
@@ -0,0 +1,32 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This header exists as a starting point for extracting some of the
+// logic out of setup_main.cc.
+
+#ifndef CHROME_INSTALLER_SETUP_SETUP_MAIN_H_
+#define CHROME_INSTALLER_SETUP_SETUP_MAIN_H_
+
+#include "chrome/installer/util/util_constants.h"
+
+class CommandLine;
+
+namespace installer {
+
+class InstallationState;
+class InstallerState;
+class MasterPreferences;
+
+// Helper function that performs the installation of a set of products.
+installer::InstallStatus InstallProductsHelper(
+ const installer::InstallationState& original_state,
+ const CommandLine& cmd_line,
+ const installer::MasterPreferences& prefs,
+ const installer::InstallerState& installer_state,
+ installer::ArchiveType* archive_type,
+ bool* delegated_to_existing);
+
+} // namespace installer
+
+#endif // CHROME_INSTALLER_SETUP_SETUP_MAIN_H_
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index 9ef0876..36f0f77 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -516,16 +516,16 @@
// Generate work_item tasks required to create current registry entry and
// add them to the given work item list.
void AddToWorkItemList(HKEY root, WorkItemList *items) const {
- items->AddCreateRegKeyWorkItem(root, _key_path);
- if (_is_string) {
- items->AddSetRegValueWorkItem(root, _key_path, _name, _value, true);
+ items->AddCreateRegKeyWorkItem(root, key_path_);
+ if (is_string_) {
+ items->AddSetRegValueWorkItem(root, key_path_, name_, value_, true);
} else {
- items->AddSetRegValueWorkItem(root, _key_path, _name, _int_value, true);
+ items->AddSetRegValueWorkItem(root, key_path_, name_, int_value_, true);
}
}
- // Checks if the current registry entry exists in HKCU\|_key_path|\|_name|
- // and value is |_value|. If the key does NOT exist in HKCU, checks for
+ // Checks if the current registry entry exists in HKCU\|key_path_|\|name_|
+ // and value is |value_|. If the key does NOT exist in HKCU, checks for
// the correct name and value in HKLM.
// |look_for_in| specifies roots (HKCU and/or HKLM) in which to look for the
// key, unspecified roots are not looked into (i.e. the the key is assumed not
@@ -550,57 +550,57 @@
private:
// States this RegistryKey can be in compared to the registry.
enum RegistryStatus {
- // |_name| does not exist in the registry
+ // |name_| does not exist in the registry
DOES_NOT_EXIST,
- // |_name| exists, but its value != |_value|
+ // |name_| exists, but its value != |value_|
DIFFERENT_VALUE,
- // |_name| exists and its value is |_value|
+ // |name_| exists and its value is |value_|
SAME_VALUE,
};
// Create a object that represent default value of a key
RegistryEntry(const string16& key_path, const string16& value)
- : _key_path(key_path), _name(),
- _is_string(true), _value(value), _int_value(0) {
+ : key_path_(key_path), name_(),
+ is_string_(true), value_(value), int_value_(0) {
}
// Create a object that represent a key of type REG_SZ
RegistryEntry(const string16& key_path, const string16& name,
const string16& value)
- : _key_path(key_path), _name(name),
- _is_string(true), _value(value), _int_value(0) {
+ : key_path_(key_path), name_(name),
+ is_string_(true), value_(value), int_value_(0) {
}
// Create a object that represent a key of integer type
RegistryEntry(const string16& key_path, const string16& name,
DWORD value)
- : _key_path(key_path), _name(name),
- _is_string(false), _value(), _int_value(value) {
+ : key_path_(key_path), name_(name),
+ is_string_(false), value_(), int_value_(value) {
}
- string16 _key_path; // key path for the registry entry
- string16 _name; // name of the registry entry
- bool _is_string; // true if current registry entry is of type REG_SZ
- string16 _value; // string value (useful if _is_string = true)
- DWORD _int_value; // integer value (useful if _is_string = false)
+ string16 key_path_; // key path for the registry entry
+ string16 name_; // name of the registry entry
+ bool is_string_; // true if current registry entry is of type REG_SZ
+ string16 value_; // string value (useful if is_string_ = true)
+ DWORD int_value_; // integer value (useful if is_string_ = false)
// Helper function for ExistsInRegistry().
// Returns the RegistryStatus of the current registry entry in
- // |root|\|_key_path|\|_name|.
+ // |root|\|key_path_|\|name_|.
RegistryStatus StatusInRegistryUnderRoot(HKEY root) const {
- RegKey key(root, _key_path.c_str(), KEY_QUERY_VALUE);
+ RegKey key(root, key_path_.c_str(), KEY_QUERY_VALUE);
bool found = false;
bool correct_value = false;
- if (_is_string) {
+ if (is_string_) {
string16 read_value;
- found = key.ReadValue(_name.c_str(), &read_value) == ERROR_SUCCESS;
- correct_value = read_value.size() == _value.size() &&
- std::equal(_value.begin(), _value.end(), read_value.begin(),
+ found = key.ReadValue(name_.c_str(), &read_value) == ERROR_SUCCESS;
+ correct_value = read_value.size() == value_.size() &&
+ std::equal(value_.begin(), value_.end(), read_value.begin(),
base::CaseInsensitiveCompare<wchar_t>());
} else {
DWORD read_value;
- found = key.ReadValueDW(_name.c_str(), &read_value) == ERROR_SUCCESS;
- correct_value = read_value == _int_value;
+ found = key.ReadValueDW(name_.c_str(), &read_value) == ERROR_SUCCESS;
+ correct_value = read_value == int_value_;
}
return found ?
(correct_value ? SAME_VALUE : DIFFERENT_VALUE) : DOES_NOT_EXIST;
diff --git a/chrome/renderer/DEPS b/chrome/renderer/DEPS
index d437fb2..3900f77 100644
--- a/chrome/renderer/DEPS
+++ b/chrome/renderer/DEPS
@@ -19,9 +19,6 @@
"+webkit/glue",
"+webkit/renderer",
- # TODO(jam): eliminate all of these. http://crbug.com/263054
- "!webkit/plugins/plugin_constants.h",
-
"+third_party/npapi/bindings",
"+third_party/re2",
"+third_party/smhasher",
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 9f8ef8d..5746899 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -17,13 +17,12 @@
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/content_settings_pattern.h"
-#include "chrome/common/extensions/chrome_manifest_handlers.h"
+#include "chrome/common/extensions/chrome_extensions_client.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_manifest_constants.h"
#include "chrome/common/extensions/extension_process_policy.h"
#include "chrome/common/extensions/extension_set.h"
-#include "chrome/common/extensions/permissions/chrome_api_permissions.h"
#include "chrome/common/external_ipc_fuzzer.h"
#include "chrome/common/localized_error.h"
#include "chrome/common/pepper_permission_util.h"
@@ -344,9 +343,8 @@
WebSecurityPolicy::registerURLSchemeAsBypassingContentSecurityPolicy(
extension_resource_scheme);
- extensions::PermissionsInfo::GetInstance()->InitializeWithDelegate(
- extensions::ChromeAPIPermissions());
- extensions::RegisterChromeManifestHandlers();
+ extensions::ExtensionsClient::Set(
+ extensions::ChromeExtensionsClient::GetInstance());
}
void ChromeContentRendererClient::RenderViewCreated(
@@ -1087,7 +1085,7 @@
bool ChromeContentRendererClient::ShouldOverridePageVisibilityState(
const content::RenderView* render_view,
- WebKit::WebPageVisibilityState* override_state) const {
+ WebKit::WebPageVisibilityState* override_state) {
if (!prerender::PrerenderHelper::IsPrerendering(render_view))
return false;
@@ -1228,8 +1226,16 @@
return NULL;
}
+bool ChromeContentRendererClient::IsExternalPepperPlugin(
+ const std::string& module_name) {
+ // TODO(bbudge) remove this when the trusted NaCl plugin has been removed.
+ // We must defer certain plugin events for NaCl instances since we switch
+ // from the in-process to the out-of-process proxy after instantiating them.
+ return module_name == "Native Client";
+}
+
bool ChromeContentRendererClient::IsPluginAllowedToCallRequestOSFileHandle(
- WebKit::WebPluginContainer* container) const {
+ WebKit::WebPluginContainer* container) {
#if defined(ENABLE_PLUGINS)
if (!container)
return false;
@@ -1252,7 +1258,7 @@
}
bool ChromeContentRendererClient::AllowBrowserPlugin(
- WebKit::WebPluginContainer* container) const {
+ WebKit::WebPluginContainer* container) {
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableBrowserPluginForAllViewTypes))
return true;
@@ -1278,7 +1284,7 @@
}
bool ChromeContentRendererClient::AllowPepperMediaStreamAPI(
- const GURL& url) const {
+ const GURL& url) {
#if !defined(OS_ANDROID)
std::string host = url.host();
// Allow only the Hangouts app to use the MediaStream APIs. It's OK to check
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index 94d9431..b4b7231 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -116,7 +116,7 @@
virtual WebKit::WebPrescientNetworking* GetPrescientNetworking() OVERRIDE;
virtual bool ShouldOverridePageVisibilityState(
const content::RenderView* render_view,
- WebKit::WebPageVisibilityState* override_state) const OVERRIDE;
+ WebKit::WebPageVisibilityState* override_state) OVERRIDE;
virtual bool HandleGetCookieRequest(content::RenderView* sender,
const GURL& url,
const GURL& first_party_for_cookies,
@@ -126,16 +126,17 @@
const GURL& first_party_for_cookies,
const std::string& value) OVERRIDE;
virtual bool AllowBrowserPlugin(
- WebKit::WebPluginContainer* container) const OVERRIDE;
+ WebKit::WebPluginContainer* container) OVERRIDE;
virtual const void* CreatePPAPIInterface(
const std::string& interface_name) OVERRIDE;
+ virtual bool IsExternalPepperPlugin(const std::string& module_name) OVERRIDE;
// TODO(victorhsieh): move to ChromeContentBrowserClient once we migrate
// PPAPI FileIO host to browser.
virtual bool IsPluginAllowedToCallRequestOSFileHandle(
- WebKit::WebPluginContainer* container) const OVERRIDE;
+ WebKit::WebPluginContainer* container) OVERRIDE;
virtual WebKit::WebSpeechSynthesizer* OverrideSpeechSynthesizer(
WebKit::WebSpeechSynthesizerClient* client) OVERRIDE;
- virtual bool AllowPepperMediaStreamAPI(const GURL& url) const OVERRIDE;
+ virtual bool AllowPepperMediaStreamAPI(const GURL& url) OVERRIDE;
// For testing.
void SetExtensionDispatcher(extensions::Dispatcher* extension_dispatcher);
diff --git a/chrome/renderer/extensions/api_definitions_natives.cc b/chrome/renderer/extensions/api_definitions_natives.cc
index 0fb03ae..6bd6af0 100644
--- a/chrome/renderer/extensions/api_definitions_natives.cc
+++ b/chrome/renderer/extensions/api_definitions_natives.cc
@@ -6,7 +6,8 @@
#include <algorithm>
-#include "chrome/common/extensions/features/base_feature_provider.h"
+#include "chrome/common/extensions/features/feature.h"
+#include "extensions/common/features/feature_provider.h"
namespace extensions {
@@ -22,7 +23,7 @@
void ApiDefinitionsNatives::GetExtensionAPIDefinitionsForTest(
const v8::FunctionCallbackInfo<v8::Value>& args) {
std::vector<std::string> apis;
- FeatureProvider* feature_provider = BaseFeatureProvider::GetByName("api");
+ FeatureProvider* feature_provider = FeatureProvider::GetByName("api");
const std::vector<std::string>& feature_names =
feature_provider->GetAllFeatureNames();
for (std::vector<std::string>::const_iterator i = feature_names.begin();
diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc
index 3b2c3ef..b569c0b 100644
--- a/chrome/renderer/extensions/dispatcher.cc
+++ b/chrome/renderer/extensions/dispatcher.cc
@@ -23,8 +23,8 @@
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_manifest_constants.h"
#include "chrome/common/extensions/extension_messages.h"
-#include "chrome/common/extensions/features/base_feature_provider.h"
#include "chrome/common/extensions/features/feature.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/common/extensions/manifest.h"
#include "chrome/common/extensions/manifest_handlers/externally_connectable.h"
#include "chrome/common/extensions/manifest_handlers/sandboxed_page_info.h"
@@ -78,14 +78,17 @@
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/v8_value_converter.h"
#include "extensions/common/constants.h"
+#include "extensions/common/features/feature_provider.h"
#include "extensions/common/view_type.h"
#include "grit/common_resources.h"
#include "grit/renderer_resources.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"
#include "third_party/WebKit/public/web/WebDataSource.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
#include "third_party/WebKit/public/web/WebView.h"
@@ -472,6 +475,9 @@
InitOriginPermissions(extension);
}
+ if (IsWithinPlatformApp())
+ EnableCustomElementWhiteList();
+
is_webkit_initialized_ = true;
}
@@ -507,7 +513,7 @@
}
void Dispatcher::OnSetChannel(int channel) {
- Feature::SetCurrentChannel(
+ extensions::SetCurrentChannel(
static_cast<chrome::VersionInfo::Channel>(channel));
}
@@ -666,8 +672,6 @@
}
if (runtime_is_available)
RegisterBinding("runtime", context);
- else
- DeregisterBinding("runtime", context);
break;
}
@@ -676,7 +680,7 @@
case Feature::CONTENT_SCRIPT_CONTEXT: {
// Extension context; iterate through all the APIs and bind the available
// ones.
- FeatureProvider* feature_provider = BaseFeatureProvider::GetByName("api");
+ FeatureProvider* feature_provider = FeatureProvider::GetByName("api");
const std::vector<std::string>& apis =
feature_provider->GetAllFeatureNames();
for (std::vector<std::string>::const_iterator it = apis.begin();
@@ -741,7 +745,7 @@
// If app is available and app.window is not, just install app.
// If app.window is available and app is not, delete app and install
// app.window on a new object so app does not have to be loaded.
- FeatureProvider* feature_provider = BaseFeatureProvider::GetByName("api");
+ FeatureProvider* feature_provider = FeatureProvider::GetByName("api");
std::string ancestor_name;
bool only_ancestor_available = false;
@@ -777,9 +781,29 @@
std::string bind_name;
v8::Handle<v8::Object> bind_object =
GetOrCreateBindObjectIfAvailable(api_name, &bind_name, context);
+
+ // Empty if the bind object failed to be created, probably because the
+ // extension overrode chrome with a non-object, e.g. window.chrome = true.
if (bind_object.IsEmpty())
return;
+ v8::Local<v8::String> v8_api_name = v8::String::New(api_name.c_str());
+ if (bind_object->HasRealNamedProperty(v8_api_name)) {
+ // The bind object may already have the property if the API has been
+ // registered before (or if the extension has put something there already,
+ // but, whatevs).
+ //
+ // In the former case, we need to re-register the bindings for the APIs
+ // which the extension now has permissions for (if any), but not touch any
+ // others so that we don't destroy state such as event listeners.
+ //
+ // TODO(kalman): Only register available APIs to make this all moot.
+ if (bind_object->HasRealNamedCallbackProperty(v8_api_name))
+ return; // lazy binding still there, nothing to do
+ if (bind_object->Get(v8_api_name)->IsObject())
+ return; // binding has already been fully installed
+ }
+
ModuleSystem* module_system = context->module_system();
if (lazy_bindings_map_.find(api_name) != lazy_bindings_map_.end()) {
InstallBindings(module_system, context->v8_context(), api_name);
@@ -1076,7 +1100,7 @@
AddOrRemoveBindingsForContext(context);
- bool is_within_platform_app = IsWithinPlatformApp(frame);
+ bool is_within_platform_app = IsWithinPlatformApp();
// Inject custom JS into the platform app context.
if (is_within_platform_app) {
module_system->Require("platformApp");
@@ -1084,7 +1108,7 @@
if (context_type == Feature::BLESSED_EXTENSION_CONTEXT &&
is_within_platform_app &&
- Feature::GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV &&
+ GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV &&
CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableAppWindowControls)) {
module_system->Require("windowControls");
@@ -1100,7 +1124,7 @@
if (extension->HasAPIPermission(APIPermission::kWebView)) {
module_system->Require("webView");
bool includeExperimental =
- Feature::GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV ||
+ GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV ||
extension->id() == extension_misc::kIdentityApiUiAppId;
if (!includeExperimental) {
// TODO(asargent) We need a whitelist for webview experimental.
@@ -1149,11 +1173,14 @@
return extensions_.GetExtensionOrAppIDByURL(frame_url);
}
-bool Dispatcher::IsWithinPlatformApp(const WebFrame* frame) {
- GURL url(UserScriptSlave::GetDataSourceURLForFrame(frame->top()));
- const Extension* extension = extensions_.GetExtensionOrAppByURL(url);
-
- return extension && extension->is_platform_app();
+bool Dispatcher::IsWithinPlatformApp() {
+ for (std::set<std::string>::iterator iter = active_extension_ids_.begin();
+ iter != active_extension_ids_.end(); ++iter) {
+ const Extension* extension = extensions_.GetByID(*iter);
+ if (extension && extension->is_platform_app())
+ return true;
+ }
+ return false;
}
void Dispatcher::WillReleaseScriptContext(
@@ -1171,7 +1198,7 @@
}
void Dispatcher::DidCreateDocumentElement(WebKit::WebFrame* frame) {
- if (IsWithinPlatformApp(frame)) {
+ if (IsWithinPlatformApp()) {
// WebKit doesn't let us define an additional user agent stylesheet, so we
// insert the default platform app stylesheet into all documents that are
// loaded in each app.
@@ -1222,6 +1249,9 @@
extension_id,
extension->url(),
string16());
+
+ if (IsWithinPlatformApp())
+ EnableCustomElementWhiteList();
}
}
@@ -1269,6 +1299,14 @@
}
}
+void Dispatcher::EnableCustomElementWhiteList() {
+ WebKit::WebRuntimeFeatures::enableCustomElements(true);
+ WebKit::WebCustomElement::allowTagName("webview");
+ // TODO(fsamuel): Add <adview> to the whitelist once it has been converted
+ // into a custom element.
+ WebKit::WebCustomElement::allowTagName("browser-plugin");
+}
+
void Dispatcher::AddOrRemoveBindings(const std::string& extension_id) {
v8_context_set().ForEach(
extension_id,
diff --git a/chrome/renderer/extensions/dispatcher.h b/chrome/renderer/extensions/dispatcher.h
index b43067d..b145eab 100644
--- a/chrome/renderer/extensions/dispatcher.h
+++ b/chrome/renderer/extensions/dispatcher.h
@@ -200,6 +200,9 @@
const Extension* extension,
const URLPatternSet& origins);
+ // Enable custom element whitelist in Apps.
+ void EnableCustomElementWhiteList();
+
// Adds or removes bindings for every context belonging to |extension_id|, or
// or all contexts if |extension_id| is empty.
void AddOrRemoveBindings(const std::string& extension_id);
@@ -226,10 +229,8 @@
v8::Handle<v8::Context> v8_context,
const std::string& api);
- // Determines whether |frame| is loading a platform app resource URL. (this
- // evaluates to true for iframes in platform apps and sandboxed resources that
- // are not in the same origin).
- bool IsWithinPlatformApp(const WebKit::WebFrame* frame);
+ // Returns whether the current renderer hosts a platform app.
+ bool IsWithinPlatformApp();
bool IsSandboxedPage(const GURL& url) const;
diff --git a/chrome/renderer/extensions/module_system.cc b/chrome/renderer/extensions/module_system.cc
index bf3dd70..8994293 100644
--- a/chrome/renderer/extensions/module_system.cc
+++ b/chrome/renderer/extensions/module_system.cc
@@ -12,6 +12,7 @@
#include "base/strings/stringprintf.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension_messages.h"
+#include "chrome/common/extensions/features/feature_channel.h"
#include "chrome/renderer/extensions/chrome_v8_context.h"
#include "chrome/renderer/extensions/console.h"
#include "chrome/renderer/extensions/safe_builtins.h"
@@ -53,7 +54,7 @@
full_message += message;
// <= dev means dev, canary, and trunk.
- if (Feature::GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV)
+ if (GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV)
console::Fatal(v8::Context::GetCalling(), full_message);
else
console::Error(v8::Context::GetCalling(), full_message);
diff --git a/chrome/renderer/extensions/runtime_custom_bindings.cc b/chrome/renderer/extensions/runtime_custom_bindings.cc
index dc43a8a..4f364a3 100644
--- a/chrome/renderer/extensions/runtime_custom_bindings.cc
+++ b/chrome/renderer/extensions/runtime_custom_bindings.cc
@@ -9,13 +9,14 @@
#include "base/values.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_messages.h"
-#include "chrome/common/extensions/features/base_feature_provider.h"
+#include "chrome/common/extensions/features/feature.h"
#include "chrome/common/extensions/manifest.h"
#include "chrome/renderer/extensions/api_activity_logger.h"
#include "chrome/renderer/extensions/chrome_v8_context.h"
#include "chrome/renderer/extensions/dispatcher.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/v8_value_converter.h"
+#include "extensions/common/features/feature_provider.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
@@ -67,7 +68,7 @@
const v8::FunctionCallbackInfo<v8::Value>& args) {
// Verify that the extension has permission to use native messaging.
Feature::Availability availability =
- BaseFeatureProvider::GetByName("permission")->
+ FeatureProvider::GetByName("permission")->
GetFeature("nativeMessaging")->IsAvailableToContext(
GetExtensionForRenderView(),
context()->context_type(),
diff --git a/chrome/renderer/pepper/pepper_flash_drm_renderer_host.cc b/chrome/renderer/pepper/pepper_flash_drm_renderer_host.cc
index ca59c7e..7f2011c 100644
--- a/chrome/renderer/pepper/pepper_flash_drm_renderer_host.cc
+++ b/chrome/renderer/pepper/pepper_flash_drm_renderer_host.cc
@@ -12,7 +12,6 @@
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
namespace chrome {
@@ -28,7 +27,8 @@
PP_Instance instance,
PP_Resource resource)
: ResourceHost(host->GetPpapiHost(), instance, resource),
- renderer_ppapi_host_(host) {
+ renderer_ppapi_host_(host),
+ weak_factory_(this) {
}
PepperFlashDRMRendererHost::~PepperFlashDRMRendererHost() {
@@ -56,13 +56,26 @@
base::FilePath voucher_file = plugin_dir.Append(
base::FilePath(kVoucherFilename));
- ppapi::PPB_FileRef_CreateInfo create_info;
- ppapi::proxy::PPB_FileRef_Proxy::SerializeFileRef(
- plugin_instance->CreateExternalFileReference(voucher_file),
- &create_info);
- context->reply_msg =
- PpapiPluginMsg_FlashDRM_GetVoucherFileReply(create_info);
- return PP_OK;
+ renderer_ppapi_host_->CreateBrowserResourceHost(
+ pp_instance(),
+ PpapiHostMsg_FileRef_CreateExternal(voucher_file),
+ base::Bind(&PepperFlashDRMRendererHost::DidCreateFileRefHost,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext(),
+ voucher_file));
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void PepperFlashDRMRendererHost::DidCreateFileRefHost(
+ const ppapi::host::ReplyMessageContext& reply_context,
+ const base::FilePath& external_path,
+ int pending_resource_id) {
+ ppapi::FileRefCreateInfo create_info =
+ ppapi::MakeExternalFileRefCreateInfo(external_path,
+ std::string(),
+ pending_resource_id);
+ host()->SendReply(reply_context,
+ PpapiPluginMsg_FlashDRM_GetVoucherFileReply(create_info));
}
} // namespace chrome
diff --git a/chrome/renderer/pepper/pepper_flash_drm_renderer_host.h b/chrome/renderer/pepper/pepper_flash_drm_renderer_host.h
index f7247d6..a0382b6 100644
--- a/chrome/renderer/pepper/pepper_flash_drm_renderer_host.h
+++ b/chrome/renderer/pepper/pepper_flash_drm_renderer_host.h
@@ -7,8 +7,13 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
#include "ppapi/host/resource_host.h"
+namespace base {
+class FilePath;
+}
+
namespace content {
class RendererPpapiHost;
}
@@ -31,9 +36,16 @@
private:
int32_t OnGetVoucherFile(ppapi::host::HostMessageContext* context);
+ void DidCreateFileRefHost(
+ const ppapi::host::ReplyMessageContext& reply_context,
+ const base::FilePath& external_path,
+ int pending_resource_id);
+
// Non-owning pointer.
content::RendererPpapiHost* renderer_ppapi_host_;
+ base::WeakPtrFactory<PepperFlashDRMRendererHost> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(PepperFlashDRMRendererHost);
};
diff --git a/chrome/renderer/plugins/plugin_placeholder.cc b/chrome/renderer/plugins/plugin_placeholder.cc
index bcc4fb2..eae3e0e 100644
--- a/chrome/renderer/plugins/plugin_placeholder.cc
+++ b/chrome/renderer/plugins/plugin_placeholder.cc
@@ -16,6 +16,7 @@
#include "chrome/renderer/chrome_content_renderer_client.h"
#include "chrome/renderer/custom_menu_commands.h"
#include "chrome/renderer/plugins/plugin_uma.h"
+#include "content/public/common/content_constants.h"
#include "content/public/common/context_menu_params.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/render_view.h"
@@ -39,10 +40,6 @@
#include "ui/base/resource/resource_bundle.h"
#include "ui/webui/jstemplate_builder.h"
-#if defined(ENABLE_MOBILE_YOUTUBE_PLUGIN)
-#include "webkit/plugins/plugin_constants.h"
-#endif
-
using content::RenderThread;
using content::RenderView;
using WebKit::WebContextMenuData;
@@ -624,6 +621,6 @@
EndsWith(host, "youtube-nocookie.com", true);
return is_youtube && IsValidYouTubeVideo(url.path()) &&
- LowerCaseEqualsASCII(mime_type, kFlashPluginSwfMimeType);
+ LowerCaseEqualsASCII(mime_type, content::kFlashPluginSwfMimeType);
}
#endif
diff --git a/chrome/renderer/plugins/plugin_uma.cc b/chrome/renderer/plugins/plugin_uma.cc
index b634074..b6c8764 100644
--- a/chrome/renderer/plugins/plugin_uma.cc
+++ b/chrome/renderer/plugins/plugin_uma.cc
@@ -11,7 +11,6 @@
#include "base/strings/string_util.h"
#include "content/public/common/content_constants.h"
#include "third_party/widevine/cdm/widevine_cdm_common.h"
-#include "webkit/plugins/plugin_constants.h"
namespace {
@@ -192,8 +191,8 @@
if (mime_type == content::kBrowserPluginMimeType)
return BROWSER_PLUGIN;
- if (mime_type == kFlashPluginSwfMimeType ||
- mime_type == kFlashPluginSplMimeType) {
+ if (mime_type == content::kFlashPluginSwfMimeType ||
+ mime_type == content::kFlashPluginSplMimeType) {
return SHOCKWAVE_FLASH;
}
diff --git a/chrome/renderer/resources/extensions/searchbox_api.js b/chrome/renderer/resources/extensions/searchbox_api.js
index 6bdb5ea..3aa3d53 100644
--- a/chrome/renderer/resources/extensions/searchbox_api.js
+++ b/chrome/renderer/resources/extensions/searchbox_api.js
@@ -21,6 +21,7 @@
native function GetStartMargin();
native function IsFocused();
native function IsKeyCaptureEnabled();
+ native function Paste();
native function SetVoiceSearchSupported();
native function StartCapturingKeyStrokes();
native function StopCapturingKeyStrokes();
@@ -42,6 +43,10 @@
return GetMostVisitedItemData(restrictedId);
};
+ this.paste = function(value) {
+ Paste(value);
+ };
+
this.setVoiceSearchSupported = function(supported) {
SetVoiceSearchSupported(supported);
};
diff --git a/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js b/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js
index c2df0b0..352b0a7 100644
--- a/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/sync_file_system_custom_bindings.js
@@ -23,7 +23,7 @@
}
$Array.forEach(['getFileStatus'], bindFileEntryFunction);
- // Functions which take in an [instanceOf=EntryArray].
+ // Functions which take in a FileEntry array.
function bindFileEntryArrayFunction(functionName) {
apiFunctions.setUpdateArgumentsPostValidate(
functionName, function(entries, callback) {
diff --git a/chrome/renderer/resources/extensions/test_custom_bindings.js b/chrome/renderer/resources/extensions/test_custom_bindings.js
index 231e339..fe330d3 100644
--- a/chrome/renderer/resources/extensions/test_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/test_custom_bindings.js
@@ -228,6 +228,18 @@
chromeTest.assertEq(expectedError, chrome.runtime.lastError.message);
});
+ apiFunctions.setHandleRequest('assertThrows',
+ function(fn, self, args, message) {
+ assertTrue(typeof fn == 'function');
+ try {
+ fn.apply(self, args);
+ chromeTest.fail('Did not throw error: ' + fn);
+ } catch (e) {
+ if (message !== undefined)
+ chromeTest.assertEq(message, e.message);
+ }
+ });
+
function safeFunctionApply(func, args) {
try {
if (func)
diff --git a/chrome/renderer/resources/extensions/web_view_experimental.js b/chrome/renderer/resources/extensions/web_view_experimental.js
index cfb11ed..c2bb066 100644
--- a/chrome/renderer/resources/extensions/web_view_experimental.js
+++ b/chrome/renderer/resources/extensions/web_view_experimental.js
@@ -41,7 +41,7 @@
self.viewInstanceId_);
}
return self[webRequestEvent.name + '_'];
- }
+ };
};
// Populate the WebRequest events from the API definition.
@@ -52,7 +52,6 @@
webRequestSchema.events[i].name,
{
get: webRequestEvent,
- configuable: false,
enumerable: true
}
);
@@ -61,7 +60,6 @@
webRequestSchema.events[i].name,
{
get: webRequestEvent,
- configuable: false,
enumerable: true
}
);
@@ -71,7 +69,6 @@
'request',
{
value: request,
- configurable: false,
enumerable: true,
writable: false
}
@@ -114,7 +111,7 @@
if (browserPluginNode['-internal-setPermission'](requestId, false, '')) {
showWarningMessage(dialogType);
}
- }
+ };
browserPluginNode.addEventListener('-internal-dialog', function(e) {
var evt = new Event('dialog', { bubbles: true, cancelable: true });
diff --git a/chrome/renderer/searchbox/searchbox.cc b/chrome/renderer/searchbox/searchbox.cc
index e184eab..05f5570 100644
--- a/chrome/renderer/searchbox/searchbox.cc
+++ b/chrome/renderer/searchbox/searchbox.cc
@@ -231,6 +231,11 @@
url, transition, disposition, is_search_type));
}
+void SearchBox::Paste(const string16& text) {
+ render_view()->Send(new ChromeViewHostMsg_PasteAndOpenDropdown(
+ render_view()->GetRoutingID(), render_view()->GetPageId(), text));
+}
+
void SearchBox::SetVoiceSearchSupported(bool supported) {
render_view()->Send(new ChromeViewHostMsg_SetVoiceSearchSupported(
render_view()->GetRoutingID(), render_view()->GetPageId(), supported));
diff --git a/chrome/renderer/searchbox/searchbox.h b/chrome/renderer/searchbox/searchbox.h
index b4743c9..685c3cb 100644
--- a/chrome/renderer/searchbox/searchbox.h
+++ b/chrome/renderer/searchbox/searchbox.h
@@ -71,6 +71,9 @@
WindowOpenDisposition disposition,
bool is_search_type);
+ // Sends ChromeViewHostMsg_SearchBoxPaste to the browser.
+ void Paste(const string16& text);
+
const ThemeBackgroundInfo& GetThemeBackgroundInfo();
// Sends ChromeViewHostMsg_SetVoiceSearchSupported to the browser.
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc
index 3eacc3c..75663b7 100644
--- a/chrome/renderer/searchbox/searchbox_extension.cc
+++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -362,6 +362,9 @@
static void NavigateContentWindow(
const v8::FunctionCallbackInfo<v8::Value>& args);
+ // Pastes provided value or clipboard's content into the omnibox.
+ static void Paste(const v8::FunctionCallbackInfo<v8::Value>& args);
+
// Indicates whether the page supports voice search.
static void SetVoiceSearchSupported(
const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -485,6 +488,8 @@
return v8::FunctionTemplate::New(LogEvent);
if (name->Equals(v8::String::New("NavigateContentWindow")))
return v8::FunctionTemplate::New(NavigateContentWindow);
+ if (name->Equals(v8::String::New("Paste")))
+ return v8::FunctionTemplate::New(Paste);
if (name->Equals(v8::String::New("SetVoiceSearchSupported")))
return v8::FunctionTemplate::New(SetVoiceSearchSupported);
if (name->Equals(v8::String::New("StartCapturingKeyStrokes")))
@@ -852,6 +857,20 @@
}
// static
+void SearchBoxExtensionWrapper::Paste(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ content::RenderView* render_view = GetRenderView();
+ if (!render_view) return;
+
+ string16 text;
+ if (!args[0]->IsUndefined())
+ text = V8ValueToUTF16(args[0]);
+
+ DVLOG(1) << render_view << " Paste: " << text;
+ SearchBox::Get(render_view)->Paste(text);
+}
+
+// static
void SearchBoxExtensionWrapper::StartCapturingKeyStrokes(
const v8::FunctionCallbackInfo<v8::Value>& args) {
content::RenderView* render_view = GetRenderView();
diff --git a/chrome/test/DEPS b/chrome/test/DEPS
index 8c88f2b..5a9fdbd 100644
--- a/chrome/test/DEPS
+++ b/chrome/test/DEPS
@@ -19,6 +19,5 @@
"+sandbox/win/src",
"+sandbox/win/tests",
"+webkit/glue",
- "+webkit/plugins",
"+win8/test",
]
diff --git a/chrome/test/base/chrome_test_suite.cc b/chrome/test/base/chrome_test_suite.cc
index 01668b4..cdb3378 100644
--- a/chrome/test/base/chrome_test_suite.cc
+++ b/chrome/test/base/chrome_test_suite.cc
@@ -21,8 +21,7 @@
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/chrome_paths.h"
-#include "chrome/common/extensions/chrome_manifest_handlers.h"
-#include "chrome/common/extensions/permissions/chrome_api_permissions.h"
+#include "chrome/common/extensions/chrome_extensions_client.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/utility/chrome_content_utility_client.h"
@@ -234,12 +233,11 @@
#if !defined(OS_IOS)
extensions::RegisterPathProvider();
+ extensions::ExtensionsClient::Set(
+ extensions::ChromeExtensionsClient::GetInstance());
+
// Only want to do this for unit tests.
if (!content::GetCurrentTestLauncherDelegate()) {
- extensions::PermissionsInfo::GetInstance()->InitializeWithDelegate(
- extensions::ChromeAPIPermissions());
- extensions::RegisterChromeManifestHandlers();
-
// For browser tests, this won't create the right object since
// TestChromeWebUIControllerFactory is used. That's created and
// registered in ChromeBrowserMainParts as in normal startup.
diff --git a/chrome/test/base/test_location_bar.h b/chrome/test/base/test_location_bar.h
index b84e35e..22ef364b 100644
--- a/chrome/test/base/test_location_bar.h
+++ b/chrome/test/base/test_location_bar.h
@@ -38,7 +38,7 @@
virtual void UpdatePageActions() OVERRIDE {}
virtual void InvalidatePageActions() OVERRIDE {}
virtual void UpdateOpenPDFInReaderPrompt() OVERRIDE {}
- virtual void UpdateAutofillCreditCardView() OVERRIDE {}
+ virtual void UpdateGeneratedCreditCardView() OVERRIDE {}
virtual void SaveStateToContents(content::WebContents* contents) OVERRIDE {}
virtual void Revert() OVERRIDE {}
virtual const OmniboxView* GetLocationEntry() const OVERRIDE;
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index 9570da0..318c14c 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -284,9 +284,9 @@
void TestingProfile::Init() {
// If threads have been initialized, we should be on the UI thread.
- DCHECK(
- !content::BrowserThread::IsWellKnownThread(content::BrowserThread::UI) ||
- content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ DCHECK(!content::BrowserThread::IsThreadInitialized(
+ content::BrowserThread::UI) ||
+ content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
// Normally this would happen during browser startup, but for tests
// we need to trigger creation of Profile-related services.
diff --git a/chrome/test/chromedriver/DEPS b/chrome/test/chromedriver/DEPS
index 0d83e87..f4ece7a 100644
--- a/chrome/test/chromedriver/DEPS
+++ b/chrome/test/chromedriver/DEPS
@@ -5,7 +5,6 @@
"+chrome/test/chromedriver",
- "+third_party/mongoose",
"+third_party/webdriver",
"+third_party/zlib",
]
diff --git a/chrome/test/chromedriver/README.txt b/chrome/test/chromedriver/README.txt
index ef3d959..43126c4 100644
--- a/chrome/test/chromedriver/README.txt
+++ b/chrome/test/chromedriver/README.txt
@@ -49,34 +49,39 @@
command is finished, it will invoke a callback, which will eventually make its
way back to the IO thread as a HTTP response for the server to send.
-=====Code structure=====
-1) chrome/test/chromedriver
+=====Code structure (relative to this file)=====
+1) .
Implements chromedriver commands.
-2) chrome/test/chromedriver/chrome
-A basic interface for controlling Chrome via DevTools. Should not have
-knowledge about WebDriver, and thus not depend on chrome/test/chromedriver.
+2) chrome/
+A basic interface for controlling Chrome. Should not depend on or reference
+WebDriver-related code or concepts.
-3) chrome/test/chromedriver/js
+3) js/
Javascript helper scripts.
-4) chrome/test/chromedriver/net
+4) net/
Code to deal with network communication, such as connection to DevTools.
-5) chrome/test/chromedriver/client
+5) client/
Code for a python client.
-6) chrome/test/chromedriver/server
+6) server/
Code for the chromedriver server.
A python wrapper to the chromedriver server.
-7) chrome/test/chromedriver/extension
+7) extension/
An extension used for automating the desktop browser.
-8) chrome/test/chromedriver/third_party
+8) test/
+Integration tests.
+
+9) third_party/
Third party libraries used by chromedriver.
=====Testing=====
+See the ChromeDriver waterfall at:
+ http://build.chromium.org/p/chromium.chromedriver/waterfall
There are 4 test suites for verifying ChromeDriver's correctness:
1) chromedriver2_unittests (chrome/chrome_tests.gypi)
@@ -88,15 +93,14 @@
This is a collection of C++ medium sized tests which can be run optionally
on the trybots.
-3) python tests
-These are integration tests which can be found in run_py_tests.py. They are
-run on the chromium QA bots:
- http://build.chromium.org/p/chromium.pyauto/waterfall
+3) python integration tests
+Run test/run_py_tests.py --help for more info. These are only run on the
+ChromeDriver waterfall.
4) WebDriver Java acceptance tests
These are integration tests from the WebDriver open source project which can
-be run via run_java_tests.py. They are also run on the chromium QA bots.
-See http://src.chromium.org/viewvc/chrome/trunk/deps/third_party/webdriver
+be run via test/run_java_tests.py. They are only run on the ChromeDriver
+bots. Run with --help for more info.
=====Contributing=====
Find an open issue and submit a patch for review by an individual listed in
diff --git a/chrome/test/chromedriver/chrome/web_view_impl.cc b/chrome/test/chromedriver/chrome/web_view_impl.cc
index 9357bbe..b463b0e 100644
--- a/chrome/test/chromedriver/chrome/web_view_impl.cc
+++ b/chrome/test/chromedriver/chrome/web_view_impl.cc
@@ -173,8 +173,9 @@
scoped_ptr<base::Value>* result) {
std::string json;
base::JSONWriter::Write(&args, &json);
+ // TODO(zachconrad): Second null should be array of shadow host ids.
std::string expression = base::StringPrintf(
- "(%s).apply(null, [%s, %s])",
+ "(%s).apply(null, [null, %s, %s])",
kCallFunctionScript,
function.c_str(),
json.c_str());
@@ -595,8 +596,9 @@
int* node_id) {
std::string json;
base::JSONWriter::Write(&args, &json);
+ // TODO(zachconrad): Second null should be array of shadow host ids.
std::string expression = base::StringPrintf(
- "(%s).apply(null, [%s, %s, true])",
+ "(%s).apply(null, [null, %s, %s, true])",
kCallFunctionScript,
function.c_str(),
json.c_str());
diff --git a/chrome/test/chromedriver/chrome_paths.py b/chrome/test/chromedriver/chrome_paths.py
index a0d3812..5b9c976 100644
--- a/chrome/test/chromedriver/chrome_paths.py
+++ b/chrome/test/chromedriver/chrome_paths.py
@@ -12,7 +12,8 @@
def GetSrc():
"""Returns the path to the root src directory."""
- return os.path.join(_THIS_DIR, os.pardir, os.pardir, os.pardir)
+ return os.path.abspath(os.path.join(_THIS_DIR, os.pardir, os.pardir,
+ os.pardir))
def GetTestData():
diff --git a/chrome/test/chromedriver/js/call_function.js b/chrome/test/chromedriver/js/call_function.js
index f9b1d0a..7a194b8 100644
--- a/chrome/test/chromedriver/js/call_function.js
+++ b/chrome/test/chromedriver/js/call_function.js
@@ -28,6 +28,13 @@
var ELEMENT_KEY = 'ELEMENT';
/**
+ * True if shadow dom is enabled.
+ * @const
+ * @type {boolean}
+ */
+var SHADOW_DOM_ENABLED = typeof WebKitShadowRoot === 'function';
+
+/**
* A cache which maps IDs <-> cached objects for the purpose of identifying
* a script object remotely.
* @constructor
@@ -79,18 +86,41 @@
clearStale: function() {
for (var id in this.cache_) {
var node = this.cache_[id];
- while (node) {
- if (node == document)
- break;
- node = node.parentNode;
- }
- if (!node)
+ if (!this.isNodeReachable_(node))
delete this.cache_[id];
}
+ },
+
+ /**
+ * @private
+ * @param {!Node} node The node to check.
+ * @return {boolean} If the nodes is reachable.
+ */
+ isNodeReachable_: function(node) {
+ var nodeRoot = getNodeRoot(node);
+ if (nodeRoot == document)
+ return true;
+ else if (SHADOW_DOM_ENABLED && nodeRoot instanceof WebKitShadowRoot)
+ return true;
+
+ return false;
}
};
/**
+ * Returns the root element of the node. Found by traversing parentNodes until
+ * a node with no parent is found. This node is considered the root.
+ * @param {!Node} node The node to find the root element for.
+ * @return {!Node} The root node.
+ */
+function getNodeRoot(node) {
+ while (node.parentNode) {
+ node = node.parentNode;
+ }
+ return node;
+}
+
+/**
* Returns the global object cache for the page.
* @param {Document=} opt_doc The document whose cache to retrieve. Defaults to
* the current document.
@@ -114,9 +144,11 @@
function wrap(value) {
if (typeof(value) == 'object' && value != null) {
var nodeType = value['nodeType'];
- if (nodeType == NodeType.ELEMENT || nodeType == NodeType.DOCUMENT) {
+ if (nodeType == NodeType.ELEMENT || nodeType == NodeType.DOCUMENT
+ || (SHADOW_DOM_ENABLED && value instanceof WebKitShadowRoot)) {
var wrapped = {};
- wrapped[ELEMENT_KEY] = getPageCache(value.ownerDocument).storeItem(value);
+ var root = getNodeRoot(value);
+ wrapped[ELEMENT_KEY] = getPageCache(root).storeItem(value);
return wrapped;
}
@@ -157,6 +189,8 @@
* between cached object reference IDs and actual JS objects. The cache will
* automatically be pruned each call to remove stale references.
*
+ * @param {Array.<string>} shadowHostIds The host ids of the nested shadow
+ * DOMs the function should be executed in the context of.
* @param {function(...[*]) : *} func The function to invoke.
* @param {!Array.<*>} args The array of arguments to supply to the function,
* which will be unwrapped before invoking the function.
@@ -167,9 +201,18 @@
* unwrapped return was specified, this will be the function's pure return
* value.
*/
-function callFunction(func, args, opt_unwrappedReturn) {
+function callFunction(shadowHostIds, func, args, opt_unwrappedReturn) {
var cache = getPageCache();
cache.clearStale();
+ if (shadowHostIds && SHADOW_DOM_ENABLED) {
+ for (var i = 0; i < shadowHostIds.length; i++) {
+ var host = cache.retrieveItem(shadowHostIds[i]);
+ // TODO(zachconrad): Use the olderShadowRoot API when available to check
+ // all of the shadow roots.
+ cache = getPageCache(host.webkitShadowRoot);
+ cache.clearStale();
+ }
+ }
if (opt_unwrappedReturn)
return func.apply(null, unwrap(args, cache));
diff --git a/chrome/test/chromedriver/js/call_function_test.html b/chrome/test/chromedriver/js/call_function_test.html
index c11bc6c..7c0a2df 100644
--- a/chrome/test/chromedriver/js/call_function_test.html
+++ b/chrome/test/chromedriver/js/call_function_test.html
@@ -11,7 +11,7 @@
function testCallFunctionNoArgs() {
clearCache();
- var result = callFunction(function() { return 1; }, []);
+ var result = callFunction(null, function() { return 1; }, []);
assertEquals(0, result.status);
assertEquals(1, result.value);
}
@@ -19,11 +19,12 @@
function testCallFunctionThrows() {
clearCache();
- var result = callFunction(function() { throw new Error('fake error'); }, []);
+ var result = callFunction(null, function() { throw new Error('fake error'); },
+ []);
assertEquals(StatusCode.UNKNOWN_ERROR, result.status);
assertEquals('fake error', result.value);
- result = callFunction(function() {
+ result = callFunction(null, function() {
var e = new Error('fake error');
e.code = 77;
e.message = 'CUSTOM';
@@ -39,7 +40,7 @@
function func(primitive, elem) {
return [primitive, elem.querySelector('div')];
}
- var result = callFunction(func, [1, wrap(document)]);
+ var result = callFunction(null, func, [1, wrap(document)]);
assertEquals(0, result.status);
assertEquals(1, result.value[0]);
var cache = getPageCache();
@@ -52,7 +53,7 @@
function func(elem) {
return elem.querySelector('div');
}
- var result = callFunction(func, [wrap(document)], true);
+ var result = callFunction(null, func, [wrap(document)], true);
assertEquals(document.querySelector('div'), result);
}
@@ -76,7 +77,7 @@
var cache = getPageCache();
var arr = [1, new Array(1, new Object({a: 1, b: {a: 1, b: {}, c: 3}}), 3)];
var originalJson = JSON.stringify(arr);
- arr[1][1].b.b[ELEMENT_KEY] = cache.idPrefix_ + ':' + cache.nextId_;
+ arr[1][1].b.b[ELEMENT_KEY] = cache.idPrefix_ + '-' + cache.nextId_;
var wrappedJson = JSON.stringify(arr);
arr[1][1].b.b = document;
assertEquals(wrappedJson, JSON.stringify(wrap(arr)));
@@ -159,6 +160,105 @@
}
}
+function testCallFunctionWithShadowHost() {
+ clearCache();
+
+ // Set up something in the shadow DOM.
+ var host = document.body.appendChild(document.createElement('div'));
+ var root = host.webkitCreateShadowRoot();
+ var shadowDiv = root.appendChild(document.createElement('div'));
+
+ function func(element) {
+ return element;
+ }
+ var wrappedHost = wrap(host);
+
+ var result = callFunction(null, func, [wrappedHost]);
+ assertEquals(0, result.status);
+ assertEquals(wrappedHost['ELEMENT'], result.value['ELEMENT']);
+ var cache = getPageCache();
+ assertEquals(host, unwrap(result.value, cache));
+
+ document.body.removeChild(host);
+}
+
+function testCallFunctionWithShadowRoot() {
+ clearCache();
+
+ // Set up something in the shadow DOM.
+ var host = document.body.appendChild(document.createElement('div'));
+ var root = host.webkitCreateShadowRoot();
+ var shadowDiv = root.appendChild(document.createElement('div'));
+
+ function func(element) {
+ return element;
+ }
+ var wrappedHost = wrap(host);
+ var wrappedRoot = wrap(root);
+
+ // Trying without setting the shadow_path should fail.
+ var result = callFunction(null, func, [wrappedRoot]);
+ assertEquals(StatusCode.STALE_ELEMENT_REFERENCE, result.status);
+ // Should succeed with the shadow_path.
+ result = callFunction([wrappedHost['ELEMENT']], func, [wrappedRoot]);
+ assertEquals(0, result.status);
+ assertEquals(wrappedRoot['ELEMENT'], result.value['ELEMENT']);
+ var cache = getPageCache(root);
+ assertEquals(root, unwrap(result.value, cache));
+
+ document.body.removeChild(host);
+}
+
+function testCacheWithShadowDomAttached() {
+ clearCache();
+ var pageCache = getPageCache();
+
+ // Set up something in the shadow DOM.
+ var host = document.body.appendChild(document.createElement('div'));
+ var root = host.webkitCreateShadowRoot();
+ var shadowDiv = root.appendChild(document.createElement('div'));
+
+ // Test with attached element in shadow DOM.
+ var wrappedDiv = wrap(shadowDiv);
+ // It should NOT be in the page cache.
+ try {
+ unwrap(wrappedDiv, pageCache);
+ assert(false);
+ } catch (e) {
+ assertEquals(StatusCode.STALE_ELEMENT_REFERENCE, e.code);
+ }
+ // It should be in the shadow root cache.
+ var rootCache = getPageCache(root);
+ rootCache.clearStale();
+ var unwrappedDiv = unwrap(wrappedDiv, rootCache);
+ assertEquals(shadowDiv, unwrappedDiv);
+
+ document.body.removeChild(host);
+}
+
+function testCacheWithShadowDomDetachedChild() {
+ clearCache();
+
+ // Set up something in the shadow DOM.
+ var host = document.body.appendChild(document.createElement('div'));
+ var root = host.webkitCreateShadowRoot();
+ var shadowDiv = root.appendChild(document.createElement('div'));
+
+ // Test with detached element in shadow DOM.
+ var wrappedDiv = wrap(shadowDiv);
+ root.removeChild(shadowDiv);
+ var rootCache = getPageCache(root);
+ rootCache.clearStale();
+ try {
+ unwrap(wrappedDiv, rootCache);
+ assert(false);
+ } catch (e) {
+ assertEquals(StatusCode.STALE_ELEMENT_REFERENCE, e.code);
+ }
+
+ document.body.removeChild(host);
+}
+
</script>
<body>
<div><span></span></div>
diff --git a/chrome/test/chromedriver/run_buildbot_steps.py b/chrome/test/chromedriver/run_buildbot_steps.py
index fb43b1f..af4a10b 100755
--- a/chrome/test/chromedriver/run_buildbot_steps.py
+++ b/chrome/test/chromedriver/run_buildbot_steps.py
@@ -202,7 +202,7 @@
cmd = [
sys.executable,
- os.path.join(_THIS_DIR, 'run_all_tests.py'),
+ os.path.join(_THIS_DIR, 'test', 'run_all_tests.py'),
]
if options.android_package:
cmd.append('--android-package=' + options.android_package)
diff --git a/chrome/test/chromedriver/java_tests.txt b/chrome/test/chromedriver/test/java_tests.txt
similarity index 100%
rename from chrome/test/chromedriver/java_tests.txt
rename to chrome/test/chromedriver/test/java_tests.txt
diff --git a/chrome/test/chromedriver/run_all_tests.py b/chrome/test/chromedriver/test/run_all_tests.py
similarity index 96%
rename from chrome/test/chromedriver/run_all_tests.py
rename to chrome/test/chromedriver/test/run_all_tests.py
index 574fa92..7236c86 100755
--- a/chrome/test/chromedriver/run_all_tests.py
+++ b/chrome/test/chromedriver/test/run_all_tests.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@@ -10,12 +10,13 @@
import platform
import sys
+_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
+sys.path.insert(0, os.path.join(_THIS_DIR, os.pardir))
+
import archive
import chrome_paths
import util
-_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
-
def _AppendEnvironmentPath(env_name, path):
if env_name in os.environ:
@@ -153,7 +154,8 @@
_AddToolsToSystemPathForWindows()
if options.android_package:
- os.environ['PATH'] += os.pathsep + os.path.join(_THIS_DIR, 'chrome')
+ os.environ['PATH'] += os.pathsep + os.path.join(
+ _THIS_DIR, os.pardir, 'chrome')
code1 = RunPythonTests(chromedriver,
ref_chromedriver,
android_package=options.android_package)
diff --git a/chrome/test/chromedriver/run_java_tests.py b/chrome/test/chromedriver/test/run_java_tests.py
similarity index 93%
rename from chrome/test/chromedriver/run_java_tests.py
rename to chrome/test/chromedriver/test/run_java_tests.py
index 495e49b..76ecaf3 100755
--- a/chrome/test/chromedriver/run_java_tests.py
+++ b/chrome/test/chromedriver/test/run_java_tests.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@@ -17,6 +17,9 @@
import sys
import xml.dom.minidom as minidom
+_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
+sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir))
+
import chrome_paths
import test_environment
import util
@@ -279,8 +282,14 @@
'java_tests')
if (not os.path.exists(java_tests_src_dir) or
not os.listdir(java_tests_src_dir)):
- print ('"%s" is empty or it doesn\'t exist.' % java_tests_src_dir +
- 'Should add deps/third_party/webdriver to source checkout config')
+ java_tests_url = ('http://src.chromium.org/svn/trunk/deps/third_party'
+ '/webdriver')
+ print ('"%s" is empty or it doesn\'t exist. ' % java_tests_src_dir +
+ 'Need to map <chrome-svn>/trunk/deps/third_party/webdriver to '
+ 'chrome/test/chromedriver/third_party/java_tests in .gclient.\n'
+ 'Alternatively, do:\n'
+ ' $ cd chrome/test/chromedriver/third_party\n'
+ ' $ svn co %s java_tests' % java_tests_url)
return 1
results = []
diff --git a/chrome/test/chromedriver/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
similarity index 98%
rename from chrome/test/chromedriver/run_py_tests.py
rename to chrome/test/chromedriver/test/run_py_tests.py
index 35d6c9d..2a19c6c 100755
--- a/chrome/test/chromedriver/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@@ -14,8 +14,9 @@
import unittest
_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
-sys.path.insert(0, os.path.join(_THIS_DIR, 'client'))
-sys.path.insert(0, os.path.join(_THIS_DIR, 'server'))
+sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir))
+sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir, 'client'))
+sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir, 'server'))
import chrome_paths
import chromedriver
@@ -25,11 +26,10 @@
from webelement import WebElement
import webserver
-_TEST_DATA_DIR = os.path.join(_THIS_DIR, os.pardir, 'data', 'chromedriver')
+_TEST_DATA_DIR = os.path.join(chrome_paths.GetTestData(), 'chromedriver')
if util.IsLinux():
- sys.path.insert(0, os.path.join(_THIS_DIR, os.pardir, os.pardir, os.pardir,
- 'build', 'android'))
+ sys.path.insert(0, os.path.join(chrome_paths.GetSrc(), 'build', 'android'))
from pylib import android_commands
from pylib import forwarder
from pylib import valgrind_tools
diff --git a/chrome/test/chromedriver/test_environment.py b/chrome/test/chromedriver/test/test_environment.py
similarity index 93%
rename from chrome/test/chromedriver/test_environment.py
rename to chrome/test/chromedriver/test/test_environment.py
index 2344ad3..de8753b 100644
--- a/chrome/test/chromedriver/test_environment.py
+++ b/chrome/test/chromedriver/test/test_environment.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@@ -11,13 +11,13 @@
import os
import sys
+import chrome_paths
import util
_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
if util.IsLinux():
- sys.path.insert(0, os.path.join(_THIS_DIR, os.pardir, os.pardir, os.pardir,
- 'build', 'android'))
+ sys.path.insert(0, os.path.join(chrome_paths.GetSrc(), 'build', 'android'))
from pylib import android_commands
from pylib import forwarder
from pylib import valgrind_tools
diff --git a/chrome/test/chromedriver/test_expectations b/chrome/test/chromedriver/test/test_expectations
similarity index 99%
rename from chrome/test/chromedriver/test_expectations
rename to chrome/test/chromedriver/test/test_expectations
index 1e17ea2..b63c41e 100644
--- a/chrome/test/chromedriver/test_expectations
+++ b/chrome/test/chromedriver/test/test_expectations
@@ -1,4 +1,4 @@
-# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
diff --git a/chrome/test/chromedriver/unittest_util.py b/chrome/test/chromedriver/test/unittest_util.py
similarity index 98%
rename from chrome/test/chromedriver/unittest_util.py
rename to chrome/test/chromedriver/test/unittest_util.py
index 9de9805..7c07312 100644
--- a/chrome/test/chromedriver/unittest_util.py
+++ b/chrome/test/chromedriver/test/unittest_util.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
diff --git a/chrome/test/chromedriver/webserver.py b/chrome/test/chromedriver/test/webserver.py
similarity index 98%
rename from chrome/test/chromedriver/webserver.py
rename to chrome/test/chromedriver/test/webserver.py
index 170a48d..fb48cc5 100644
--- a/chrome/test/chromedriver/webserver.py
+++ b/chrome/test/chromedriver/test/webserver.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
diff --git a/chrome/test/nacl/nacl_browsertest.cc b/chrome/test/nacl/nacl_browsertest.cc
index e24b910..356d183 100644
--- a/chrome/test/nacl/nacl_browsertest.cc
+++ b/chrome/test/nacl/nacl_browsertest.cc
@@ -52,12 +52,12 @@
RunLoadTest(FILE_PATH_LITERAL("nacl_load_test.html"));
})
-IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclWithNewCache,
+IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclWithOldCache,
MAYBE_PNACL(SimpleLoad)) {
RunLoadTest(FILE_PATH_LITERAL("nacl_load_test.html"));
}
-IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclWithNewCache,
+IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclWithOldCache,
MAYBE_PNACL(PnaclErrorHandling)) {
RunNaClIntegrationTest(FILE_PATH_LITERAL("pnacl_error_handling.html"));
}
diff --git a/chrome/test/nacl/nacl_browsertest_util.cc b/chrome/test/nacl/nacl_browsertest_util.cc
index c1e5655..3cd7e35 100644
--- a/chrome/test/nacl/nacl_browsertest_util.cc
+++ b/chrome/test/nacl/nacl_browsertest_util.cc
@@ -203,7 +203,6 @@
}
void NaClBrowserTestBase::SetUpCommandLine(CommandLine* command_line) {
- command_line->AppendSwitch(switches::kNoFirstRun);
command_line->AppendSwitch(switches::kEnableNaCl);
}
@@ -321,9 +320,9 @@
command_line->AppendSwitch(switches::kDisablePnacl);
}
-NaClBrowserTestPnaclWithNewCache::NaClBrowserTestPnaclWithNewCache() {
+NaClBrowserTestPnaclWithOldCache::NaClBrowserTestPnaclWithOldCache() {
scoped_ptr<base::Environment> env(base::Environment::Create());
- env->SetVar("PNACL_USE_NEW_CACHE", "true");
+ env->SetVar("PNACL_USE_OLD_CACHE", "true");
}
base::FilePath::StringType NaClBrowserTestStatic::Variant() {
diff --git a/chrome/test/nacl/nacl_browsertest_util.h b/chrome/test/nacl/nacl_browsertest_util.h
index ba58e93..5400acc 100644
--- a/chrome/test/nacl/nacl_browsertest_util.h
+++ b/chrome/test/nacl/nacl_browsertest_util.h
@@ -136,11 +136,11 @@
virtual bool IsPnaclDisabled() OVERRIDE;
};
-// Temporary class for running tests with the new cache enabled. Once all the
-// pieces land, this will go away and the new cache will be on by default.
-class NaClBrowserTestPnaclWithNewCache : public NaClBrowserTestPnacl {
+// Temporary class for running tests with the old cache enabled. Once all the
+// pieces are stable and the old code is gone, this will go away.
+class NaClBrowserTestPnaclWithOldCache : public NaClBrowserTestPnacl {
public:
- NaClBrowserTestPnaclWithNewCache();
+ NaClBrowserTestPnaclWithOldCache();
};
// A NaCl browser test only using static files.
diff --git a/chrome/test/nacl_test_injection/buildbot_nacl_integration.py b/chrome/test/nacl_test_injection/buildbot_nacl_integration.py
index a23de63..4df51b3 100755
--- a/chrome/test/nacl_test_injection/buildbot_nacl_integration.py
+++ b/chrome/test/nacl_test_injection/buildbot_nacl_integration.py
@@ -9,10 +9,6 @@
def Main(args):
- if sys.platform == 'darwin':
- print >> sys.stderr, "SKIPPING NACL INTEGRATION DUE TO BUG #261724."
- return 0
-
pwd = os.environ.get('PWD', '')
is_integration_bot = 'nacl-chrome' in pwd
diff --git a/chrome/test/ppapi/ppapi_test.cc b/chrome/test/ppapi/ppapi_test.cc
index 5973877..1c912a1 100644
--- a/chrome/test/ppapi/ppapi_test.cc
+++ b/chrome/test/ppapi/ppapi_test.cc
@@ -36,7 +36,6 @@
#include "net/base/test_data_directory.h"
#include "ppapi/shared_impl/ppapi_switches.h"
#include "ui/gl/gl_switches.h"
-#include "webkit/plugins/plugin_switches.h"
#if defined(OS_WIN) && defined(USE_ASH)
#include "base/win/windows_version.h"
diff --git a/chrome/tools/build/generate_policy_source.py b/chrome/tools/build/generate_policy_source.py
index 8998700..d88374d 100755
--- a/chrome/tools/build/generate_policy_source.py
+++ b/chrome/tools/build/generate_policy_source.py
@@ -11,6 +11,7 @@
template is the path to a .json policy template file.'''
from __future__ import with_statement
+import json
from optparse import OptionParser
import re
import sys
@@ -55,25 +56,32 @@
if is_chromium_os:
expected_platform = 'chrome_os'
- wildcard_platform = None
- elif os == 'android':
- expected_platform = 'android'
- wildcard_platform = None
else:
- expected_platform = 'chrome.' + os.lower()
- wildcard_platform = 'chrome.*'
- is_supported = False
+ expected_platform = os.lower()
+
+ self.platforms = []
for platform, version in [ p.split(':') for p in policy['supported_on'] ]:
- if (platform == expected_platform or platform == wildcard_platform) and \
- version.endswith('-'):
- is_supported = True
- self.is_supported = is_supported
+ if not version.endswith('-'):
+ continue
+
+ if platform.startswith('chrome.'):
+ platform_sub = platform[7:]
+ if platform_sub == '*':
+ self.platforms.extend(['win', 'mac', 'linux'])
+ else:
+ self.platforms.append(platform_sub)
+ else:
+ self.platforms.append(platform)
+
+ self.platforms.sort()
+ self.is_supported = expected_platform in self.platforms
if not PolicyDetails.TYPE_MAP.has_key(policy['type']):
raise NotImplementedError('Unknown policy type for %s: %s' %
(policy['name'], policy['type']))
self.policy_type, self.protobuf_type, self.policy_protobuf_type = \
PolicyDetails.TYPE_MAP[policy['type']]
+ self.schema = policy['schema']
self.desc = '\n'.join(
map(str.strip,
@@ -397,6 +405,11 @@
_OutputComment(f, '\nValid values:')
for item in policy.items:
_OutputComment(f, ' %s: %s' % (str(item.value), item.caption))
+ if policy.policy_type == 'TYPE_DICTIONARY':
+ _OutputComment(f, '\nValue schema:\n%s' %
+ json.dumps(policy.schema, sort_keys=True, indent=4,
+ separators=(',', ': ')))
+ _OutputComment(f, '\nSupported on: %s' % ', '.join(policy.platforms))
f.write('message %sProto {\n' % policy.name)
f.write(' optional PolicyOptions policy_options = 1;\n')
f.write(' optional %s %s = 2;\n' % (policy.protobuf_type, policy.name))
diff --git a/chrome/tools/build/win/FILES.cfg b/chrome/tools/build/win/FILES.cfg
index b893451..4fba1cd 100644
--- a/chrome/tools/build/win/FILES.cfg
+++ b/chrome/tools/build/win/FILES.cfg
@@ -339,6 +339,7 @@
# ANGLE files:
{
'filename': 'D3DCompiler_43.dll',
+ 'arch': ['32bit'],
'buildtype': ['dev', 'official'],
},
{
@@ -364,11 +365,9 @@
'buildtype': ['dev', 'official'],
'filegroup': ['default', 'symsrc'],
},
- # Windows Chrome does not have separate x86-32 and x86-64 installs.
- # A single install supports both x86-32 and x86-64 versions of NaCl,
- # so the 'arch' field does not seem to make much sense in this case.
{
'filename': 'nacl_irt_x86_32.nexe',
+ 'arch': ['32bit'],
'buildtype': ['dev', 'official'],
},
{
@@ -768,6 +767,7 @@
},
{
'filename': 'nacl_irt_x86_32.nexe.debug',
+ 'arch': ['32bit'],
'buildtype': ['official'],
'archive': 'chrome-win32-nacl-irt-syms.zip',
},
diff --git a/chrome/utility/DEPS b/chrome/utility/DEPS
index deea898..c2b5436 100644
--- a/chrome/utility/DEPS
+++ b/chrome/utility/DEPS
@@ -1,10 +1,10 @@
include_rules = [
"+content/public/child",
"+content/public/utility",
- "+webkit/glue",
# For generated headers.
"+grit",
"+skia/ext",
+ "+media",
]
diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc
index 7b1ecca..0976190 100644
--- a/chrome/utility/chrome_content_utility_client.cc
+++ b/chrome/utility/chrome_content_utility_client.cc
@@ -7,22 +7,27 @@
#include "base/base64.h"
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/files/file_path.h"
#include "base/json/json_reader.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/path_service.h"
+#include "base/time/time.h"
#include "chrome/common/chrome_utility_messages.h"
-#include "chrome/common/extensions/chrome_manifest_handlers.h"
+#include "chrome/common/extensions/chrome_extensions_client.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_l10n_util.h"
#include "chrome/common/extensions/manifest.h"
-#include "chrome/common/extensions/permissions/chrome_api_permissions.h"
#include "chrome/common/extensions/update_manifest.h"
#include "chrome/common/safe_browsing/zip_analyzer.h"
#include "chrome/utility/extensions/unpacker.h"
#include "chrome/utility/profile_import_handler.h"
#include "chrome/utility/web_resource_unpacker.h"
#include "content/public/child/image_decoder_utils.h"
+#include "content/public/common/content_paths.h"
#include "content/public/utility/utility_thread.h"
+#include "media/base/media.h"
+#include "media/base/media_file_checker.h"
#include "printing/page_range.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/zlib/google/zip.h"
@@ -124,6 +129,10 @@
IPC_MESSAGE_HANDLER(ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection,
OnAnalyzeZipFileForDownloadProtection)
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ IPC_MESSAGE_HANDLER(ChromeUtilityMsg_CheckMediaFile, OnCheckMediaFile)
+#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
+
#if defined(OS_CHROMEOS)
IPC_MESSAGE_HANDLER(ChromeUtilityMsg_CreateZipFile, OnCreateZipFile)
#endif // defined(OS_CHROMEOS)
@@ -151,10 +160,17 @@
return handled;
}
+// static
void ChromeContentUtilityClient::PreSandboxStartup() {
#if defined(ENABLE_MDNS)
local_discovery::ServiceDiscoveryMessageHandler::PreSandboxStartup();
#endif // ENABLE_MDNS
+
+ // Load media libraries for media file validation.
+ base::FilePath media_path;
+ PathService::Get(content::DIR_MEDIA_LIBS, &media_path);
+ if (!media_path.empty())
+ media::InitializeMediaLibrary(media_path);
}
void ChromeContentUtilityClient::OnUnpackExtension(
@@ -164,9 +180,8 @@
int creation_flags) {
CHECK_GT(location, extensions::Manifest::INVALID_LOCATION);
CHECK_LT(location, extensions::Manifest::NUM_LOCATIONS);
- extensions::PermissionsInfo::GetInstance()->InitializeWithDelegate(
- extensions::ChromeAPIPermissions());
- extensions::RegisterChromeManifestHandlers();
+ extensions::ExtensionsClient::Set(
+ extensions::ChromeExtensionsClient::GetInstance());
extensions::Unpacker unpacker(
extension_path,
extension_id,
@@ -505,7 +520,7 @@
}
void ChromeContentUtilityClient::OnAnalyzeZipFileForDownloadProtection(
- IPC::PlatformFileForTransit zip_file) {
+ const IPC::PlatformFileForTransit& zip_file) {
safe_browsing::zip_analyzer::Results results;
safe_browsing::zip_analyzer::AnalyzeZipFile(
IPC::PlatformFileForTransitToPlatformFile(zip_file), &results);
@@ -514,6 +529,19 @@
ReleaseProcessIfNeeded();
}
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+void ChromeContentUtilityClient::OnCheckMediaFile(
+ int64 milliseconds_of_decoding,
+ const IPC::PlatformFileForTransit& media_file) {
+ media::MediaFileChecker
+ checker(IPC::PlatformFileForTransitToPlatformFile(media_file));
+ const bool check_success = checker.Start(
+ base::TimeDelta::FromMilliseconds(milliseconds_of_decoding));
+ Send(new ChromeUtilityHostMsg_CheckMediaFile_Finished(check_success));
+ ReleaseProcessIfNeeded();
+}
+#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
+
#if defined(OS_WIN)
void ChromeContentUtilityClient::OnParseITunesPrefXml(
const std::string& itunes_xml_data) {
@@ -526,7 +554,7 @@
#if defined(OS_WIN) || defined(OS_MACOSX)
void ChromeContentUtilityClient::OnParseITunesLibraryXmlFile(
- IPC::PlatformFileForTransit itunes_library_file) {
+ const IPC::PlatformFileForTransit& itunes_library_file) {
itunes::ITunesLibraryParser parser;
base::PlatformFile file =
IPC::PlatformFileForTransitToPlatformFile(itunes_library_file);
diff --git a/chrome/utility/chrome_content_utility_client.h b/chrome/utility/chrome_content_utility_client.h
index 419c155..4f8187e 100644
--- a/chrome/utility/chrome_content_utility_client.h
+++ b/chrome/utility/chrome_content_utility_client.h
@@ -81,7 +81,11 @@
void OnGetPrinterCapsAndDefaults(const std::string& printer_name);
void OnStartupPing();
void OnAnalyzeZipFileForDownloadProtection(
- IPC::PlatformFileForTransit zip_file);
+ const IPC::PlatformFileForTransit& zip_file);
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ void OnCheckMediaFile(int64 milliseconds_of_decoding,
+ const IPC::PlatformFileForTransit& media_file);
+#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
#if defined(OS_WIN)
void OnParseITunesPrefXml(const std::string& itunes_xml_data);
@@ -89,7 +93,7 @@
#if defined(OS_WIN) || defined(OS_MACOSX)
void OnParseITunesLibraryXmlFile(
- IPC::PlatformFileForTransit itunes_library_file);
+ const IPC::PlatformFileForTransit& itunes_library_file);
void OnParsePicasaPMPDatabase(
const picasa::AlbumTableFilesForTransit& album_table_files);
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 80e13f6..728cc40 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-4509.0.0
\ No newline at end of file
+4521.0.0
\ No newline at end of file
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp
index 32691f1..69d2a67 100644
--- a/chromeos/chromeos.gyp
+++ b/chromeos/chromeos.gyp
@@ -17,6 +17,7 @@
'dependencies': [
'../base/base.gyp:base',
'../base/base.gyp:base_prefs',
+ '../crypto/crypto.gyp:crypto',
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
'../build/linux/system.gyp:dbus',
'../build/linux/system.gyp:ssl',
@@ -84,6 +85,8 @@
'dbus/cros_disks_client.h',
'dbus/cryptohome_client.cc',
'dbus/cryptohome_client.h',
+ 'dbus/cryptohome_client_stub.cc',
+ 'dbus/cryptohome_client_stub.h',
'dbus/dbus_client_implementation_type.h',
'dbus/dbus_method_call_status.h',
'dbus/dbus_thread_manager.cc',
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index 26c3752..8577279 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -82,10 +82,6 @@
const char kEnableChromeCaptivePortalDetector[] =
"enable-chrome-captive-portal-detector";
-// Disables the new NetworkChangeNotifier which uses NetworkStateHandler.
-const char kDisableNewNetworkChangeNotifier[] =
- "disable-new-network-change-notifier";
-
// Enables screensaver extensions.
const char kEnableScreensaverExtensions[] = "enable-screensaver-extensions";
@@ -124,8 +120,9 @@
const char kFileManagerEnableWebstoreIntegration[] =
"file-manager-enable-webstore-integration";
-// Passed to Chrome on first boot. Not passed on restart after sign out.
-const char kFirstBoot[] = "first-boot";
+// Passed to Chrome the first time that it's run after the system boots.
+// Not passed on restart after sign out.
+const char kFirstExecAfterBoot[] = "first-exec-after-boot";
// Usually in browser tests the usual login manager bringup is skipped so that
// tests can change how it's brought up. This flag disables that.
@@ -192,8 +189,5 @@
const char kUseNewNetworkConfigurationHandlers[] =
"use-new-network-configuration-handlers";
-const char kUseNewNetworkConnectionHandler[] =
- "use-new-network-connection-handler";
-
} // namespace switches
} // namespace chromeos
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h
index 76a66bc..2281d03 100644
--- a/chromeos/chromeos_switches.h
+++ b/chromeos/chromeos_switches.h
@@ -31,7 +31,6 @@
CHROMEOS_EXPORT extern const char kDisableLocalAccounts[];
CHROMEOS_EXPORT extern const char kDisableLoginAnimations[];
CHROMEOS_EXPORT extern const char kDisableNewChannelSwitcherUI[];
-CHROMEOS_EXPORT extern const char kDisableNewNetworkChangeNotifier[];
CHROMEOS_EXPORT extern const char kDisableOOBEBlockingUpdate[];
CHROMEOS_EXPORT extern const char kDisableOnlineEULA[];
CHROMEOS_EXPORT extern const char kDisableOobeAnimation[];
@@ -52,7 +51,7 @@
CHROMEOS_EXPORT extern const char kEnterpriseEnrollmentModulusLimit[];
CHROMEOS_EXPORT extern const char kFileManagerShowCheckboxes[];
CHROMEOS_EXPORT extern const char kFileManagerEnableWebstoreIntegration[];
-CHROMEOS_EXPORT extern const char kFirstBoot[];
+CHROMEOS_EXPORT extern const char kFirstExecAfterBoot[];
CHROMEOS_EXPORT extern const char kForceLoginManagerInTests[];
CHROMEOS_EXPORT extern const char kGuestSession[];
CHROMEOS_EXPORT extern const char kHasChromeOSDiamondKey[];
@@ -71,7 +70,6 @@
CHROMEOS_EXPORT extern const char kSmsTestMessages[];
CHROMEOS_EXPORT extern const char kStubCrosSettings[];
CHROMEOS_EXPORT extern const char kUseNewNetworkConfigurationHandlers[];
-CHROMEOS_EXPORT extern const char kUseNewNetworkConnectionHandler[];
} // namespace switches
} // namespace chromeos
diff --git a/chromeos/dbus/cryptohome_client.cc b/chromeos/dbus/cryptohome_client.cc
index 6ba9834..445ba0b 100644
--- a/chromeos/dbus/cryptohome_client.cc
+++ b/chromeos/dbus/cryptohome_client.cc
@@ -5,9 +5,12 @@
#include "chromeos/dbus/cryptohome_client.h"
#include "base/bind.h"
+#include "base/location.h"
+#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "chromeos/cryptohome/async_method_caller.h"
#include "chromeos/dbus/blocking_method_caller.h"
+#include "chromeos/dbus/cryptohome_client_stub.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_path.h"
@@ -838,425 +841,6 @@
DISALLOW_COPY_AND_ASSIGN(CryptohomeClientImpl);
};
-// A stub implementaion of CryptohomeClient.
-class CryptohomeClientStubImpl : public CryptohomeClient {
- public:
- CryptohomeClientStubImpl()
- : async_call_id_(1),
- tpm_is_ready_counter_(0),
- locked_(false),
- weak_ptr_factory_(this) {
- }
-
- virtual ~CryptohomeClientStubImpl() {}
-
- // CryptohomeClient override.
- virtual void SetAsyncCallStatusHandlers(
- const AsyncCallStatusHandler& handler,
- const AsyncCallStatusWithDataHandler& data_handler) OVERRIDE {
- async_call_status_handler_ = handler;
- async_call_status_data_handler_ = data_handler;
- }
-
- // CryptohomeClient override.
- virtual void ResetAsyncCallStatusHandlers() OVERRIDE {
- async_call_status_handler_.Reset();
- async_call_status_data_handler_.Reset();
- }
-
- // CryptohomeClient override.
- virtual void IsMounted(const BoolDBusMethodCallback& callback) OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
- }
-
- // CryptohomeClient override.
- virtual bool Unmount(bool* success) OVERRIDE {
- *success = true;
- return true;
- }
-
- // CryptohomeClient override.
- virtual void AsyncCheckKey(const std::string& username,
- const std::string& key,
- const AsyncMethodCallback& callback) OVERRIDE {
- ReturnAsyncMethodResult(callback, false);
- }
-
- // CryptohomeClient override.
- virtual void AsyncMigrateKey(const std::string& username,
- const std::string& from_key,
- const std::string& to_key,
- const AsyncMethodCallback& callback) OVERRIDE {
- ReturnAsyncMethodResult(callback, false);
- }
-
- // CryptohomeClient override.
- virtual void AsyncRemove(const std::string& username,
- const AsyncMethodCallback& callback) OVERRIDE {
- ReturnAsyncMethodResult(callback, false);
- }
-
- // CryptohomeClient override.
- virtual bool GetSystemSalt(std::vector<uint8>* salt) OVERRIDE {
- const char kStubSystemSalt[] = "stub_system_salt";
- salt->assign(kStubSystemSalt,
- kStubSystemSalt + arraysize(kStubSystemSalt) - 1);
- return true;
- }
-
- // CryptohomeClient override.
- virtual void GetSanitizedUsername(
- const std::string& username,
- const StringDBusMethodCallback& callback) OVERRIDE {
- // Even for stub implementation we have to return different values
- // so that multi-profiles would work.
- std::string sanitized_username = GetStubSanitizedUsername(username);
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, sanitized_username));
- }
-
- // CryptohomeClient override.
- virtual std::string BlockingGetSanitizedUsername(
- const std::string& username) OVERRIDE {
- return GetStubSanitizedUsername(username);
- }
-
- // CryptohomeClient override.
- virtual void AsyncMount(const std::string& username,
- const std::string& key,
- int flags,
- const AsyncMethodCallback& callback) OVERRIDE {
- ReturnAsyncMethodResult(callback, false);
- }
-
- // CryptohomeClient override.
- virtual void AsyncAddKey(const std::string& username,
- const std::string& key,
- const std::string& new_key,
- const AsyncMethodCallback& callback) OVERRIDE {
- ReturnAsyncMethodResult(callback, false);
- }
-
- // CryptohomeClient override.
- virtual void AsyncMountGuest(const AsyncMethodCallback& callback) OVERRIDE {
- ReturnAsyncMethodResult(callback, false);
- }
-
- // CryptohomeClient override.
- virtual void AsyncMountPublic(const std::string& public_mount_id,
- int flags,
- const AsyncMethodCallback& callback) OVERRIDE {
- ReturnAsyncMethodResult(callback, false);
- }
-
- // CryptohomeClient override.
- virtual void TpmIsReady(const BoolDBusMethodCallback& callback) OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
- }
-
- // CryptohomeClient override.
- virtual void TpmIsEnabled(const BoolDBusMethodCallback& callback) OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
- }
-
- // CryptohomeClient override.
- virtual bool CallTpmIsEnabledAndBlock(bool* enabled) OVERRIDE {
- *enabled = true;
- return true;
- }
-
- // CryptohomeClient override.
- virtual void TpmGetPassword(
- const StringDBusMethodCallback& callback) OVERRIDE {
- const char kStubTpmPassword[] = "Stub-TPM-password";
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, kStubTpmPassword));
- }
-
- // CryptohomeClient override.
- virtual void TpmIsOwned(const BoolDBusMethodCallback& callback) OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
- }
-
- // CryptohomeClient override.
- virtual bool CallTpmIsOwnedAndBlock(bool* owned) OVERRIDE {
- *owned = true;
- return true;
- }
-
- // CryptohomeClient override.
- virtual void TpmIsBeingOwned(const BoolDBusMethodCallback& callback)
- OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
- }
-
- // CryptohomeClient override.
- virtual bool CallTpmIsBeingOwnedAndBlock(bool* owning) OVERRIDE {
- *owning = true;
- return true;
- }
-
- // CryptohomeClient override.
- virtual void TpmCanAttemptOwnership(
- const VoidDBusMethodCallback& callback) OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS));
- }
-
- // CryptohomeClient override.
- virtual void TpmClearStoredPassword(const VoidDBusMethodCallback& callback)
- OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS));
- }
-
- // CryptohomeClient override.
- virtual bool CallTpmClearStoredPasswordAndBlock() OVERRIDE { return true; }
-
- // CryptohomeClient override.
- virtual void Pkcs11IsTpmTokenReady(
- const BoolDBusMethodCallback& callback) OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
- }
-
- // CryptohomeClient override.
- virtual void Pkcs11GetTpmTokenInfo(
- const Pkcs11GetTpmTokenInfoCallback& callback) OVERRIDE {
- const char kStubLabel[] = "Stub TPM Token";
- const char kStubUserPin[] = "012345";
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(callback,
- DBUS_METHOD_CALL_SUCCESS,
- std::string(kStubLabel),
- std::string(kStubUserPin)));
- }
-
- // CryptohomeClient override.
- virtual bool InstallAttributesGet(const std::string& name,
- std::vector<uint8>* value,
- bool* successful) OVERRIDE {
- if (install_attrs_.find(name) != install_attrs_.end()) {
- *value = install_attrs_[name];
- *successful = true;
- } else {
- value->clear();
- *successful = false;
- }
- return true;
- }
-
- // CryptohomeClient override.
- virtual bool InstallAttributesSet(const std::string& name,
- const std::vector<uint8>& value,
- bool* successful) OVERRIDE {
- install_attrs_[name] = value;
- *successful = true;
- return true;
- }
-
- // CryptohomeClient override.
- virtual bool InstallAttributesFinalize(bool* successful) OVERRIDE {
- locked_ = true;
- *successful = true;
- return true;
- }
-
- // CryptohomeClient override.
- virtual void InstallAttributesIsReady(const BoolDBusMethodCallback& callback)
- OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
- }
-
- // CryptohomeClient override.
- virtual bool InstallAttributesIsInvalid(bool* is_invalid) OVERRIDE {
- *is_invalid = false;
- return true;
- }
-
- // CryptohomeClient override.
- virtual bool InstallAttributesIsFirstInstall(
- bool* is_first_install) OVERRIDE {
- *is_first_install = !locked_;
- return true;
- }
-
- // CryptohomeClient override.
- virtual void TpmAttestationIsPrepared(
- const BoolDBusMethodCallback& callback) OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
- }
-
- // CryptohomeClient override.
- virtual void TpmAttestationIsEnrolled(
- const BoolDBusMethodCallback& callback) OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
- }
-
- // CryptohomeClient override.
- virtual void AsyncTpmAttestationCreateEnrollRequest(
- const AsyncMethodCallback& callback) OVERRIDE {
- ReturnAsyncMethodResult(callback, true);
- }
-
- // CryptohomeClient override.
- virtual void AsyncTpmAttestationEnroll(
- const std::string& pca_response,
- const AsyncMethodCallback& callback) OVERRIDE {
- ReturnAsyncMethodResult(callback, false);
- }
-
- // CryptohomeClient override.
- virtual void AsyncTpmAttestationCreateCertRequest(
- int options,
- const AsyncMethodCallback& callback) OVERRIDE {
- ReturnAsyncMethodResult(callback, true);
- }
-
- // CryptohomeClient override.
- virtual void AsyncTpmAttestationFinishCertRequest(
- const std::string& pca_response,
- attestation::AttestationKeyType key_type,
- const std::string& key_name,
- const AsyncMethodCallback& callback) OVERRIDE {
- ReturnAsyncMethodResult(callback, true);
- }
-
- // CryptohomeClient override.
- virtual void TpmAttestationDoesKeyExist(
- attestation::AttestationKeyType key_type,
- const std::string& key_name,
- const BoolDBusMethodCallback& callback) OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false));
- }
-
- // CryptohomeClient override.
- virtual void TpmAttestationGetCertificate(
- attestation::AttestationKeyType key_type,
- const std::string& key_name,
- const DataMethodCallback& callback) OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string()));
- }
-
- // CryptohomeClient override.
- virtual void TpmAttestationGetPublicKey(
- attestation::AttestationKeyType key_type,
- const std::string& key_name,
- const DataMethodCallback& callback) OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string()));
- }
-
- // CryptohomeClient override.
- virtual void TpmAttestationRegisterKey(
- attestation::AttestationKeyType key_type,
- const std::string& key_name,
- const AsyncMethodCallback& callback) OVERRIDE {
- ReturnAsyncMethodResult(callback, true);
- }
-
- // CryptohomeClient override.
- virtual void TpmAttestationSignEnterpriseChallenge(
- attestation::AttestationKeyType key_type,
- const std::string& key_name,
- const std::string& domain,
- const std::string& device_id,
- attestation::AttestationChallengeOptions options,
- const std::string& challenge,
- const AsyncMethodCallback& callback) OVERRIDE {
- ReturnAsyncMethodResult(callback, true);
- }
-
- // CryptohomeClient override.
- virtual void TpmAttestationSignSimpleChallenge(
- attestation::AttestationKeyType key_type,
- const std::string& key_name,
- const std::string& challenge,
- const AsyncMethodCallback& callback) OVERRIDE {
- ReturnAsyncMethodResult(callback, true);
- }
-
- virtual void TpmAttestationGetKeyPayload(
- attestation::AttestationKeyType key_type,
- const std::string& key_name,
- const DataMethodCallback& callback) OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string()));
- }
-
- virtual void TpmAttestationSetKeyPayload(
- attestation::AttestationKeyType key_type,
- const std::string& key_name,
- const std::string& payload,
- const BoolDBusMethodCallback& callback) OVERRIDE {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false));
- }
-
-
- private:
- // Posts tasks which return fake results to the UI thread.
- void ReturnAsyncMethodResult(const AsyncMethodCallback& callback,
- bool returns_data) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&CryptohomeClientStubImpl::ReturnAsyncMethodResultInternal,
- weak_ptr_factory_.GetWeakPtr(),
- callback,
- returns_data));
- }
-
- // This method is used to implement ReturnAsyncMethodResult.
- void ReturnAsyncMethodResultInternal(const AsyncMethodCallback& callback,
- bool returns_data) {
- callback.Run(async_call_id_);
- if (!returns_data && !async_call_status_handler_.is_null()) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(async_call_status_handler_,
- async_call_id_,
- true,
- cryptohome::MOUNT_ERROR_NONE));
- } else if (returns_data && !async_call_status_data_handler_.is_null()) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(async_call_status_data_handler_,
- async_call_id_,
- true,
- std::string()));
- }
- ++async_call_id_;
- }
-
- int async_call_id_;
- AsyncCallStatusHandler async_call_status_handler_;
- AsyncCallStatusWithDataHandler async_call_status_data_handler_;
- int tpm_is_ready_counter_;
- std::map<std::string, std::vector<uint8> > install_attrs_;
- bool locked_;
- base::WeakPtrFactory<CryptohomeClientStubImpl> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(CryptohomeClientStubImpl);
-};
-
} // namespace
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromeos/dbus/cryptohome_client_stub.cc b/chromeos/dbus/cryptohome_client_stub.cc
new file mode 100644
index 0000000..e9faeec
--- /dev/null
+++ b/chromeos/dbus/cryptohome_client_stub.cc
@@ -0,0 +1,381 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/dbus/cryptohome_client_stub.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/message_loop/message_loop.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+CryptohomeClientStubImpl::CryptohomeClientStubImpl()
+ : async_call_id_(1),
+ tpm_is_ready_counter_(0),
+ locked_(false),
+ weak_ptr_factory_(this) {}
+
+CryptohomeClientStubImpl::~CryptohomeClientStubImpl() {}
+
+void CryptohomeClientStubImpl::SetAsyncCallStatusHandlers(
+ const AsyncCallStatusHandler& handler,
+ const AsyncCallStatusWithDataHandler& data_handler) {
+ async_call_status_handler_ = handler;
+ async_call_status_data_handler_ = data_handler;
+}
+
+void CryptohomeClientStubImpl::ResetAsyncCallStatusHandlers() {
+ async_call_status_handler_.Reset();
+ async_call_status_data_handler_.Reset();
+}
+
+void CryptohomeClientStubImpl::IsMounted(
+ const BoolDBusMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+bool CryptohomeClientStubImpl::Unmount(bool* success) {
+ *success = true;
+ return true;
+}
+
+void CryptohomeClientStubImpl::AsyncCheckKey(
+ const std::string& username,
+ const std::string& key,
+ const AsyncMethodCallback& callback) {
+ ReturnAsyncMethodResult(callback, false);
+}
+
+void CryptohomeClientStubImpl::AsyncMigrateKey(
+ const std::string& username,
+ const std::string& from_key,
+ const std::string& to_key,
+ const AsyncMethodCallback& callback) {
+ ReturnAsyncMethodResult(callback, false);
+}
+
+void CryptohomeClientStubImpl::AsyncRemove(
+ const std::string& username,
+ const AsyncMethodCallback& callback) {
+ ReturnAsyncMethodResult(callback, false);
+}
+
+bool CryptohomeClientStubImpl::GetSystemSalt(std::vector<uint8>* salt) {
+ const char kStubSystemSalt[] = "stub_system_salt";
+ salt->assign(kStubSystemSalt,
+ kStubSystemSalt + arraysize(kStubSystemSalt) - 1);
+ return true;
+}
+
+void CryptohomeClientStubImpl::GetSanitizedUsername(
+ const std::string& username,
+ const StringDBusMethodCallback& callback) {
+ // Even for stub implementation we have to return different values so that
+ // multi-profiles would work.
+ std::string sanitized_username = GetStubSanitizedUsername(username);
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, sanitized_username));
+}
+
+std::string CryptohomeClientStubImpl::BlockingGetSanitizedUsername(
+ const std::string& username) {
+ return GetStubSanitizedUsername(username);
+}
+
+void CryptohomeClientStubImpl::AsyncMount(const std::string& username,
+ const std::string& key,
+ int flags,
+ const AsyncMethodCallback& callback) {
+ ReturnAsyncMethodResult(callback, false);
+}
+
+void CryptohomeClientStubImpl::AsyncAddKey(
+ const std::string& username,
+ const std::string& key,
+ const std::string& new_key,
+ const AsyncMethodCallback& callback) {
+ ReturnAsyncMethodResult(callback, false);
+}
+
+void CryptohomeClientStubImpl::AsyncMountGuest(
+ const AsyncMethodCallback& callback) {
+ ReturnAsyncMethodResult(callback, false);
+}
+
+void CryptohomeClientStubImpl::AsyncMountPublic(
+ const std::string& public_mount_id,
+ int flags,
+ const AsyncMethodCallback& callback) {
+ ReturnAsyncMethodResult(callback, false);
+}
+
+void CryptohomeClientStubImpl::TpmIsReady(
+ const BoolDBusMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+void CryptohomeClientStubImpl::TpmIsEnabled(
+ const BoolDBusMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+bool CryptohomeClientStubImpl::CallTpmIsEnabledAndBlock(bool* enabled) {
+ *enabled = true;
+ return true;
+}
+
+void CryptohomeClientStubImpl::TpmGetPassword(
+ const StringDBusMethodCallback& callback) {
+ const char kStubTpmPassword[] = "Stub-TPM-password";
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, kStubTpmPassword));
+}
+
+void CryptohomeClientStubImpl::TpmIsOwned(
+ const BoolDBusMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+bool CryptohomeClientStubImpl::CallTpmIsOwnedAndBlock(bool* owned) {
+ *owned = true;
+ return true;
+}
+
+void CryptohomeClientStubImpl::TpmIsBeingOwned(
+ const BoolDBusMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+bool CryptohomeClientStubImpl::CallTpmIsBeingOwnedAndBlock(bool* owning) {
+ *owning = true;
+ return true;
+}
+
+void CryptohomeClientStubImpl::TpmCanAttemptOwnership(
+ const VoidDBusMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS));
+}
+
+void CryptohomeClientStubImpl::TpmClearStoredPassword(
+ const VoidDBusMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS));
+}
+
+bool CryptohomeClientStubImpl::CallTpmClearStoredPasswordAndBlock() {
+ return true;
+}
+
+void CryptohomeClientStubImpl::Pkcs11IsTpmTokenReady(
+ const BoolDBusMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+void CryptohomeClientStubImpl::Pkcs11GetTpmTokenInfo(
+ const Pkcs11GetTpmTokenInfoCallback& callback) {
+ const char kStubLabel[] = "Stub TPM Token";
+ const char kStubUserPin[] = "012345";
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(callback,
+ DBUS_METHOD_CALL_SUCCESS,
+ std::string(kStubLabel),
+ std::string(kStubUserPin)));
+}
+
+bool CryptohomeClientStubImpl::InstallAttributesGet(const std::string& name,
+ std::vector<uint8>* value,
+ bool* successful) {
+ if (install_attrs_.find(name) != install_attrs_.end()) {
+ *value = install_attrs_[name];
+ *successful = true;
+ } else {
+ value->clear();
+ *successful = false;
+ }
+ return true;
+}
+
+bool CryptohomeClientStubImpl::InstallAttributesSet(
+ const std::string& name,
+ const std::vector<uint8>& value,
+ bool* successful) {
+ install_attrs_[name] = value;
+ *successful = true;
+ return true;
+}
+
+bool CryptohomeClientStubImpl::InstallAttributesFinalize(bool* successful) {
+ locked_ = true;
+ *successful = true;
+ return true;
+}
+
+void CryptohomeClientStubImpl::InstallAttributesIsReady(
+ const BoolDBusMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+bool CryptohomeClientStubImpl::InstallAttributesIsInvalid(bool* is_invalid) {
+ *is_invalid = false;
+ return true;
+}
+
+bool CryptohomeClientStubImpl::InstallAttributesIsFirstInstall(
+ bool* is_first_install) {
+ *is_first_install = !locked_;
+ return true;
+}
+
+void CryptohomeClientStubImpl::TpmAttestationIsPrepared(
+ const BoolDBusMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+void CryptohomeClientStubImpl::TpmAttestationIsEnrolled(
+ const BoolDBusMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
+}
+
+void CryptohomeClientStubImpl::AsyncTpmAttestationCreateEnrollRequest(
+ const AsyncMethodCallback& callback) {
+ ReturnAsyncMethodResult(callback, true);
+}
+
+void CryptohomeClientStubImpl::AsyncTpmAttestationEnroll(
+ const std::string& pca_response,
+ const AsyncMethodCallback& callback) {
+ ReturnAsyncMethodResult(callback, false);
+}
+
+void CryptohomeClientStubImpl::AsyncTpmAttestationCreateCertRequest(
+ int options,
+ const AsyncMethodCallback& callback) {
+ ReturnAsyncMethodResult(callback, true);
+}
+
+void CryptohomeClientStubImpl::AsyncTpmAttestationFinishCertRequest(
+ const std::string& pca_response,
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const AsyncMethodCallback& callback) {
+ ReturnAsyncMethodResult(callback, true);
+}
+
+void CryptohomeClientStubImpl::TpmAttestationDoesKeyExist(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const BoolDBusMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false));
+}
+
+void CryptohomeClientStubImpl::TpmAttestationGetCertificate(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const DataMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string()));
+}
+
+void CryptohomeClientStubImpl::TpmAttestationGetPublicKey(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const DataMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string()));
+}
+
+void CryptohomeClientStubImpl::TpmAttestationRegisterKey(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const AsyncMethodCallback& callback) {
+ ReturnAsyncMethodResult(callback, true);
+}
+
+void CryptohomeClientStubImpl::TpmAttestationSignEnterpriseChallenge(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const std::string& domain,
+ const std::string& device_id,
+ attestation::AttestationChallengeOptions options,
+ const std::string& challenge,
+ const AsyncMethodCallback& callback) {
+ ReturnAsyncMethodResult(callback, true);
+}
+
+void CryptohomeClientStubImpl::TpmAttestationSignSimpleChallenge(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const std::string& challenge,
+ const AsyncMethodCallback& callback) {
+ ReturnAsyncMethodResult(callback, true);
+}
+
+void CryptohomeClientStubImpl::TpmAttestationGetKeyPayload(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const DataMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string()));
+}
+
+void CryptohomeClientStubImpl::TpmAttestationSetKeyPayload(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const std::string& payload,
+ const BoolDBusMethodCallback& callback) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false));
+}
+
+void CryptohomeClientStubImpl::ReturnAsyncMethodResult(
+ const AsyncMethodCallback& callback,
+ bool returns_data) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&CryptohomeClientStubImpl::ReturnAsyncMethodResultInternal,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback,
+ returns_data));
+}
+
+void CryptohomeClientStubImpl::ReturnAsyncMethodResultInternal(
+ const AsyncMethodCallback& callback,
+ bool returns_data) {
+ callback.Run(async_call_id_);
+ if (!returns_data && !async_call_status_handler_.is_null()) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(async_call_status_handler_,
+ async_call_id_,
+ true,
+ cryptohome::MOUNT_ERROR_NONE));
+ } else if (returns_data && !async_call_status_data_handler_.is_null()) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(async_call_status_data_handler_,
+ async_call_id_,
+ true,
+ std::string()));
+ }
+ ++async_call_id_;
+}
+
+} // namespace chromeos
diff --git a/chromeos/dbus/cryptohome_client_stub.h b/chromeos/dbus/cryptohome_client_stub.h
new file mode 100644
index 0000000..e38925a
--- /dev/null
+++ b/chromeos/dbus/cryptohome_client_stub.h
@@ -0,0 +1,164 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_DBUS_CRYPTOHOME_CLIENT_STUB_H_
+#define CHROMEOS_DBUS_CRYPTOHOME_CLIENT_STUB_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/memory/weak_ptr.h"
+#include "chromeos/dbus/cryptohome_client.h"
+
+namespace chromeos {
+
+class CryptohomeClientStubImpl : public CryptohomeClient {
+ public:
+ CryptohomeClientStubImpl();
+ virtual ~CryptohomeClientStubImpl();
+
+ virtual void SetAsyncCallStatusHandlers(
+ const AsyncCallStatusHandler& handler,
+ const AsyncCallStatusWithDataHandler& data_handler) OVERRIDE;
+ virtual void ResetAsyncCallStatusHandlers() OVERRIDE;
+ virtual void IsMounted(const BoolDBusMethodCallback& callback) OVERRIDE;
+ virtual bool Unmount(bool* success) OVERRIDE;
+ virtual void AsyncCheckKey(const std::string& username,
+ const std::string& key,
+ const AsyncMethodCallback& callback) OVERRIDE;
+ virtual void AsyncMigrateKey(const std::string& username,
+ const std::string& from_key,
+ const std::string& to_key,
+ const AsyncMethodCallback& callback) OVERRIDE;
+ virtual void AsyncRemove(const std::string& username,
+ const AsyncMethodCallback& callback) OVERRIDE;
+ virtual bool GetSystemSalt(std::vector<uint8>* salt) OVERRIDE;
+ virtual void GetSanitizedUsername(
+ const std::string& username,
+ const StringDBusMethodCallback& callback) OVERRIDE;
+ virtual std::string BlockingGetSanitizedUsername(
+ const std::string& username) OVERRIDE;
+ virtual void AsyncMount(const std::string& username,
+ const std::string& key,
+ int flags,
+ const AsyncMethodCallback& callback) OVERRIDE;
+ virtual void AsyncAddKey(const std::string& username,
+ const std::string& key,
+ const std::string& new_key,
+ const AsyncMethodCallback& callback) OVERRIDE;
+ virtual void AsyncMountGuest(const AsyncMethodCallback& callback) OVERRIDE;
+ virtual void AsyncMountPublic(const std::string& public_mount_id,
+ int flags,
+ const AsyncMethodCallback& callback) OVERRIDE;
+ virtual void TpmIsReady(const BoolDBusMethodCallback& callback) OVERRIDE;
+ virtual void TpmIsEnabled(const BoolDBusMethodCallback& callback) OVERRIDE;
+ virtual bool CallTpmIsEnabledAndBlock(bool* enabled) OVERRIDE;
+ virtual void TpmGetPassword(
+ const StringDBusMethodCallback& callback) OVERRIDE;
+ virtual void TpmIsOwned(const BoolDBusMethodCallback& callback) OVERRIDE;
+ virtual bool CallTpmIsOwnedAndBlock(bool* owned) OVERRIDE;
+ virtual void TpmIsBeingOwned(const BoolDBusMethodCallback& callback) OVERRIDE;
+ virtual bool CallTpmIsBeingOwnedAndBlock(bool* owning) OVERRIDE;
+ virtual void TpmCanAttemptOwnership(
+ const VoidDBusMethodCallback& callback) OVERRIDE;
+ virtual void TpmClearStoredPassword(
+ const VoidDBusMethodCallback& callback) OVERRIDE;
+ virtual bool CallTpmClearStoredPasswordAndBlock() OVERRIDE;
+ virtual void Pkcs11IsTpmTokenReady(
+ const BoolDBusMethodCallback& callback) OVERRIDE;
+ virtual void Pkcs11GetTpmTokenInfo(
+ const Pkcs11GetTpmTokenInfoCallback& callback) OVERRIDE;
+ virtual bool InstallAttributesGet(const std::string& name,
+ std::vector<uint8>* value,
+ bool* successful) OVERRIDE;
+ virtual bool InstallAttributesSet(const std::string& name,
+ const std::vector<uint8>& value,
+ bool* successful) OVERRIDE;
+ virtual bool InstallAttributesFinalize(bool* successful) OVERRIDE;
+ virtual void InstallAttributesIsReady(
+ const BoolDBusMethodCallback& callback) OVERRIDE;
+ virtual bool InstallAttributesIsInvalid(bool* is_invalid) OVERRIDE;
+ virtual bool InstallAttributesIsFirstInstall(bool* is_first_install) OVERRIDE;
+ virtual void TpmAttestationIsPrepared(
+ const BoolDBusMethodCallback& callback) OVERRIDE;
+ virtual void TpmAttestationIsEnrolled(
+ const BoolDBusMethodCallback& callback) OVERRIDE;
+ virtual void AsyncTpmAttestationCreateEnrollRequest(
+ const AsyncMethodCallback& callback) OVERRIDE;
+ virtual void AsyncTpmAttestationEnroll(
+ const std::string& pca_response,
+ const AsyncMethodCallback& callback) OVERRIDE;
+ virtual void AsyncTpmAttestationCreateCertRequest(
+ int options,
+ const AsyncMethodCallback& callback) OVERRIDE;
+ virtual void AsyncTpmAttestationFinishCertRequest(
+ const std::string& pca_response,
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const AsyncMethodCallback& callback) OVERRIDE;
+ virtual void TpmAttestationDoesKeyExist(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const BoolDBusMethodCallback& callback) OVERRIDE;
+ virtual void TpmAttestationGetCertificate(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const DataMethodCallback& callback) OVERRIDE;
+ virtual void TpmAttestationGetPublicKey(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const DataMethodCallback& callback) OVERRIDE;
+ virtual void TpmAttestationRegisterKey(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const AsyncMethodCallback& callback) OVERRIDE;
+ virtual void TpmAttestationSignEnterpriseChallenge(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const std::string& domain,
+ const std::string& device_id,
+ attestation::AttestationChallengeOptions options,
+ const std::string& challenge,
+ const AsyncMethodCallback& callback) OVERRIDE;
+ virtual void TpmAttestationSignSimpleChallenge(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const std::string& challenge,
+ const AsyncMethodCallback& callback) OVERRIDE;
+ virtual void TpmAttestationGetKeyPayload(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const DataMethodCallback& callback) OVERRIDE;
+ virtual void TpmAttestationSetKeyPayload(
+ attestation::AttestationKeyType key_type,
+ const std::string& key_name,
+ const std::string& payload,
+ const BoolDBusMethodCallback& callback) OVERRIDE;
+
+ private:
+ // Posts tasks which return fake results to the UI thread.
+ void ReturnAsyncMethodResult(const AsyncMethodCallback& callback,
+ bool returns_data);
+
+ // This method is used to implement ReturnAsyncMethodResult.
+ void ReturnAsyncMethodResultInternal(const AsyncMethodCallback& callback,
+ bool returns_data);
+
+ int async_call_id_;
+ AsyncCallStatusHandler async_call_status_handler_;
+ AsyncCallStatusWithDataHandler async_call_status_data_handler_;
+ int tpm_is_ready_counter_;
+
+ // A stub store for InstallAttributes, mapping an attribute name to the
+ // associated data blob. Used to implement InstallAttributesSet and -Get.
+ std::map<std::string, std::vector<uint8> > install_attrs_;
+ bool locked_;
+ base::WeakPtrFactory<CryptohomeClientStubImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(CryptohomeClientStubImpl);
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_DBUS_CRYPTOHOME_CLIENT_STUB_H_
diff --git a/chromeos/dbus/debug_daemon_client.cc b/chromeos/dbus/debug_daemon_client.cc
index 50d5d4b..3efbe7d 100644
--- a/chromeos/dbus/debug_daemon_client.cc
+++ b/chromeos/dbus/debug_daemon_client.cc
@@ -269,6 +269,17 @@
callback));
}
+ virtual void GetScrubbedLogs(const GetLogsCallback& callback) OVERRIDE {
+ dbus::MethodCall method_call(debugd::kDebugdInterface,
+ debugd::kGetFeedbackLogs);
+ debugdaemon_proxy_->CallMethod(
+ &method_call,
+ dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+ base::Bind(&DebugDaemonClientImpl::OnGetAllLogs,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback));
+ }
+
virtual void GetAllLogs(const GetLogsCallback& callback)
OVERRIDE {
dbus::MethodCall method_call(debugd::kDebugdInterface,
@@ -653,12 +664,19 @@
const GetPerfDataCallback& callback) OVERRIDE {
std::vector<uint8> data;
base::MessageLoop::current()->PostTask(FROM_HERE,
- base::Bind(callback, data));
+ base::Bind(callback, data));
+ }
+ virtual void GetScrubbedLogs(const GetLogsCallback& callback) OVERRIDE {
+ std::map<std::string, std::string> sample;
+ sample["Sample Scrubbed Log"] = "Your email address is xxxxxxxx";
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, false, sample));
}
virtual void GetAllLogs(const GetLogsCallback& callback) OVERRIDE {
- std::map<std::string, std::string> empty;
- base::MessageLoop::current()->PostTask(FROM_HERE,
- base::Bind(callback, false, empty));
+ std::map<std::string, std::string> sample;
+ sample["Sample Log"] = "Your email address is abc@abc.com";
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(callback, false, sample));
}
virtual void GetUserLogFiles(const GetLogsCallback& callback) OVERRIDE {
std::map<std::string, std::string> user_logs;
diff --git a/chromeos/dbus/debug_daemon_client.h b/chromeos/dbus/debug_daemon_client.h
index 92652e3..7c09a78 100644
--- a/chromeos/dbus/debug_daemon_client.h
+++ b/chromeos/dbus/debug_daemon_client.h
@@ -95,11 +95,14 @@
virtual void GetPerfData(uint32_t duration,
const GetPerfDataCallback& callback) = 0;
- // Callback type for GetAllLogs() or GetUserLogFiles().
+ // Callback type for GetScrubbedLogs(), GetAllLogs() or GetUserLogFiles().
typedef base::Callback<void(bool succeeded,
const std::map<std::string, std::string>& logs)>
GetLogsCallback;
+ // Gets scrubbed logs from debugd.
+ virtual void GetScrubbedLogs(const GetLogsCallback& callback) = 0;
+
// Gets all logs collected by debugd.
virtual void GetAllLogs(const GetLogsCallback& callback) = 0;
diff --git a/chromeos/dbus/shill_service_client_stub.cc b/chromeos/dbus/shill_service_client_stub.cc
index 5060650..03d7b75 100644
--- a/chromeos/dbus/shill_service_client_stub.cc
+++ b/chromeos/dbus/shill_service_client_stub.cc
@@ -165,8 +165,9 @@
const base::Closure& callback,
const ErrorCallback& error_callback) {
VLOG(1) << "ShillServiceClientStub::Connect: " << service_path.value();
- base::Value* service;
- if (!stub_services_.Get(service_path.value(), &service)) {
+ base::DictionaryValue* service_properties;
+ if (!stub_services_.GetDictionary(
+ service_path.value(), &service_properties)) {
LOG(ERROR) << "Service not found: " << service_path.value();
error_callback.Run("Error.InvalidService", "Invalid Service");
return;
@@ -191,6 +192,11 @@
delay = base::TimeDelta::FromSeconds(kConnectDelaySeconds);
}
base::StringValue online_value(flimflam::kStateOnline);
+ std::string passphrase;
+ service_properties->GetStringWithoutPathExpansion(
+ flimflam::kPassphraseProperty, &passphrase);
+ if (passphrase == "failure")
+ online_value = base::StringValue(flimflam::kStateFailure);
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&ShillServiceClientStub::SetProperty,
@@ -202,6 +208,19 @@
error_callback),
delay);
callback.Run();
+ // On failure, also set the Error property.
+ if (passphrase == "failure") {
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&ShillServiceClientStub::SetProperty,
+ weak_ptr_factory_.GetWeakPtr(),
+ service_path,
+ flimflam::kErrorProperty,
+ base::StringValue(flimflam::kErrorBadPassphrase),
+ base::Bind(&base::DoNothing),
+ error_callback),
+ delay);
+ }
}
void ShillServiceClientStub::Disconnect(const dbus::ObjectPath& service_path,
diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc
index c1d2b30..a8c1681 100644
--- a/chromeos/display/output_configurator.cc
+++ b/chromeos/display/output_configurator.cc
@@ -98,6 +98,12 @@
} // namespace
+OutputConfigurator::CoordinateTransformation::CoordinateTransformation()
+ : x_scale(1.0),
+ x_offset(0.0),
+ y_scale(1.0),
+ y_offset(0.0) {}
+
OutputConfigurator::OutputSnapshot::OutputSnapshot()
: output(None),
crtc(None),
@@ -105,37 +111,14 @@
native_mode(None),
mirror_mode(None),
selected_mode(None),
+ x(0),
y(0),
- height(0),
is_internal(false),
is_aspect_preserving_scaling(false),
touch_device_id(0),
display_id(0),
has_display_id(false) {}
-OutputConfigurator::CoordinateTransformation::CoordinateTransformation()
- : x_scale(1.0),
- x_offset(0.0),
- y_scale(1.0),
- y_offset(0.0) {}
-
-OutputConfigurator::CrtcConfig::CrtcConfig()
- : crtc(None),
- x(0),
- y(0),
- mode(None),
- output(None) {}
-
-OutputConfigurator::CrtcConfig::CrtcConfig(RRCrtc crtc,
- int x, int y,
- RRMode mode,
- RROutput output)
- : crtc(crtc),
- x(x),
- y(y),
- mode(mode),
- output(output) {}
-
bool OutputConfigurator::TestApi::SendOutputChangeEvents(bool connected) {
XRRScreenChangeNotifyEvent screen_event;
memset(&screen_event, 0, sizeof(screen_event));
@@ -418,7 +401,16 @@
int num_on_outputs = GetOutputPower(outputs, power_state, &output_power);
VLOG(1) << "EnterState: output=" << OutputStateToString(output_state)
<< " power=" << DisplayPowerStateToString(power_state);
+
+ // Framebuffer dimensions.
+ int width = 0, height = 0;
+ std::vector<OutputSnapshot> updated_outputs = outputs;
+
switch (output_state) {
+ case STATE_INVALID:
+ NOTREACHED() << "Ignoring request to enter invalid state with "
+ << outputs.size() << " connected output(s)";
+ return false;
case STATE_HEADLESS:
if (outputs.size() != 0) {
LOG(WARNING) << "Ignoring request to enter headless mode with "
@@ -435,28 +427,16 @@
return false;
}
- // Determine which output to use.
- const OutputSnapshot& output = outputs.size() == 1 ? outputs[0] :
- (output_power[0] ? outputs[0] : outputs[1]);
- int width = 0, height = 0;
- if (!delegate_->GetModeDetails(
- output.selected_mode, &width, &height, NULL))
- return false;
+ for (size_t i = 0; i < updated_outputs.size(); ++i) {
+ OutputSnapshot* output = &updated_outputs[i];
+ output->x = 0;
+ output->y = 0;
+ output->current_mode = output_power[i] ? output->selected_mode : None;
- std::vector<CrtcConfig> configs(outputs.size());
- for (size_t i = 0; i < outputs.size(); ++i) {
- configs[i] = CrtcConfig(
- outputs[i].crtc, 0, 0,
- output_power[i] ? outputs[i].selected_mode : None,
- outputs[i].output);
- }
- delegate_->CreateFrameBuffer(width, height, configs);
-
- for (size_t i = 0; i < outputs.size(); ++i) {
- delegate_->ConfigureCrtc(&configs[i]);
- if (outputs[i].touch_device_id) {
- delegate_->ConfigureCTM(outputs[i].touch_device_id,
- CoordinateTransformation());
+ if (output_power[i] || outputs.size() == 1) {
+ if (!delegate_->GetModeDetails(
+ output->selected_mode, &width, &height, NULL))
+ return false;
}
}
break;
@@ -469,34 +449,24 @@
return false;
}
- int width = 0, height = 0;
if (!delegate_->GetModeDetails(
- outputs[0].mirror_mode, &width, &height, NULL)) {
+ outputs[0].mirror_mode, &width, &height, NULL))
return false;
- }
-
- std::vector<CrtcConfig> configs(outputs.size());
- for (size_t i = 0; i < outputs.size(); ++i) {
- configs[i] = CrtcConfig(
- outputs[i].crtc, 0, 0,
- output_power[i] ? outputs[i].mirror_mode : None,
- outputs[i].output);
- }
- delegate_->CreateFrameBuffer(width, height, configs);
for (size_t i = 0; i < outputs.size(); ++i) {
- delegate_->ConfigureCrtc(&configs[i]);
- if (outputs[i].touch_device_id) {
- CoordinateTransformation ctm;
+ OutputSnapshot* output = &updated_outputs[i];
+ output->x = 0;
+ output->y = 0;
+ output->current_mode = output_power[i] ? output->mirror_mode : None;
+ if (output->touch_device_id) {
// CTM needs to be calculated if aspect preserving scaling is used.
// Otherwise, assume it is full screen, and use identity CTM.
- if (outputs[i].mirror_mode != outputs[i].native_mode &&
- outputs[i].is_aspect_preserving_scaling) {
- ctm = GetMirrorModeCTM(&outputs[i]);
- mirrored_display_area_ratio_map_[outputs[i].touch_device_id] =
- GetMirroredDisplayAreaRatio(&outputs[i]);
+ if (output->mirror_mode != output->native_mode &&
+ output->is_aspect_preserving_scaling) {
+ output->transform = GetMirrorModeCTM(output);
+ mirrored_display_area_ratio_map_[output->touch_device_id] =
+ GetMirroredDisplayAreaRatio(output);
}
- delegate_->ConfigureCTM(outputs[i].touch_device_id, ctm);
}
}
break;
@@ -511,8 +481,6 @@
// Pairs are [width, height] corresponding to the given output's mode.
std::vector<std::pair<int, int> > mode_sizes(outputs.size());
- std::vector<CrtcConfig> configs(outputs.size());
- int width = 0, height = 0;
for (size_t i = 0; i < outputs.size(); ++i) {
if (!delegate_->GetModeDetails(outputs[i].selected_mode,
@@ -520,10 +488,10 @@
return false;
}
- configs[i] = CrtcConfig(
- outputs[i].crtc, 0, (height ? height + kVerticalGap : 0),
- output_power[i] ? outputs[i].selected_mode : None,
- outputs[i].output);
+ OutputSnapshot* output = &updated_outputs[i];
+ output->x = 0;
+ output->y = height ? height + kVerticalGap : 0;
+ output->current_mode = output_power[i] ? output->selected_mode : None;
// Retain the full screen size even if all outputs are off so the
// same desktop configuration can be restored when the outputs are
@@ -532,29 +500,44 @@
height += (height ? kVerticalGap : 0) + mode_sizes[i].second;
}
- delegate_->CreateFrameBuffer(width, height, configs);
-
for (size_t i = 0; i < outputs.size(); ++i) {
- delegate_->ConfigureCrtc(&configs[i]);
- if (outputs[i].touch_device_id) {
- CoordinateTransformation ctm;
- ctm.x_scale = static_cast<float>(mode_sizes[i].first) / width;
- ctm.x_offset = static_cast<float>(configs[i].x) / width;
- ctm.y_scale = static_cast<float>(mode_sizes[i].second) / height;
- ctm.y_offset = static_cast<float>(configs[i].y) / height;
- delegate_->ConfigureCTM(outputs[i].touch_device_id, ctm);
+ OutputSnapshot* output = &updated_outputs[i];
+ if (output->touch_device_id) {
+ CoordinateTransformation* ctm = &(output->transform);
+ ctm->x_scale = static_cast<float>(mode_sizes[i].first) / width;
+ ctm->x_offset = static_cast<float>(output->x) / width;
+ ctm->y_scale = static_cast<float>(mode_sizes[i].second) / height;
+ ctm->y_offset = static_cast<float>(output->y) / height;
}
}
break;
}
- default:
- NOTREACHED() << "Got request to enter output state " << output_state
- << " with " << outputs.size() << " output(s)";
- return false;
+ }
+
+ // Finally, apply the desired changes.
+ DCHECK_EQ(outputs.size(), updated_outputs.size());
+ if (!outputs.empty()) {
+ delegate_->CreateFrameBuffer(width, height, updated_outputs);
+ for (size_t i = 0; i < outputs.size(); ++i) {
+ const OutputSnapshot& output = updated_outputs[i];
+ if (delegate_->ConfigureCrtc(output.crtc, output.current_mode,
+ output.output, output.x, output.y)) {
+ if (output.touch_device_id)
+ delegate_->ConfigureCTM(output.touch_device_id, output.transform);
+ } else {
+ LOG(WARNING) << "Unable to configure CRTC " << output.crtc << ":"
+ << " mode=" << output.current_mode
+ << " output=" << output.output
+ << " x=" << output.x
+ << " y=" << output.y;
+ updated_outputs[i] = outputs[i];
+ }
+ }
}
output_state_ = output_state;
power_state_ = power_state;
+ cached_outputs_ = updated_outputs;
return true;
}
diff --git a/chromeos/display/output_configurator.h b/chromeos/display/output_configurator.h
index a308a45..fbc7804 100644
--- a/chromeos/display/output_configurator.h
+++ b/chromeos/display/output_configurator.h
@@ -42,36 +42,6 @@
: public base::MessageLoop::Dispatcher,
public base::MessagePumpObserver {
public:
- // Information about an output's current state.
- struct OutputSnapshot {
- OutputSnapshot();
-
- RROutput output;
-
- // CRTC that should be used for this output. Not necessarily the CRTC
- // that XRandR reports is currently being used.
- RRCrtc crtc;
-
- RRMode current_mode;
- RRMode native_mode;
- RRMode mirror_mode;
- RRMode selected_mode;
-
- int y;
- int height;
-
- bool is_internal;
- bool is_aspect_preserving_scaling;
-
- // XInput device ID or 0 if this output isn't a touchscreen.
- int touch_device_id;
-
- // Display id for this output.
- int64 display_id;
-
- bool has_display_id;
- };
-
struct CoordinateTransformation {
// Initialized to the identity transformation.
CoordinateTransformation();
@@ -82,15 +52,44 @@
float y_offset;
};
- struct CrtcConfig {
- CrtcConfig();
- CrtcConfig(RRCrtc crtc, int x, int y, RRMode mode, RROutput output);
+ // Information about an output's current state.
+ struct OutputSnapshot {
+ OutputSnapshot();
+ RROutput output;
+
+ // CRTC that should be used for this output. Not necessarily the CRTC
+ // that XRandR reports is currently being used.
RRCrtc crtc;
+
+ // Mode currently being used by the output.
+ RRMode current_mode;
+
+ // "Best" mode supported by the output.
+ RRMode native_mode;
+
+ // Mode used when displaying the same desktop on multiple outputs.
+ RRMode mirror_mode;
+
+ // User-selected mode for the output.
+ RRMode selected_mode;
+
+ // Output's origin on the framebuffer.
int x;
int y;
- RRMode mode;
- RROutput output;
+
+ bool is_internal;
+ bool is_aspect_preserving_scaling;
+
+ // XInput device ID or 0 if this output isn't a touchscreen.
+ int touch_device_id;
+
+ CoordinateTransformation transform;
+
+ // Display id for this output.
+ int64 display_id;
+
+ bool has_display_id;
};
class Observer {
@@ -176,16 +175,20 @@
int* height,
bool* interlaced) = 0;
- // Calls XRRSetCrtcConfig() with the given options but some of our
- // default output count and rotation arguments.
- virtual void ConfigureCrtc(CrtcConfig* config) = 0;
+ // Calls XRRSetCrtcConfig() with the given options but some of our default
+ // output count and rotation arguments. Returns true on success.
+ virtual bool ConfigureCrtc(RRCrtc crtc,
+ RRMode mode,
+ RROutput output,
+ int x,
+ int y) = 0;
// Called to set the frame buffer (underlying XRR "screen") size. Has
// a side-effect of disabling all CRTCs.
virtual void CreateFrameBuffer(
int width,
int height,
- const std::vector<OutputConfigurator::CrtcConfig>& configs) = 0;
+ const std::vector<OutputConfigurator::OutputSnapshot>& outputs) = 0;
// Configures XInput's Coordinate Transformation Matrix property.
// |touch_device_id| the ID of the touchscreen device to configure.
@@ -325,15 +328,17 @@
// Switches to the state specified in |output_state| and |power_state|.
// If the hardware mirroring failed and |mirroring_controller_| is set,
// it switches to |STATE_DUAL_EXTENDED| and calls |SetSoftwareMirroring()|
- // to enable software based mirroing.
- // On success, updates |output_state_| and |power_state_| and returns true.
+ // to enable software based mirroring.
+ // On success, updates |output_state_|, |power_state_|, and |cached_outputs_|
+ // and returns true.
bool EnterStateOrFallBackToSoftwareMirroring(
OutputState output_state,
DisplayPowerState power_state,
const std::vector<OutputSnapshot>& outputs);
// Switches to the state specified in |output_state| and |power_state|.
- // On success, updates |output_state_| and |power_state_| and returns true.
+ // On success, updates |output_state_|, |power_state_|, and
+ // |cached_outputs_| and returns true.
bool EnterState(OutputState output_state,
DisplayPowerState power_state,
const std::vector<OutputSnapshot>& outputs);
@@ -383,6 +388,10 @@
// The current power state.
DisplayPowerState power_state_;
+ // Most-recently-used output configuration. Note that the actual
+ // configuration changes asynchronously.
+ std::vector<OutputSnapshot> cached_outputs_;
+
ObserverList<Observer> observers_;
// The timer to delay configuring outputs. See also the comments in
diff --git a/chromeos/display/output_configurator_unittest.cc b/chromeos/display/output_configurator_unittest.cc
index 246a436..96386f5 100644
--- a/chromeos/display/output_configurator_unittest.cc
+++ b/chromeos/display/output_configurator_unittest.cc
@@ -148,19 +148,23 @@
*interlaced = it->second.interlaced;
return true;
}
- virtual void ConfigureCrtc(OutputConfigurator::CrtcConfig* config) OVERRIDE {
- AppendAction(GetCrtcAction(config->crtc, config->x, config->y, config->mode,
- config->output));
+ virtual bool ConfigureCrtc(RRCrtc crtc,
+ RRMode mode,
+ RROutput output,
+ int x,
+ int y) OVERRIDE {
+ AppendAction(GetCrtcAction(crtc, x, y, mode, output));
+ return true;
}
virtual void CreateFrameBuffer(
int width,
int height,
- const std::vector<OutputConfigurator::CrtcConfig>& configs) OVERRIDE {
+ const std::vector<OutputConfigurator::OutputSnapshot>& outputs) OVERRIDE {
AppendAction(
GetFramebufferAction(width,
height,
- configs.size() >= 1 ? configs[0].crtc : 0,
- configs.size() >= 2 ? configs[1].crtc : 0));
+ outputs.size() >= 1 ? outputs[0].crtc : 0,
+ outputs.size() >= 2 ? outputs[1].crtc : 0));
}
virtual void ConfigureCTM(
int touch_device_id,
@@ -263,8 +267,8 @@
o->native_mode = kSmallModeId;
o->selected_mode = kSmallModeId;
o->mirror_mode = kSmallModeId;
+ o->x = 0;
o->y = 0;
- o->height = kSmallModeHeight;
o->is_internal = true;
o->is_aspect_preserving_scaling = true;
o->touch_device_id = 0;
@@ -277,8 +281,8 @@
o->native_mode = kBigModeId;
o->selected_mode = kBigModeId;
o->mirror_mode = kSmallModeId;
+ o->x = 0;
o->y = 0;
- o->height = kBigModeHeight;
o->is_internal = false;
o->is_aspect_preserving_scaling = true;
o->touch_device_id = 0;
diff --git a/chromeos/display/real_output_configurator_delegate.cc b/chromeos/display/real_output_configurator_delegate.cc
index 0ed0437..47fbd58 100644
--- a/chromeos/display/real_output_configurator_delegate.cc
+++ b/chromeos/display/real_output_configurator_delegate.cc
@@ -138,7 +138,7 @@
XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(
display_, screen_, output_info->crtc);
to_populate.current_mode = crtc_info->mode;
- to_populate.height = crtc_info->height;
+ to_populate.x = crtc_info->x;
to_populate.y = crtc_info->y;
XRRFreeCrtcInfo(crtc_info);
}
@@ -252,38 +252,37 @@
return false;
}
-void RealOutputConfiguratorDelegate::ConfigureCrtc(
- OutputConfigurator::CrtcConfig* config) {
+bool RealOutputConfiguratorDelegate::ConfigureCrtc(
+ RRCrtc crtc,
+ RRMode mode,
+ RROutput output,
+ int x,
+ int y) {
CHECK(screen_) << "Server not grabbed";
- VLOG(1) << "ConfigureCrtc: crtc=" << config->crtc
- << " mode=" << config->mode
- << " output=" << config->output
- << " x=" << config->x
- << " y=" << config->y;
-
- RROutput* outputs = NULL;
- int num_outputs = 0;
- if (config->output && config->mode) {
- outputs = &config->output;
- num_outputs = 1;
- }
-
- XRRSetCrtcConfig(display_,
- screen_,
- config->crtc,
- CurrentTime,
- config->x,
- config->y,
- config->mode,
- RR_Rotate_0,
- outputs,
- num_outputs);
+ VLOG(1) << "ConfigureCrtc: crtc=" << crtc
+ << " mode=" << mode
+ << " output=" << output
+ << " x=" << x
+ << " y=" << y;
+ // Xrandr.h is full of lies. XRRSetCrtcConfig() is defined as returning a
+ // Status, which is typically 0 for failure and 1 for success. In
+ // actuality it returns a RRCONFIGSTATUS, which uses 0 for success.
+ return XRRSetCrtcConfig(display_,
+ screen_,
+ crtc,
+ CurrentTime,
+ x,
+ y,
+ mode,
+ RR_Rotate_0,
+ (output && mode) ? &output : NULL,
+ (output && mode) ? 1 : 0) == RRSetConfigSuccess;
}
void RealOutputConfiguratorDelegate::CreateFrameBuffer(
int width,
int height,
- const std::vector<OutputConfigurator::CrtcConfig>& configs) {
+ const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
CHECK(screen_) << "Server not grabbed";
int current_width = DisplayWidth(display_, DefaultScreen(display_));
int current_height = DisplayHeight(display_, DefaultScreen(display_));
@@ -292,7 +291,7 @@
if (width == current_width && height == current_height)
return;
- DestroyUnusedCrtcs(configs);
+ DestroyUnusedCrtcs(outputs);
int mm_width = width * kPixelsToMmScale;
int mm_height = height * kPixelsToMmScale;
XRRSetScreenSize(display_, window_, width, height, mm_width, mm_height);
@@ -345,7 +344,7 @@
}
void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs(
- const std::vector<OutputConfigurator::CrtcConfig>& configs) {
+ const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
CHECK(screen_) << "Server not grabbed";
// Setting the screen size will fail if any CRTC doesn't fit afterwards.
// At the same time, turning CRTCs off and back on uses up a lot of time.
@@ -360,31 +359,32 @@
// out of the way so we can rebuild the frame buffer.
for (int i = 0; i < screen_->ncrtc; ++i) {
// Default config is to disable the crtcs.
- OutputConfigurator::CrtcConfig config(
- screen_->crtcs[i], 0, 0, None, None);
- for (std::vector<OutputConfigurator::CrtcConfig>::const_iterator it =
- configs.begin(); it != configs.end(); ++it) {
- if (config.crtc == it->crtc) {
- config.mode = it->mode;
- config.output = it->output;
+ RRCrtc crtc = screen_->crtcs[i];
+ RRMode mode = None;
+ RROutput output = None;
+ for (std::vector<OutputConfigurator::OutputSnapshot>::const_iterator it =
+ outputs.begin(); it != outputs.end(); ++it) {
+ if (crtc == it->crtc) {
+ mode = it->current_mode;
+ output = it->output;
break;
}
}
- if (config.mode != None) {
+ if (mode != None) {
// In case our CRTC doesn't fit in our current framebuffer, disable it.
// It'll get reenabled after we resize the framebuffer.
int mode_width = 0, mode_height = 0;
- CHECK(GetModeDetails(config.mode, &mode_width, &mode_height, NULL));
+ CHECK(GetModeDetails(mode, &mode_width, &mode_height, NULL));
int current_width = DisplayWidth(display_, DefaultScreen(display_));
int current_height = DisplayHeight(display_, DefaultScreen(display_));
if (mode_width > current_width || mode_height > current_height) {
- config.mode = None;
- config.output = None;
+ mode = None;
+ output = None;
}
}
- ConfigureCrtc(&config);
+ ConfigureCrtc(crtc, mode, output, 0, 0);
}
}
diff --git a/chromeos/display/real_output_configurator_delegate.h b/chromeos/display/real_output_configurator_delegate.h
index eeec2ab..9f083cf 100644
--- a/chromeos/display/real_output_configurator_delegate.h
+++ b/chromeos/display/real_output_configurator_delegate.h
@@ -44,11 +44,16 @@
int* width,
int* height,
bool* interlaced) OVERRIDE;
- virtual void ConfigureCrtc(OutputConfigurator::CrtcConfig* config) OVERRIDE;
+ virtual bool ConfigureCrtc(
+ RRCrtc crtc,
+ RRMode mode,
+ RROutput output,
+ int x,
+ int y) OVERRIDE;
virtual void CreateFrameBuffer(
int width,
int height,
- const std::vector<OutputConfigurator::CrtcConfig>& configs) OVERRIDE;
+ const std::vector<OutputConfigurator::OutputSnapshot>& outputs) OVERRIDE;
virtual void ConfigureCTM(
int touch_device_id,
const OutputConfigurator::CoordinateTransformation& ctm) OVERRIDE;
@@ -59,7 +64,7 @@
// framebuffer resize. This is faster than turning them off, resizing,
// then turning them back on.
void DestroyUnusedCrtcs(
- const std::vector<OutputConfigurator::CrtcConfig>& configs);
+ const std::vector<OutputConfigurator::OutputSnapshot>& outputs);
// Returns whether |id| is configured to preserve aspect when scaling.
bool IsOutputAspectPreservingScaling(RROutput id);
diff --git a/chromeos/ime/input_methods.txt b/chromeos/ime/input_methods.txt
index 11a9f88..2b4bc91 100644
--- a/chromeos/ime/input_methods.txt
+++ b/chromeos/ime/input_methods.txt
@@ -97,10 +97,6 @@
# a new Mozc Japanese IME for another keyboard layout is added.
xkb:jp::jpn jp ja
-# Traditional Chinese
-mozc-chewing us zh-TW
-m17n:zh:quick us zh-TW
-
# Russian
xkb:ru::rus ru ru
xkb:ru:phonetic:rus ru(phonetic) ru
diff --git a/chromeos/network/favorite_state.cc b/chromeos/network/favorite_state.cc
index 90043e9..2bc6b8e 100644
--- a/chromeos/network/favorite_state.cc
+++ b/chromeos/network/favorite_state.cc
@@ -15,32 +15,31 @@
namespace chromeos {
FavoriteState::FavoriteState(const std::string& path)
- : ManagedState(MANAGED_TYPE_FAVORITE, path),
- onc_source_(onc::ONC_SOURCE_NONE) {
+ : ManagedState(MANAGED_TYPE_FAVORITE, path) {
}
FavoriteState::~FavoriteState() {
}
bool FavoriteState::PropertyChanged(const std::string& key,
- const base::Value& value) {
+ const base::Value& value) {
if (ManagedStatePropertyChanged(key, value))
return true;
if (key == flimflam::kProfileProperty) {
return GetStringValue(key, value, &profile_path_);
} else if (key == flimflam::kUIDataProperty) {
- if (!NetworkState::GetOncSource(value, &onc_source_)) {
+ if (!NetworkState::GetUIDataFromValue(value, &ui_data_)) {
NET_LOG_ERROR("Failed to parse " + key, path());
return false;
}
return true;
-}
+ }
return false;
}
bool FavoriteState::IsManaged() const {
- return onc_source_ == onc::ONC_SOURCE_DEVICE_POLICY ||
- onc_source_ == onc::ONC_SOURCE_USER_POLICY;
+ return ui_data_.onc_source() == onc::ONC_SOURCE_DEVICE_POLICY ||
+ ui_data_.onc_source() == onc::ONC_SOURCE_USER_POLICY;
}
bool FavoriteState::IsPrivate() const {
diff --git a/chromeos/network/favorite_state.h b/chromeos/network/favorite_state.h
index 4fa03f3..53f9281 100644
--- a/chromeos/network/favorite_state.h
+++ b/chromeos/network/favorite_state.h
@@ -6,6 +6,7 @@
#define CHROMEOS_NETWORK_FAVORITE_STATE_H_
#include "chromeos/network/managed_state.h"
+#include "chromeos/network/network_ui_data.h"
#include "chromeos/network/onc/onc_constants.h"
namespace chromeos {
@@ -30,7 +31,7 @@
// Accessors
const std::string& profile_path() const { return profile_path_; }
bool is_favorite() const { return !profile_path_.empty(); }
- onc::ONCSource onc_source() const { return onc_source_; }
+ const NetworkUIData& ui_data() const { return ui_data_; }
// Returns true if the ONC source is a device or user policy.
bool IsManaged() const;
@@ -40,7 +41,7 @@
private:
std::string profile_path_;
- onc::ONCSource onc_source_;
+ NetworkUIData ui_data_;
DISALLOW_COPY_AND_ASSIGN(FavoriteState);
};
diff --git a/chromeos/network/network_configuration_handler.cc b/chromeos/network/network_configuration_handler.cc
index f7f118e..fbd73c6 100644
--- a/chromeos/network/network_configuration_handler.cc
+++ b/chromeos/network/network_configuration_handler.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/format_macros.h"
+#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
@@ -66,6 +67,43 @@
*properties_copy.get());
}
+void SetNetworkProfileErrorCallback(
+ const std::string& service_path,
+ const std::string& profile_path,
+ const network_handler::ErrorCallback& error_callback,
+ const std::string& dbus_error_name,
+ const std::string& dbus_error_message) {
+ network_handler::ShillErrorCallbackFunction(
+ "Config.SetNetworkProfile Failed: " + profile_path,
+ service_path, error_callback,
+ dbus_error_name, dbus_error_message);
+}
+
+bool IsPassphrase(const std::string& key) {
+ return key == flimflam::kEapPrivateKeyPasswordProperty ||
+ key == flimflam::kEapPasswordProperty ||
+ key == flimflam::kL2tpIpsecPasswordProperty ||
+ key == flimflam::kOpenVPNPasswordProperty ||
+ key == flimflam::kPassphraseProperty ||
+ key == flimflam::kOpenVPNOTPProperty ||
+ key == flimflam::kEapPrivateKeyProperty ||
+ key == flimflam::kEapPrivateKeyPasswordProperty ||
+ key == flimflam::kEapPinProperty ||
+ key == flimflam::kApnPasswordProperty;
+}
+
+void LogConfigProperties(const std::string& desc,
+ const std::string& path,
+ const base::DictionaryValue& properties) {
+ for (base::DictionaryValue::Iterator iter(properties);
+ !iter.IsAtEnd(); iter.Advance()) {
+ std::string v = "******";
+ if (!IsPassphrase(iter.key()))
+ base::JSONWriter::Write(&iter.value(), &v);
+ NET_LOG_DEBUG(desc, path + "." + iter.key() + "=" + v);
+ }
+}
+
} // namespace
// Helper class to request from Shill the profile entries associated with a
@@ -188,7 +226,14 @@
const base::DictionaryValue& properties,
const base::Closure& callback,
const network_handler::ErrorCallback& error_callback) {
+ if (properties.empty()) {
+ if (!callback.is_null())
+ callback.Run();
+ return;
+ }
NET_LOG_USER("SetProperties", service_path);
+ LogConfigProperties("SetProperty", service_path, properties);
+
DBusThreadManager::Get()->GetShillServiceClient()->SetProperties(
dbus::ObjectPath(service_path),
properties,
@@ -203,7 +248,16 @@
const std::vector<std::string>& names,
const base::Closure& callback,
const network_handler::ErrorCallback& error_callback) {
+ if (names.empty()) {
+ if (!callback.is_null())
+ callback.Run();
+ return;
+ }
NET_LOG_USER("ClearProperties", service_path);
+ for (std::vector<std::string>::const_iterator iter = names.begin();
+ iter != names.end(); ++iter) {
+ NET_LOG_DEBUG("ClearProperty", service_path + "." + *iter);
+ }
DBusThreadManager::Get()->GetShillServiceClient()->ClearProperties(
dbus::ObjectPath(service_path),
names,
@@ -219,9 +273,12 @@
const network_handler::ErrorCallback& error_callback) {
ShillManagerClient* manager =
DBusThreadManager::Get()->GetShillManagerClient();
-
std::string type;
properties.GetStringWithoutPathExpansion(flimflam::kTypeProperty, &type);
+
+ NET_LOG_USER("CreateConfiguration", type);
+ LogConfigProperties("Configure", type, properties);
+
// Shill supports ConfigureServiceForProfile only for network type WiFi. In
// all other cases, we have to rely on GetService for now. This is
// unproblematic for VPN (user profile only), but will lead to inconsistencies
@@ -265,6 +322,22 @@
deleter->Run();
}
+void NetworkConfigurationHandler::SetNetworkProfile(
+ const std::string& service_path,
+ const std::string& profile_path,
+ const base::Closure& callback,
+ const network_handler::ErrorCallback& error_callback) {
+ NET_LOG_USER("SetNetworkProfile", service_path + ": " + profile_path);
+ base::StringValue profile_path_value(profile_path);
+ DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
+ dbus::ObjectPath(service_path),
+ flimflam::kProfileProperty,
+ profile_path_value,
+ callback,
+ base::Bind(&SetNetworkProfileErrorCallback,
+ service_path, profile_path, error_callback));
+}
+
// NetworkConfigurationHandler Private methods
NetworkConfigurationHandler::NetworkConfigurationHandler()
diff --git a/chromeos/network/network_configuration_handler.h b/chromeos/network/network_configuration_handler.h
index 9ef1131..f1ee856 100644
--- a/chromeos/network/network_configuration_handler.h
+++ b/chromeos/network/network_configuration_handler.h
@@ -99,6 +99,13 @@
const base::Closure& callback,
const network_handler::ErrorCallback& error_callback);
+ // Changes the profile for the network |service_path| to |profile_path|.
+ // See note on |callback| and |error_callback| in class description above.
+ void SetNetworkProfile(const std::string& service_path,
+ const std::string& profile_path,
+ const base::Closure& callback,
+ const network_handler::ErrorCallback& error_callback);
+
// Construct and initialize an instance for testing.
static NetworkConfigurationHandler* InitializeForTest(
NetworkStateHandler* network_state_handler);
diff --git a/chromeos/network/network_connection_handler.cc b/chromeos/network/network_connection_handler.cc
index 66e8d4f..25e03de 100644
--- a/chromeos/network/network_connection_handler.cc
+++ b/chromeos/network/network_connection_handler.cc
@@ -62,56 +62,40 @@
}
bool VPNIsConfigured(const std::string& service_path,
- const base::DictionaryValue& service_properties) {
- // VPN Provider values are read from the "Provider" dictionary, not the
- // "Provider.Type", etc keys (which are used only to set the values).
- const base::DictionaryValue* provider_properties;
- if (!service_properties.GetDictionaryWithoutPathExpansion(
- flimflam::kProviderProperty, &provider_properties)) {
- NET_LOG_ERROR("VPN Provider Dictionary not present", service_path);
- return false;
- }
- std::string provider_type;
- if (!provider_properties->GetStringWithoutPathExpansion(
- flimflam::kTypeProperty, &provider_type)) {
- NET_LOG_ERROR("VPN Provider Type not present", service_path);
- return false;
- }
+ const std::string& provider_type,
+ const base::DictionaryValue& provider_properties) {
if (provider_type == flimflam::kProviderOpenVpn) {
std::string hostname;
- provider_properties->GetStringWithoutPathExpansion(
+ provider_properties.GetStringWithoutPathExpansion(
flimflam::kHostProperty, &hostname);
if (hostname.empty()) {
NET_LOG_EVENT("OpenVPN: No hostname", service_path);
return false;
}
std::string username;
- provider_properties->GetStringWithoutPathExpansion(
+ provider_properties.GetStringWithoutPathExpansion(
flimflam::kOpenVPNUserProperty, &username);
if (username.empty()) {
NET_LOG_EVENT("OpenVPN: No username", service_path);
return false;
}
bool passphrase_required = false;
- provider_properties->GetBooleanWithoutPathExpansion(
+ provider_properties.GetBooleanWithoutPathExpansion(
flimflam::kPassphraseRequiredProperty, &passphrase_required);
- std::string passphrase;
- provider_properties->GetStringWithoutPathExpansion(
- flimflam::kOpenVPNPasswordProperty, &passphrase);
- if (passphrase_required && passphrase.empty()) {
- NET_LOG_EVENT("OpenVPN: No passphrase", service_path);
+ if (passphrase_required) {
+ NET_LOG_EVENT("OpenVPN: Passphrase Required", service_path);
return false;
}
NET_LOG_EVENT("OpenVPN Is Configured", service_path);
} else {
bool passphrase_required = false;
std::string passphrase;
- provider_properties->GetBooleanWithoutPathExpansion(
+ provider_properties.GetBooleanWithoutPathExpansion(
flimflam::kL2tpIpsecPskRequiredProperty, &passphrase_required);
- provider_properties->GetStringWithoutPathExpansion(
- flimflam::kL2tpIpsecPskProperty, &passphrase);
- if (passphrase_required && passphrase.empty())
+ if (passphrase_required) {
+ NET_LOG_EVENT("VPN: Passphrase Required", service_path);
return false;
+ }
NET_LOG_EVENT("VPN Is Configured", service_path);
}
return true;
@@ -135,10 +119,14 @@
"authentication-required";
const char NetworkConnectionHandler::kErrorShillError[] = "shill-error";
const char NetworkConnectionHandler::kErrorConnectFailed[] = "connect-failed";
-const char NetworkConnectionHandler::kErrorDisconnectFailed[] =
- "disconnect-failed";
-const char NetworkConnectionHandler::kErrorMissingProviderType[] =
- "missing-provider-type";
+const char NetworkConnectionHandler::kErrorConfigureFailed[] =
+ "configure-failed";
+const char NetworkConnectionHandler::kErrorActivateFailed[] =
+ "activate-failed";
+const char NetworkConnectionHandler::kErrorMissingProvider[] =
+ "missing-provider";
+const char NetworkConnectionHandler::kErrorConnectCanceled[] =
+ "connect-canceled";
const char NetworkConnectionHandler::kErrorUnknown[] = "unknown-error";
struct NetworkConnectionHandler::ConnectRequest {
@@ -203,10 +191,6 @@
void NetworkConnectionHandler::LoggedInStateChanged(
LoginState::LoggedInState state) {
- NET_LOG_EVENT("NewNetworkConnectionHandler",
- CommandLine::ForCurrentProcess()->HasSwitch(
- chromeos::switches::kUseNewNetworkConnectionHandler) ?
- "enabled" : "disabled");
if (state == LoginState::LOGGED_IN_ACTIVE) {
logged_in_ = true;
NET_LOG_EVENT("Logged In", "");
@@ -266,6 +250,26 @@
return;
}
+ if (check_error_state) {
+ const std::string& error = network->error();
+ if (error == flimflam::kErrorConnectFailed) {
+ InvokeErrorCallback(
+ service_path, error_callback, kErrorPassphraseRequired);
+ return;
+ }
+ if (error == flimflam::kErrorBadPassphrase) {
+ InvokeErrorCallback(
+ service_path, error_callback, kErrorPassphraseRequired);
+ return;
+ }
+
+ if (IsAuthenticationError(error)) {
+ InvokeErrorCallback(
+ service_path, error_callback, kErrorAuthenticationRequired);
+ return;
+ }
+ }
+
// All synchronous checks passed, add |service_path| to connecting list.
pending_requests_.insert(std::make_pair(
service_path,
@@ -316,6 +320,21 @@
CallShillDisconnect(service_path, success_callback, error_callback);
}
+void NetworkConnectionHandler::ActivateNetwork(
+ const std::string& service_path,
+ const std::string& carrier,
+ const base::Closure& success_callback,
+ const network_handler::ErrorCallback& error_callback) {
+ NET_LOG_USER("DisconnectNetwork", service_path);
+ const NetworkState* network =
+ network_state_handler_->GetNetworkState(service_path);
+ if (!network) {
+ InvokeErrorCallback(service_path, error_callback, kErrorNotFound);
+ return;
+ }
+ CallShillActivate(service_path, carrier, success_callback, error_callback);
+}
+
bool NetworkConnectionHandler::HasConnectingNetwork(
const std::string& service_path) {
return pending_requests_.count(service_path) != 0;
@@ -347,30 +366,6 @@
const base::DictionaryValue& service_properties) {
NET_LOG_EVENT("VerifyConfiguredAndConnect", service_path);
- std::string type;
- service_properties.GetStringWithoutPathExpansion(
- flimflam::kTypeProperty, &type);
-
- if (check_error_state) {
- std::string error;
- service_properties.GetStringWithoutPathExpansion(
- flimflam::kErrorProperty, &error);
- if (error == flimflam::kErrorConnectFailed) {
- ErrorCallbackForPendingRequest(service_path, kErrorPassphraseRequired);
- return;
- }
- if (error == flimflam::kErrorBadPassphrase) {
- ErrorCallbackForPendingRequest(service_path, kErrorPassphraseRequired);
- return;
- }
-
- if (IsAuthenticationError(error)) {
- ErrorCallbackForPendingRequest(service_path,
- kErrorAuthenticationRequired);
- return;
- }
- }
-
// If 'passphrase_required' is still true, then the 'Passphrase' property
// has not been set to a minimum length value.
bool passphrase_required = false;
@@ -381,14 +376,43 @@
return;
}
- // VPN requires a host and username to be set.
- if (type == flimflam::kTypeVPN &&
- !VPNIsConfigured(service_path, service_properties)) {
- ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired);
- return;
+ std::string type;
+ service_properties.GetStringWithoutPathExpansion(
+ flimflam::kTypeProperty, &type);
+
+ // Get VPN provider type and host (required for configuration) and ensure
+ // that required VPN non-cert properties are set.
+ std::string vpn_provider_type, vpn_provider_host;
+ if (type == flimflam::kTypeVPN) {
+ // VPN Provider values are read from the "Provider" dictionary, not the
+ // "Provider.Type", etc keys (which are used only to set the values).
+ const base::DictionaryValue* provider_properties;
+ if (service_properties.GetDictionaryWithoutPathExpansion(
+ flimflam::kProviderProperty, &provider_properties)) {
+ provider_properties->GetStringWithoutPathExpansion(
+ flimflam::kTypeProperty, &vpn_provider_type);
+ provider_properties->GetStringWithoutPathExpansion(
+ flimflam::kHostProperty, &vpn_provider_host);
+ }
+ if (vpn_provider_type.empty() || vpn_provider_host.empty()) {
+ ErrorCallbackForPendingRequest(service_path, kErrorMissingProvider);
+ return;
+ }
+ // VPN requires a host and username to be set.
+ if (!VPNIsConfigured(
+ service_path, vpn_provider_type, *provider_properties)) {
+ NET_LOG_ERROR("VPN Not Configured", service_path);
+ ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired);
+ return;
+ }
}
- // Check certificate properties in kUIDataProperty.
+ // These will be set if they need to be configured, otherwise they will
+ // be left empty and the properties will not be set.
+ std::string pkcs11_id, tpm_slot, tpm_pin;
+
+ // Check certificate properties in kUIDataProperty if configured.
+ // Note: Wifi/VPNConfigView set these properties explicitly.
scoped_ptr<NetworkUIData> ui_data =
ManagedNetworkConfigurationHandler::GetUIData(service_properties);
if (ui_data && ui_data->certificate_type() == CLIENT_CERT_TYPE_PATTERN) {
@@ -397,6 +421,7 @@
ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired);
return;
}
+
// If certificates have not been loaded yet, queue the connect request.
if (!certificates_loaded_) {
ConnectRequest* request = pending_request(service_path);
@@ -408,68 +433,79 @@
return;
}
- // Ensure the certificate is available.
- std::string pkcs11_id;
+ // Ensure the certificate is available and configured.
if (!CertificateIsConfigured(ui_data.get(), &pkcs11_id)) {
ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired);
return;
}
+ }
- // The network may not be 'Connectable' because the certificate data is
- // not set up, so configure tpm slot/pin and pkcs11_id before connecting.
- // TODO(stevenjb): Remove this code once NetworkConfigurationHandler
- // handles this.
- NET_LOG_EVENT("Configuring Network", service_path);
- const std::string& tpm_slot = cert_loader_->tpm_token_slot();
- const std::string& tpm_pin = cert_loader_->tpm_user_pin();
- base::DictionaryValue config_properties;
- // Set configuration properties required by Shill to identify the network.
- config_properties.SetStringWithoutPathExpansion(
- flimflam::kTypeProperty, type);
- CopyStringFromDictionary(service_properties, flimflam::kNameProperty,
- &config_properties);
- CopyStringFromDictionary(service_properties, flimflam::kSecurityProperty,
- &config_properties);
- CopyStringFromDictionary(service_properties, flimflam::kGuidProperty,
- &config_properties);
+ // The network may not be 'Connectable' because the TPM properties are
+ // not set up, so configure tpm slot/pin before connecting.
+ if (cert_loader_) {
+ tpm_slot = cert_loader_->tpm_token_slot();
+ tpm_pin = cert_loader_->tpm_user_pin();
+ }
- if (type == flimflam::kTypeVPN) {
- // VPN Provider values are read from the "Provider" dictionary, not the
- // "Provider.Type", etc keys (which are used only to set the values).
- std::string provider_type;
- const base::DictionaryValue* provider_properties;
- if (service_properties.GetDictionaryWithoutPathExpansion(
- flimflam::kProviderProperty, &provider_properties)) {
- provider_properties->GetStringWithoutPathExpansion(
- flimflam::kTypeProperty, &provider_type);
- }
- if (provider_type.empty()) {
- ErrorCallbackForPendingRequest(service_path, kErrorMissingProviderType);
- return;
- }
- if (provider_type == flimflam::kProviderOpenVpn) {
- config_properties.SetStringWithoutPathExpansion(
- flimflam::kOpenVPNClientCertSlotProperty, tpm_slot);
- config_properties.SetStringWithoutPathExpansion(
- flimflam::kOpenVPNPinProperty, tpm_pin);
+ base::DictionaryValue config_properties;
+
+ if (type == flimflam::kTypeVPN) {
+ if (vpn_provider_type == flimflam::kProviderOpenVpn) {
+ if (!pkcs11_id.empty()) {
config_properties.SetStringWithoutPathExpansion(
flimflam::kOpenVPNClientCertIdProperty, pkcs11_id);
- } else {
+ }
+ if (!tpm_pin.empty()) {
config_properties.SetStringWithoutPathExpansion(
- flimflam::kL2tpIpsecClientCertSlotProperty, tpm_slot);
- config_properties.SetStringWithoutPathExpansion(
- flimflam::kL2tpIpsecPinProperty, tpm_pin);
+ flimflam::kOpenVPNPinProperty, tpm_pin);
+ }
+ } else {
+ if (!pkcs11_id.empty()) {
config_properties.SetStringWithoutPathExpansion(
flimflam::kL2tpIpsecClientCertIdProperty, pkcs11_id);
}
- } else if (type == flimflam::kTypeWifi) {
- config_properties.SetStringWithoutPathExpansion(
- flimflam::kEapPinProperty, cert_loader_->tpm_user_pin());
+ if (!tpm_slot.empty()) {
+ config_properties.SetStringWithoutPathExpansion(
+ flimflam::kL2tpIpsecClientCertSlotProperty, tpm_slot);
+ }
+ if (!tpm_pin.empty()) {
+ config_properties.SetStringWithoutPathExpansion(
+ flimflam::kL2tpIpsecPinProperty, tpm_pin);
+ }
+ }
+ } else if (type == flimflam::kTypeWifi) {
+ if (!pkcs11_id.empty()) {
config_properties.SetStringWithoutPathExpansion(
flimflam::kEapCertIdProperty, pkcs11_id);
config_properties.SetStringWithoutPathExpansion(
flimflam::kEapKeyIdProperty, pkcs11_id);
}
+ if (!tpm_pin.empty()) {
+ config_properties.SetStringWithoutPathExpansion(
+ flimflam::kEapPinProperty, tpm_pin);
+ }
+ }
+
+ if (!config_properties.empty()) {
+ NET_LOG_EVENT("Configuring Network", service_path);
+
+ // Set configuration properties required by Shill to identify the network.
+ config_properties.SetStringWithoutPathExpansion(
+ flimflam::kTypeProperty, type);
+ CopyStringFromDictionary(service_properties, flimflam::kNameProperty,
+ &config_properties);
+ CopyStringFromDictionary(service_properties, flimflam::kGuidProperty,
+ &config_properties);
+ if (type == flimflam::kTypeVPN) {
+ config_properties.SetStringWithoutPathExpansion(
+ flimflam::kProviderTypeProperty, vpn_provider_type);
+ config_properties.SetStringWithoutPathExpansion(
+ flimflam::kProviderHostProperty, vpn_provider_host);
+ } else if (type == flimflam::kTypeWifi) {
+ CopyStringFromDictionary(service_properties, flimflam::kSecurityProperty,
+ &config_properties);
+ }
+
network_configuration_handler_->SetProperties(
service_path,
config_properties,
@@ -480,8 +516,14 @@
return;
}
- // Otherwise, we need to configure the network.
- ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired);
+ // Otherwise, we probably still need to configure the network since
+ // 'Connectable' is false. If |check_error_state| is true, signal an
+ // error, otherwise attempt to connect to possibly gain additional error
+ // state from Shill (or in case 'Connectable' is improperly unset).
+ if (check_error_state)
+ ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired);
+ else
+ CallShillConnect(service_path);
}
void NetworkConnectionHandler::CallShillConnect(
@@ -504,7 +546,7 @@
network_handler::ErrorCallback error_callback = request->error_callback;
pending_requests_.erase(service_path);
if (!error_callback.is_null())
- error_callback.Run(error_name, error_data.Pass());
+ error_callback.Run(kErrorConfigureFailed, error_data.Pass());
}
void NetworkConnectionHandler::HandleShillConnectSuccess(
@@ -563,13 +605,21 @@
}
// Network is neither connecting or connected; an error occurred.
- std::string error_name = kErrorConnectFailed;
- std::string error_detail = network->error();
- if (error_detail.empty()) {
- if (network->connection_state() == flimflam::kStateFailure)
- error_detail = flimflam::kUnknownString;
- else
- error_detail = "Unexpected State: " + network->connection_state();
+ std::string error_name, error_detail;
+ if (network->connection_state() == flimflam::kStateIdle &&
+ pending_requests_.size() > 1) {
+ // Another connect request canceled this one.
+ error_name = kErrorConnectCanceled;
+ error_detail = "";
+ } else {
+ error_name = kErrorConnectFailed;
+ error_detail = network->error();
+ if (error_detail.empty()) {
+ if (network->connection_state() == flimflam::kStateFailure)
+ error_detail = flimflam::kUnknownString;
+ else
+ error_detail = "Unexpected State: " + network->connection_state();
+ }
}
std::string error_msg = error_name + ": " + error_detail;
NET_LOG_ERROR(error_msg, service_path);
@@ -627,7 +677,7 @@
base::Bind(&NetworkConnectionHandler::HandleShillDisconnectSuccess,
AsWeakPtr(), service_path, success_callback),
base::Bind(&network_handler::ShillErrorCallbackFunction,
- kErrorDisconnectFailed, service_path, error_callback));
+ kErrorShillError, service_path, error_callback));
}
void NetworkConnectionHandler::HandleShillDisconnectSuccess(
@@ -638,4 +688,29 @@
success_callback.Run();
}
+// Activate
+
+void NetworkConnectionHandler::CallShillActivate(
+ const std::string& service_path,
+ const std::string& carrier,
+ const base::Closure& success_callback,
+ const network_handler::ErrorCallback& error_callback) {
+ NET_LOG_USER("Activate Request", service_path + ": '" + carrier + "'");
+ DBusThreadManager::Get()->GetShillServiceClient()->ActivateCellularModem(
+ dbus::ObjectPath(service_path),
+ carrier,
+ base::Bind(&NetworkConnectionHandler::HandleShillActivateSuccess,
+ AsWeakPtr(), service_path, success_callback),
+ base::Bind(&network_handler::ShillErrorCallbackFunction,
+ kErrorShillError, service_path, error_callback));
+}
+
+void NetworkConnectionHandler::HandleShillActivateSuccess(
+ const std::string& service_path,
+ const base::Closure& success_callback) {
+ NET_LOG_EVENT("Activate Request Sent", service_path);
+ if (!success_callback.is_null())
+ success_callback.Run();
+}
+
} // namespace chromeos
diff --git a/chromeos/network/network_connection_handler.h b/chromeos/network/network_connection_handler.h
index 8f00a8a..90f91e2 100644
--- a/chromeos/network/network_connection_handler.h
+++ b/chromeos/network/network_connection_handler.h
@@ -58,8 +58,10 @@
static const char kErrorConfigurationRequired[];
static const char kErrorShillError[];
static const char kErrorConnectFailed[];
- static const char kErrorDisconnectFailed[];
- static const char kErrorMissingProviderType[];
+ static const char kErrorConfigureFailed[];
+ static const char kErrorActivateFailed[];
+ static const char kErrorMissingProvider[];
+ static const char kErrorConnectCanceled[];
static const char kErrorUnknown[];
// Constants for |error_name| from |error_callback| for Disconnect.
@@ -99,6 +101,18 @@
const base::Closure& success_callback,
const network_handler::ErrorCallback& error_callback);
+ // ActivateNetwork() will start an asynchronous activation attempt.
+ // |carrier| may be empty or may specify a carrier to activate.
+ // On success, |success_callback| will be called.
+ // On failure, |error_callback| will be called with |error_name| one of:
+ // kErrorNotFound if no network matching |service_path| is found.
+ // kErrorShillError if a DBus or Shill error occurred.
+ // TODO(stevenjb/armansito): Move this to a separate NetworkActivationHandler.
+ void ActivateNetwork(const std::string& service_path,
+ const std::string& carrier,
+ const base::Closure& success_callback,
+ const network_handler::ErrorCallback& error_callback);
+
// Returns true if ConnectToNetwork has been called with |service_path| and
// has not completed (i.e. success or error callback has been called).
bool HasConnectingNetwork(const std::string& service_path);
@@ -163,10 +177,21 @@
const base::Closure& success_callback,
const network_handler::ErrorCallback& error_callback);
- // Handle success or failure from Shill.Service.Disconnect.
+ // Handle success from Shill.Service.Disconnect.
void HandleShillDisconnectSuccess(const std::string& service_path,
const base::Closure& success_callback);
+ // Calls Shill.Manager.Activate asynchronously.
+ void CallShillActivate(
+ const std::string& service_path,
+ const std::string& carrier,
+ const base::Closure& success_callback,
+ const network_handler::ErrorCallback& error_callback);
+
+ // Handle success from Shill.Service.ActivateCellularModem.
+ void HandleShillActivateSuccess(const std::string& service_path,
+ const base::Closure& success_callback);
+
// Local references to the associated handler instances.
CertLoader* cert_loader_;
NetworkStateHandler* network_state_handler_;
diff --git a/chromeos/network/network_handler_callbacks.h b/chromeos/network/network_handler_callbacks.h
index 8ba2f7d..92fb1d1 100644
--- a/chromeos/network/network_handler_callbacks.h
+++ b/chromeos/network/network_handler_callbacks.h
@@ -19,6 +19,11 @@
namespace chromeos {
namespace network_handler {
+CHROMEOS_EXPORT extern const char kErrorName[];
+CHROMEOS_EXPORT extern const char kErrorDetail[];
+CHROMEOS_EXPORT extern const char kDbusErrorName[];
+CHROMEOS_EXPORT extern const char kDbusErrorMessage[];
+
// An error callback used by both the configuration handler and the state
// handler to receive error results from the API.
typedef base::Callback<
diff --git a/chromeos/network/network_profile_handler.cc b/chromeos/network/network_profile_handler.cc
index d209265..26b1bef 100644
--- a/chromeos/network/network_profile_handler.cc
+++ b/chromeos/network/network_profile_handler.cc
@@ -188,6 +188,16 @@
return NULL;
}
+const NetworkProfile* NetworkProfileHandler::GetDefaultUserProfile() const {
+ for (NetworkProfileHandler::ProfileList::const_iterator it =
+ profiles_.begin();
+ it != profiles_.end(); ++it) {
+ if (!it->userhash.empty())
+ return &*it;
+ }
+ return NULL;
+}
+
NetworkProfileHandler::NetworkProfileHandler()
: network_state_handler_(NULL),
weak_ptr_factory_(this) {
diff --git a/chromeos/network/network_profile_handler.h b/chromeos/network/network_profile_handler.h
index d3c784e..15bb0fd 100644
--- a/chromeos/network/network_profile_handler.h
+++ b/chromeos/network/network_profile_handler.h
@@ -52,6 +52,11 @@
const NetworkProfile* GetProfileForUserhash(
const std::string& userhash) const;
+ // Returns the first profile entry with a non-empty userhash.
+ // TODO(stevenjb): Replace with GetProfileForUserhash() with the correct
+ // userhash.
+ const NetworkProfile* GetDefaultUserProfile() const;
+
static const char kSharedProfilePath[];
protected:
diff --git a/chromeos/network/network_state.cc b/chromeos/network/network_state.cc
index f0da62d..deff647 100644
--- a/chromeos/network/network_state.cc
+++ b/chromeos/network/network_state.cc
@@ -13,13 +13,14 @@
#include "base/strings/utf_string_conversion_utils.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_profile_handler.h"
-#include "chromeos/network/network_ui_data.h"
#include "chromeos/network/network_util.h"
#include "chromeos/network/onc/onc_utils.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace {
+const char kErrorUnknown[] = "Unknown";
+
bool ConvertListValueToStringVector(const base::ListValue& string_list,
std::vector<std::string>* result) {
for (size_t i = 0; i < string_list.GetSize(); ++i) {
@@ -51,23 +52,6 @@
return result;
}
-// Returns a new NetworkUIData* if |ui_data_value| is a valid NetworkUIData
-// dictionary string, otherwise returns NULL.
-chromeos::NetworkUIData* CreateUIDataFromValue(
- const base::Value& ui_data_value) {
- std::string ui_data_str;
- if (!ui_data_value.GetAsString(&ui_data_str))
- return NULL;
- if (ui_data_str.empty())
- return new chromeos::NetworkUIData();
-
- scoped_ptr<base::DictionaryValue> ui_data_dict(
- chromeos::onc::ReadDictionaryFromJson(ui_data_str));
- if (!ui_data_dict)
- return NULL;
- return new chromeos::NetworkUIData(*ui_data_dict);
-}
-
bool IsCaCertNssSet(const base::DictionaryValue& properties) {
std::string ca_cert_nss;
if (properties.GetStringWithoutPathExpansion(flimflam::kEapCaCertNssProperty,
@@ -104,7 +88,6 @@
auto_connect_(false),
favorite_(false),
priority_(0),
- onc_source_(onc::ONC_SOURCE_NONE),
prefix_length_(0),
signal_strength_(0),
connectable_(false),
@@ -128,7 +111,12 @@
} else if (key == flimflam::kConnectableProperty) {
return GetBooleanValue(key, value, &connectable_);
} else if (key == flimflam::kErrorProperty) {
- return GetStringValue(key, value, &error_);
+ if (!GetStringValue(key, value, &error_))
+ return false;
+ // Shill uses "Unknown" to indicate an unset error state.
+ if (error_ == kErrorUnknown)
+ error_.clear();
+ return true;
} else if (key == shill::kErrorDetailsProperty) {
return GetStringValue(key, value, &error_details_);
} else if (key == IPConfigProperty(flimflam::kAddressProperty)) {
@@ -180,7 +168,7 @@
}
return true;
} else if (key == flimflam::kUIDataProperty) {
- if (!GetOncSource(value, &onc_source_)) {
+ if (!GetUIDataFromValue(value, &ui_data_)) {
NET_LOG_ERROR("Failed to parse " + key, path());
return false;
}
@@ -310,8 +298,8 @@
}
bool NetworkState::IsManaged() const {
- return onc_source_ == onc::ONC_SOURCE_DEVICE_POLICY ||
- onc_source_ == onc::ONC_SOURCE_USER_POLICY;
+ return ui_data_.onc_source() == onc::ONC_SOURCE_DEVICE_POLICY ||
+ ui_data_.onc_source() == onc::ONC_SOURCE_USER_POLICY;
}
bool NetworkState::IsPrivate() const {
@@ -432,12 +420,20 @@
}
// static
-bool NetworkState::GetOncSource(const base::Value& ui_data_value,
- onc::ONCSource* out) {
- scoped_ptr<NetworkUIData> ui_data(CreateUIDataFromValue(ui_data_value));
- if (!ui_data)
+bool NetworkState::GetUIDataFromValue(const base::Value& ui_data_value,
+ NetworkUIData* out) {
+ std::string ui_data_str;
+ if (!ui_data_value.GetAsString(&ui_data_str))
return false;
- *out = ui_data->onc_source();
+ if (ui_data_str.empty()) {
+ *out = NetworkUIData();
+ return true;
+ }
+ scoped_ptr<base::DictionaryValue> ui_data_dict(
+ chromeos::onc::ReadDictionaryFromJson(ui_data_str));
+ if (!ui_data_dict)
+ return false;
+ *out = NetworkUIData(*ui_data_dict);
return true;
}
diff --git a/chromeos/network/network_state.h b/chromeos/network/network_state.h
index f177794..6759082 100644
--- a/chromeos/network/network_state.h
+++ b/chromeos/network/network_state.h
@@ -10,6 +10,7 @@
#include "base/values.h"
#include "chromeos/network/managed_state.h"
+#include "chromeos/network/network_ui_data.h"
#include "chromeos/network/onc/onc_constants.h"
namespace chromeos {
@@ -50,7 +51,7 @@
bool favorite() const { return favorite_; }
int priority() const { return priority_; }
const base::DictionaryValue& proxy_config() const { return proxy_config_; }
- onc::ONCSource onc_source() const { return onc_source_; }
+ const NetworkUIData& ui_data() const { return ui_data_; }
// IPConfig Properties
const std::string& ip_address() const { return ip_address_; }
const std::string& gateway() const { return gateway_; }
@@ -90,7 +91,7 @@
// Returns a comma separated string of name servers.
std::string GetDnsServersAsString() const;
- // Converts the prefix length to a netmaks string.
+ // Converts the prefix length to a netmask string.
std::string GetNetmask() const;
// Helpers (used e.g. when a state is cached)
@@ -101,9 +102,9 @@
// key.
static std::string IPConfigProperty(const char* key);
- // Sets |out| to the ONCSource specified by the UIData property |value|.
- // Returns true if the source was successfully parsed.
- static bool GetOncSource(const base::Value& value, onc::ONCSource* out);
+ // Sets |out| to the UIData specified by |value|. Returns true if successfully
+ // parsed.
+ static bool GetUIDataFromValue(const base::Value& value, NetworkUIData* out);
// Generates a name from properties."Wifi.HexSSID" if present, otherwise
// validates properties.Name and returns a valid utf8 version.
@@ -134,7 +135,7 @@
// TODO(pneubeck): Remove ProxyConfig once NetworkConfigurationHandler
// provides proxy configuration. crbug/241775
base::DictionaryValue proxy_config_;
- onc::ONCSource onc_source_;
+ NetworkUIData ui_data_;
// IPConfig properties.
// Note: These do not correspond to actual Shill.Service properties
// but are derived from the service's corresponding IPConfig object.
diff --git a/chromeos/network/network_state_handler.cc b/chromeos/network/network_state_handler.cc
index e3f3dd3..04b6e28 100644
--- a/chromeos/network/network_state_handler.cc
+++ b/chromeos/network/network_state_handler.cc
@@ -368,16 +368,6 @@
}
}
-void NetworkStateHandler::SetConnectingNetwork(
- const std::string& service_path) {
- connecting_network_ = service_path;
- const NetworkState* network = GetNetworkState(service_path);
- if (network)
- NET_LOG_EVENT("SetConnectingNetwork", GetManagedStateLogName(network));
- else
- NET_LOG_ERROR("SetConnectingNetwork to unknown network", service_path);
-}
-
void NetworkStateHandler::SetCheckPortalList(
const std::string& check_portal_list) {
NET_LOG_EVENT("SetCheckPortalList", check_portal_list);
@@ -440,7 +430,7 @@
}
list_entries.insert(path);
}
- // Delete any remaning entries in managed_map.
+ // Delete any remaining entries in managed_map.
STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end());
}
@@ -524,29 +514,43 @@
if (!network)
return;
std::string prev_connection_state = network->connection_state();
+ std::string prev_profile_path = network->profile_path();
if (!network->PropertyChanged(key, value))
return;
if (key == flimflam::kStateProperty) {
- if (ConnectionStateChanged(network, prev_connection_state))
+ if (ConnectionStateChanged(network, prev_connection_state)) {
OnNetworkConnectionStateChanged(network);
+ // If the connection state changes, other properties such as IPConfig
+ // may have changed, so request a full update.
+ RequestUpdateForNetwork(service_path);
+ }
} else {
- if (network->path() == default_network_path_ &&
- key != flimflam::kSignalStrengthProperty &&
- key != shill::kWifiFrequencyListProperty) {
- // WiFi SignalStrength and WifiFrequencyList updates are too noisy, so
+ bool noisy_property =
+ key == flimflam::kSignalStrengthProperty ||
+ key == shill::kWifiFrequencyListProperty;
+ if (network->path() == default_network_path_ && !noisy_property) {
+ // Wifi SignalStrength and WifiFrequencyList updates are too noisy, so
// don't trigger default network updates for those changes.
OnDefaultNetworkChanged();
}
- std::string detail = network->name() + "." + key;
- detail += " = " + network_event_log::ValueAsString(value);
- network_event_log::LogLevel log_level = network_event_log::LOG_LEVEL_EVENT;
- if (key == flimflam::kErrorProperty || key == shill::kErrorDetailsProperty)
- log_level = network_event_log::LOG_LEVEL_ERROR;
- else if (key == flimflam::kSignalStrengthProperty ||
- key == shill::kWifiFrequencyListProperty)
- log_level = network_event_log::LOG_LEVEL_DEBUG;
- NET_LOG_LEVEL(log_level, "NetworkPropertyUpdated", detail);
+ if (prev_profile_path.empty() && !network->profile_path().empty()) {
+ // If added to a Profile, request a full update so that a FavoriteState
+ // gets created.
+ RequestUpdateForNetwork(service_path);
+ }
+ if (!noisy_property) {
+ std::string detail = network->name() + "." + key;
+ detail += " = " + network_event_log::ValueAsString(value);
+ network_event_log::LogLevel log_level;
+ if (key == flimflam::kErrorProperty ||
+ key == shill::kErrorDetailsProperty) {
+ log_level = network_event_log::LOG_LEVEL_ERROR;
+ } else {
+ log_level = network_event_log::LOG_LEVEL_EVENT;
+ }
+ NET_LOG_LEVEL(log_level, "NetworkPropertyUpdated", detail);
+ }
}
NetworkPropertiesUpdated(network);
}
@@ -596,8 +600,8 @@
} else if (type == ManagedState::MANAGED_TYPE_FAVORITE) {
NET_LOG_DEBUG("FavoriteListChanged",
base::StringPrintf("Size:%" PRIuS, favorite_list_.size()));
- FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
- NetworkListChanged());
+ // The FavoriteState list only changes when the NetworkState list changes,
+ // so no need to signal observers here again.
} else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
NET_LOG_DEBUG("DeviceListChanged",
base::StringPrintf("Size:%" PRIuS, device_list_.size()));
@@ -689,16 +693,6 @@
const NetworkState* network) {
FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_,
NetworkPropertiesUpdated(network));
- // If |connecting_network_| transitions to a non-idle, non-connecting state,
- // clear it *after* signalling observers.
- if (network->path() == connecting_network_ &&
- !network->IsConnectingState() &&
- network->connection_state() != flimflam::kStateIdle) {
- connecting_network_.clear();
- NET_LOG_EVENT("ClearConnectingNetwork", base::StringPrintf(
- "%s:%s", GetManagedStateLogName(network).c_str(),
- network->connection_state().c_str()));
- }
}
void NetworkStateHandler::ScanCompleted(const std::string& type) {
diff --git a/chromeos/network/network_state_handler.h b/chromeos/network/network_state_handler.h
index 161e196..ab99e33 100644
--- a/chromeos/network/network_state_handler.h
+++ b/chromeos/network/network_state_handler.h
@@ -191,13 +191,9 @@
// existing networks.
void RequestUpdateForAllNetworks();
- // Set the user initiated connecting network.
- void SetConnectingNetwork(const std::string& service_path);
-
// Set the list of devices on which portal check is enabled.
void SetCheckPortalList(const std::string& check_portal_list);
- const std::string& connecting_network() const { return connecting_network_; }
const std::string& check_portal_list() const { return check_portal_list_; }
// Generates a DictionaryValue of all NetworkState properties. Currently
@@ -332,12 +328,6 @@
// Keeps track of the default network for notifying observers when it changes.
std::string default_network_path_;
- // Convenience member to track the user initiated connecting network. Set
- // externally when a connection is requested and cleared here when the state
- // changes to something other than Connecting (after observers are notified).
- // TODO(stevenjb): Move this to NetworkConfigurationHandler.
- std::string connecting_network_;
-
// List of interfaces on which portal check is enabled.
std::string check_portal_list_;
diff --git a/cloud_print/gcp20/prototype/dns_sd_server.cc b/cloud_print/gcp20/prototype/dns_sd_server.cc
index 8a6653f..4ef9bb3 100644
--- a/cloud_print/gcp20/prototype/dns_sd_server.cc
+++ b/cloud_print/gcp20/prototype/dns_sd_server.cc
@@ -183,13 +183,13 @@
VLOG(1) << "Current TTL for respond: " << current_ttl;
- bool multicast_respond =
- CommandLine::ForCurrentProcess()->HasSwitch("multicast-respond");
+ bool unicast_respond =
+ CommandLine::ForCurrentProcess()->HasSwitch("unicast-respond");
socket_->SendTo(buffer.get(), buffer.get()->size(),
- multicast_respond ? multicast_address_ : recv_address_,
+ unicast_respond ? recv_address_ : multicast_address_,
base::Bind(&DoNothingAfterSendToSocket));
VLOG(1) << "Responded to "
- << (multicast_respond ? multicast_address_ : recv_address_).ToString();
+ << (unicast_respond ? recv_address_ : multicast_address_).ToString();
}
void DnsSdServer::ProccessQuery(uint32 current_ttl, const DnsQueryRecord& query,
diff --git a/cloud_print/gcp20/prototype/gcp20_device.cc b/cloud_print/gcp20/prototype/gcp20_device.cc
index 01d34ed..2d2c1d5 100644
--- a/cloud_print/gcp20/prototype/gcp20_device.cc
+++ b/cloud_print/gcp20/prototype/gcp20_device.cc
@@ -26,8 +26,8 @@
"HTTP header\n"
" -h, --help prints this message\n"
" --no-announcement disables DNS announcements\n"
- " --multicast-respond DNS responses will be sent in multicast "
- "instead of unicast\n"
+ " --unicast-respond DNS responses will be sent in unicast "
+ "instead of multicast\n"
"\n"
"options:\n"
" --domain-name=<name> sets, should ends with '.local'\n"
@@ -49,17 +49,24 @@
base::RunLoop* g_runner = NULL;
Printer* g_printer = NULL;
+base::MessageLoop* g_message_loop;
+
+void StopLoop() {
+ // Always do after printer.Stop() to make sure XMPP will
+ // be disabled fully before |Quit| will be called
+ // (XMPP disables itself via MessageLoop call).
+ g_message_loop->PostTask(FROM_HERE, g_runner->QuitClosure());
+ g_message_loop = NULL;
+ g_runner = NULL;
+}
void OnAbort(int val) {
- if (g_runner) {
- g_printer->Stop(); // TODO(maksymb): Make this call in safe place call:
- // |OnAbort| is called from different thread.
+ if (g_printer) {
+ g_message_loop->PostTask(
+ FROM_HERE,
+ base::Bind(&Printer::Stop, base::Unretained(g_printer)));
+ g_message_loop->PostTask(FROM_HERE, base::Bind(&StopLoop));
g_printer = NULL;
-
- g_runner->Quit(); // Always do after printer.Stop() to make sure XMPP will
- // be disabled fully before |Quit| will be called
- // (XMPP disables itself via MessageLoop call).
- g_runner = NULL;
}
}
@@ -83,8 +90,8 @@
signal(SIGINT, OnAbort); // Handle Ctrl+C signal.
base::MessageLoop loop(base::MessageLoop::TYPE_IO);
- base::MessageLoop::current()->PostTask(FROM_HERE,
- base::Bind(&StartPrinter, &printer));
+ g_message_loop = &loop;
+ g_message_loop->PostTask(FROM_HERE, base::Bind(&StartPrinter, &printer));
base::RunLoop runner;
g_printer = &printer;
g_runner = &runner;
diff --git a/cloud_print/gcp20/prototype/privet_http_server.cc b/cloud_print/gcp20/prototype/privet_http_server.cc
index 0ffcfbc..0a21059 100644
--- a/cloud_print/gcp20/prototype/privet_http_server.cc
+++ b/cloud_print/gcp20/prototype/privet_http_server.cc
@@ -85,10 +85,10 @@
if (server_->GetLocalAddress(&address) != net::OK) {
NOTREACHED() << "Cannot start HTTP server";
- } else {
- VLOG(1) << "Address of HTTP server: " << address.ToString();
+ return false;
}
+ VLOG(1) << "Address of HTTP server: " << address.ToString();
return true;
}
diff --git a/components/autofill/content/browser/DEPS b/components/autofill/content/browser/DEPS
index 0b9fb92..fb768b6 100644
--- a/components/autofill/content/browser/DEPS
+++ b/components/autofill/content/browser/DEPS
@@ -9,7 +9,6 @@
"+sql",
"+third_party/libjingle",
"+third_party/libphonenumber", # For phone number i18n.
- "+webkit/plugins/webplugininfo.h",
]
specific_include_rules = {
diff --git a/components/autofill/content/browser/wallet/full_wallet.cc b/components/autofill/content/browser/wallet/full_wallet.cc
index 28c47b3..f66b28a 100644
--- a/components/autofill/content/browser/wallet/full_wallet.cc
+++ b/components/autofill/content/browser/wallet/full_wallet.cc
@@ -42,6 +42,7 @@
FullWallet::~FullWallet() {}
+// static
scoped_ptr<FullWallet>
FullWallet::CreateFullWallet(const DictionaryValue& dictionary) {
const ListValue* required_actions_list;
@@ -127,6 +128,32 @@
required_actions));
}
+// static
+scoped_ptr<FullWallet>
+ FullWallet::CreateFullWalletFromClearText(
+ int expiration_month,
+ int expiration_year,
+ const std::string& pan,
+ const std::string& cvn,
+ scoped_ptr<Address> billing_address,
+ scoped_ptr<Address> shipping_address) {
+ DCHECK(billing_address);
+ DCHECK(!pan.empty());
+ DCHECK(!cvn.empty());
+
+ scoped_ptr<FullWallet> wallet(new FullWallet(
+ expiration_month,
+ expiration_year,
+ std::string(), // no iin -- clear text pan/cvn are set below.
+ std::string(), // no encrypted_rest -- clear text pan/cvn are set below.
+ billing_address.Pass(),
+ shipping_address.Pass(),
+ std::vector<RequiredAction>())); // no required actions in clear text.
+ wallet->pan_ = pan;
+ wallet->cvn_ = cvn;
+ return wallet.Pass();
+}
+
base::string16 FullWallet::GetInfo(const AutofillType& type) {
switch (type.GetStorableType()) {
case CREDIT_CARD_NUMBER:
diff --git a/components/autofill/content/browser/wallet/full_wallet.h b/components/autofill/content/browser/wallet/full_wallet.h
index 61e846a..84cc82e 100644
--- a/components/autofill/content/browser/wallet/full_wallet.h
+++ b/components/autofill/content/browser/wallet/full_wallet.h
@@ -41,6 +41,16 @@
static scoped_ptr<FullWallet>
CreateFullWallet(const base::DictionaryValue& dictionary);
+ // Returns a wallet built from the provided clear-text data.
+ // Data is not validated; |pan|, |cvn| and |billing_address| must be set.
+ static scoped_ptr<FullWallet>
+ CreateFullWalletFromClearText(int expiration_month,
+ int expiration_year,
+ const std::string& pan,
+ const std::string& cvn,
+ scoped_ptr<Address> billing_address,
+ scoped_ptr<Address> shipping_address);
+
// Returns corresponding data for |type|.
base::string16 GetInfo(const AutofillType& type);
@@ -80,6 +90,7 @@
FRIEND_TEST_ALL_PREFIXES(FullWalletTest, RestLengthCorrectDecryptionTest);
FRIEND_TEST_ALL_PREFIXES(FullWalletTest, RestLengthUnderDecryptionTest);
FRIEND_TEST_ALL_PREFIXES(FullWalletTest, GetCreditCardInfo);
+
FullWallet(int expiration_month,
int expiration_year,
const std::string& iin,
diff --git a/components/autofill/content/browser/wallet/full_wallet_unittest.cc b/components/autofill/content/browser/wallet/full_wallet_unittest.cc
index 5225bc4..6f66213 100644
--- a/components/autofill/content/browser/wallet/full_wallet_unittest.cc
+++ b/components/autofill/content/browser/wallet/full_wallet_unittest.cc
@@ -505,5 +505,26 @@
full_wallet.GetInfo(AutofillType(CREDIT_CARD_TYPE)));
}
+TEST_F(FullWalletTest, CreateFullWalletFromClearTextData) {
+ scoped_ptr<FullWallet> full_wallet =
+ FullWallet::CreateFullWalletFromClearText(
+ 11, 2012,
+ "5555555555554444", "123",
+ GetTestAddress(), GetTestShippingAddress());
+ EXPECT_EQ(ASCIIToUTF16("5555555555554444"),
+ full_wallet->GetInfo(AutofillType(CREDIT_CARD_NUMBER)));
+ EXPECT_EQ(ASCIIToUTF16("MasterCard"),
+ full_wallet->GetInfo(AutofillType(CREDIT_CARD_TYPE)));
+ EXPECT_EQ(ASCIIToUTF16("123"),
+ full_wallet->GetInfo(AutofillType(CREDIT_CARD_VERIFICATION_CODE)));
+ EXPECT_EQ(ASCIIToUTF16("11/12"),
+ full_wallet->GetInfo(
+ AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR)));
+ EXPECT_TRUE(GetTestAddress()->EqualsIgnoreID(
+ *full_wallet->billing_address()));
+ EXPECT_TRUE(GetTestShippingAddress()->EqualsIgnoreID(
+ *full_wallet->shipping_address()));
+}
+
} // namespace wallet
} // namespace autofill
diff --git a/components/autofill/content/browser/wallet/wallet_address.cc b/components/autofill/content/browser/wallet/wallet_address.cc
index 9595c3c..8ab5998 100644
--- a/components/autofill/content/browser/wallet/wallet_address.cc
+++ b/components/autofill/content/browser/wallet/wallet_address.cc
@@ -264,6 +264,16 @@
string16 Address::GetInfo(const AutofillType& type,
const std::string& app_locale) const {
+ if (type.html_type() == HTML_TYPE_COUNTRY_CODE) {
+ DCHECK(IsStringASCII(country_name_code()));
+ return ASCIIToUTF16(country_name_code());
+ } else if (type.html_type() == HTML_TYPE_STREET_ADDRESS) {
+ base::string16 address = address_line_1();
+ if (!address_line_2().empty())
+ address += ASCIIToUTF16(", ") + address_line_2();
+ return address;
+ }
+
switch (type.GetStorableType()) {
case NAME_FULL:
return recipient_name();
diff --git a/components/autofill/content/browser/wallet/wallet_address_unittest.cc b/components/autofill/content/browser/wallet/wallet_address_unittest.cc
index 6a09fa9..9135f54 100644
--- a/components/autofill/content/browser/wallet/wallet_address_unittest.cc
+++ b/components/autofill/content/browser/wallet/wallet_address_unittest.cc
@@ -409,5 +409,70 @@
}
}
+// Verifies that WalletAddress::GetInfo() can correctly return both country
+// codes and localized country names.
+TEST_F(WalletAddressTest, GetCountryInfo) {
+ Address address("FR",
+ ASCIIToUTF16("recipient_name"),
+ ASCIIToUTF16("address_line_1"),
+ ASCIIToUTF16("address_line_2"),
+ ASCIIToUTF16("locality_name"),
+ ASCIIToUTF16("administrative_area_name"),
+ ASCIIToUTF16("postal_code_number"),
+ ASCIIToUTF16("phone_number"),
+ "id1");
+
+ AutofillType type = AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE);
+ EXPECT_EQ(ASCIIToUTF16("FR"), address.GetInfo(type, "en-US"));
+
+ type = AutofillType(HTML_TYPE_COUNTRY_NAME, HTML_MODE_NONE);
+ EXPECT_EQ(ASCIIToUTF16("France"), address.GetInfo(type, "en-US"));
+
+ type = AutofillType(ADDRESS_HOME_COUNTRY);
+ EXPECT_EQ(ASCIIToUTF16("France"), address.GetInfo(type, "en-US"));
+}
+
+// Verifies that WalletAddress::GetInfo() can correctly return a concatenated
+// full street address.
+TEST_F(WalletAddressTest, GetStreetAddress) {
+ // Address has both lines 1 and 2.
+ Address address1("FR",
+ ASCIIToUTF16("recipient_name"),
+ ASCIIToUTF16("address_line_1"),
+ ASCIIToUTF16("address_line_2"),
+ ASCIIToUTF16("locality_name"),
+ ASCIIToUTF16("administrative_area_name"),
+ ASCIIToUTF16("postal_code_number"),
+ ASCIIToUTF16("phone_number"),
+ "id1");
+ AutofillType type = AutofillType(HTML_TYPE_STREET_ADDRESS, HTML_MODE_NONE);
+ EXPECT_EQ(ASCIIToUTF16("address_line_1, address_line_2"),
+ address1.GetInfo(type, "en-US"));
+
+ // Address has only line 1.
+ Address address2("FR",
+ ASCIIToUTF16("recipient_name"),
+ ASCIIToUTF16("address_line_1"),
+ base::string16(),
+ ASCIIToUTF16("locality_name"),
+ ASCIIToUTF16("administrative_area_name"),
+ ASCIIToUTF16("postal_code_number"),
+ ASCIIToUTF16("phone_number"),
+ "id1");
+ EXPECT_EQ(ASCIIToUTF16("address_line_1"), address2.GetInfo(type, "en-US"));
+
+ // Address has no address lines.
+ Address address3("FR",
+ ASCIIToUTF16("recipient_name"),
+ base::string16(),
+ base::string16(),
+ ASCIIToUTF16("locality_name"),
+ ASCIIToUTF16("administrative_area_name"),
+ ASCIIToUTF16("postal_code_number"),
+ ASCIIToUTF16("phone_number"),
+ "id1");
+ EXPECT_EQ(base::string16(), address3.GetInfo(type, "en-US"));
+}
+
} // namespace wallet
} // namespace autofill
diff --git a/components/autofill/content/browser/wallet/wallet_client.cc b/components/autofill/content/browser/wallet/wallet_client.cc
index 09afa60..bb5c525 100644
--- a/components/autofill/content/browser/wallet/wallet_client.cc
+++ b/components/autofill/content/browser/wallet/wallet_client.cc
@@ -105,6 +105,8 @@
&trimmed);
if (LowerCaseEqualsASCII(trimmed, "buyer_account_error"))
return WalletClient::BUYER_ACCOUNT_ERROR;
+ if (LowerCaseEqualsASCII(trimmed, "unsupported_merchant"))
+ return WalletClient::UNSUPPORTED_MERCHANT;
if (LowerCaseEqualsASCII(trimmed, "internal_error"))
return WalletClient::INTERNAL_ERROR;
if (LowerCaseEqualsASCII(trimmed, "invalid_params"))
@@ -113,9 +115,26 @@
return WalletClient::SERVICE_UNAVAILABLE;
if (LowerCaseEqualsASCII(trimmed, "unsupported_api_version"))
return WalletClient::UNSUPPORTED_API_VERSION;
+
return WalletClient::UNKNOWN_ERROR;
}
+// Get the more specific WalletClient::ErrorType when the error is
+// |BUYER_ACCOUNT_ERROR|.
+WalletClient::ErrorType BuyerErrorStringToErrorType(
+ const std::string& buyer_error_type) {
+ std::string trimmed;
+ TrimWhitespaceASCII(buyer_error_type,
+ TRIM_ALL,
+ &trimmed);
+ if (LowerCaseEqualsASCII(trimmed, "bla_country_not_supported"))
+ return WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED;
+ if (LowerCaseEqualsASCII(trimmed, "buyer_kyc_error"))
+ return WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS;
+
+ return WalletClient::BUYER_ACCOUNT_ERROR;
+}
+
// Gets and parses required actions from a SaveToWallet response. Returns
// false if any unknown required actions are seen and true otherwise.
void GetRequiredActionsForSaveToWallet(
@@ -161,16 +180,22 @@
switch (error_type) {
case WalletClient::BAD_REQUEST:
return AutofillMetrics::WALLET_BAD_REQUEST;
+ case WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED:
+ return AutofillMetrics::WALLET_BUYER_LEGAL_ADDRESS_NOT_SUPPORTED;
case WalletClient::BUYER_ACCOUNT_ERROR:
return AutofillMetrics::WALLET_BUYER_ACCOUNT_ERROR;
case WalletClient::INTERNAL_ERROR:
return AutofillMetrics::WALLET_INTERNAL_ERROR;
case WalletClient::INVALID_PARAMS:
return AutofillMetrics::WALLET_INVALID_PARAMS;
+ case WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS:
+ return AutofillMetrics::WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS;
case WalletClient::SERVICE_UNAVAILABLE:
return AutofillMetrics::WALLET_SERVICE_UNAVAILABLE;
case WalletClient::UNSUPPORTED_API_VERSION:
return AutofillMetrics::WALLET_UNSUPPORTED_API_VERSION;
+ case WalletClient::UNSUPPORTED_MERCHANT:
+ return AutofillMetrics::WALLET_UNSUPPORTED_MERCHANT;
case WalletClient::MALFORMED_RESPONSE:
return AutofillMetrics::WALLET_MALFORMED_RESPONSE;
case WalletClient::NETWORK_ERROR:
@@ -220,6 +245,7 @@
const char kAcceptedLegalDocumentKey[] = "accepted_legal_document";
const char kApiKeyKey[] = "api_key";
const char kAuthResultKey[] = "auth_result";
+const char kBuyerErrorTypeKey[] = "wallet_error.buyer_error_type";
const char kEncryptedOtpKey[] = "encrypted_otp";
const char kErrorTypeKey[] = "wallet_error.error_type";
const char kFeatureKey[] = "feature";
@@ -669,13 +695,24 @@
if (response_code == net::HTTP_INTERNAL_SERVER_ERROR) {
request_type_ = NO_PENDING_REQUEST;
- std::string error_type;
- if (!response_dict->GetString(kErrorTypeKey, &error_type)) {
+ std::string error_type_string;
+ if (!response_dict->GetString(kErrorTypeKey, &error_type_string)) {
HandleWalletError(UNKNOWN_ERROR);
return;
}
+ WalletClient::ErrorType error_type =
+ StringToErrorType(error_type_string);
+ if (error_type == BUYER_ACCOUNT_ERROR) {
+ // If the error_type is |BUYER_ACCOUNT_ERROR|, then buyer_error_type
+ // field contains more specific information about the error.
+ std::string buyer_error_type_string;
+ if (response_dict->GetString(kBuyerErrorTypeKey,
+ &buyer_error_type_string)) {
+ error_type = BuyerErrorStringToErrorType(buyer_error_type_string);
+ }
+ }
- HandleWalletError(StringToErrorType(error_type));
+ HandleWalletError(error_type);
return;
}
break;
@@ -794,6 +831,9 @@
case WalletClient::BAD_REQUEST:
error_message = "WALLET_BAD_REQUEST";
break;
+ case WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED:
+ error_message = "WALLET_BUYER_LEGAL_ADDRESS_NOT_SUPPORTED";
+ break;
case WalletClient::BUYER_ACCOUNT_ERROR:
error_message = "WALLET_BUYER_ACCOUNT_ERROR";
break;
@@ -803,12 +843,18 @@
case WalletClient::INVALID_PARAMS:
error_message = "WALLET_INVALID_PARAMS";
break;
+ case WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS:
+ error_message = "WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS";
+ break;
case WalletClient::SERVICE_UNAVAILABLE:
error_message = "WALLET_SERVICE_UNAVAILABLE";
break;
case WalletClient::UNSUPPORTED_API_VERSION:
error_message = "WALLET_UNSUPPORTED_API_VERSION";
break;
+ case WalletClient::UNSUPPORTED_MERCHANT:
+ error_message = "WALLET_UNSUPPORTED_MERCHANT";
+ break;
case WalletClient::MALFORMED_RESPONSE:
error_message = "WALLET_MALFORMED_RESPONSE";
break;
diff --git a/components/autofill/content/browser/wallet/wallet_client.h b/components/autofill/content/browser/wallet/wallet_client.h
index ecaae3d..d4f9607 100644
--- a/components/autofill/content/browser/wallet/wallet_client.h
+++ b/components/autofill/content/browser/wallet/wallet_client.h
@@ -75,8 +75,15 @@
// The type of error returned by Online Wallet.
enum ErrorType {
// Errors to display to users.
- BUYER_ACCOUNT_ERROR, // Risk deny, unsupported country, or account
- // closed.
+ BUYER_ACCOUNT_ERROR, // Risk deny, unsupported country, or
+ // account closed.
+ BUYER_LEGAL_ADDRESS_NOT_SUPPORTED, // User's Buyer Legal Address is
+ // unsupported by Online Wallet.
+ UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS, // User's "know your customer" KYC
+ // state is not verified (either
+ // KYC_REFER or KYC_FAIL).
+ UNSUPPORTED_MERCHANT, // Merchant is blacklisted due to
+ // compliance violation.
// API errors.
BAD_REQUEST, // Request was very malformed or sent to the
diff --git a/components/autofill/content/browser/wallet/wallet_client_unittest.cc b/components/autofill/content/browser/wallet/wallet_client_unittest.cc
index 3f20337..031e5cd 100644
--- a/components/autofill/content/browser/wallet/wallet_client_unittest.cc
+++ b/components/autofill/content/browser/wallet/wallet_client_unittest.cc
@@ -10,6 +10,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "chrome/test/base/testing_profile.h"
#include "components/autofill/content/browser/autocheckout_steps.h"
@@ -794,6 +795,58 @@
fetcher->delegate()->OnURLFetchComplete(fetcher);
}
+ void TestWalletErrorCode(
+ const std::string& error_type_string,
+ const std::string& buyer_error_type_string,
+ WalletClient::ErrorType expected_error_type,
+ AutofillMetrics::WalletErrorMetric expected_autofill_metric) {
+ static const char kResponseTemplate[] =
+ "{"
+ " \"error_type\":\"APPLICATION_ERROR\","
+ " \"error_detail\":\"error_detail\","
+ " \"application_error\":\"application_error\","
+ " \"debug_data\":"
+ " {"
+ " \"debug_message\":\"debug_message\","
+ " \"stack_trace\":\"stack_trace\""
+ " },"
+ " \"application_error_data\":\"application_error_data\","
+ " \"wallet_error\":"
+ " {"
+ " \"error_type\":\"%s\","
+ " %s" // Placeholder for |user_error_type|.
+ " \"error_detail\":\"error_detail\","
+ " \"message_for_user\":"
+ " {"
+ " \"text\":\"text\","
+ " \"subtext\":\"subtext\","
+ " \"details\":\"details\""
+ " }"
+ " }"
+ "}";
+ EXPECT_CALL(delegate_, OnWalletError(expected_error_type)).Times(1);
+ delegate_.ExpectLogWalletApiCallDuration(AutofillMetrics::SEND_STATUS, 1);
+ delegate_.ExpectBaselineMetrics();
+ delegate_.ExpectWalletErrorMetric(expected_autofill_metric);
+
+ std::vector<AutocheckoutStatistic> statistics;
+ wallet_client_->SendAutocheckoutStatus(autofill::SUCCESS,
+ GURL(kMerchantUrl),
+ statistics,
+ "google_transaction_id");
+ std::string buyer_error;
+ if (!buyer_error_type_string.empty()) {
+ buyer_error = base::StringPrintf("\"buyer_error_type\":\"%s\",",
+ buyer_error_type_string.c_str());
+ }
+ std::string response = base::StringPrintf(kResponseTemplate,
+ error_type_string.c_str(),
+ buyer_error.c_str());
+ VerifyAndFinishRequest(net::HTTP_INTERNAL_SERVER_ERROR,
+ kSendAutocheckoutStatusOfSuccessValidRequest,
+ response);
+ }
+
protected:
content::TestBrowserThreadBundle thread_bundle_;
scoped_ptr<WalletClient> wallet_client_;
@@ -819,22 +872,98 @@
net::TestURLFetcherFactory factory_;
};
-TEST_F(WalletClientTest, WalletError) {
- EXPECT_CALL(delegate_, OnWalletError(
- WalletClient::SERVICE_UNAVAILABLE)).Times(1);
- delegate_.ExpectLogWalletApiCallDuration(AutofillMetrics::SEND_STATUS, 1);
- delegate_.ExpectBaselineMetrics();
- delegate_.ExpectWalletErrorMetric(
- AutofillMetrics::WALLET_SERVICE_UNAVAILABLE);
+TEST_F(WalletClientTest, WalletErrorCodes) {
+ struct {
+ std::string error_type_string;
+ std::string buyer_error_type_string;
+ WalletClient::ErrorType expected_error_type;
+ AutofillMetrics::WalletErrorMetric expected_autofill_metric;
+ } test_cases[] = {
+ // General |BUYER_ACCOUNT_ERROR| with no |buyer_error_type_string|.
+ {
+ "buyer_account_error",
+ "",
+ WalletClient::BUYER_ACCOUNT_ERROR,
+ AutofillMetrics::WALLET_BUYER_ACCOUNT_ERROR
+ },
+ // |BUYER_ACCOUNT_ERROR| with "buyer_legal_address_not_supported" in
+ // buyer_error_type field.
+ {
+ "buyer_account_error",
+ "bla_country_not_supported",
+ WalletClient::BUYER_LEGAL_ADDRESS_NOT_SUPPORTED,
+ AutofillMetrics::WALLET_BUYER_LEGAL_ADDRESS_NOT_SUPPORTED
+ },
+ // |BUYER_ACCOUNT_ERROR| with KYC error code in buyer_error_type field.
+ {
+ "buyer_account_error",
+ "buyer_kyc_error",
+ WalletClient::UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS,
+ AutofillMetrics::WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS
+ },
+ // |BUYER_ACCOUNT_ERROR| with un-recognizable |buyer_error_type|.
+ {
+ "buyer_account_error",
+ "random_string",
+ WalletClient::BUYER_ACCOUNT_ERROR,
+ AutofillMetrics::WALLET_BUYER_ACCOUNT_ERROR
+ },
+ // The following are other error types we could get from Wallet.
+ {
+ "unsupported_merchant",
+ "",
+ WalletClient::UNSUPPORTED_MERCHANT,
+ AutofillMetrics::WALLET_UNSUPPORTED_MERCHANT
+ },
+ {
+ "internal_error",
+ "",
+ WalletClient::INTERNAL_ERROR,
+ AutofillMetrics::WALLET_INTERNAL_ERROR
+ },
+ {
+ "invalid_params",
+ "",
+ WalletClient::INVALID_PARAMS,
+ AutofillMetrics::WALLET_INVALID_PARAMS
+ },
+ {
+ "service_unavailable",
+ "",
+ WalletClient::SERVICE_UNAVAILABLE,
+ AutofillMetrics::WALLET_SERVICE_UNAVAILABLE
+ },
+ {
+ "unsupported_api_version",
+ "",
+ WalletClient::UNSUPPORTED_API_VERSION,
+ AutofillMetrics::WALLET_UNSUPPORTED_API_VERSION
+ },
+ // Any un-recognizable |error_type| is a |UNKNOWN_ERROR|.
+ {
+ "random_string_1",
+ "",
+ WalletClient::UNKNOWN_ERROR,
+ AutofillMetrics::WALLET_UNKNOWN_ERROR
+ },
+ {
+ "random_string_2",
+ "",
+ WalletClient::UNKNOWN_ERROR,
+ AutofillMetrics::WALLET_UNKNOWN_ERROR
+ },
+ };
- std::vector<AutocheckoutStatistic> statistics;
- wallet_client_->SendAutocheckoutStatus(autofill::SUCCESS,
- GURL(kMerchantUrl),
- statistics,
- "google_transaction_id");
- VerifyAndFinishRequest(net::HTTP_INTERNAL_SERVER_ERROR,
- kSendAutocheckoutStatusOfSuccessValidRequest,
- kErrorResponse);
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
+ SCOPED_TRACE(
+ base::StringPrintf("%s - %s",
+ test_cases[i].error_type_string.c_str(),
+ test_cases[i].buyer_error_type_string.c_str()));
+ TestWalletErrorCode(test_cases[i].error_type_string,
+ test_cases[i].buyer_error_type_string,
+ test_cases[i].expected_error_type,
+ test_cases[i].expected_autofill_metric);
+ }
}
TEST_F(WalletClientTest, WalletErrorResponseMissing) {
diff --git a/components/autofill/core/browser/address.cc b/components/autofill/core/browser/address.cc
index ca522f6..6f7f2a9 100644
--- a/components/autofill/core/browser/address.cc
+++ b/components/autofill/core/browser/address.cc
@@ -62,7 +62,7 @@
return zip_code_;
case ADDRESS_HOME_COUNTRY:
- return country_code_;
+ return ASCIIToUTF16(country_code_);
default:
return base::string16();
@@ -89,8 +89,9 @@
break;
case ADDRESS_HOME_COUNTRY:
- DCHECK(value.empty() || value.length() == 2u);
- country_code_ = value;
+ DCHECK(value.empty() ||
+ (value.length() == 2u && IsStringASCII(value)));
+ country_code_ = UTF16ToASCII(value);
break;
case ADDRESS_HOME_ZIP:
@@ -104,9 +105,18 @@
base::string16 Address::GetInfo(const AutofillType& type,
const std::string& app_locale) const {
+ if (type.html_type() == HTML_TYPE_COUNTRY_CODE) {
+ return ASCIIToUTF16(country_code_);
+ } else if (type.html_type() == HTML_TYPE_STREET_ADDRESS) {
+ base::string16 address = line1_;
+ if (!line2_.empty())
+ address += ASCIIToUTF16(", ") + line2_;
+ return address;
+ }
+
ServerFieldType storable_type = type.GetStorableType();
if (storable_type == ADDRESS_HOME_COUNTRY && !country_code_.empty())
- return AutofillCountry(UTF16ToASCII(country_code_), app_locale).name();
+ return AutofillCountry(country_code_, app_locale).name();
return GetRawInfo(storable_type);
}
@@ -114,10 +124,26 @@
bool Address::SetInfo(const AutofillType& type,
const base::string16& value,
const std::string& app_locale) {
+ if (type.html_type() == HTML_TYPE_COUNTRY_CODE) {
+ if (!value.empty() && (value.size() != 2u || !IsStringASCII(value))) {
+ country_code_ = std::string();
+ return false;
+ }
+
+ country_code_ = StringToUpperASCII(UTF16ToASCII(value));
+ return true;
+ } else if (type.html_type() == HTML_TYPE_STREET_ADDRESS) {
+ // Don't attempt to parse the address into lines, since this is potentially
+ // a user-entered address in the user's own format, so the code would have
+ // to rely on iffy heuristics at best. Instead, just give up when importing
+ // addresses like this.
+ line1_ = line2_ = base::string16();
+ return false;
+ }
+
ServerFieldType storable_type = type.GetStorableType();
if (storable_type == ADDRESS_HOME_COUNTRY && !value.empty()) {
- country_code_ =
- ASCIIToUTF16(AutofillCountry::GetCountryCode(value, app_locale));
+ country_code_ = AutofillCountry::GetCountryCode(value, app_locale);
return !country_code_.empty();
}
@@ -132,7 +158,7 @@
// Check to see if the |text| canonicalized as a country name is a match.
std::string country_code = AutofillCountry::GetCountryCode(text, app_locale);
- if (!country_code.empty() && country_code_ == ASCIIToUTF16(country_code))
+ if (!country_code.empty() && country_code_ == country_code)
matching_types->insert(ADDRESS_HOME_COUNTRY);
}
diff --git a/components/autofill/core/browser/address.h b/components/autofill/core/browser/address.h
index db1c731..f62c32e 100644
--- a/components/autofill/core/browser/address.h
+++ b/components/autofill/core/browser/address.h
@@ -42,13 +42,16 @@
virtual void GetSupportedTypes(
ServerFieldTypeSet* supported_types) const OVERRIDE;
- // The address.
+ // The address, sans country info.
base::string16 line1_;
base::string16 line2_;
base::string16 city_;
base::string16 state_;
- base::string16 country_code_;
base::string16 zip_code_;
+
+ // The ISO 3166 2-letter country code, or an empty string if there is no
+ // country data specified for this address.
+ std::string country_code_;
};
} // namespace autofill
diff --git a/components/autofill/core/browser/address_unittest.cc b/components/autofill/core/browser/address_unittest.cc
index 8d2e920..b5bcfaf 100644
--- a/components/autofill/core/browser/address_unittest.cc
+++ b/components/autofill/core/browser/address_unittest.cc
@@ -4,33 +4,17 @@
#include <string>
-#include "base/message_loop/message_loop.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/address.h"
#include "components/autofill/core/browser/autofill_type.h"
-#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
-using content::BrowserThread;
-
namespace autofill {
-class AddressTest : public testing::Test {
- public:
- // In order to access the application locale -- which the tested functions do
- // internally -- this test must run on the UI thread.
- AddressTest() : ui_thread_(BrowserThread::UI, &message_loop_) {}
-
- private:
- base::MessageLoopForUI message_loop_;
- content::TestBrowserThread ui_thread_;
-
- DISALLOW_COPY_AND_ASSIGN(AddressTest);
-};
-
-// Test that country codes are properly decoded as country names.
-TEST_F(AddressTest, GetCountry) {
+// Test that country data can be properly returned as either a country code or a
+// localized country name.
+TEST(AddressTest, GetCountry) {
Address address;
EXPECT_EQ(base::string16(), address.GetRawInfo(ADDRESS_HOME_COUNTRY));
@@ -43,14 +27,26 @@
AutofillType(ADDRESS_HOME_COUNTRY), ASCIIToUTF16("US"), "en-US");
country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
EXPECT_EQ(ASCIIToUTF16("United States"), country);
+ country = address.GetInfo(
+ AutofillType(HTML_TYPE_COUNTRY_NAME, HTML_MODE_NONE), "en-US");
+ EXPECT_EQ(ASCIIToUTF16("United States"), country);
+ country = address.GetInfo(
+ AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE), "en-US");
+ EXPECT_EQ(ASCIIToUTF16("US"), country);
address.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("CA"));
country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
EXPECT_EQ(ASCIIToUTF16("Canada"), country);
+ country = address.GetInfo(
+ AutofillType(HTML_TYPE_COUNTRY_NAME, HTML_MODE_NONE), "en-US");
+ EXPECT_EQ(ASCIIToUTF16("Canada"), country);
+ country = address.GetInfo(
+ AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE), "en-US");
+ EXPECT_EQ(ASCIIToUTF16("CA"), country);
}
// Test that we properly detect country codes appropriate for each country.
-TEST_F(AddressTest, SetCountry) {
+TEST(AddressTest, SetCountry) {
Address address;
EXPECT_EQ(base::string16(), address.GetRawInfo(ADDRESS_HOME_COUNTRY));
@@ -90,10 +86,31 @@
country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
EXPECT_EQ(base::string16(), address.GetRawInfo(ADDRESS_HOME_COUNTRY));
EXPECT_EQ(base::string16(), country);
+
+ // Test setting the country based on an HTML field type.
+ AutofillType html_type_country_code =
+ AutofillType(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE);
+ address.SetInfo(html_type_country_code, ASCIIToUTF16("US"), "en-US");
+ country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
+ EXPECT_EQ(ASCIIToUTF16("US"), address.GetRawInfo(ADDRESS_HOME_COUNTRY));
+ EXPECT_EQ(ASCIIToUTF16("United States"), country);
+
+ // Test case-insensitivity when setting the country based on an HTML field
+ // type.
+ address.SetInfo(html_type_country_code, ASCIIToUTF16("cA"), "en-US");
+ country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
+ EXPECT_EQ(ASCIIToUTF16("CA"), address.GetRawInfo(ADDRESS_HOME_COUNTRY));
+ EXPECT_EQ(ASCIIToUTF16("Canada"), country);
+
+ // Test setting the country based on invalid data with an HTML field type.
+ address.SetInfo(html_type_country_code, ASCIIToUTF16("unknown"), "en-US");
+ country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US");
+ EXPECT_EQ(base::string16(), address.GetRawInfo(ADDRESS_HOME_COUNTRY));
+ EXPECT_EQ(base::string16(), country);
}
// Test that we properly match typed values to stored country data.
-TEST_F(AddressTest, IsCountry) {
+TEST(AddressTest, IsCountry) {
Address address;
address.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("US"));
@@ -132,4 +149,50 @@
EXPECT_EQ(0U, matching_types.size());
}
+// Verifies that Address::GetInfo() can correctly return a concatenated full
+// street address.
+TEST(AddressTest, GetStreetAddress) {
+ // Address has no address lines.
+ Address address;
+ EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty());
+ EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty());
+
+ AutofillType type = AutofillType(HTML_TYPE_STREET_ADDRESS, HTML_MODE_NONE);
+ EXPECT_EQ(base::string16(), address.GetInfo(type, "en-US"));
+
+ // Address has only line 1.
+ address.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("123 Example Ave."));
+ EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty());
+ EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty());
+
+ EXPECT_EQ(ASCIIToUTF16("123 Example Ave."),
+ address.GetInfo(type, "en-US"));
+
+ // Address has lines 1 and 2.
+ address.SetRawInfo(ADDRESS_HOME_LINE2, ASCIIToUTF16("Apt. 42"));
+ EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty());
+ EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty());
+
+ EXPECT_EQ(ASCIIToUTF16("123 Example Ave., Apt. 42"),
+ address.GetInfo(type, "en-US"));
+}
+
+// Verifies that Address::SetInfo() rejects setting data for
+// HTML_TYPE_STREET_ADDRESS, as there is no good general way to parse that data
+// into the consituent address lines.
+TEST(AddressTest, SetStreetAddress) {
+ // Address has no address lines.
+ Address address;
+ address.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("123 Example Ave."));
+ address.SetRawInfo(ADDRESS_HOME_LINE2, ASCIIToUTF16("Apt. 42"));
+ EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty());
+ EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty());
+
+ AutofillType type = AutofillType(HTML_TYPE_STREET_ADDRESS, HTML_MODE_NONE);
+ base::string16 street_address = ASCIIToUTF16("456 New St., Apt. 17");
+ EXPECT_FALSE(address.SetInfo(type, street_address, "en-US"));
+ EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty());
+ EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty());
+}
+
} // namespace autofill
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index e69ed0f..7aeb81e 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -2159,7 +2159,7 @@
EXPECT_TRUE(response_data.user_submitted);
ASSERT_EQ(11U, response_data.fields.size());
- ExpectFilledField("", "country", "United States", "text",
+ ExpectFilledField("", "country", "US", "text",
response_data.fields[0]);
ExpectFilledField("", "firstname", "", "text", response_data.fields[1]);
ExpectFilledField("", "lastname", "", "text", response_data.fields[2]);
diff --git a/components/autofill/core/browser/autofill_merge_unittest.cc b/components/autofill/core/browser/autofill_merge_unittest.cc
index 21918d7..e007a59 100644
--- a/components/autofill/core/browser/autofill_merge_unittest.cc
+++ b/components/autofill/core/browser/autofill_merge_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <map>
#include <vector>
#include "base/basictypes.h"
@@ -143,13 +144,22 @@
// sequentially, and fills |merged_profiles| with the serialized result.
void MergeProfiles(const std::string& profiles, std::string* merged_profiles);
+ // Deserializes |str| into a field type.
+ ServerFieldType StringToFieldType(const std::string& str);
+
PersonalDataManagerMock personal_data_;
private:
+ std::map<std::string, ServerFieldType> string_to_field_type_map_;
+
DISALLOW_COPY_AND_ASSIGN(AutofillMergeTest);
};
AutofillMergeTest::AutofillMergeTest() : DataDrivenTest(GetTestDataDir()) {
+ for (size_t i = NO_SERVER_DATA; i < MAX_VALID_FIELD_TYPE; ++i) {
+ ServerFieldType field_type = static_cast<ServerFieldType>(i);
+ string_to_field_type_map_[AutofillType(field_type).ToString()] = field_type;
+ }
}
AutofillMergeTest::~AutofillMergeTest() {
@@ -209,8 +219,7 @@
// into the field's name.
AutofillField* field =
const_cast<AutofillField*>(form_structure.field(i));
- ServerFieldType type =
- AutofillType::StringToFieldType(UTF16ToUTF8(field->name));
+ ServerFieldType type = StringToFieldType(UTF16ToUTF8(field->name));
field->set_heuristic_type(type);
}
@@ -227,6 +236,10 @@
*merged_profiles = SerializeProfiles(personal_data_.web_profiles());
}
+ServerFieldType AutofillMergeTest::StringToFieldType(const std::string& str) {
+ return string_to_field_type_map_[str];
+}
+
TEST_F(AutofillMergeTest, DataDrivenMergeProfiles) {
RunDataDrivenTest(GetInputDirectory(kTestName), GetOutputDirectory(kTestName),
kFileNamePattern);
diff --git a/components/autofill/core/browser/autofill_metrics.h b/components/autofill/core/browser/autofill_metrics.h
index 05d3a8d..d6ae790 100644
--- a/components/autofill/core/browser/autofill_metrics.h
+++ b/components/autofill/core/browser/autofill_metrics.h
@@ -329,6 +329,13 @@
WALLET_UNSUPPORTED_API_VERSION,
// Catch all error type.
WALLET_UNKNOWN_ERROR,
+ // The merchant has been blacklisted for Online Wallet due to some manner
+ // of compliance violation.
+ WALLET_UNSUPPORTED_MERCHANT,
+ // Buyer Legal Address has a country which is unsupported by Wallet.
+ WALLET_BUYER_LEGAL_ADDRESS_NOT_SUPPORTED,
+ // Wallet's Know Your Customer(KYC) action is pending/failed for this user.
+ WALLET_UNVERIFIED_KNOW_YOUR_CUSTOMER_STATUS,
NUM_WALLET_ERROR_METRICS
};
diff --git a/components/autofill/core/browser/autofill_type.cc b/components/autofill/core/browser/autofill_type.cc
index c47a9df..f1e280b 100644
--- a/components/autofill/core/browser/autofill_type.cc
+++ b/components/autofill/core/browser/autofill_type.cc
@@ -137,6 +137,7 @@
case HTML_TYPE_ORGANIZATION:
return COMPANY;
+ case HTML_TYPE_STREET_ADDRESS:
case HTML_TYPE_ADDRESS_LINE1:
case HTML_TYPE_ADDRESS_LINE2:
case HTML_TYPE_LOCALITY:
@@ -265,6 +266,9 @@
case HTML_TYPE_ORGANIZATION:
return COMPANY_NAME;
+ case HTML_TYPE_STREET_ADDRESS:
+ return ADDRESS_HOME_LINE1;
+
case HTML_TYPE_ADDRESS_LINE1:
return ADDRESS_HOME_LINE1;
@@ -543,6 +547,8 @@
return "HTML_TYPE_FAMILY_NAME";
case HTML_TYPE_ORGANIZATION:
return "HTML_TYPE_ORGANIZATION";
+ case HTML_TYPE_STREET_ADDRESS:
+ return "HTML_TYPE_STREET_ADDRESS";
case HTML_TYPE_ADDRESS_LINE1:
return "HTML_TYPE_ADDRESS_LINE1";
case HTML_TYPE_ADDRESS_LINE2:
@@ -603,101 +609,4 @@
return std::string();
}
-// static
-ServerFieldType AutofillType::StringToFieldType(const std::string& str) {
- if (str == "NO_SERVER_DATA")
- return NO_SERVER_DATA;
- if (str == "UNKNOWN_TYPE")
- return UNKNOWN_TYPE;
- if (str == "EMPTY_TYPE")
- return EMPTY_TYPE;
- if (str == "NAME_FIRST")
- return NAME_FIRST;
- if (str == "NAME_MIDDLE")
- return NAME_MIDDLE;
- if (str == "NAME_LAST")
- return NAME_LAST;
- if (str == "NAME_MIDDLE_INITIAL")
- return NAME_MIDDLE_INITIAL;
- if (str == "NAME_FULL")
- return NAME_FULL;
- if (str == "NAME_SUFFIX")
- return NAME_SUFFIX;
- if (str == "NAME_BILLING_FIRST")
- return NAME_BILLING_FIRST;
- if (str == "NAME_BILLING_MIDDLE")
- return NAME_BILLING_MIDDLE;
- if (str == "NAME_BILLING_LAST")
- return NAME_BILLING_LAST;
- if (str == "NAME_BILLING_MIDDLE_INITIAL")
- return NAME_BILLING_MIDDLE_INITIAL;
- if (str == "NAME_BILLING_FULL")
- return NAME_BILLING_FULL;
- if (str == "NAME_BILLING_SUFFIX")
- return NAME_BILLING_SUFFIX;
- if (str == "EMAIL_ADDRESS")
- return EMAIL_ADDRESS;
- if (str == "PHONE_HOME_NUMBER")
- return PHONE_HOME_NUMBER;
- if (str == "PHONE_HOME_CITY_CODE")
- return PHONE_HOME_CITY_CODE;
- if (str == "PHONE_HOME_COUNTRY_CODE")
- return PHONE_HOME_COUNTRY_CODE;
- if (str == "PHONE_HOME_CITY_AND_NUMBER")
- return PHONE_HOME_CITY_AND_NUMBER;
- if (str == "PHONE_HOME_WHOLE_NUMBER")
- return PHONE_HOME_WHOLE_NUMBER;
- if (str == "ADDRESS_HOME_LINE1")
- return ADDRESS_HOME_LINE1;
- if (str == "ADDRESS_HOME_LINE2")
- return ADDRESS_HOME_LINE2;
- if (str == "ADDRESS_HOME_APT_NUM")
- return ADDRESS_HOME_APT_NUM;
- if (str == "ADDRESS_HOME_CITY")
- return ADDRESS_HOME_CITY;
- if (str == "ADDRESS_HOME_STATE")
- return ADDRESS_HOME_STATE;
- if (str == "ADDRESS_HOME_ZIP")
- return ADDRESS_HOME_ZIP;
- if (str == "ADDRESS_HOME_COUNTRY")
- return ADDRESS_HOME_COUNTRY;
- if (str == "ADDRESS_BILLING_LINE1")
- return ADDRESS_BILLING_LINE1;
- if (str == "ADDRESS_BILLING_LINE2")
- return ADDRESS_BILLING_LINE2;
- if (str == "ADDRESS_BILLING_APT_NUM")
- return ADDRESS_BILLING_APT_NUM;
- if (str == "ADDRESS_BILLING_CITY")
- return ADDRESS_BILLING_CITY;
- if (str == "ADDRESS_BILLING_STATE")
- return ADDRESS_BILLING_STATE;
- if (str == "ADDRESS_BILLING_ZIP")
- return ADDRESS_BILLING_ZIP;
- if (str == "ADDRESS_BILLING_COUNTRY")
- return ADDRESS_BILLING_COUNTRY;
- if (str == "CREDIT_CARD_NAME")
- return CREDIT_CARD_NAME;
- if (str == "CREDIT_CARD_NUMBER")
- return CREDIT_CARD_NUMBER;
- if (str == "CREDIT_CARD_EXP_MONTH")
- return CREDIT_CARD_EXP_MONTH;
- if (str == "CREDIT_CARD_EXP_2_DIGIT_YEAR")
- return CREDIT_CARD_EXP_2_DIGIT_YEAR;
- if (str == "CREDIT_CARD_EXP_4_DIGIT_YEAR")
- return CREDIT_CARD_EXP_4_DIGIT_YEAR;
- if (str == "CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR")
- return CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR;
- if (str == "CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR")
- return CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR;
- if (str == "CREDIT_CARD_TYPE")
- return CREDIT_CARD_TYPE;
- if (str == "CREDIT_CARD_VERIFICATION_CODE")
- return CREDIT_CARD_VERIFICATION_CODE;
- if (str == "COMPANY_NAME")
- return COMPANY_NAME;
-
- NOTREACHED() << "Unknown ServerFieldType " << str;
- return UNKNOWN_TYPE;
-}
-
} // namespace autofill
diff --git a/components/autofill/core/browser/autofill_type.h b/components/autofill/core/browser/autofill_type.h
index 653c023..41fa613 100644
--- a/components/autofill/core/browser/autofill_type.h
+++ b/components/autofill/core/browser/autofill_type.h
@@ -20,6 +20,8 @@
AutofillType(const AutofillType& autofill_type);
AutofillType& operator=(const AutofillType& autofill_type);
+ HtmlFieldType html_type() const { return html_type_; }
+
FieldTypeGroup group() const;
// Returns true if both the |server_type_| and the |html_type_| are set to
@@ -29,24 +31,19 @@
// Maps |this| type to a field type that can be directly stored in an Autofill
// data model (in the sense that it makes sense to call
// |AutofillDataModel::SetRawInfo()| with the returned field type as the first
- // parameter).
+ // parameter). Note that the returned type might not be exactly equivalent to
+ // |this| type. For example, there is no exact analogue to the
+ // 'street-address' HTML type hint among the storable field types.
ServerFieldType GetStorableType() const;
// Serializes |this| type to a string.
std::string ToString() const;
- // Maps |field_type| to a field type from ADDRESS_BILLING FieldTypeGroup if
- // field type is an Address type.
- // TODO(isherman): This method is only used by the
- // AutofillDialogControllerImpl class. Consider moving it to a more focused
- // location.
+ // Maps |field_type| to the corresponding billing field type if the field type
+ // is an address, name, or phone number type.
static ServerFieldType GetEquivalentBillingFieldType(
ServerFieldType field_type);
- // TODO(isherman): This method is only used be a single test class. Move the
- // logic into there or something, eh?
- static ServerFieldType StringToFieldType(const std::string& str);
-
private:
// The server-native field type, or UNKNOWN_TYPE if unset.
ServerFieldType server_type_;
diff --git a/components/autofill/core/browser/field_types.h b/components/autofill/core/browser/field_types.h
index dc86ffd..081a7a7 100644
--- a/components/autofill/core/browser/field_types.h
+++ b/components/autofill/core/browser/field_types.h
@@ -121,6 +121,7 @@
HTML_TYPE_ORGANIZATION,
// Address types.
+ HTML_TYPE_STREET_ADDRESS,
HTML_TYPE_ADDRESS_LINE1,
HTML_TYPE_ADDRESS_LINE2,
HTML_TYPE_LOCALITY, // For U.S. addresses, corresponds to the city.
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index fd907dc..0a534f8 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -212,6 +212,9 @@
if (autocomplete_attribute_value == "organization")
return HTML_TYPE_ORGANIZATION;
+ if (autocomplete_attribute_value == "street-address")
+ return HTML_TYPE_STREET_ADDRESS;
+
if (autocomplete_attribute_value == "address-line1")
return HTML_TYPE_ADDRESS_LINE1;
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h
index b9ab979..9b71aa5 100644
--- a/components/autofill/core/browser/personal_data_manager.h
+++ b/components/autofill/core/browser/personal_data_manager.h
@@ -26,6 +26,7 @@
}
namespace autofill {
+class AutofillInteractiveTest;
class AutofillMetrics;
class AutofillTest;
class FormStructure;
@@ -182,6 +183,7 @@
FRIEND_TEST_ALL_PREFIXES(AutofillMetricsTest, AutofillIsEnabledAtStartup);
FRIEND_TEST_ALL_PREFIXES(PersonalDataManagerTest,
AggregateExistingAuxiliaryProfile);
+ friend class autofill::AutofillInteractiveTest;
friend class autofill::AutofillTest;
friend class autofill::PersonalDataManagerFactory;
friend class PersonalDataManagerTest;
diff --git a/components/autofill_content_browser.target.darwin-arm.mk b/components/autofill_content_browser.target.darwin-arm.mk
index a29898a..7e8787a 100644
--- a/components/autofill_content_browser.target.darwin-arm.mk
+++ b/components/autofill_content_browser.target.darwin-arm.mk
@@ -107,6 +107,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -242,6 +243,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_content_browser.target.darwin-mips.mk b/components/autofill_content_browser.target.darwin-mips.mk
index 8e550a8..83d058b 100644
--- a/components/autofill_content_browser.target.darwin-mips.mk
+++ b/components/autofill_content_browser.target.darwin-mips.mk
@@ -106,6 +106,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -240,6 +241,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_content_browser.target.darwin-x86.mk b/components/autofill_content_browser.target.darwin-x86.mk
index a2c9ed2..8760e97 100644
--- a/components/autofill_content_browser.target.darwin-x86.mk
+++ b/components/autofill_content_browser.target.darwin-x86.mk
@@ -109,6 +109,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -246,6 +247,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_content_browser.target.linux-arm.mk b/components/autofill_content_browser.target.linux-arm.mk
index a29898a..7e8787a 100644
--- a/components/autofill_content_browser.target.linux-arm.mk
+++ b/components/autofill_content_browser.target.linux-arm.mk
@@ -107,6 +107,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -242,6 +243,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_content_browser.target.linux-mips.mk b/components/autofill_content_browser.target.linux-mips.mk
index 8e550a8..83d058b 100644
--- a/components/autofill_content_browser.target.linux-mips.mk
+++ b/components/autofill_content_browser.target.linux-mips.mk
@@ -106,6 +106,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -240,6 +241,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_content_browser.target.linux-x86.mk b/components/autofill_content_browser.target.linux-x86.mk
index a2c9ed2..8760e97 100644
--- a/components/autofill_content_browser.target.linux-x86.mk
+++ b/components/autofill_content_browser.target.linux-x86.mk
@@ -109,6 +109,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -246,6 +247,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_content_renderer.target.darwin-arm.mk b/components/autofill_content_renderer.target.darwin-arm.mk
index c3a932b..607bd46 100644
--- a/components/autofill_content_renderer.target.darwin-arm.mk
+++ b/components/autofill_content_renderer.target.darwin-arm.mk
@@ -87,6 +87,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -192,6 +193,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/components/autofill_content_renderer.target.darwin-mips.mk b/components/autofill_content_renderer.target.darwin-mips.mk
index e09cdbc..1bb72f6 100644
--- a/components/autofill_content_renderer.target.darwin-mips.mk
+++ b/components/autofill_content_renderer.target.darwin-mips.mk
@@ -86,6 +86,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -190,6 +191,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/components/autofill_content_renderer.target.darwin-x86.mk b/components/autofill_content_renderer.target.darwin-x86.mk
index 5fef75e..e9b88c5 100644
--- a/components/autofill_content_renderer.target.darwin-x86.mk
+++ b/components/autofill_content_renderer.target.darwin-x86.mk
@@ -89,6 +89,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -197,6 +198,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/components/autofill_content_renderer.target.linux-arm.mk b/components/autofill_content_renderer.target.linux-arm.mk
index c3a932b..607bd46 100644
--- a/components/autofill_content_renderer.target.linux-arm.mk
+++ b/components/autofill_content_renderer.target.linux-arm.mk
@@ -87,6 +87,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -192,6 +193,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/components/autofill_content_renderer.target.linux-mips.mk b/components/autofill_content_renderer.target.linux-mips.mk
index e09cdbc..1bb72f6 100644
--- a/components/autofill_content_renderer.target.linux-mips.mk
+++ b/components/autofill_content_renderer.target.linux-mips.mk
@@ -86,6 +86,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -190,6 +191,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/components/autofill_content_renderer.target.linux-x86.mk b/components/autofill_content_renderer.target.linux-x86.mk
index 5fef75e..e9b88c5 100644
--- a/components/autofill_content_renderer.target.linux-x86.mk
+++ b/components/autofill_content_renderer.target.linux-x86.mk
@@ -89,6 +89,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -197,6 +198,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/components/autofill_core_browser.target.darwin-arm.mk b/components/autofill_core_browser.target.darwin-arm.mk
index d69fa71..b7503b7 100644
--- a/components/autofill_core_browser.target.darwin-arm.mk
+++ b/components/autofill_core_browser.target.darwin-arm.mk
@@ -128,6 +128,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -263,6 +264,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_core_browser.target.darwin-mips.mk b/components/autofill_core_browser.target.darwin-mips.mk
index 643a018..e12ca1d 100644
--- a/components/autofill_core_browser.target.darwin-mips.mk
+++ b/components/autofill_core_browser.target.darwin-mips.mk
@@ -127,6 +127,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -261,6 +262,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_core_browser.target.darwin-x86.mk b/components/autofill_core_browser.target.darwin-x86.mk
index 81fd1d1..826f78b 100644
--- a/components/autofill_core_browser.target.darwin-x86.mk
+++ b/components/autofill_core_browser.target.darwin-x86.mk
@@ -130,6 +130,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -267,6 +268,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_core_browser.target.linux-arm.mk b/components/autofill_core_browser.target.linux-arm.mk
index d69fa71..b7503b7 100644
--- a/components/autofill_core_browser.target.linux-arm.mk
+++ b/components/autofill_core_browser.target.linux-arm.mk
@@ -128,6 +128,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -263,6 +264,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_core_browser.target.linux-mips.mk b/components/autofill_core_browser.target.linux-mips.mk
index 643a018..e12ca1d 100644
--- a/components/autofill_core_browser.target.linux-mips.mk
+++ b/components/autofill_core_browser.target.linux-mips.mk
@@ -127,6 +127,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -261,6 +262,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_core_browser.target.linux-x86.mk b/components/autofill_core_browser.target.linux-x86.mk
index 81fd1d1..826f78b 100644
--- a/components/autofill_core_browser.target.linux-x86.mk
+++ b/components/autofill_core_browser.target.linux-x86.mk
@@ -130,6 +130,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -267,6 +268,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/components/autofill_core_common.target.darwin-arm.mk b/components/autofill_core_common.target.darwin-arm.mk
index e6d5505..49e5c78 100644
--- a/components/autofill_core_common.target.darwin-arm.mk
+++ b/components/autofill_core_common.target.darwin-arm.mk
@@ -97,6 +97,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -207,6 +208,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/components/autofill_core_common.target.darwin-mips.mk b/components/autofill_core_common.target.darwin-mips.mk
index 6ca808c..3cab27f 100644
--- a/components/autofill_core_common.target.darwin-mips.mk
+++ b/components/autofill_core_common.target.darwin-mips.mk
@@ -96,6 +96,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -205,6 +206,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/components/autofill_core_common.target.darwin-x86.mk b/components/autofill_core_common.target.darwin-x86.mk
index 3de9cad..5208989 100644
--- a/components/autofill_core_common.target.darwin-x86.mk
+++ b/components/autofill_core_common.target.darwin-x86.mk
@@ -99,6 +99,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -211,6 +212,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/components/autofill_core_common.target.linux-arm.mk b/components/autofill_core_common.target.linux-arm.mk
index e6d5505..49e5c78 100644
--- a/components/autofill_core_common.target.linux-arm.mk
+++ b/components/autofill_core_common.target.linux-arm.mk
@@ -97,6 +97,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -207,6 +208,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/components/autofill_core_common.target.linux-mips.mk b/components/autofill_core_common.target.linux-mips.mk
index 6ca808c..3cab27f 100644
--- a/components/autofill_core_common.target.linux-mips.mk
+++ b/components/autofill_core_common.target.linux-mips.mk
@@ -96,6 +96,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -205,6 +206,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/components/autofill_core_common.target.linux-x86.mk b/components/autofill_core_common.target.linux-x86.mk
index 3de9cad..5208989 100644
--- a/components/autofill_core_common.target.linux-x86.mk
+++ b/components/autofill_core_common.target.linux-x86.mk
@@ -99,6 +99,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -211,6 +212,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/components/nacl/loader/nacl_sandbox_linux.cc b/components/nacl/loader/nacl_sandbox_linux.cc
index 3041db6..c93aba7 100644
--- a/components/nacl/loader/nacl_sandbox_linux.cc
+++ b/components/nacl/loader/nacl_sandbox_linux.cc
@@ -137,11 +137,6 @@
content::InitializeSandbox(NaClBpfSandboxPolicy);
if (sandbox_is_initialized) {
RunSandboxSanityChecks();
- // TODO(jln): Find a way to fix this.
- // The sandbox' SIGSYS handler trips NaCl, so we disable it.
- // If SIGSYS is triggered it'll now execute the default action
- // (CORE). This will make it hard to track down bugs and sandbox violations.
- CHECK(signal(SIGSYS, SIG_DFL) != SIG_ERR);
return true;
}
return false;
diff --git a/components/visitedlink_renderer.target.darwin-arm.mk b/components/visitedlink_renderer.target.darwin-arm.mk
index ebabeb0..4930623 100644
--- a/components/visitedlink_renderer.target.darwin-arm.mk
+++ b/components/visitedlink_renderer.target.darwin-arm.mk
@@ -81,6 +81,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -192,6 +193,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/components/visitedlink_renderer.target.darwin-mips.mk b/components/visitedlink_renderer.target.darwin-mips.mk
index 7ce00dd..00836e3 100644
--- a/components/visitedlink_renderer.target.darwin-mips.mk
+++ b/components/visitedlink_renderer.target.darwin-mips.mk
@@ -80,6 +80,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -190,6 +191,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/components/visitedlink_renderer.target.darwin-x86.mk b/components/visitedlink_renderer.target.darwin-x86.mk
index b734a55..69f3038 100644
--- a/components/visitedlink_renderer.target.darwin-x86.mk
+++ b/components/visitedlink_renderer.target.darwin-x86.mk
@@ -83,6 +83,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -197,6 +198,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/components/visitedlink_renderer.target.linux-arm.mk b/components/visitedlink_renderer.target.linux-arm.mk
index ebabeb0..4930623 100644
--- a/components/visitedlink_renderer.target.linux-arm.mk
+++ b/components/visitedlink_renderer.target.linux-arm.mk
@@ -81,6 +81,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -192,6 +193,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/components/visitedlink_renderer.target.linux-mips.mk b/components/visitedlink_renderer.target.linux-mips.mk
index 7ce00dd..00836e3 100644
--- a/components/visitedlink_renderer.target.linux-mips.mk
+++ b/components/visitedlink_renderer.target.linux-mips.mk
@@ -80,6 +80,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -190,6 +191,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/components/visitedlink_renderer.target.linux-x86.mk b/components/visitedlink_renderer.target.linux-x86.mk
index b734a55..69f3038 100644
--- a/components/visitedlink_renderer.target.linux-x86.mk
+++ b/components/visitedlink_renderer.target.linux-x86.mk
@@ -83,6 +83,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -197,6 +198,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/components/web_contents_delegate_android.target.darwin-arm.mk b/components/web_contents_delegate_android.target.darwin-arm.mk
index 1fca453..8ff1cbd 100644
--- a/components/web_contents_delegate_android.target.darwin-arm.mk
+++ b/components/web_contents_delegate_android.target.darwin-arm.mk
@@ -87,6 +87,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -196,6 +197,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/components/web_contents_delegate_android.target.darwin-mips.mk b/components/web_contents_delegate_android.target.darwin-mips.mk
index 2966843..953f1f2 100644
--- a/components/web_contents_delegate_android.target.darwin-mips.mk
+++ b/components/web_contents_delegate_android.target.darwin-mips.mk
@@ -86,6 +86,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -194,6 +195,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/components/web_contents_delegate_android.target.darwin-x86.mk b/components/web_contents_delegate_android.target.darwin-x86.mk
index e15029a..0410db5 100644
--- a/components/web_contents_delegate_android.target.darwin-x86.mk
+++ b/components/web_contents_delegate_android.target.darwin-x86.mk
@@ -88,6 +88,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -199,6 +200,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/components/web_contents_delegate_android.target.linux-arm.mk b/components/web_contents_delegate_android.target.linux-arm.mk
index 1fca453..8ff1cbd 100644
--- a/components/web_contents_delegate_android.target.linux-arm.mk
+++ b/components/web_contents_delegate_android.target.linux-arm.mk
@@ -87,6 +87,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -196,6 +197,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/components/web_contents_delegate_android.target.linux-mips.mk b/components/web_contents_delegate_android.target.linux-mips.mk
index 2966843..953f1f2 100644
--- a/components/web_contents_delegate_android.target.linux-mips.mk
+++ b/components/web_contents_delegate_android.target.linux-mips.mk
@@ -86,6 +86,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -194,6 +195,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/components/web_contents_delegate_android.target.linux-x86.mk b/components/web_contents_delegate_android.target.linux-x86.mk
index e15029a..0410db5 100644
--- a/components/web_contents_delegate_android.target.linux-x86.mk
+++ b/components/web_contents_delegate_android.target.linux-x86.mk
@@ -88,6 +88,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -199,6 +200,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/content/browser/android/in_process/synchronous_compositor_impl.cc b/content/browser/android/in_process/synchronous_compositor_impl.cc
index 041511e..74048d8 100644
--- a/content/browser/android/in_process/synchronous_compositor_impl.cc
+++ b/content/browser/android/in_process/synchronous_compositor_impl.cc
@@ -66,10 +66,16 @@
}
virtual scoped_refptr<cc::ContextProvider>
- GetOffscreenContextProviderForMainThread() OVERRIDE {
- NOTIMPLEMENTED()
- << "Synchronous compositor does not support main thread context yet.";
- return scoped_refptr<cc::ContextProvider>();
+ GetOffscreenContextProviderForMainThread() OVERRIDE {
+ if (!offscreen_context_for_main_thread_.get() ||
+ offscreen_context_for_main_thread_->DestroyedOnMainThread()) {
+ offscreen_context_for_main_thread_ =
+ webkit::gpu::ContextProviderInProcess::Create();
+ if (offscreen_context_for_main_thread_.get() &&
+ !offscreen_context_for_main_thread_->BindToCurrentThread())
+ offscreen_context_for_main_thread_ = NULL;
+ }
+ return offscreen_context_for_main_thread_;
}
// This is called on both renderer main thread (offscreen context creation
@@ -95,6 +101,7 @@
// Only guards construction of |offscreen_context_for_compositor_thread_|,
// not usage.
base::Lock offscreen_context_for_compositor_thread_creation_lock_;
+ scoped_refptr<cc::ContextProvider> offscreen_context_for_main_thread_;
scoped_refptr<cc::ContextProvider> offscreen_context_for_compositor_thread_;
};
diff --git a/content/browser/aura/gpu_process_transport_factory.cc b/content/browser/aura/gpu_process_transport_factory.cc
index 8822e85..4a047c6 100644
--- a/content/browser/aura/gpu_process_transport_factory.cc
+++ b/content/browser/aura/gpu_process_transport_factory.cc
@@ -232,6 +232,11 @@
CreateContextCommon(data->swap_client->AsWeakPtr(), data->surface_id);
}
if (!context) {
+ if (ui::Compositor::WasInitializedWithThread()) {
+ LOG(FATAL) << "Failed to create UI context, but can't use software "
+ " compositing with browser threaded compositing. Aborting.";
+ }
+
scoped_ptr<SoftwareBrowserCompositorOutputSurface> surface =
SoftwareBrowserCompositorOutputSurface::Create(
CreateSoftwareOutputDevice(compositor));
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 1c6b1a0..c51b5c5 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -7,10 +7,12 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
+#include "base/file_util.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
+#include "base/path_service.h"
#include "base/pending_task.h"
#include "base/power_monitor/power_monitor.h"
#include "base/power_monitor/power_monitor_device_source.h"
@@ -120,48 +122,54 @@
TRACE_EVENT0("startup", "SetupSandbox");
// TODO(evanm): move this into SandboxWrapper; I'm just trying to move this
// code en masse out of chrome_main for now.
- const char* sandbox_binary = NULL;
+ base::FilePath sandbox_binary;
+ bool env_chrome_devel_sandbox_set = false;
struct stat st;
- // In Chromium branded builds, developers can set an environment variable to
- // use the development sandbox. See
- // http://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment
- if (stat(base::kProcSelfExe, &st) == 0 && st.st_uid == getuid())
- sandbox_binary = getenv("CHROME_DEVEL_SANDBOX");
-
-#if defined(LINUX_SANDBOX_PATH)
- if (!sandbox_binary)
- sandbox_binary = LINUX_SANDBOX_PATH;
-#endif
-
const bool want_setuid_sandbox =
!parsed_command_line.HasSwitch(switches::kNoSandbox) &&
!parsed_command_line.HasSwitch(switches::kDisableSetuidSandbox);
if (want_setuid_sandbox) {
+ base::FilePath exe_dir;
+ if (PathService::Get(base::DIR_EXE, &exe_dir)) {
+ base::FilePath sandbox_candidate = exe_dir.AppendASCII("chrome-sandbox");
+ if (base::PathExists(sandbox_candidate))
+ sandbox_binary = sandbox_candidate;
+ }
+
+ // In user-managed builds, including development builds, an environment
+ // variable is required to enable the sandbox. See
+ // http://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment
+ if (sandbox_binary.empty() &&
+ stat(base::kProcSelfExe, &st) == 0 && st.st_uid == getuid()) {
+ const char* devel_sandbox_path = getenv("CHROME_DEVEL_SANDBOX");
+ if (devel_sandbox_path) {
+ env_chrome_devel_sandbox_set = true;
+ sandbox_binary = base::FilePath(devel_sandbox_path);
+ }
+ }
+
static const char no_suid_error[] = "Running without the SUID sandbox! See "
"https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment "
"for more information on developing with the sandbox on.";
- if (!sandbox_binary) {
- // This needs to be fatal. Talk to security@chromium.org if you feel
- // otherwise.
- LOG(FATAL) << no_suid_error;
- }
- // TODO(jln): an empty CHROME_DEVEL_SANDBOX environment variable (as
- // opposed to a non existing one) is not fatal yet. This is needed because
- // of existing bots and scripts. Fix it (crbug.com/245376).
- if (sandbox_binary && *sandbox_binary == '\0')
- LOG(ERROR) << no_suid_error;
- }
+ if (sandbox_binary.empty()) {
+ if (!env_chrome_devel_sandbox_set) {
+ // This needs to be fatal. Talk to security@chromium.org if you feel
+ // otherwise.
+ LOG(FATAL) << no_suid_error;
+ }
- std::string sandbox_cmd;
- if (want_setuid_sandbox && sandbox_binary) {
- sandbox_cmd = sandbox_binary;
+ // TODO(jln): an empty CHROME_DEVEL_SANDBOX environment variable (as
+ // opposed to a non existing one) is not fatal yet. This is needed
+ // because of existing bots and scripts. Fix it (crbug.com/245376).
+ LOG(ERROR) << no_suid_error;
+ }
}
// Tickle the sandbox host and zygote host so they fork now.
- RenderSandboxHostLinux::GetInstance()->Init(sandbox_cmd);
- ZygoteHostImpl::GetInstance()->Init(sandbox_cmd);
+ RenderSandboxHostLinux::GetInstance()->Init(sandbox_binary.value());
+ ZygoteHostImpl::GetInstance()->Init(sandbox_binary.value());
}
#endif
diff --git a/content/browser/browser_thread_impl.cc b/content/browser/browser_thread_impl.cc
index 90f660a..fb6feac 100644
--- a/content/browser/browser_thread_impl.cc
+++ b/content/browser/browser_thread_impl.cc
@@ -339,14 +339,14 @@
}
// static
-bool BrowserThread::IsWellKnownThread(ID identifier) {
+bool BrowserThread::IsThreadInitialized(ID identifier) {
if (g_globals == NULL)
return false;
BrowserThreadGlobals& globals = g_globals.Get();
base::AutoLock lock(globals.lock);
- return (identifier >= 0 && identifier < ID_COUNT &&
- globals.threads[identifier]);
+ DCHECK(identifier >= 0 && identifier < ID_COUNT);
+ return globals.threads[identifier] != NULL;
}
// static
diff --git a/content/browser/device_orientation/data_fetcher_shared_memory_android.cc b/content/browser/device_orientation/data_fetcher_shared_memory_android.cc
index b051557..8f6e202 100644
--- a/content/browser/device_orientation/data_fetcher_shared_memory_android.cc
+++ b/content/browser/device_orientation/data_fetcher_shared_memory_android.cc
@@ -27,9 +27,9 @@
DeviceMotionHardwareBuffer* buffer) {
DCHECK(buffer);
device_motion_buffer_ = buffer;
- return DataFetcherImplAndroid::GetInstance()->
+ started_ = DataFetcherImplAndroid::GetInstance()->
StartFetchingDeviceMotionData(buffer);
- started_ = true;
+ return started_;
}
void DataFetcherSharedMemory::StopFetchingDeviceMotionData() {
diff --git a/content/browser/devtools/devtools_protocol.cc b/content/browser/devtools/devtools_protocol.cc
index d39cc33..8398084 100644
--- a/content/browser/devtools/devtools_protocol.cc
+++ b/content/browser/devtools/devtools_protocol.cc
@@ -132,7 +132,11 @@
DevToolsProtocol::Response::Response(int id,
int error_code,
const std::string& error_message)
- : id_(id), error_code_(error_code), error_message_(error_message) {}
+ : id_(id),
+ error_code_(error_code),
+ error_message_(error_message),
+ is_async_promise_(false) {
+}
DevToolsProtocol::Notification::Notification(const std::string& method,
base::DictionaryValue* params)
diff --git a/content/browser/devtools/render_view_devtools_agent_host.cc b/content/browser/devtools/render_view_devtools_agent_host.cc
index 0c2d323..efc5242 100644
--- a/content/browser/devtools/render_view_devtools_agent_host.cc
+++ b/content/browser/devtools/render_view_devtools_agent_host.cc
@@ -229,7 +229,7 @@
void RenderViewDevToolsAgentHost::AboutToNavigateRenderView(
RenderViewHost* dest_rvh) {
- if (!render_view_host_)
+ if (!render_view_host_ || !IsAttached())
return;
if (render_view_host_ == dest_rvh && static_cast<RenderViewHostImpl*>(
diff --git a/content/browser/download/base_file.cc b/content/browser/download/base_file.cc
index 466be32..90ab485 100644
--- a/content/browser/download/base_file.cc
+++ b/content/browser/download/base_file.cc
@@ -211,6 +211,10 @@
Close();
}
+void BaseFile::SetClientGuid(const std::string& guid) {
+ client_guid_ = guid;
+}
+
// OS_WIN, OS_MACOSX and OS_LINUX have specialized implementations.
#if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_LINUX)
DownloadInterruptReason BaseFile::AnnotateWithSourceInformation() {
diff --git a/content/browser/download/base_file.h b/content/browser/download/base_file.h
index 9c1261c..f1686c8 100644
--- a/content/browser/download/base_file.h
+++ b/content/browser/download/base_file.h
@@ -69,8 +69,15 @@
// Indicate that the download has finished. No new data will be received.
void Finish();
+ // Set the client guid which will be used to identify the app to the
+ // system AV scanning function. Should be called before
+ // AnnotateWithSourceInformation() to take effect.
+ void SetClientGuid(const std::string& guid);
+
// Informs the OS that this file came from the internet. Returns a
// DownloadInterruptReason indicating the result of the operation.
+ // Note: SetClientGuid() should be called before this function on
+ // Windows to ensure the correct app client ID is available.
DownloadInterruptReason AnnotateWithSourceInformation();
base::FilePath full_path() const { return full_path_; }
@@ -142,6 +149,8 @@
// The URL where the download was initiated.
GURL referrer_url_;
+ std::string client_guid_;
+
// OS file stream for writing
scoped_ptr<net::FileStream> file_stream_;
diff --git a/content/browser/download/base_file_win.cc b/content/browser/download/base_file_win.cc
index 398e5fc..252f049 100644
--- a/content/browser/download/base_file_win.cc
+++ b/content/browser/download/base_file_win.cc
@@ -5,9 +5,12 @@
#include "content/browser/download/base_file.h"
#include <windows.h>
+#include <cguid.h>
+#include <objbase.h>
#include <shellapi.h>
#include "base/file_util.h"
+#include "base/guid.h"
#include "base/metrics/histogram.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
@@ -326,7 +329,16 @@
bound_net_log_.BeginEvent(net::NetLog::TYPE_DOWNLOAD_FILE_ANNOTATED);
DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE;
- HRESULT hr = ScanAndSaveDownloadedFile(full_path_, source_url_);
+ std::string braces_guid = "{" + client_guid_ + "}";
+ GUID guid = GUID_NULL;
+ if (base::IsValidGUID(client_guid_)) {
+ HRESULT hr = CLSIDFromString(
+ base::UTF8ToUTF16(braces_guid).c_str(), &guid);
+ if (FAILED(hr))
+ guid = GUID_NULL;
+ }
+
+ HRESULT hr = AVScanFile(full_path_, source_url_.spec(), guid);
// If the download file is missing after the call, then treat this as an
// interrupted download.
diff --git a/content/browser/download/download_file.h b/content/browser/download/download_file.h
index a8e18ff..568e7ee 100644
--- a/content/browser/download/download_file.h
+++ b/content/browser/download/download_file.h
@@ -73,6 +73,11 @@
// Returns the current (intermediate) state of the hash as a byte string.
virtual std::string GetHashState() = 0;
+ // Set the application GUID to be used to identify the app to the
+ // system AV function when scanning downloaded files. Should be called
+ // before RenameAndAnnotate() to take effect.
+ virtual void SetClientGuid(const std::string& guid) = 0;
+
// For testing. Must be called on FILE thread.
// TODO(rdsmith): Replace use of EnsureNoPendingDownloads()
// on the DownloadManager with a test-specific DownloadFileFactory
diff --git a/content/browser/download/download_file_impl.cc b/content/browser/download/download_file_impl.cc
index bbe317b..67bee81 100644
--- a/content/browser/download/download_file_impl.cc
+++ b/content/browser/download/download_file_impl.cc
@@ -200,6 +200,10 @@
return file_.GetHashState();
}
+void DownloadFileImpl::SetClientGuid(const std::string& guid) {
+ file_.SetClientGuid(guid);
+}
+
void DownloadFileImpl::StreamActive() {
base::TimeTicks start(base::TimeTicks::Now());
base::TimeTicks now;
diff --git a/content/browser/download/download_file_impl.h b/content/browser/download/download_file_impl.h
index 963ae9f..9a50870 100644
--- a/content/browser/download/download_file_impl.h
+++ b/content/browser/download/download_file_impl.h
@@ -63,6 +63,7 @@
virtual int64 CurrentSpeed() const OVERRIDE;
virtual bool GetHash(std::string* hash) OVERRIDE;
virtual std::string GetHashState() OVERRIDE;
+ virtual void SetClientGuid(const std::string& guid) OVERRIDE;
protected:
// For test class overrides.
diff --git a/content/browser/download/download_file_unittest.cc b/content/browser/download/download_file_unittest.cc
index ebf501d..867b76f 100644
--- a/content/browser/download/download_file_unittest.cc
+++ b/content/browser/download/download_file_unittest.cc
@@ -138,6 +138,8 @@
net::BoundNetLog(),
scoped_ptr<PowerSaveBlocker>().Pass(),
observer_factory_.GetWeakPtr()));
+ download_file_->SetClientGuid(
+ "12345678-ABCD-1234-DCBA-123456789ABC");
EXPECT_CALL(*input_stream_, Read(_, _))
.WillOnce(Return(ByteStreamReader::STREAM_EMPTY))
diff --git a/content/browser/download/download_item_factory.h b/content/browser/download/download_item_factory.h
index 36197d5..c5e03f5 100644
--- a/content/browser/download/download_item_factory.h
+++ b/content/browser/download/download_item_factory.h
@@ -46,6 +46,8 @@
const GURL& referrer_url,
const base::Time& start_time,
const base::Time& end_time,
+ const std::string& etag,
+ const std::string& last_modified,
int64 received_bytes,
int64 total_bytes,
DownloadItem::DownloadState state,
diff --git a/content/browser/download/download_item_impl.cc b/content/browser/download/download_item_impl.cc
index e54ab9e..e2e86a3 100644
--- a/content/browser/download/download_item_impl.cc
+++ b/content/browser/download/download_item_impl.cc
@@ -104,6 +104,8 @@
const GURL& referrer_url,
const base::Time& start_time,
const base::Time& end_time,
+ const std::string& etag,
+ const std::string& last_modified,
int64 received_bytes,
int64 total_bytes,
DownloadItem::DownloadState state,
@@ -123,6 +125,8 @@
total_bytes_(total_bytes),
received_bytes_(received_bytes),
bytes_per_sec_(0),
+ last_modified_time_(last_modified),
+ etag_(etag),
last_reason_(interrupt_reason),
start_tick_(base::TimeTicks()),
state_(ExternalToInternalState(state)),
diff --git a/content/browser/download/download_item_impl.h b/content/browser/download/download_item_impl.h
index ac260b1..2086a54 100644
--- a/content/browser/download/download_item_impl.h
+++ b/content/browser/download/download_item_impl.h
@@ -58,6 +58,8 @@
const GURL& referrer_url,
const base::Time& start_time,
const base::Time& end_time,
+ const std::string& etag,
+ const std::string& last_modified,
int64 received_bytes,
int64 total_bytes,
DownloadItem::DownloadState state,
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 58fe952..ccfb4cc 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -177,6 +177,8 @@
const GURL& referrer_url,
const base::Time& start_time,
const base::Time& end_time,
+ const std::string& etag,
+ const std::string& last_modified,
int64 received_bytes,
int64 total_bytes,
DownloadItem::DownloadState state,
@@ -193,6 +195,8 @@
referrer_url,
start_time,
end_time,
+ etag,
+ last_modified,
received_bytes,
total_bytes,
state,
@@ -418,6 +422,13 @@
delegate_->GenerateFileHash(),
stream.Pass(), download->GetBoundNetLog(),
download->DestinationObserverAsWeakPtr()));
+
+ // Attach the client ID identifying the app to the AV system.
+ if (download_file.get() && delegate_) {
+ download_file->SetClientGuid(
+ delegate_->ApplicationClientIdForFileScanning());
+ }
+
scoped_ptr<DownloadRequestHandleInterface> req_handle(
new DownloadRequestHandle(info->request_handle));
download->Start(download_file.Pass(), req_handle.Pass());
@@ -617,6 +628,8 @@
const GURL& referrer_url,
const base::Time& start_time,
const base::Time& end_time,
+ const std::string& etag,
+ const std::string& last_modified,
int64 received_bytes,
int64 total_bytes,
DownloadItem::DownloadState state,
@@ -635,6 +648,8 @@
referrer_url,
start_time,
end_time,
+ etag,
+ last_modified,
received_bytes,
total_bytes,
state,
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h
index 46d3eb7..a9384c7 100644
--- a/content/browser/download/download_manager_impl.h
+++ b/content/browser/download/download_manager_impl.h
@@ -80,6 +80,8 @@
const GURL& referrer_url,
const base::Time& start_time,
const base::Time& end_time,
+ const std::string& etag,
+ const std::string& last_modified,
int64 received_bytes,
int64 total_bytes,
content::DownloadItem::DownloadState state,
diff --git a/content/browser/download/download_manager_impl_unittest.cc b/content/browser/download/download_manager_impl_unittest.cc
index 2e9eff4..eba2833 100644
--- a/content/browser/download/download_manager_impl_unittest.cc
+++ b/content/browser/download/download_manager_impl_unittest.cc
@@ -78,6 +78,8 @@
GURL(),
base::Time(),
base::Time(),
+ std::string(),
+ std::string(),
0,
0,
DownloadItem::COMPLETE,
@@ -193,6 +195,7 @@
MOCK_METHOD5(ChooseSavePath, void(
WebContents*, const base::FilePath&, const base::FilePath::StringType&,
bool, const SavePackagePathPickedCallback&));
+ MOCK_CONST_METHOD0(ApplicationClientIdForFileScanning, std::string());
};
MockDownloadManagerDelegate::MockDownloadManagerDelegate() {}
@@ -231,6 +234,8 @@
const GURL& referrer_url,
const base::Time& start_time,
const base::Time& end_time,
+ const std::string& etag,
+ const std::string& last_modofied,
int64 received_bytes,
int64 total_bytes,
DownloadItem::DownloadState state,
@@ -294,6 +299,8 @@
const GURL& referrer_url,
const base::Time& start_time,
const base::Time& end_time,
+ const std::string& etag,
+ const std::string& last_modified,
int64 received_bytes,
int64 total_bytes,
DownloadItem::DownloadState state,
@@ -357,7 +364,7 @@
virtual ~MockDownloadFileFactory() {}
// Overridden method from DownloadFileFactory
- MOCK_METHOD8(MockCreateFile, DownloadFile*(
+ MOCK_METHOD8(MockCreateFile, MockDownloadFile*(
const DownloadSaveInfo&,
const base::FilePath&,
const GURL&, const GURL&, bool,
@@ -587,9 +594,15 @@
EXPECT_CALL(GetMockDownloadManagerDelegate(), GetSaveDir(_, _, _, _));
EXPECT_CALL(GetMockDownloadManagerDelegate(), GenerateFileHash())
.WillOnce(Return(true));
+ EXPECT_CALL(GetMockDownloadManagerDelegate(),
+ ApplicationClientIdForFileScanning())
+ .WillRepeatedly(Return("client-id"));
+ MockDownloadFile* mock_file = new MockDownloadFile;
+ EXPECT_CALL(*mock_file, SetClientGuid("client-id"));
EXPECT_CALL(*mock_download_file_factory_.get(),
MockCreateFile(Ref(*info->save_info.get()), _, _, _, true,
- stream.get(), _, _));
+ stream.get(), _, _))
+ .WillOnce(Return(mock_file));
download_manager_->StartDownload(
info.Pass(), stream.Pass(), DownloadUrlParameters::OnStartedCallback());
diff --git a/content/browser/download/download_stats.cc b/content/browser/download/download_stats.cc
index f8a1e09..7831a4d 100644
--- a/content/browser/download/download_stats.cc
+++ b/content/browser/download/download_stats.cc
@@ -168,13 +168,11 @@
}
void RecordDownloadWriteSize(size_t data_len) {
- RecordDownloadCount(WRITE_SIZE_COUNT);
int max = 1024 * 1024; // One Megabyte.
UMA_HISTOGRAM_CUSTOM_COUNTS("Download.WriteSize", data_len, 1, max, 256);
}
void RecordDownloadWriteLoopCount(int count) {
- RecordDownloadCount(WRITE_LOOP_COUNT);
UMA_HISTOGRAM_ENUMERATION("Download.WriteLoopCount", count, 20);
}
diff --git a/content/browser/download/download_stats.h b/content/browser/download/download_stats.h
index be2ae4b..ebe643e 100644
--- a/content/browser/download/download_stats.h
+++ b/content/browser/download/download_stats.h
@@ -48,11 +48,14 @@
// Downloads that were interrupted by the OS.
INTERRUPTED_COUNT,
- // Write sizes for downloads.
- WRITE_SIZE_COUNT,
+ // (Deprecated) Write sizes for downloads.
+ // This is equal to the number of samples in Download.WriteSize histogram.
+ DOWNLOAD_COUNT_UNUSED_10,
- // Counts iterations of the BaseFile::AppendDataToFile() loop.
- WRITE_LOOP_COUNT,
+ // (Deprecated) Counts iterations of the BaseFile::AppendDataToFile() loop.
+ // This is equal to the number of samples in Download.WriteLoopCount
+ // histogram.
+ DOWNLOAD_COUNT_UNUSED_11,
// Counts interruptions that happened at the end of the download.
INTERRUPTED_AT_END_COUNT,
diff --git a/content/browser/download/mock_download_file.h b/content/browser/download/mock_download_file.h
index 74dc75c..5d4b270 100644
--- a/content/browser/download/mock_download_file.h
+++ b/content/browser/download/mock_download_file.h
@@ -48,6 +48,7 @@
MOCK_CONST_METHOD0(Id, int());
MOCK_METHOD0(GetDownloadManager, DownloadManager*());
MOCK_CONST_METHOD0(DebugString, std::string());
+ MOCK_METHOD1(SetClientGuid, void(const std::string&));
};
} // namespace content
diff --git a/content/browser/download/save_file.cc b/content/browser/download/save_file.cc
index 80caf13..e8885e4 100644
--- a/content/browser/download/save_file.cc
+++ b/content/browser/download/save_file.cc
@@ -60,6 +60,8 @@
}
void SaveFile::AnnotateWithSourceInformation() {
+ // TODO(gbillock): If this method is called, it should set the
+ // file_.SetClientGuid() method first.
file_.AnnotateWithSourceInformation();
}
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc
index 14ed4df..bb3e5b1 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -34,7 +34,6 @@
#include "ui/gl/gl_switches.h"
#include "ui/gl/gpu_switching_manager.h"
#include "webkit/common/webpreferences.h"
-#include "webkit/plugins/plugin_switches.h"
#if defined(OS_MACOSX)
#include <ApplicationServices/ApplicationServices.h>
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc
index 8267a62..5836911 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -21,6 +21,7 @@
#include "content/common/indexed_db/indexed_db_key_path.h"
#include "content/common/indexed_db/indexed_db_key_range.h"
#include "third_party/WebKit/public/platform/WebIDBTypes.h"
+#include "third_party/leveldatabase/env_chromium.h"
using base::StringPiece;
@@ -347,11 +348,12 @@
class DefaultLevelDBFactory : public LevelDBFactory {
public:
- virtual scoped_ptr<LevelDBDatabase> OpenLevelDB(
+ virtual leveldb::Status OpenLevelDB(
const base::FilePath& file_name,
const LevelDBComparator* comparator,
+ scoped_ptr<LevelDBDatabase>* db,
bool* is_disk_full) OVERRIDE {
- return LevelDBDatabase::Open(file_name, comparator, is_disk_full);
+ return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full);
}
virtual bool DestroyLevelDB(const base::FilePath& file_name) OVERRIDE {
return LevelDBDatabase::Destroy(file_name);
@@ -400,9 +402,45 @@
INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII,
INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_DISK_FULL,
INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG,
+ INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_NO_RECOVERY,
INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
};
+bool RecoveryCouldBeFruitful(leveldb::Status status) {
+ leveldb_env::MethodID method;
+ int error = -1;
+ leveldb_env::ErrorParsingResult result = leveldb_env::ParseMethodAndError(
+ status.ToString().c_str(), &method, &error);
+ switch (result) {
+ case leveldb_env::NONE:
+ return true;
+ case leveldb_env::METHOD_AND_PFE: {
+ base::PlatformFileError pfe = static_cast<base::PlatformFileError>(error);
+ switch (pfe) {
+ case base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED:
+ case base::PLATFORM_FILE_ERROR_NO_MEMORY:
+ case base::PLATFORM_FILE_ERROR_NO_SPACE:
+ return false;
+ default:
+ return true;
+ }
+ }
+ case leveldb_env::METHOD_AND_ERRNO: {
+ switch (error) {
+ case EMFILE:
+ case ENOMEM:
+ case ENOSPC:
+ return false;
+ default:
+ return true;
+ }
+ }
+ default:
+ return true;
+ }
+ return true;
+}
+
scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
const std::string& origin_identifier,
const base::FilePath& path_base,
@@ -428,7 +466,6 @@
*data_loss = WebKit::WebIDBCallbacks::DataLossNone;
scoped_ptr<LevelDBComparator> comparator(new Comparator());
- scoped_ptr<LevelDBDatabase> db;
if (!IsStringASCII(path_base.AsUTF8Unsafe())) {
base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
@@ -493,7 +530,9 @@
base::FilePath file_path = path_base.Append(identifier_path);
bool is_disk_full = false;
- db = leveldb_factory->OpenLevelDB(file_path, comparator.get(), &is_disk_full);
+ scoped_ptr<LevelDBDatabase> db;
+ leveldb::Status status = leveldb_factory->OpenLevelDB(
+ file_path, comparator.get(), &db, &is_disk_full);
if (db) {
bool known = false;
@@ -539,6 +578,16 @@
base::HistogramBase::kUmaTargetedHistogramFlag)
->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_DISK_FULL);
return scoped_refptr<IndexedDBBackingStore>();
+ } else if (!RecoveryCouldBeFruitful(status)) {
+ LOG(ERROR) << "Unable to open backing store, not trying to recover - "
+ << status.ToString();
+ base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
+ 1,
+ INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
+ INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
+ base::HistogramBase::kUmaTargetedHistogramFlag)
+ ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_NO_RECOVERY);
+ return scoped_refptr<IndexedDBBackingStore>();
} else {
LOG(ERROR) << "IndexedDB backing store open failed, attempting cleanup";
*data_loss = WebKit::WebIDBCallbacks::DataLossTotal;
@@ -556,7 +605,7 @@
}
LOG(ERROR) << "IndexedDB backing store cleanup succeeded, reopening";
- db = leveldb_factory->OpenLevelDB(file_path, comparator.get(), NULL);
+ leveldb_factory->OpenLevelDB(file_path, comparator.get(), &db, NULL);
if (!db) {
LOG(ERROR) << "IndexedDB backing store reopen after recovery failed";
base::Histogram::FactoryGet(
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h
index 7dbdc53..4498b08 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/content/browser/indexed_db/indexed_db_backing_store.h
@@ -31,9 +31,10 @@
class LevelDBFactory {
public:
virtual ~LevelDBFactory() {}
- virtual scoped_ptr<LevelDBDatabase> OpenLevelDB(
+ virtual leveldb::Status OpenLevelDB(
const base::FilePath& file_name,
const LevelDBComparator* comparator,
+ scoped_ptr<LevelDBDatabase>* db,
bool* is_disk_full) = 0;
virtual bool DestroyLevelDB(const base::FilePath& file_name) = 0;
};
diff --git a/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc b/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
index 1f37a12..e05ceb9 100644
--- a/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <cerrno>
+
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/strings/string16.h"
@@ -9,6 +11,7 @@
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/leveldb/leveldb_database.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/leveldatabase/env_chromium.h"
using base::StringPiece;
using content::IndexedDBBackingStore;
@@ -38,11 +41,13 @@
class MockLevelDBFactory : public LevelDBFactory {
public:
MockLevelDBFactory() : destroy_called_(false) {}
- virtual scoped_ptr<LevelDBDatabase> OpenLevelDB(
+ virtual leveldb::Status OpenLevelDB(
const base::FilePath& file_name,
const LevelDBComparator* comparator,
+ scoped_ptr<LevelDBDatabase>* db,
bool* is_disk_full = 0) OVERRIDE {
- return BustedLevelDBDatabase::Open(file_name, comparator);
+ *db = BustedLevelDBDatabase::Open(file_name, comparator);
+ return leveldb::Status::OK();
}
virtual bool DestroyLevelDB(const base::FilePath& file_name) OVERRIDE {
EXPECT_FALSE(destroy_called_);
@@ -72,4 +77,78 @@
&mock_leveldb_factory);
}
+template <class T>
+class MockErrorLevelDBFactory : public LevelDBFactory {
+ public:
+ MockErrorLevelDBFactory(T error, bool expect_destroy)
+ : error_(error),
+ expect_destroy_(expect_destroy),
+ destroy_called_(false) {}
+ virtual leveldb::Status OpenLevelDB(
+ const base::FilePath& file_name,
+ const LevelDBComparator* comparator,
+ scoped_ptr<LevelDBDatabase>* db,
+ bool* is_disk_full = 0) OVERRIDE {
+ return MakeIOError(
+ "some filename", "some message", leveldb_env::kNewLogger, error_);
+ }
+ virtual bool DestroyLevelDB(const base::FilePath& file_name) OVERRIDE {
+ EXPECT_FALSE(destroy_called_);
+ destroy_called_ = true;
+ return false;
+ }
+ virtual ~MockErrorLevelDBFactory() {
+ EXPECT_EQ(expect_destroy_, destroy_called_);
+ }
+
+ private:
+ T error_;
+ bool expect_destroy_;
+ bool destroy_called_;
+};
+
+TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
+ std::string origin_identifier("http_localhost_81");
+ base::ScopedTempDir temp_directory;
+ ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
+ const base::FilePath path = temp_directory.path();
+ std::string dummy_file_identifier;
+ WebKit::WebIDBCallbacks::DataLoss data_loss =
+ WebKit::WebIDBCallbacks::DataLossNone;
+
+ MockErrorLevelDBFactory<int> mock_leveldb_factory(ENOSPC, false);
+ scoped_refptr<IndexedDBBackingStore> backing_store =
+ IndexedDBBackingStore::Open(origin_identifier,
+ path,
+ dummy_file_identifier,
+ &data_loss,
+ &mock_leveldb_factory);
+
+ MockErrorLevelDBFactory<base::PlatformFileError> mock_leveldb_factory2(
+ base::PLATFORM_FILE_ERROR_NO_MEMORY, false);
+ scoped_refptr<IndexedDBBackingStore> backing_store2 =
+ IndexedDBBackingStore::Open(origin_identifier,
+ path,
+ dummy_file_identifier,
+ &data_loss,
+ &mock_leveldb_factory2);
+
+ MockErrorLevelDBFactory<int> mock_leveldb_factory3(EIO, true);
+ scoped_refptr<IndexedDBBackingStore> backing_store3 =
+ IndexedDBBackingStore::Open(origin_identifier,
+ path,
+ dummy_file_identifier,
+ &data_loss,
+ &mock_leveldb_factory3);
+
+ MockErrorLevelDBFactory<base::PlatformFileError> mock_leveldb_factory4(
+ base::PLATFORM_FILE_ERROR_FAILED, true);
+ scoped_refptr<IndexedDBBackingStore> backing_store4 =
+ IndexedDBBackingStore::Open(origin_identifier,
+ path,
+ dummy_file_identifier,
+ &data_loss,
+ &mock_leveldb_factory4);
+}
+
} // namespace
diff --git a/content/browser/indexed_db/leveldb/leveldb_database.cc b/content/browser/indexed_db/leveldb/leveldb_database.cc
index cb67cd9..03d8ca6 100644
--- a/content/browser/indexed_db/leveldb/leveldb_database.cc
+++ b/content/browser/indexed_db/leveldb/leveldb_database.cc
@@ -268,9 +268,10 @@
ParseAndHistogramCorruptionDetails(histogram_name, s);
}
-scoped_ptr<LevelDBDatabase> LevelDBDatabase::Open(
+leveldb::Status LevelDBDatabase::Open(
const base::FilePath& file_name,
const LevelDBComparator* comparator,
+ scoped_ptr<LevelDBDatabase>* result,
bool* is_disk_full) {
scoped_ptr<ComparatorAdapter> comparator_adapter(
new ComparatorAdapter(comparator));
@@ -289,17 +290,17 @@
LOG(ERROR) << "Failed to open LevelDB database from "
<< file_name.AsUTF8Unsafe() << "," << s.ToString();
- return scoped_ptr<LevelDBDatabase>();
+ return s;
}
CheckFreeSpace("Success", file_name);
- scoped_ptr<LevelDBDatabase> result(new LevelDBDatabase);
- result->db_ = make_scoped_ptr(db);
- result->comparator_adapter_ = comparator_adapter.Pass();
- result->comparator_ = comparator;
+ (*result).reset(new LevelDBDatabase);
+ (*result)->db_ = make_scoped_ptr(db);
+ (*result)->comparator_adapter_ = comparator_adapter.Pass();
+ (*result)->comparator_ = comparator;
- return result.Pass();
+ return s;
}
scoped_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory(
diff --git a/content/browser/indexed_db/leveldb/leveldb_database.h b/content/browser/indexed_db/leveldb/leveldb_database.h
index ad1942c..1efeefa 100644
--- a/content/browser/indexed_db/leveldb/leveldb_database.h
+++ b/content/browser/indexed_db/leveldb/leveldb_database.h
@@ -13,6 +13,7 @@
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "content/common/content_export.h"
+#include "third_party/leveldatabase/src/include/leveldb/status.h"
namespace leveldb {
class Comparator;
@@ -42,9 +43,10 @@
class CONTENT_EXPORT LevelDBDatabase {
public:
- static scoped_ptr<LevelDBDatabase> Open(const base::FilePath& file_name,
- const LevelDBComparator* comparator,
- bool* is_disk_full = 0);
+ static leveldb::Status Open(const base::FilePath& file_name,
+ const LevelDBComparator* comparator,
+ scoped_ptr<LevelDBDatabase>* db,
+ bool* is_disk_full = 0);
static scoped_ptr<LevelDBDatabase> OpenInMemory(
const LevelDBComparator* comparator);
static bool Destroy(const base::FilePath& file_name);
diff --git a/content/browser/indexed_db/leveldb/leveldb_unittest.cc b/content/browser/indexed_db/leveldb/leveldb_unittest.cc
index ac7ebe0..9ce0664 100644
--- a/content/browser/indexed_db/leveldb/leveldb_unittest.cc
+++ b/content/browser/indexed_db/leveldb/leveldb_unittest.cc
@@ -41,8 +41,8 @@
std::string got_value;
SimpleComparator comparator;
- scoped_ptr<LevelDBDatabase> leveldb =
- LevelDBDatabase::Open(temp_directory.path(), &comparator);
+ scoped_ptr<LevelDBDatabase> leveldb;
+ LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
EXPECT_TRUE(leveldb);
put_value = value;
bool success = leveldb->Put(key, &put_value);
@@ -50,7 +50,7 @@
leveldb.Pass();
EXPECT_FALSE(leveldb);
- leveldb = LevelDBDatabase::Open(temp_directory.path(), &comparator);
+ LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
EXPECT_TRUE(leveldb);
bool found = false;
success = leveldb->Get(key, &got_value, &found);
@@ -69,13 +69,16 @@
base::TruncatePlatformFile(handle, 0);
base::ClosePlatformFile(handle);
- leveldb = LevelDBDatabase::Open(temp_directory.path(), &comparator);
+ leveldb::Status status =
+ LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
EXPECT_FALSE(leveldb);
+ EXPECT_FALSE(status.ok());
bool destroyed = LevelDBDatabase::Destroy(temp_directory.path());
EXPECT_TRUE(destroyed);
- leveldb = LevelDBDatabase::Open(temp_directory.path(), &comparator);
+ status = LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
+ EXPECT_TRUE(status.ok());
EXPECT_TRUE(leveldb);
success = leveldb->Get(key, &got_value, &found);
EXPECT_TRUE(success);
@@ -91,8 +94,8 @@
std::string put_value;
SimpleComparator comparator;
- scoped_ptr<LevelDBDatabase> leveldb =
- LevelDBDatabase::Open(temp_directory.path(), &comparator);
+ scoped_ptr<LevelDBDatabase> leveldb;
+ LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
EXPECT_TRUE(leveldb);
const std::string old_value("value");
@@ -158,8 +161,8 @@
SimpleComparator comparator;
bool success;
- scoped_ptr<LevelDBDatabase> leveldb =
- LevelDBDatabase::Open(temp_directory.path(), &comparator);
+ scoped_ptr<LevelDBDatabase> leveldb;
+ LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
EXPECT_TRUE(leveldb);
put_value = value1;
diff --git a/content/browser/loader/resource_loader.cc b/content/browser/loader/resource_loader.cc
index b7b1e9d..b43d5d6 100644
--- a/content/browser/loader/resource_loader.cc
+++ b/content/browser/loader/resource_loader.cc
@@ -6,6 +6,7 @@
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
#include "base/time/time.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/loader/doomed_resource_handler.h"
@@ -560,6 +561,7 @@
info->GetRequestID(), response.get(), &defer)) {
Cancel();
} else if (defer) {
+ read_deferral_start_time_ = base::TimeTicks::Now();
deferred_stage_ = DEFERRED_READ; // Read first chunk when resumed.
}
}
@@ -589,6 +591,11 @@
void ResourceLoader::ResumeReading() {
DCHECK(!is_deferred());
+ if (!read_deferral_start_time_.is_null()) {
+ UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral",
+ base::TimeTicks::Now() - read_deferral_start_time_);
+ read_deferral_start_time_ = base::TimeTicks();
+ }
if (request_->status().is_success()) {
StartReading(false); // Read the next chunk (OK to complete synchronously).
} else {
diff --git a/content/browser/loader/resource_loader.h b/content/browser/loader/resource_loader.h
index 03667e3..9687c3b 100644
--- a/content/browser/loader/resource_loader.h
+++ b/content/browser/loader/resource_loader.h
@@ -127,6 +127,7 @@
uint64 last_upload_position_;
bool waiting_for_upload_progress_ack_;
base::TimeTicks last_upload_ticks_;
+ base::TimeTicks read_deferral_start_time_;
// Indicates that we are in a state of being transferred to a new downstream
// consumer. We are waiting for a notification to complete the transfer, at
diff --git a/content/browser/media/webrtc_identity_store.cc b/content/browser/media/webrtc_identity_store.cc
index ee19f1e..1c77862 100644
--- a/content/browser/media/webrtc_identity_store.cc
+++ b/content/browser/media/webrtc_identity_store.cc
@@ -4,11 +4,14 @@
#include "content/browser/media/webrtc_identity_store.h"
+#include <map>
+
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/rand_util.h"
#include "base/threading/worker_pool.h"
+#include "content/browser/media/webrtc_identity_store_backend.h"
#include "content/public/browser/browser_thread.h"
#include "crypto/rsa_private_key.h"
#include "net/base/net_errors.h"
@@ -18,11 +21,18 @@
namespace content {
struct WebRTCIdentityRequestResult {
+ WebRTCIdentityRequestResult(int error,
+ const std::string& certificate,
+ const std::string& private_key)
+ : error(error), certificate(certificate), private_key(private_key) {}
+
int error;
std::string certificate;
std::string private_key;
};
+// Generates a new identity using |common_name| and returns the result in
+// |result|.
static void GenerateIdentityWorker(const std::string& common_name,
WebRTCIdentityRequestResult* result) {
result->error = net::OK;
@@ -60,33 +70,57 @@
std::string(private_key_info.begin(), private_key_info.end());
}
+class WebRTCIdentityRequestHandle;
+
// The class represents an identity request internal to WebRTCIdentityStore.
-// It has a one-to-one mapping to the external version of the request
-// WebRTCIdentityRequestHandle, which is the target of the
-// WebRTCIdentityRequest's completion callback.
+// It has a one-to-many mapping to the external version of the request,
+// WebRTCIdentityRequestHandle, i.e. multiple identical external requests are
+// combined into one internal request.
// It's deleted automatically when the request is completed.
class WebRTCIdentityRequest {
public:
- WebRTCIdentityRequest(const WebRTCIdentityStore::CompletionCallback& callback)
- : callback_(callback) {}
+ WebRTCIdentityRequest(const GURL& origin,
+ const std::string& identity_name,
+ const std::string& common_name)
+ : origin_(origin),
+ identity_name_(identity_name),
+ common_name_(common_name) {}
- void Cancel() {
+ void Cancel(WebRTCIdentityRequestHandle* handle) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- callback_.Reset();
+ if (callbacks_.find(handle) == callbacks_.end())
+ return;
+ callbacks_.erase(handle);
}
private:
friend class WebRTCIdentityStore;
- void Post(WebRTCIdentityRequestResult* result) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (callback_.is_null())
- return;
- callback_.Run(result->error, result->certificate, result->private_key);
- // "this" will be deleted after this point.
+ void AddCallback(WebRTCIdentityRequestHandle* handle,
+ const WebRTCIdentityStore::CompletionCallback& callback) {
+ DCHECK(callbacks_.find(handle) == callbacks_.end());
+ callbacks_[handle] = callback;
}
- WebRTCIdentityStore::CompletionCallback callback_;
+ // This method deletes "this" and no one should access it after the request
+ // completes.
+ // We do not use base::Owned to tie its lifetime to the callback for
+ // WebRTCIdentityStoreBackend::FindIdentity, because it needs to live longer
+ // than that if the identity does not exist in DB.
+ void Post(const WebRTCIdentityRequestResult& result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ for (CallbackMap::iterator it = callbacks_.begin(); it != callbacks_.end();
+ ++it)
+ it->second.Run(result.error, result.certificate, result.private_key);
+ delete this;
+ }
+
+ GURL origin_;
+ std::string identity_name_;
+ std::string common_name_;
+ typedef std::map<WebRTCIdentityRequestHandle*,
+ WebRTCIdentityStore::CompletionCallback> CallbackMap;
+ CallbackMap callbacks_;
};
// The class represents an identity request which calls back to the external
@@ -115,7 +149,7 @@
request_ = NULL;
// "this" will be deleted after the following call, because "this" is
// owned by the Callback held by |request|.
- request->Cancel();
+ request->Cancel(this);
}
void OnRequestStarted(WebRTCIdentityRequest* request) {
@@ -140,10 +174,12 @@
DISALLOW_COPY_AND_ASSIGN(WebRTCIdentityRequestHandle);
};
-WebRTCIdentityStore::WebRTCIdentityStore()
- : task_runner_(base::WorkerPool::GetTaskRunner(true)) {}
+WebRTCIdentityStore::WebRTCIdentityStore(const base::FilePath& path,
+ quota::SpecialStoragePolicy* policy)
+ : task_runner_(base::WorkerPool::GetTaskRunner(true)),
+ backend_(new WebRTCIdentityStoreBackend(path, policy)) {}
-WebRTCIdentityStore::~WebRTCIdentityStore() {}
+WebRTCIdentityStore::~WebRTCIdentityStore() { backend_->Close(); }
base::Closure WebRTCIdentityStore::RequestIdentity(
const GURL& origin,
@@ -155,26 +191,118 @@
WebRTCIdentityRequestHandle* handle =
new WebRTCIdentityRequestHandle(this, callback);
- WebRTCIdentityRequest* request = new WebRTCIdentityRequest(base::Bind(
- &WebRTCIdentityRequestHandle::OnRequestComplete, base::Owned(handle)));
+ WebRTCIdentityRequest* request =
+ FindRequest(origin, identity_name, common_name);
+
+ // If there is no identical request in flight, create a new one, queue it,
+ // and make the backend request.
+ if (!request) {
+ request = new WebRTCIdentityRequest(origin, identity_name, common_name);
+
+ if (!backend_->FindIdentity(
+ origin,
+ identity_name,
+ common_name,
+ base::Bind(
+ &WebRTCIdentityStore::BackendFindCallback, this, request))) {
+ delete request;
+ return base::Closure();
+ }
+ in_flight_requests_.push_back(request);
+ }
+
+ request->AddCallback(
+ handle,
+ base::Bind(&WebRTCIdentityRequestHandle::OnRequestComplete,
+ base::Owned(handle)));
handle->OnRequestStarted(request);
-
- WebRTCIdentityRequestResult* result = new WebRTCIdentityRequestResult();
- if (!task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::Bind(&GenerateIdentityWorker, common_name, result),
- base::Bind(&WebRTCIdentityRequest::Post,
- base::Owned(request),
- base::Owned(result))))
- return base::Closure();
-
return base::Bind(&WebRTCIdentityRequestHandle::Cancel,
base::Unretained(handle));
}
+void WebRTCIdentityStore::DeleteBetween(base::Time delete_begin,
+ base::Time delete_end,
+ const base::Closure& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ backend_->DeleteBetween(delete_begin, delete_end, callback);
+}
+
void WebRTCIdentityStore::SetTaskRunnerForTesting(
const scoped_refptr<base::TaskRunner>& task_runner) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
task_runner_ = task_runner;
}
+void WebRTCIdentityStore::BackendFindCallback(WebRTCIdentityRequest* request,
+ int error,
+ const std::string& certificate,
+ const std::string& private_key) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (error == net::OK) {
+ DVLOG(2) << "Identity found in DB.";
+ WebRTCIdentityRequestResult result(error, certificate, private_key);
+ PostRequestResult(request, result);
+ return;
+ }
+ // Generate a new identity if not found in the DB.
+ WebRTCIdentityRequestResult* result =
+ new WebRTCIdentityRequestResult(0, "", "");
+ if (!task_runner_->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&GenerateIdentityWorker, request->common_name_, result),
+ base::Bind(&WebRTCIdentityStore::GenerateIdentityCallback,
+ this,
+ request,
+ base::Owned(result)))) {
+ // Completes the request with error if failed to post the task.
+ WebRTCIdentityRequestResult result(net::ERR_UNEXPECTED, "", "");
+ PostRequestResult(request, result);
+ }
+}
+
+void WebRTCIdentityStore::GenerateIdentityCallback(
+ WebRTCIdentityRequest* request,
+ WebRTCIdentityRequestResult* result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (result->error == net::OK) {
+ DVLOG(2) << "New identity generated and added to the backend.";
+ backend_->AddIdentity(request->origin_,
+ request->identity_name_,
+ request->common_name_,
+ result->certificate,
+ result->private_key);
+ }
+ PostRequestResult(request, *result);
+}
+
+void WebRTCIdentityStore::PostRequestResult(
+ WebRTCIdentityRequest* request,
+ const WebRTCIdentityRequestResult& result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // Removes the in flight request from the queue.
+ for (size_t i = 0; i < in_flight_requests_.size(); ++i) {
+ if (in_flight_requests_[i] == request) {
+ in_flight_requests_.erase(in_flight_requests_.begin() + i);
+ break;
+ }
+ }
+ // |request| will be deleted after this call.
+ request->Post(result);
+}
+
+// Find an identical request from the in flight requests.
+WebRTCIdentityRequest* WebRTCIdentityStore::FindRequest(
+ const GURL& origin,
+ const std::string& identity_name,
+ const std::string& common_name) {
+ for (size_t i = 0; i < in_flight_requests_.size(); ++i) {
+ if (in_flight_requests_[i]->origin_ == origin &&
+ in_flight_requests_[i]->identity_name_ == identity_name &&
+ in_flight_requests_[i]->common_name_ == common_name) {
+ return in_flight_requests_[i];
+ }
+ }
+ return NULL;
+}
+
} // namespace content
diff --git a/content/browser/media/webrtc_identity_store.h b/content/browser/media/webrtc_identity_store.h
index 1649384..c2b523e 100644
--- a/content/browser/media/webrtc_identity_store.h
+++ b/content/browser/media/webrtc_identity_store.h
@@ -6,32 +6,44 @@
#define CONTENT_BROWSER_MEDIA_WEBRTC_IDENTITY_STORE_H_
#include <string>
+#include <vector>
#include "base/callback.h"
+#include "base/time/time.h"
#include "content/common/content_export.h"
class GURL;
namespace base {
+class FilePath;
class TaskRunner;
} // namespace base
-namespace content {
+namespace quota {
+class SpecialStoragePolicy;
+} // namespace quota
+namespace content {
+class WebRTCIdentityRequest;
+struct WebRTCIdentityRequestResult;
+class WebRTCIdentityStoreBackend;
class WebRTCIdentityStoreTest;
// A class for creating and fetching DTLS identities, i.e. the private key and
// the self-signed certificate.
-class CONTENT_EXPORT WebRTCIdentityStore {
+// It can be created/destroyed on any thread, but the public methods must be
+// called on the IO thread.
+class CONTENT_EXPORT WebRTCIdentityStore
+ : public base::RefCountedThreadSafe<WebRTCIdentityStore> {
public:
typedef base::Callback<void(int error,
const std::string& certificate,
const std::string& private_key)>
CompletionCallback;
- WebRTCIdentityStore();
- // Only virtual to allow subclassing for test mock.
- virtual ~WebRTCIdentityStore();
+ // If |path| is empty, nothing will be saved to disk.
+ WebRTCIdentityStore(const base::FilePath& path,
+ quota::SpecialStoragePolicy* policy);
// Retrieve the cached DTLS private key and certificate, i.e. identity, for
// the |origin| and |identity_name| pair, or generate a new identity using
@@ -39,7 +51,6 @@
// If the given |common_name| is different from the common name in the cached
// identity that has the same origin and identity_name, a new private key and
// a new certificate will be generated, overwriting the old one.
- // TODO(jiayl): implement identity caching through a persistent storage.
//
// |origin| is the origin of the DTLS connection;
// |identity_name| is used to identify an identity within an origin; it is
@@ -49,7 +60,7 @@
// be shared with the peer of the DTLS connection. Identities created for
// different origins or different identity names may have the same common
// name.
- // |callback| is the callback to return the result.
+ // |callback| is the callback to return the result as DER strings.
//
// Returns the Closure used to cancel the request if the request is accepted.
// The Closure can only be called before the request completes.
@@ -58,14 +69,42 @@
const std::string& common_name,
const CompletionCallback& callback);
+ // Delete the identities created between |delete_begin| and |delete_end|.
+ // |callback| will be called when the operation is done.
+ void DeleteBetween(base::Time delete_begin,
+ base::Time delete_end,
+ const base::Closure& callback);
+
+ protected:
+ // Only virtual to allow subclassing for test mock.
+ virtual ~WebRTCIdentityStore();
+
private:
+ friend class base::RefCountedThreadSafe<WebRTCIdentityStore>;
friend class WebRTCIdentityStoreTest;
void SetTaskRunnerForTesting(
const scoped_refptr<base::TaskRunner>& task_runner);
+ void BackendFindCallback(WebRTCIdentityRequest* request,
+ int error,
+ const std::string& certificate,
+ const std::string& private_key);
+ void GenerateIdentityCallback(WebRTCIdentityRequest* request,
+ WebRTCIdentityRequestResult* result);
+ WebRTCIdentityRequest* FindRequest(const GURL& origin,
+ const std::string& identity_name,
+ const std::string& common_name);
+ void PostRequestResult(WebRTCIdentityRequest* request,
+ const WebRTCIdentityRequestResult& result);
+
// The TaskRunner for doing work on a worker thread.
scoped_refptr<base::TaskRunner> task_runner_;
+ // Weak references of the in flight requests. Used to join identical external
+ // requests.
+ std::vector<WebRTCIdentityRequest*> in_flight_requests_;
+
+ scoped_refptr<WebRTCIdentityStoreBackend> backend_;
DISALLOW_COPY_AND_ASSIGN(WebRTCIdentityStore);
};
diff --git a/content/browser/media/webrtc_identity_store_backend.cc b/content/browser/media/webrtc_identity_store_backend.cc
new file mode 100644
index 0000000..a86cc20
--- /dev/null
+++ b/content/browser/media/webrtc_identity_store_backend.cc
@@ -0,0 +1,543 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/webrtc_identity_store_backend.h"
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/net_errors.h"
+#include "sql/error_delegate_util.h"
+#include "sql/statement.h"
+#include "sql/transaction.h"
+#include "url/gurl.h"
+#include "webkit/browser/quota/special_storage_policy.h"
+
+namespace content {
+
+static const char* kWebRTCIdentityStoreDBName = "webrtc_identity_store";
+
+static const base::FilePath::CharType kWebRTCIdentityStoreDirectory[] =
+ FILE_PATH_LITERAL("WebRTCIdentityStore");
+
+// Initializes the identity table, returning true on success.
+static bool InitDB(sql::Connection* db) {
+ if (db->DoesTableExist(kWebRTCIdentityStoreDBName)) {
+ if (db->DoesColumnExist(kWebRTCIdentityStoreDBName, "origin") &&
+ db->DoesColumnExist(kWebRTCIdentityStoreDBName, "identity_name") &&
+ db->DoesColumnExist(kWebRTCIdentityStoreDBName, "common_name") &&
+ db->DoesColumnExist(kWebRTCIdentityStoreDBName, "certificate") &&
+ db->DoesColumnExist(kWebRTCIdentityStoreDBName, "private_key") &&
+ db->DoesColumnExist(kWebRTCIdentityStoreDBName, "creation_time"))
+ return true;
+ if (!db->Execute("DROP TABLE webrtc_identity_store"))
+ return false;
+ }
+
+ return db->Execute(
+ "CREATE TABLE webrtc_identity_store"
+ " ("
+ "origin TEXT NOT NULL,"
+ "identity_name TEXT NOT NULL,"
+ "common_name TEXT NOT NULL,"
+ "certificate BLOB NOT NULL,"
+ "private_key BLOB NOT NULL,"
+ "creation_time INTEGER)");
+}
+
+struct WebRTCIdentityStoreBackend::IdentityKey {
+ IdentityKey(const GURL& origin, const std::string& identity_name)
+ : origin(origin), identity_name(identity_name) {}
+
+ bool operator<(const IdentityKey& other) const {
+ return origin < other.origin ||
+ (origin == other.origin && identity_name < other.identity_name);
+ }
+
+ GURL origin;
+ std::string identity_name;
+};
+
+struct WebRTCIdentityStoreBackend::Identity {
+ Identity(const std::string& common_name,
+ const std::string& certificate,
+ const std::string& private_key)
+ : common_name(common_name),
+ certificate(certificate),
+ private_key(private_key),
+ creation_time(base::Time::Now().ToInternalValue()) {}
+
+ Identity(const std::string& common_name,
+ const std::string& certificate,
+ const std::string& private_key,
+ int64 creation_time)
+ : common_name(common_name),
+ certificate(certificate),
+ private_key(private_key),
+ creation_time(creation_time) {}
+
+ std::string common_name;
+ std::string certificate;
+ std::string private_key;
+ int64 creation_time;
+};
+
+struct WebRTCIdentityStoreBackend::PendingFindRequest {
+ PendingFindRequest(const GURL& origin,
+ const std::string& identity_name,
+ const std::string& common_name,
+ const FindIdentityCallback& callback)
+ : origin(origin),
+ identity_name(identity_name),
+ common_name(common_name),
+ callback(callback) {}
+
+ ~PendingFindRequest() {}
+
+ GURL origin;
+ std::string identity_name;
+ std::string common_name;
+ FindIdentityCallback callback;
+};
+
+// The class encapsulates the database operations. All members except ctor and
+// dtor should be accessed on the DB thread.
+// It can be created/destroyed on any thread.
+class WebRTCIdentityStoreBackend::SqlLiteStorage
+ : public base::RefCountedThreadSafe<SqlLiteStorage> {
+ public:
+ SqlLiteStorage(const base::FilePath& path,
+ quota::SpecialStoragePolicy* policy)
+ : special_storage_policy_(policy) {
+ if (!path.empty())
+ path_ = path.Append(kWebRTCIdentityStoreDirectory);
+ }
+
+ void Load(IdentityMap* out_map);
+ void Close();
+ void AddIdentity(const GURL& origin,
+ const std::string& identity_name,
+ const Identity& identity);
+ void DeleteIdentity(const GURL& origin,
+ const std::string& identity_name,
+ const Identity& identity);
+ void DeleteBetween(base::Time delete_begin,
+ base::Time delete_end,
+ const base::Closure& callback);
+
+ private:
+ friend class base::RefCountedThreadSafe<SqlLiteStorage>;
+
+ enum OperationType {
+ ADD_IDENTITY,
+ DELETE_IDENTITY
+ };
+ struct PendingOperation {
+ PendingOperation(OperationType type,
+ const GURL& origin,
+ const std::string& identity_name,
+ const Identity& identity)
+ : type(type),
+ origin(origin),
+ identity_name(identity_name),
+ identity(identity) {}
+
+ OperationType type;
+ GURL origin;
+ std::string identity_name;
+ Identity identity;
+ };
+ typedef std::vector<PendingOperation*> PendingOperationList;
+
+ virtual ~SqlLiteStorage() {}
+ void OnDatabaseError(int error, sql::Statement* stmt);
+ void BatchOperation(OperationType type,
+ const GURL& origin,
+ const std::string& identity_name,
+ const Identity& identity);
+ void Commit();
+
+ // The file path of the DB. Empty if temporary.
+ base::FilePath path_;
+ scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
+ scoped_ptr<sql::Connection> db_;
+ // Batched DB operations pending to commit.
+ PendingOperationList pending_operations_;
+
+ DISALLOW_COPY_AND_ASSIGN(SqlLiteStorage);
+};
+
+WebRTCIdentityStoreBackend::WebRTCIdentityStoreBackend(
+ const base::FilePath& path,
+ quota::SpecialStoragePolicy* policy)
+ : state_(NOT_STARTED),
+ sql_lite_storage_(new SqlLiteStorage(path, policy)) {}
+
+bool WebRTCIdentityStoreBackend::FindIdentity(
+ const GURL& origin,
+ const std::string& identity_name,
+ const std::string& common_name,
+ const FindIdentityCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (state_ == CLOSED)
+ return false;
+
+ if (state_ != LOADED) {
+ // Queues the request to wait for the DB to load.
+ pending_find_requests_.push_back(
+ new PendingFindRequest(origin, identity_name, common_name, callback));
+ if (state_ == LOADING)
+ return true;
+
+ DCHECK_EQ(state_, NOT_STARTED);
+
+ // Kick off loading the DB.
+ scoped_ptr<IdentityMap> out_map(new IdentityMap());
+ if (BrowserThread::PostTaskAndReply(
+ BrowserThread::DB,
+ FROM_HERE,
+ base::Bind(&SqlLiteStorage::Load, sql_lite_storage_, out_map.get()),
+ base::Bind(&WebRTCIdentityStoreBackend::OnLoaded,
+ this,
+ base::Passed(&out_map)))) {
+ state_ = LOADING;
+ return true;
+ }
+ // If it fails to post task, falls back to ERR_FILE_NOT_FOUND.
+ }
+
+ IdentityKey key(origin, identity_name);
+ IdentityMap::iterator iter = identities_.find(key);
+ if (iter != identities_.end() && iter->second.common_name == common_name) {
+ // Identity found.
+ return BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(callback,
+ net::OK,
+ iter->second.certificate,
+ iter->second.private_key));
+ }
+
+ return BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(callback, net::ERR_FILE_NOT_FOUND, "", ""));
+}
+
+void WebRTCIdentityStoreBackend::AddIdentity(const GURL& origin,
+ const std::string& identity_name,
+ const std::string& common_name,
+ const std::string& certificate,
+ const std::string& private_key) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (state_ == CLOSED)
+ return;
+
+ // If there is an existing identity for the same origin and identity_name,
+ // delete it.
+ IdentityKey key(origin, identity_name);
+ Identity identity(common_name, certificate, private_key);
+
+ if (identities_.find(key) != identities_.end()) {
+ if (!BrowserThread::PostTask(BrowserThread::DB,
+ FROM_HERE,
+ base::Bind(&SqlLiteStorage::DeleteIdentity,
+ sql_lite_storage_,
+ origin,
+ identity_name,
+ identities_.find(key)->second)))
+ return;
+ }
+ identities_.insert(std::pair<IdentityKey, Identity>(key, identity));
+
+ BrowserThread::PostTask(BrowserThread::DB,
+ FROM_HERE,
+ base::Bind(&SqlLiteStorage::AddIdentity,
+ sql_lite_storage_,
+ origin,
+ identity_name,
+ identity));
+}
+
+void WebRTCIdentityStoreBackend::Close() {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&WebRTCIdentityStoreBackend::Close, this));
+ return;
+ }
+
+ if (state_ == CLOSED)
+ return;
+
+ state_ = CLOSED;
+ BrowserThread::PostTask(
+ BrowserThread::DB,
+ FROM_HERE,
+ base::Bind(&SqlLiteStorage::Close, sql_lite_storage_));
+}
+
+void WebRTCIdentityStoreBackend::DeleteBetween(base::Time delete_begin,
+ base::Time delete_end,
+ const base::Closure& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // Delete the in-memory cache.
+ IdentityMap::iterator it = identities_.begin();
+ while (it != identities_.end()) {
+ if (it->second.creation_time >= delete_begin.ToInternalValue() &&
+ it->second.creation_time <= delete_end.ToInternalValue())
+ identities_.erase(it++);
+ else
+ it++;
+ }
+
+ BrowserThread::PostTaskAndReply(BrowserThread::DB,
+ FROM_HERE,
+ base::Bind(&SqlLiteStorage::DeleteBetween,
+ sql_lite_storage_,
+ delete_begin,
+ delete_end,
+ callback),
+ callback);
+}
+
+WebRTCIdentityStoreBackend::~WebRTCIdentityStoreBackend() {}
+
+void WebRTCIdentityStoreBackend::OnLoaded(scoped_ptr<IdentityMap> out_map) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ state_ = LOADED;
+ identities_.swap(*out_map);
+
+ for (size_t i = 0; i < pending_find_requests_.size(); ++i) {
+ FindIdentity(pending_find_requests_[i]->origin,
+ pending_find_requests_[i]->identity_name,
+ pending_find_requests_[i]->common_name,
+ pending_find_requests_[i]->callback);
+ delete pending_find_requests_[i];
+ }
+ pending_find_requests_.clear();
+}
+
+//
+// Implementation of SqlLiteStorage.
+//
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::Load(IdentityMap* out_map) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ DCHECK(!db_.get());
+
+ // Ensure the parent directory for storing certs is created before reading
+ // from it.
+ const base::FilePath dir = path_.DirName();
+ if (!base::PathExists(dir) && !file_util::CreateDirectory(dir)) {
+ DLOG(ERROR) << "Unable to open DB file path.";
+ return;
+ }
+
+ db_.reset(new sql::Connection());
+
+ db_->set_error_callback(base::Bind(&SqlLiteStorage::OnDatabaseError, this));
+
+ if (!db_->Open(path_)) {
+ DLOG(ERROR) << "Unable to open DB.";
+ db_.reset();
+ return;
+ }
+
+ if (!InitDB(db_.get())) {
+ DLOG(ERROR) << "Unable to init DB.";
+ db_.reset();
+ return;
+ }
+
+ db_->Preload();
+
+ // Slurp all the identities into the out_map.
+ sql::Statement stmt(db_->GetUniqueStatement(
+ "SELECT origin, identity_name, common_name, "
+ "certificate, private_key, creation_time "
+ "FROM webrtc_identity_store"));
+ CHECK(stmt.is_valid());
+
+ while (stmt.Step()) {
+ IdentityKey key(GURL(stmt.ColumnString(0)), stmt.ColumnString(1));
+ std::string common_name(stmt.ColumnString(2));
+ std::string cert, private_key;
+ stmt.ColumnBlobAsString(3, &cert);
+ stmt.ColumnBlobAsString(4, &private_key);
+ int64 creation_time = stmt.ColumnInt64(5);
+ std::pair<IdentityMap::iterator, bool> result =
+ out_map->insert(std::pair<IdentityKey, Identity>(
+ key, Identity(common_name, cert, private_key, creation_time)));
+ DCHECK(result.second);
+ }
+}
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::Close() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ Commit();
+ db_.reset();
+}
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::AddIdentity(
+ const GURL& origin,
+ const std::string& identity_name,
+ const Identity& identity) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ if (!db_.get())
+ return;
+
+ // Do not add for session only origins.
+ if (special_storage_policy_.get() &&
+ !special_storage_policy_->IsStorageProtected(origin) &&
+ special_storage_policy_->IsStorageSessionOnly(origin)) {
+ return;
+ }
+ BatchOperation(ADD_IDENTITY, origin, identity_name, identity);
+}
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteIdentity(
+ const GURL& origin,
+ const std::string& identity_name,
+ const Identity& identity) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ if (!db_.get())
+ return;
+ BatchOperation(DELETE_IDENTITY, origin, identity_name, identity);
+}
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::OnDatabaseError(
+ int error,
+ sql::Statement* stmt) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ if (!sql::IsErrorCatastrophic(error))
+ return;
+ db_->RazeAndClose();
+}
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::BatchOperation(
+ OperationType type,
+ const GURL& origin,
+ const std::string& identity_name,
+ const Identity& identity) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ // Commit every 30 seconds.
+ static const base::TimeDelta kCommitInterval(
+ base::TimeDelta::FromSeconds(30));
+ // Commit right away if we have more than 512 outstanding operations.
+ static const size_t kCommitAfterBatchSize = 512;
+
+ // We do a full copy of the cert here, and hopefully just here.
+ scoped_ptr<PendingOperation> operation(
+ new PendingOperation(type, origin, identity_name, identity));
+
+ pending_operations_.push_back(operation.release());
+
+ if (pending_operations_.size() == 1) {
+ // We've gotten our first entry for this batch, fire off the timer.
+ BrowserThread::PostDelayedTask(BrowserThread::DB,
+ FROM_HERE,
+ base::Bind(&SqlLiteStorage::Commit, this),
+ kCommitInterval);
+ } else if (pending_operations_.size() >= kCommitAfterBatchSize) {
+ // We've reached a big enough batch, fire off a commit now.
+ BrowserThread::PostTask(BrowserThread::DB,
+ FROM_HERE,
+ base::Bind(&SqlLiteStorage::Commit, this));
+ }
+}
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::Commit() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ // Maybe an old timer fired or we are already Close()'ed.
+ if (!db_.get() || pending_operations_.empty())
+ return;
+
+ sql::Statement add_stmt(db_->GetCachedStatement(
+ SQL_FROM_HERE,
+ "INSERT INTO webrtc_identity_store "
+ "(origin, identity_name, common_name, certificate,"
+ " private_key, creation_time) VALUES"
+ " (?,?,?,?,?,?)"));
+
+ CHECK(add_stmt.is_valid());
+
+ sql::Statement del_stmt(db_->GetCachedStatement(
+ SQL_FROM_HERE,
+ "DELETE FROM webrtc_identity_store WHERE origin=? AND identity_name=?"));
+
+ CHECK(del_stmt.is_valid());
+
+ sql::Transaction transaction(db_.get());
+ if (!transaction.Begin()) {
+ DLOG(ERROR) << "Failed to begin the transaction.";
+ return;
+ }
+
+ for (PendingOperationList::iterator it = pending_operations_.begin();
+ it != pending_operations_.end();
+ ++it) {
+ scoped_ptr<PendingOperation> po(*it);
+ switch (po->type) {
+ case ADD_IDENTITY: {
+ add_stmt.Reset(true);
+ add_stmt.BindString(0, po->origin.spec());
+ add_stmt.BindString(1, po->identity_name);
+ add_stmt.BindString(2, po->identity.common_name);
+ const std::string& cert = po->identity.certificate;
+ add_stmt.BindBlob(3, cert.data(), cert.size());
+ const std::string& private_key = po->identity.private_key;
+ add_stmt.BindBlob(4, private_key.data(), private_key.size());
+ add_stmt.BindInt64(5, po->identity.creation_time);
+ CHECK(add_stmt.Run());
+ break;
+ }
+ case DELETE_IDENTITY:
+ del_stmt.Reset(true);
+ del_stmt.BindString(0, po->origin.spec());
+ add_stmt.BindString(1, po->identity_name);
+ CHECK(del_stmt.Run());
+ break;
+
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+ transaction.Commit();
+ pending_operations_.clear();
+}
+
+void WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteBetween(
+ base::Time delete_begin,
+ base::Time delete_end,
+ const base::Closure& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ if (!db_.get())
+ return;
+
+ // Commit pending operations first.
+ Commit();
+
+ sql::Statement del_stmt(db_->GetCachedStatement(
+ SQL_FROM_HERE,
+ "DELETE FROM webrtc_identity_store"
+ " WHERE creation_time >= ? AND creation_time <= ?"));
+ CHECK(del_stmt.is_valid());
+
+ del_stmt.BindInt64(0, delete_begin.ToInternalValue());
+ del_stmt.BindInt64(1, delete_end.ToInternalValue());
+
+ sql::Transaction transaction(db_.get());
+ if (!transaction.Begin()) {
+ DLOG(ERROR) << "Failed to begin the transaction.";
+ return;
+ }
+
+ CHECK(del_stmt.Run());
+ transaction.Commit();
+}
+
+} // namespace content
diff --git a/content/browser/media/webrtc_identity_store_backend.h b/content/browser/media/webrtc_identity_store_backend.h
new file mode 100644
index 0000000..ab4e1ed
--- /dev/null
+++ b/content/browser/media/webrtc_identity_store_backend.h
@@ -0,0 +1,111 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_WEBRTC_IDENTITY_STORE_BACKEND_H_
+#define CONTENT_BROWSER_MEDIA_WEBRTC_IDENTITY_STORE_BACKEND_H_
+
+#include <map>
+#include <string>
+
+#include "base/time/time.h"
+#include "sql/connection.h"
+#include "sql/meta_table.h"
+
+class GURL;
+
+namespace base {
+class FilePath;
+} // namespace base
+
+namespace quota {
+class SpecialStoragePolicy;
+} // namespace quota
+
+namespace content {
+
+// This class represents a persistent cache of WebRTC identities.
+// It can be created/destroyed/Close() on any thread. All other members should
+// be accessed on the IO thread.
+class WebRTCIdentityStoreBackend
+ : public base::RefCountedThreadSafe<WebRTCIdentityStoreBackend> {
+ public:
+ typedef base::Callback<void(int error,
+ const std::string& certificate,
+ const std::string& private_key)>
+ FindIdentityCallback;
+
+ // No data is saved on disk if |path| is empty.
+ WebRTCIdentityStoreBackend(const base::FilePath& path,
+ quota::SpecialStoragePolicy* policy);
+
+ // Finds the identity with |origin|, |identity_name|, and |common_name| from
+ // the DB.
+ // |origin| is the origin of the identity;
+ // |identity_name| is used to identify an identity within an origin;
+ // |common_name| is the common name used to generate the certificate;
+ // |callback| is the callback to return the find result.
+ // Returns true if |callback| will be called.
+ // Should be called on the IO thread.
+ bool FindIdentity(const GURL& origin,
+ const std::string& identity_name,
+ const std::string& common_name,
+ const FindIdentityCallback& callback);
+
+ // Adds the identity to the DB and overwrites any existing identity having the
+ // same origin and identity_name.
+ // |origin| is the origin of the identity;
+ // |identity_name| is used to identify an identity within an origin;
+ // |common_name| is the common name used to generate the certificate;
+ // |certificate| is the DER string of the certificate;
+ // |private_key| is the DER string of the private key.
+ // Should be called on the IO thread.
+ void AddIdentity(const GURL& origin,
+ const std::string& identity_name,
+ const std::string& common_name,
+ const std::string& certificate,
+ const std::string& private_key);
+
+ // Commits all pending DB operations and closes the DB connection. Any API
+ // call after this will fail.
+ // Can be called on any thread.
+ void Close();
+
+ // Delete the data created between |delete_begin| and |delete_end|.
+ // Should be called on the IO thread.
+ void DeleteBetween(base::Time delete_begin,
+ base::Time delete_end,
+ const base::Closure& callback);
+
+ private:
+ friend class base::RefCountedThreadSafe<WebRTCIdentityStoreBackend>;
+ class SqlLiteStorage;
+ enum LoadingState {
+ NOT_STARTED,
+ LOADING,
+ LOADED,
+ CLOSED,
+ };
+ struct PendingFindRequest;
+ struct IdentityKey;
+ struct Identity;
+ typedef std::map<IdentityKey, Identity> IdentityMap;
+
+ ~WebRTCIdentityStoreBackend();
+
+ void OnLoaded(scoped_ptr<IdentityMap> out_map);
+
+ // In-memory copy of the identities.
+ IdentityMap identities_;
+ // "Find identity" requests waiting for the DB to load.
+ std::vector<PendingFindRequest*> pending_find_requests_;
+ // The persistent storage loading state.
+ LoadingState state_;
+ // The persistent storage of identities.
+ scoped_refptr<SqlLiteStorage> sql_lite_storage_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebRTCIdentityStoreBackend);
+};
+}
+
+#endif // CONTENT_BROWSER_MEDIA_WEBRTC_IDENTITY_STORE_BACKEND_H_
diff --git a/content/browser/media/webrtc_identity_store_unittest.cc b/content/browser/media/webrtc_identity_store_unittest.cc
index a975dd4..81c25d7 100644
--- a/content/browser/media/webrtc_identity_store_unittest.cc
+++ b/content/browser/media/webrtc_identity_store_unittest.cc
@@ -17,15 +17,37 @@
// TODO(jiayl): the tests fail on Android since the openssl version of
// CreateSelfSignedCert is not implemented. We should mock out this dependency
// and remove the if-defined.
-
#if !defined(OS_ANDROID)
+
+static const char* kFakeOrigin = "http://foo.com";
+static const char* kFakeIdentityName1 = "name1";
+static const char* kFakeIdentityName2 = "name2";
+static const char* kFakeCommonName1 = "cname1";
+static const char* kFakeCommonName2 = "cname2";
+
+static void OnRequestCompleted(bool* completed,
+ std::string* out_cert,
+ std::string* out_key,
+ int error,
+ const std::string& certificate,
+ const std::string& private_key) {
+ ASSERT_EQ(net::OK, error);
+ ASSERT_NE("", certificate);
+ ASSERT_NE("", private_key);
+ *completed = true;
+ *out_cert = certificate;
+ *out_key = private_key;
+}
+
class WebRTCIdentityStoreTest : public testing::Test {
public:
WebRTCIdentityStoreTest()
- : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP |
+ TestBrowserThreadBundle::REAL_DB_THREAD),
pool_owner_(
new base::SequencedWorkerPoolOwner(3, "WebRTCIdentityStoreTest")),
- webrtc_identity_store_(new WebRTCIdentityStore()) {
+ webrtc_identity_store_(
+ new WebRTCIdentityStore(base::FilePath(), NULL)) {
webrtc_identity_store_->SetTaskRunnerForTesting(pool_owner_->pool());
}
@@ -33,74 +55,224 @@
pool_owner_->pool()->Shutdown();
}
+ void RunUntilIdle() {
+ RunAllPendingInMessageLoop(BrowserThread::DB);
+ RunAllPendingInMessageLoop(BrowserThread::IO);
+ pool_owner_->pool()->FlushForTesting();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ base::Closure RequestIdentityAndRunUtilIdle(const std::string& origin,
+ const std::string& identity_name,
+ const std::string& common_name,
+ bool* completed,
+ std::string* certificate,
+ std::string* private_key) {
+ base::Closure cancel_callback = webrtc_identity_store_->RequestIdentity(
+ GURL(origin),
+ identity_name,
+ common_name,
+ base::Bind(&OnRequestCompleted, completed, certificate, private_key));
+ EXPECT_FALSE(cancel_callback.is_null());
+ RunUntilIdle();
+ return cancel_callback;
+ }
+
protected:
TestBrowserThreadBundle browser_thread_bundle_;
scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_;
- scoped_ptr<WebRTCIdentityStore> webrtc_identity_store_;
+ scoped_refptr<WebRTCIdentityStore> webrtc_identity_store_;
};
-static void OnRequestCompleted(bool* completed,
- int error,
- const std::string& certificate,
- const std::string& private_key) {
- ASSERT_EQ(net::OK, error);
- ASSERT_NE("", certificate);
- ASSERT_NE("", private_key);
- *completed = true;
-}
-
TEST_F(WebRTCIdentityStoreTest, RequestIdentity) {
bool completed = false;
+ std::string dummy;
base::Closure cancel_callback =
- webrtc_identity_store_->RequestIdentity(
- GURL("http://google.com"),
- "a",
- "b",
- base::Bind(&OnRequestCompleted, &completed));
- ASSERT_FALSE(cancel_callback.is_null());
- pool_owner_->pool()->FlushForTesting();
- base::RunLoop().RunUntilIdle();
+ RequestIdentityAndRunUtilIdle(kFakeOrigin,
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ &completed,
+ &dummy,
+ &dummy);
EXPECT_TRUE(completed);
}
TEST_F(WebRTCIdentityStoreTest, CancelRequest) {
bool completed = false;
- base::Closure cancel_callback =
- webrtc_identity_store_->RequestIdentity(
- GURL("http://google.com"),
- "a",
- "b",
- base::Bind(&OnRequestCompleted, &completed));
+ std::string dummy;
+ base::Closure cancel_callback = webrtc_identity_store_->RequestIdentity(
+ GURL(kFakeOrigin),
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ base::Bind(&OnRequestCompleted, &completed, &dummy, &dummy));
ASSERT_FALSE(cancel_callback.is_null());
cancel_callback.Run();
- pool_owner_->pool()->FlushForTesting();
- base::RunLoop().RunUntilIdle();
+
+ RunUntilIdle();
EXPECT_FALSE(completed);
}
-TEST_F(WebRTCIdentityStoreTest, MultipleRequests) {
+TEST_F(WebRTCIdentityStoreTest, ConcurrentUniqueRequests) {
bool completed_1 = false;
bool completed_2 = false;
- base::Closure cancel_callback_1 =
- webrtc_identity_store_->RequestIdentity(
- GURL("http://foo.com"),
- "a",
- "b",
- base::Bind(&OnRequestCompleted, &completed_1));
+ std::string dummy;
+ base::Closure cancel_callback_1 = webrtc_identity_store_->RequestIdentity(
+ GURL(kFakeOrigin),
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ base::Bind(&OnRequestCompleted, &completed_1, &dummy, &dummy));
ASSERT_FALSE(cancel_callback_1.is_null());
- base::Closure cancel_callback_2 =
- webrtc_identity_store_->RequestIdentity(
- GURL("http://bar.com"),
- "a",
- "b",
- base::Bind(&OnRequestCompleted, &completed_2));
+ base::Closure cancel_callback_2 = webrtc_identity_store_->RequestIdentity(
+ GURL(kFakeOrigin),
+ kFakeIdentityName2,
+ kFakeCommonName1,
+ base::Bind(&OnRequestCompleted, &completed_2, &dummy, &dummy));
ASSERT_FALSE(cancel_callback_2.is_null());
- pool_owner_->pool()->FlushForTesting();
- base::RunLoop().RunUntilIdle();
+ RunUntilIdle();
EXPECT_TRUE(completed_1);
EXPECT_TRUE(completed_2);
}
+
+TEST_F(WebRTCIdentityStoreTest, DifferentCommonNameReturnNewIdentity) {
+ bool completed_1 = false;
+ bool completed_2 = false;
+ std::string cert_1, cert_2, key_1, key_2;
+
+ base::Closure cancel_callback_1 =
+ RequestIdentityAndRunUtilIdle(kFakeOrigin,
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ &completed_1,
+ &cert_1,
+ &key_1);
+
+ base::Closure cancel_callback_2 =
+ RequestIdentityAndRunUtilIdle(kFakeOrigin,
+ kFakeIdentityName1,
+ kFakeCommonName2,
+ &completed_2,
+ &cert_2,
+ &key_2);
+
+ EXPECT_TRUE(completed_1);
+ EXPECT_TRUE(completed_2);
+ EXPECT_NE(cert_1, cert_2);
+ EXPECT_NE(key_1, key_2);
+}
+
+TEST_F(WebRTCIdentityStoreTest, SerialIdenticalRequests) {
+ bool completed_1 = false;
+ bool completed_2 = false;
+ std::string cert_1, cert_2, key_1, key_2;
+
+ base::Closure cancel_callback_1 =
+ RequestIdentityAndRunUtilIdle(kFakeOrigin,
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ &completed_1,
+ &cert_1,
+ &key_1);
+
+ base::Closure cancel_callback_2 =
+ RequestIdentityAndRunUtilIdle(kFakeOrigin,
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ &completed_2,
+ &cert_2,
+ &key_2);
+
+ EXPECT_TRUE(completed_1);
+ EXPECT_TRUE(completed_2);
+ EXPECT_EQ(cert_1, cert_2);
+ EXPECT_EQ(key_1, key_2);
+}
+
+TEST_F(WebRTCIdentityStoreTest, ConcurrentIdenticalRequestsJoined) {
+ bool completed_1 = false;
+ bool completed_2 = false;
+ std::string cert_1, cert_2, key_1, key_2;
+
+ base::Closure cancel_callback_1 = webrtc_identity_store_->RequestIdentity(
+ GURL(kFakeOrigin),
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ base::Bind(&OnRequestCompleted, &completed_1, &cert_1, &key_1));
+ ASSERT_FALSE(cancel_callback_1.is_null());
+
+ base::Closure cancel_callback_2 = webrtc_identity_store_->RequestIdentity(
+ GURL(kFakeOrigin),
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ base::Bind(&OnRequestCompleted, &completed_2, &cert_2, &key_2));
+ ASSERT_FALSE(cancel_callback_2.is_null());
+
+ RunUntilIdle();
+ EXPECT_TRUE(completed_1);
+ EXPECT_TRUE(completed_2);
+ EXPECT_EQ(cert_1, cert_2);
+ EXPECT_EQ(key_1, key_2);
+}
+
+TEST_F(WebRTCIdentityStoreTest, CancelOneOfIdenticalRequests) {
+ bool completed_1 = false;
+ bool completed_2 = false;
+ std::string cert_1, cert_2, key_1, key_2;
+
+ base::Closure cancel_callback_1 = webrtc_identity_store_->RequestIdentity(
+ GURL(kFakeOrigin),
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ base::Bind(&OnRequestCompleted, &completed_1, &cert_1, &key_1));
+ ASSERT_FALSE(cancel_callback_1.is_null());
+
+ base::Closure cancel_callback_2 = webrtc_identity_store_->RequestIdentity(
+ GURL(kFakeOrigin),
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ base::Bind(&OnRequestCompleted, &completed_2, &cert_2, &key_2));
+ ASSERT_FALSE(cancel_callback_2.is_null());
+
+ cancel_callback_1.Run();
+
+ RunUntilIdle();
+ EXPECT_FALSE(completed_1);
+ EXPECT_TRUE(completed_2);
+}
+
+TEST_F(WebRTCIdentityStoreTest, DeleteDataAndGenerateNewIdentity) {
+ bool completed_1 = false;
+ bool completed_2 = false;
+ std::string cert_1, cert_2, key_1, key_2;
+
+ // Generate the first identity.
+ base::Closure cancel_callback_1 =
+ RequestIdentityAndRunUtilIdle(kFakeOrigin,
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ &completed_1,
+ &cert_1,
+ &key_1);
+
+ // Clear the data and the second request should return a new identity.
+ webrtc_identity_store_->DeleteBetween(
+ base::Time(), base::Time::Now(), base::Bind(&base::DoNothing));
+ RunUntilIdle();
+
+ base::Closure cancel_callback_2 =
+ RequestIdentityAndRunUtilIdle(kFakeOrigin,
+ kFakeIdentityName1,
+ kFakeCommonName1,
+ &completed_2,
+ &cert_2,
+ &key_2);
+
+ EXPECT_TRUE(completed_1);
+ EXPECT_TRUE(completed_2);
+ EXPECT_NE(cert_1, cert_2);
+ EXPECT_NE(key_1, key_2);
+}
+
#endif
} // namespace content
diff --git a/content/browser/plugin_browsertest.cc b/content/browser/plugin_browsertest.cc
index ddb5683..c1dfa1f 100644
--- a/content/browser/plugin_browsertest.cc
+++ b/content/browser/plugin_browsertest.cc
@@ -15,7 +15,6 @@
#include "content/test/content_browser_test_utils.h"
#include "content/test/net/url_request_mock_http_job.h"
#include "ui/gfx/rect.h"
-#include "webkit/plugins/plugin_switches.h"
#if defined(OS_WIN)
#include "base/win/registry.h"
diff --git a/content/browser/plugin_data_remover_impl.cc b/content/browser/plugin_data_remover_impl.cc
index d711f80..670d80d 100644
--- a/content/browser/plugin_data_remover_impl.cc
+++ b/content/browser/plugin_data_remover_impl.cc
@@ -19,9 +19,9 @@
#include "content/common/plugin_process_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_constants.h"
#include "content/public/common/pepper_plugin_info.h"
#include "ppapi/proxy/ppapi_messages.h"
-#include "webkit/plugins/plugin_constants.h"
namespace content {
diff --git a/content/browser/plugin_service_impl.cc b/content/browser/plugin_service_impl.cc
index f596977..6682a4d 100644
--- a/content/browser/plugin_service_impl.cc
+++ b/content/browser/plugin_service_impl.cc
@@ -26,10 +26,10 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/plugin_service_filter.h"
#include "content/public/browser/resource_context.h"
+#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/process_type.h"
#include "content/public/common/webplugininfo.h"
-#include "webkit/plugins/plugin_constants.h"
#if defined(OS_WIN)
#include "content/common/plugin_constants_win.h"
diff --git a/content/browser/power_monitor_message_broadcaster_unittest.cc b/content/browser/power_monitor_message_broadcaster_unittest.cc
index 6eb0cb4..5155082 100644
--- a/content/browser/power_monitor_message_broadcaster_unittest.cc
+++ b/content/browser/power_monitor_message_broadcaster_unittest.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 "base/power_monitor/power_monitor_test_base.h"
+#include "base/test/power_monitor_test_base.h"
#include "content/browser/power_monitor_message_broadcaster.h"
#include "content/common/power_monitor_messages.h"
#include "ipc/ipc_sender.h"
diff --git a/content/browser/power_save_blocker_android.cc b/content/browser/power_save_blocker_android.cc
index 45dda18..720fbb2 100644
--- a/content/browser/power_save_blocker_android.cc
+++ b/content/browser/power_save_blocker_android.cc
@@ -5,23 +5,26 @@
#include "content/browser/power_save_blocker_android.h"
#include "base/android/jni_android.h"
+#include "base/android/jni_helper.h"
#include "base/logging.h"
#include "content/browser/power_save_blocker_impl.h"
+#include "content/public/browser/android/content_view_core.h"
#include "content/public/browser/browser_thread.h"
#include "jni/PowerSaveBlocker_jni.h"
-#include "ui/android/window_android.h"
+#include "ui/android/view_android.h"
using base::android::AttachCurrentThread;
using base::android::ScopedJavaLocalRef;
+using gfx::NativeView;
namespace content {
class PowerSaveBlockerImpl::Delegate
: public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> {
public:
- explicit Delegate(gfx::NativeWindow native_window) {
- j_window_android_ = JavaObjectWeakGlobalRef(AttachCurrentThread(),
- static_cast<ui::WindowAndroid*>(native_window)->GetJavaObject().obj());
+ explicit Delegate(NativeView view_android) {
+ j_view_android_ = JavaObjectWeakGlobalRef(
+ AttachCurrentThread(), view_android->GetJavaObject().obj());
}
// Does the actual work to apply or remove the desired power save block.
@@ -32,7 +35,7 @@
friend class base::RefCountedThreadSafe<Delegate>;
~Delegate() {}
- JavaObjectWeakGlobalRef j_window_android_;
+ JavaObjectWeakGlobalRef j_view_android_;
DISALLOW_COPY_AND_ASSIGN(Delegate);
};
@@ -40,7 +43,7 @@
void PowerSaveBlockerImpl::Delegate::ApplyBlock() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> j_object = j_window_android_.get(env);
+ ScopedJavaLocalRef<jobject> j_object = j_view_android_.get(env);
if (j_object.obj())
Java_PowerSaveBlocker_applyBlock(env, j_object.obj());
}
@@ -48,7 +51,7 @@
void PowerSaveBlockerImpl::Delegate::RemoveBlock() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> j_object = j_window_android_.get(env);
+ ScopedJavaLocalRef<jobject> j_object = j_view_android_.get(env);
if (j_object.obj())
Java_PowerSaveBlocker_removeBlock(env, j_object.obj());
}
@@ -66,9 +69,11 @@
}
}
-void PowerSaveBlockerImpl::InitDisplaySleepBlocker(
- gfx::NativeWindow native_window) {
- delegate_ = new Delegate(native_window);
+void PowerSaveBlockerImpl::InitDisplaySleepBlocker(NativeView view_android) {
+ if (!view_android)
+ return;
+
+ delegate_ = new Delegate(view_android);
// This may be called on any thread.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
diff --git a/content/browser/power_save_blocker_impl.h b/content/browser/power_save_blocker_impl.h
index c3a105d..948aced 100644
--- a/content/browser/power_save_blocker_impl.h
+++ b/content/browser/power_save_blocker_impl.h
@@ -17,11 +17,10 @@
virtual ~PowerSaveBlockerImpl();
#if defined(OS_ANDROID)
- // In Android platform, the |native_window| is needed to create the
- // kPowerSaveBlockPreventDisplaySleep type of PowerSaveBlocker
- // so the blocker could be removed by platform if the window isn't in the
- // foreground.
- void InitDisplaySleepBlocker(gfx::NativeWindow native_window);
+ // In Android platform, the kPowerSaveBlockPreventDisplaySleep type of
+ // PowerSaveBlocker should associated with the ViewAndroid,
+ // so the blocker could be removed by platform if the view isn't visble
+ void InitDisplaySleepBlocker(gfx::NativeView view_android);
#endif
private:
diff --git a/content/browser/ppapi_plugin_process_host.cc b/content/browser/ppapi_plugin_process_host.cc
index f440be4..c9aa699 100644
--- a/content/browser/ppapi_plugin_process_host.cc
+++ b/content/browser/ppapi_plugin_process_host.cc
@@ -25,7 +25,6 @@
#include "net/base/network_change_notifier.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ui/base/ui_base_switches.h"
-#include "webkit/plugins/plugin_switches.h"
#if defined(OS_WIN)
#include "content/common/sandbox_win.h"
diff --git a/content/browser/renderer_host/compositing_iosurface_mac.h b/content/browser/renderer_host/compositing_iosurface_mac.h
index 1b3ece3..674e4e5 100644
--- a/content/browser/renderer_host/compositing_iosurface_mac.h
+++ b/content/browser/renderer_host/compositing_iosurface_mac.h
@@ -203,6 +203,7 @@
void PrepareForAsynchronousReadback();
const scoped_ptr<CompositingIOSurfaceTransformer> transformer;
+ GLenum output_readback_format;
int num_outputs;
GLuint output_textures[3]; // Not owned.
// Note: For YUV, the |output_texture_sizes| widths are in terms of 4-byte
diff --git a/content/browser/renderer_host/compositing_iosurface_mac.mm b/content/browser/renderer_host/compositing_iosurface_mac.mm
index be99891..a9ca707 100644
--- a/content/browser/renderer_host/compositing_iosurface_mac.mm
+++ b/content/browser/renderer_host/compositing_iosurface_mac.mm
@@ -173,6 +173,7 @@
const scoped_refptr<CompositingIOSurfaceContext>& context)
: transformer(new CompositingIOSurfaceTransformer(
GL_TEXTURE_RECTANGLE_ARB, true, context->shader_program_cache())),
+ output_readback_format(GL_BGRA),
num_outputs(0),
fence(0),
cycles_elapsed(0) {
@@ -744,7 +745,13 @@
DCHECK_NE(bitmap_output != NULL, video_frame_output.get() != NULL);
DCHECK(!done_callback.is_null());
- const bool async_copy = IsAsynchronousReadbackSupported();
+ // SWIZZLE_RGBA_FOR_ASYNC_READPIXELS workaround: Fall-back to synchronous
+ // readback for SkBitmap output since the Blit shader program doesn't support
+ // switchable output formats.
+ const bool require_sync_copy_for_workaround = bitmap_output &&
+ context_->shader_program_cache()->rgb_to_yv12_output_format() == GL_RGBA;
+ const bool async_copy = !require_sync_copy_for_workaround &&
+ IsAsynchronousReadbackSupported();
TRACE_EVENT2(
"browser", "CompositingIOSurfaceMac::CopyToSelectedOutputWithinContext",
"output", bitmap_output ? "SkBitmap (ARGB)" : "VideoFrame (YV12)",
@@ -780,6 +787,7 @@
if (copy_context->transformer->ResizeBilinear(
texture_, src_rect, dst_pixel_rect.size(),
©_context->output_textures[0])) {
+ copy_context->output_readback_format = GL_BGRA;
copy_context->num_outputs = 1;
copy_context->output_texture_sizes[0] = dst_pixel_rect.size();
}
@@ -791,6 +799,8 @@
©_context->output_textures[2],
©_context->output_texture_sizes[0],
©_context->output_texture_sizes[1])) {
+ copy_context->output_readback_format =
+ context_->shader_program_cache()->rgb_to_yv12_output_format();
copy_context->num_outputs = 3;
copy_context->output_texture_sizes[2] =
copy_context->output_texture_sizes[1];
@@ -851,7 +861,8 @@
glReadPixels(0, 0,
copy_context->output_texture_sizes[i].width(),
copy_context->output_texture_sizes[i].height(),
- GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
+ copy_context->output_readback_format,
+ GL_UNSIGNED_INT_8_8_8_8_REV, 0);
CHECK_AND_SAVE_GL_ERROR();
}
@@ -993,8 +1004,9 @@
glReadPixels(0, 0,
copy_context->output_texture_sizes[i].width(),
copy_context->output_texture_sizes[i].height(),
- GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
- buf); CHECK_AND_SAVE_GL_ERROR();
+ copy_context->output_readback_format,
+ GL_UNSIGNED_INT_8_8_8_8_REV, buf);
+ CHECK_AND_SAVE_GL_ERROR();
if (video_frame_output.get()) {
if (!temp_readback_buffer) {
// Apply letterbox black-out around view region.
diff --git a/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc b/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc
index 12988a1..87f0f34 100644
--- a/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc
+++ b/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc
@@ -11,18 +11,27 @@
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "content/browser/gpu/gpu_data_manager_impl.h"
+#include "gpu/config/gpu_driver_bug_workaround_type.h"
namespace content {
namespace {
// Convenience macro allowing GLSL programs to be specified inline, and to be
-// automatically converted into string form by the C preprocessor. As required
-// by the spec, add the version directive to the beginning of each program to
-// activate the expected syntax and built-in features. GLSL version 1.2 is the
-// latest version supported by MacOS 10.6.
-#define GLSL_PROGRAM_AS_STRING(shader_code) "#version 120\n" #shader_code
+// automatically converted into string form by the C preprocessor.
+#define GLSL_PROGRAM_AS_STRING(shader_code) #shader_code
+// As required by the spec, add the version directive to the beginning of each
+// program to activate the expected syntax and built-in features. GLSL version
+// 1.2 is the latest version supported by MacOS 10.6.
+const char kVersionDirective[] = "#version 120\n";
+
+// Allow switchable output swizzling from RGBToYV12 fragment shaders (needed for
+// workaround; see comments in CompositingIOSurfaceShaderPrograms ctor).
+const char kOutputSwizzleMacroNormal[] = "#define OUTPUT_PIXEL_ORDERING bgra\n";
+const char kOutputSwizzleMacroSwapRB[] = "#define OUTPUT_PIXEL_ORDERING rgba\n";
// Only the bare-bones calculations here for speed.
const char kvsBlit[] = GLSL_PROGRAM_AS_STRING(
@@ -144,8 +153,7 @@
vec2 vv = vec2(dot(blended_pixel0, rgb_to_v),
dot(blended_pixel1, rgb_to_v)) / 2.0;
- // Note: Packaging the result to account for BGRA byte ordering.
- gl_FragData[0] = yyyy.bgra;
+ gl_FragData[0] = yyyy.OUTPUT_PIXEL_ORDERING;
gl_FragData[1] = vec4(uu, vv) + uv_bias;
}
);
@@ -178,9 +186,8 @@
// sampler takes care of that.
vec4 lo_uuvv = texture2DRect(texture_, texture_coord0);
vec4 hi_uuvv = texture2DRect(texture_, texture_coord1);
- // Note: Packaging the result to account for BGRA byte ordering.
- gl_FragData[0] = vec4(lo_uuvv.rg, hi_uuvv.rg).bgra;
- gl_FragData[1] = vec4(lo_uuvv.ba, hi_uuvv.ba).bgra;
+ gl_FragData[0] = vec4(lo_uuvv.rg, hi_uuvv.rg).OUTPUT_PIXEL_ORDERING;
+ gl_FragData[1] = vec4(lo_uuvv.ba, hi_uuvv.ba).OUTPUT_PIXEL_ORDERING;
}
);
@@ -219,7 +226,8 @@
kRGBtoYV12_fsConvertUV44toU2V2,
};
-GLuint CompileShaderGLSL(ShaderProgram shader_program, GLenum shader_type) {
+GLuint CompileShaderGLSL(ShaderProgram shader_program, GLenum shader_type,
+ bool output_swap_rb) {
TRACE_EVENT2("gpu", "CompileShaderGLSL",
"program", shader_program,
"type", shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment");
@@ -231,11 +239,21 @@
DCHECK_NE(shader, 0u);
// Select and compile the shader program source code.
- glShaderSource(shader,
- 1,
- (shader_type == GL_VERTEX_SHADER ? kVertexShaderSourceCodeMap :
- kFragmentShaderSourceCodeMap) + shader_program,
- NULL);
+ if (shader_type == GL_VERTEX_SHADER) {
+ const GLchar* source_snippets[] = {
+ kVersionDirective,
+ kVertexShaderSourceCodeMap[shader_program],
+ };
+ glShaderSource(shader, arraysize(source_snippets), source_snippets, NULL);
+ } else {
+ DCHECK(shader_type == GL_FRAGMENT_SHADER);
+ const GLchar* source_snippets[] = {
+ kVersionDirective,
+ output_swap_rb ? kOutputSwizzleMacroSwapRB : kOutputSwizzleMacroNormal,
+ kFragmentShaderSourceCodeMap[shader_program],
+ };
+ glShaderSource(shader, arraysize(source_snippets), source_snippets, NULL);
+ }
glCompileShader(shader);
// Check for successful compilation. On error in debug builds, pull the info
@@ -265,12 +283,14 @@
return shader;
}
-GLuint CompileAndLinkProgram(ShaderProgram which) {
+GLuint CompileAndLinkProgram(ShaderProgram which, bool output_swap_rb) {
TRACE_EVENT1("gpu", "CompileAndLinkProgram", "program", which);
// Compile and link a new shader program.
- const GLuint vertex_shader = CompileShaderGLSL(which, GL_VERTEX_SHADER);
- const GLuint fragment_shader = CompileShaderGLSL(which, GL_FRAGMENT_SHADER);
+ const GLuint vertex_shader =
+ CompileShaderGLSL(which, GL_VERTEX_SHADER, false);
+ const GLuint fragment_shader =
+ CompileShaderGLSL(which, GL_FRAGMENT_SHADER, output_swap_rb);
const GLuint program = glCreateProgram();
DCHECK_NE(program, 0u);
glAttachShader(program, vertex_shader);
@@ -295,7 +315,8 @@
} // namespace
-CompositingIOSurfaceShaderPrograms::CompositingIOSurfaceShaderPrograms() {
+CompositingIOSurfaceShaderPrograms::CompositingIOSurfaceShaderPrograms()
+ : rgb_to_yv12_output_format_(GL_BGRA) {
COMPILE_ASSERT(kNumShaderPrograms == NUM_SHADER_PROGRAMS,
header_constant_disagrees_with_enum);
COMPILE_ASSERT(arraysize(kVertexShaderSourceCodeMap) == NUM_SHADER_PROGRAMS,
@@ -308,6 +329,22 @@
texture_var_locations_[i] = -1;
for (size_t i = 0; i < arraysize(texel_scale_x_var_locations_); ++i)
texel_scale_x_var_locations_[i] = -1;
+
+ // Look for the swizzle_rgba_for_async_readpixels driver bug workaround and
+ // modify rgb_to_yv12_output_format_ if necessary.
+ // See: http://crbug.com/265115
+ GpuDataManagerImpl* const manager = GpuDataManagerImpl::GetInstance();
+ if (manager) {
+ base::ListValue workarounds;
+ manager->GetDriverBugWorkarounds(&workarounds);
+ base::ListValue::const_iterator it = workarounds.Find(
+ base::StringValue(gpu::GpuDriverBugWorkaroundTypeToString(
+ gpu::SWIZZLE_RGBA_FOR_ASYNC_READPIXELS)));
+ if (it != workarounds.end())
+ rgb_to_yv12_output_format_ = GL_RGBA;
+ }
+ DVLOG(1) << "Using RGBToYV12 fragment shader output format: "
+ << (rgb_to_yv12_output_format_ == GL_BGRA ? "BGRA" : "RGBA");
}
CompositingIOSurfaceShaderPrograms::~CompositingIOSurfaceShaderPrograms() {
@@ -371,10 +408,17 @@
return true;
}
+void CompositingIOSurfaceShaderPrograms::SetOutputFormatForTesting(
+ GLenum format) {
+ rgb_to_yv12_output_format_ = format;
+ Reset();
+}
+
GLuint CompositingIOSurfaceShaderPrograms::GetShaderProgram(int which) {
if (shader_programs_[which] == 0u) {
shader_programs_[which] =
- CompileAndLinkProgram(static_cast<ShaderProgram>(which));
+ CompileAndLinkProgram(static_cast<ShaderProgram>(which),
+ rgb_to_yv12_output_format_ == GL_RGBA);
DCHECK_NE(shader_programs_[which], 0u)
<< "Failed to create ShaderProgram " << which;
}
diff --git a/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h b/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h
index 152858c..de1987f 100644
--- a/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h
+++ b/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h
@@ -8,13 +8,16 @@
#include <OpenGL/gl.h>
#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
namespace content {
// Provides caching of the compile-and-link step for shader programs at runtime
// since, once compiled and linked, the programs can be shared. Callers invoke
-// one of the UseXXX() methods within a GL context to glUseProgram() the program
-// and have its uniform variables bound with the given parameters.
+// one of the UseXXX() methods to glUseProgram() the program and have its
+// uniform variables bound with the given parameters.
+//
+// Note: All public methods must be invoked within the the same GL context!
class CompositingIOSurfaceShaderPrograms {
public:
CompositingIOSurfaceShaderPrograms();
@@ -39,6 +42,19 @@
// Returns false on error.
bool UseRGBToYV12Program(int pass_number, float texel_scale_x);
+ // |format| argument to use for glReadPixels() when reading back textures
+ // generated by the RGBToYV12 program.
+ GLenum rgb_to_yv12_output_format() const {
+ return rgb_to_yv12_output_format_;
+ }
+
+ protected:
+ FRIEND_TEST_ALL_PREFIXES(CompositingIOSurfaceTransformerTest,
+ TransformsRGBToYV12);
+
+ // Side effect: Calls Reset(), deleting any cached programs.
+ void SetOutputFormatForTesting(GLenum format);
+
private:
enum { kNumShaderPrograms = 4 };
@@ -53,6 +69,10 @@
GLint texture_var_locations_[kNumShaderPrograms];
GLint texel_scale_x_var_locations_[kNumShaderPrograms];
+ // Byte order of the quads generated by the RGBToYV12 shader program. Must
+ // always be GL_BGRA (default) or GL_RGBA (workaround case).
+ GLenum rgb_to_yv12_output_format_;
+
DISALLOW_COPY_AND_ASSIGN(CompositingIOSurfaceShaderPrograms);
};
diff --git a/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc b/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc
index 6f2562c..7d9452f 100644
--- a/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc
+++ b/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc
@@ -144,7 +144,7 @@
}
// Read back a texture from the GPU, returning the image data as an SkBitmap.
-SkBitmap ReadBackTexture(GLuint texture, const gfx::Size& size) {
+SkBitmap ReadBackTexture(GLuint texture, const gfx::Size& size, GLenum format) {
SkBitmap result;
result.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
CHECK(result.allocPixels());
@@ -162,7 +162,7 @@
{
SkAutoLockPixels lock_result(result);
EXPECT_NO_GL_ERROR(glReadPixels(
- 0, 0, size.width(), size.height(), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
+ 0, 0, size.width(), size.height(), format, GL_UNSIGNED_INT_8_8_8_8_REV,
result.getPixels()));
}
@@ -303,7 +303,8 @@
original_texture, src_rect, dst_size, &scaled_texture));
EXPECT_NE(0u, scaled_texture);
CGLFlushDrawable(context_); // Account for some buggy driver impls.
- const SkBitmap result_bitmap = ReadBackTexture(scaled_texture, dst_size);
+ const SkBitmap result_bitmap =
+ ReadBackTexture(scaled_texture, dst_size, GL_BGRA);
EXPECT_NO_GL_ERROR(glDeleteTextures(1, &original_texture));
// Compare the image read back to the version produced by a known-working
@@ -344,9 +345,13 @@
// Read-back the texture for each plane.
CGLFlushDrawable(context_); // Account for some buggy driver impls.
- const SkBitmap result_y_bitmap = ReadBackTexture(texture_y, packed_y_size);
- const SkBitmap result_u_bitmap = ReadBackTexture(texture_u, packed_uv_size);
- const SkBitmap result_v_bitmap = ReadBackTexture(texture_v, packed_uv_size);
+ const GLenum format = shader_program_cache_->rgb_to_yv12_output_format();
+ const SkBitmap result_y_bitmap =
+ ReadBackTexture(texture_y, packed_y_size, format);
+ const SkBitmap result_u_bitmap =
+ ReadBackTexture(texture_u, packed_uv_size, format);
+ const SkBitmap result_v_bitmap =
+ ReadBackTexture(texture_v, packed_uv_size, format);
// Compare the Y, U, and V planes read-back to the version produced by a
// known-working software implementation. Allow up to 2 lines of mismatch
@@ -485,35 +490,43 @@
}
TEST_F(CompositingIOSurfaceTransformerTest, TransformsRGBToYV12) {
- for (size_t i = 0; i < arraysize(kTestParameters); ++i) {
- SCOPED_TRACE(::testing::Message() << "kTestParameters[" << i << ']');
+ static const GLenum kOutputFormats[] = { GL_BGRA, GL_RGBA };
- const TestParameters& params = kTestParameters[i];
- const gfx::Size src_size(params.src_width, params.src_height);
- const gfx::Size dst_size(params.scaled_width, params.scaled_height);
- const SkBitmap src_bitmap = GenerateTestPatternBitmap(src_size);
+ for (size_t i = 0; i < arraysize(kOutputFormats); ++i) {
+ SCOPED_TRACE(::testing::Message() << "kOutputFormats[" << i << ']');
- // Full texture resize test.
- RunTransformRGBToYV12Test(src_bitmap, gfx::Rect(src_size), dst_size);
- // Subrect resize test: missing top row in source.
- RunTransformRGBToYV12Test(
- src_bitmap, gfx::Rect(0, 1, params.src_width, params.src_height - 1),
- dst_size);
- // Subrect resize test: missing left column in source.
- RunTransformRGBToYV12Test(
- src_bitmap, gfx::Rect(1, 0, params.src_width - 1, params.src_height),
- dst_size);
- // Subrect resize test: missing top+bottom rows, and left column in
- // source.
- RunTransformRGBToYV12Test(
- src_bitmap,
- gfx::Rect(1, 1, params.src_width - 1, params.src_height - 2),
- dst_size);
- // Subrect resize test: missing top row, and left+right columns in source.
- RunTransformRGBToYV12Test(
- src_bitmap,
- gfx::Rect(1, 1, params.src_width - 2, params.src_height - 1),
- dst_size);
+ shader_program_cache()->SetOutputFormatForTesting(kOutputFormats[i]);
+
+ for (size_t j = 0; j < arraysize(kTestParameters); ++j) {
+ SCOPED_TRACE(::testing::Message() << "kTestParameters[" << j << ']');
+
+ const TestParameters& params = kTestParameters[j];
+ const gfx::Size src_size(params.src_width, params.src_height);
+ const gfx::Size dst_size(params.scaled_width, params.scaled_height);
+ const SkBitmap src_bitmap = GenerateTestPatternBitmap(src_size);
+
+ // Full texture resize test.
+ RunTransformRGBToYV12Test(src_bitmap, gfx::Rect(src_size), dst_size);
+ // Subrect resize test: missing top row in source.
+ RunTransformRGBToYV12Test(
+ src_bitmap, gfx::Rect(0, 1, params.src_width, params.src_height - 1),
+ dst_size);
+ // Subrect resize test: missing left column in source.
+ RunTransformRGBToYV12Test(
+ src_bitmap, gfx::Rect(1, 0, params.src_width - 1, params.src_height),
+ dst_size);
+ // Subrect resize test: missing top+bottom rows, and left column in
+ // source.
+ RunTransformRGBToYV12Test(
+ src_bitmap,
+ gfx::Rect(1, 1, params.src_width - 1, params.src_height - 2),
+ dst_size);
+ // Subrect resize test: missing top row, and left+right columns in source.
+ RunTransformRGBToYV12Test(
+ src_bitmap,
+ gfx::Rect(1, 1, params.src_width - 2, params.src_height - 1),
+ dst_size);
+ }
}
}
diff --git a/content/browser/renderer_host/input/gesture_event_filter.cc b/content/browser/renderer_host/input/gesture_event_filter.cc
index bbc01db..c2ff887 100644
--- a/content/browser/renderer_host/input/gesture_event_filter.cc
+++ b/content/browser/renderer_host/input/gesture_event_filter.cc
@@ -75,10 +75,10 @@
GestureEventFilter::~GestureEventFilter() { }
bool GestureEventFilter::ShouldDiscardFlingCancelEvent(
- const GestureEventWithLatencyInfo& gesture_event) {
+ const GestureEventWithLatencyInfo& gesture_event) const {
if (coalesced_gesture_events_.empty() && fling_in_progress_)
return false;
- GestureEventQueue::reverse_iterator it =
+ GestureEventQueue::const_reverse_iterator it =
coalesced_gesture_events_.rbegin();
while (it != coalesced_gesture_events_.rend()) {
if (it->event.type == WebInputEvent::GestureFlingStart)
@@ -138,7 +138,7 @@
}
bool GestureEventFilter::ShouldForwardForZeroVelocityFlingStart(
- const GestureEventWithLatencyInfo& gesture_event) {
+ const GestureEventWithLatencyInfo& gesture_event) const {
return gesture_event.event.type != WebInputEvent::GestureFlingStart ||
gesture_event.event.sourceDevice != WebGestureEvent::Touchpad ||
gesture_event.event.data.flingStart.velocityX != 0 ||
@@ -146,7 +146,7 @@
}
bool GestureEventFilter::ShouldForwardForGFCFiltering(
- const GestureEventWithLatencyInfo& gesture_event) {
+ const GestureEventWithLatencyInfo& gesture_event) const {
return gesture_event.event.type != WebInputEvent::GestureFlingCancel ||
!ShouldDiscardFlingCancelEvent(gesture_event);
}
@@ -301,7 +301,7 @@
fling_in_progress_ = false;
}
-bool GestureEventFilter::ShouldHandleEventNow() {
+bool GestureEventFilter::ShouldHandleEventNow() const {
return coalesced_gesture_events_.size() == 1;
}
@@ -328,7 +328,7 @@
void GestureEventFilter::SendScrollEndingEventsNow() {
scrolling_in_progress_ = false;
- for (GestureEventQueue::iterator it =
+ for (GestureEventQueue::const_iterator it =
debouncing_deferral_queue_.begin();
it != debouncing_deferral_queue_.end(); it++) {
if (ShouldForwardForGFCFiltering(*it) &&
@@ -407,7 +407,7 @@
bool GestureEventFilter::ShouldTryMerging(
const GestureEventWithLatencyInfo& new_event,
- const GestureEventWithLatencyInfo& event_in_queue) {
+ const GestureEventWithLatencyInfo& event_in_queue) const {
DLOG_IF(WARNING,
new_event.event.timeStampSeconds <
event_in_queue.event.timeStampSeconds)
@@ -418,7 +418,7 @@
}
gfx::Transform GestureEventFilter::GetTransformForEvent(
- const GestureEventWithLatencyInfo& gesture_event) {
+ const GestureEventWithLatencyInfo& gesture_event) const {
gfx::Transform gesture_transform = gfx::Transform();
if (gesture_event.event.type == WebInputEvent::GestureScrollUpdate) {
gesture_transform.Translate(gesture_event.event.data.scrollUpdate.deltaX,
diff --git a/content/browser/renderer_host/input/gesture_event_filter.h b/content/browser/renderer_host/input/gesture_event_filter.h
index c4dd911..b0c3782 100644
--- a/content/browser/renderer_host/input/gesture_event_filter.h
+++ b/content/browser/renderer_host/input/gesture_event_filter.h
@@ -96,11 +96,11 @@
// Returns |true| if the given GestureFlingCancel should be discarded
// as unnecessary.
bool ShouldDiscardFlingCancelEvent(
- const GestureEventWithLatencyInfo& gesture_event);
+ const GestureEventWithLatencyInfo& gesture_event) const;
// Returns |true| if the only event in the queue is the current event and
// hence that event should be handled now.
- bool ShouldHandleEventNow();
+ bool ShouldHandleEventNow() const;
// Merge or append a GestureScrollUpdate or GesturePinchUpdate into
// the coalescing queue.
@@ -109,7 +109,7 @@
// Sub-filter for removing zero-velocity fling-starts from touchpad.
bool ShouldForwardForZeroVelocityFlingStart(
- const GestureEventWithLatencyInfo& gesture_event);
+ const GestureEventWithLatencyInfo& gesture_event) const;
// Sub-filter for removing bounces from in-progress scrolls.
bool ShouldForwardForBounceReduction(
@@ -117,7 +117,7 @@
// Sub-filter for removing unnecessary GestureFlingCancels.
bool ShouldForwardForGFCFiltering(
- const GestureEventWithLatencyInfo& gesture_event);
+ const GestureEventWithLatencyInfo& gesture_event) const;
// Sub-filter for suppressing taps immediately after a GestureFlingCancel.
bool ShouldForwardForTapSuppression(
@@ -136,14 +136,15 @@
// Whether the event_in_queue is GesturePinchUpdate or
// GestureScrollUpdate and it has the same modifiers as the
// new event.
- bool ShouldTryMerging(const GestureEventWithLatencyInfo& new_event,
- const GestureEventWithLatencyInfo& event_in_queue);
+ bool ShouldTryMerging(
+ const GestureEventWithLatencyInfo& new_event,
+ const GestureEventWithLatencyInfo& event_in_queue)const;
// Returns the transform matrix corresponding to the gesture event.
// Assumes the gesture event sent is either GestureScrollUpdate or
// GesturePinchUpdate. Returns the identity matrix otherwise.
gfx::Transform GetTransformForEvent(
- const GestureEventWithLatencyInfo& gesture_event);
+ const GestureEventWithLatencyInfo& gesture_event) const;
// The receiver of all forwarded gesture events.
InputRouter* input_router_;
diff --git a/content/browser/renderer_host/media/OWNERS b/content/browser/renderer_host/media/OWNERS
index 084677c..45ac661 100644
--- a/content/browser/renderer_host/media/OWNERS
+++ b/content/browser/renderer_host/media/OWNERS
@@ -22,5 +22,5 @@
per-file video_capture_oracle*=nick@chromium.org
# Screen capture OWNERS.
-per-file screen_capture_*=sergeyu@chromium.org
-per-file screen_capture_*=wez@chromium.org
\ No newline at end of file
+per-file desktop_capture_*=sergeyu@chromium.org
+per-file desktop_capture_*=wez@chromium.org
diff --git a/content/browser/renderer_host/media/screen_capture_device.cc b/content/browser/renderer_host/media/desktop_capture_device.cc
similarity index 68%
rename from content/browser/renderer_host/media/screen_capture_device.cc
rename to content/browser/renderer_host/media/desktop_capture_device.cc
index 3edd6cc..5a03e46 100644
--- a/content/browser/renderer_host/media/screen_capture_device.cc
+++ b/content/browser/renderer_host/media/desktop_capture_device.cc
@@ -2,18 +2,23 @@
// 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/media/screen_capture_device.h"
+#include "content/browser/renderer_host/media/desktop_capture_device.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/sequenced_task_runner.h"
+#include "base/strings/string_number_conversions.h"
#include "base/synchronization/lock.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/desktop_media_id.h"
#include "media/base/video_util.h"
#include "third_party/libyuv/include/libyuv/scale_argb.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
-#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_shape.h"
#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
+#include "third_party/webrtc/modules/desktop_capture/window_capturer.h"
namespace content {
@@ -21,16 +26,12 @@
const int kBytesPerPixel = 4;
} // namespace
-class ScreenCaptureDevice::Core
+class DesktopCaptureDevice::Core
: public base::RefCountedThreadSafe<Core>,
public webrtc::DesktopCapturer::Callback {
public:
- explicit Core(scoped_refptr<base::SequencedTaskRunner> task_runner);
-
- // Helper used in tests to supply a fake capturer.
- void SetScreenCapturerForTest(scoped_ptr<webrtc::ScreenCapturer> capturer) {
- screen_capturer_ = capturer.Pass();
- }
+ Core(scoped_refptr<base::SequencedTaskRunner> task_runner,
+ scoped_ptr<webrtc::DesktopCapturer> capturer);
// Implementation of VideoCaptureDevice methods.
void Allocate(int width, int height,
@@ -59,15 +60,18 @@
void ScheduleCaptureTimer();
// Method that is scheduled on |task_runner_| to be called on regular interval
- // to capture the screen.
+ // to capture a frame.
void OnCaptureTimer();
// Captures a single frame.
void DoCapture();
- // Task runner used for screen capturing operations.
+ // Task runner used for capturing operations.
scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ // The underlying DesktopCapturer instance used to capture frames.
+ scoped_ptr<webrtc::DesktopCapturer> desktop_capturer_;
+
// |event_handler_lock_| must be locked whenever |event_handler_| is used.
// It's necessary because DeAllocate() needs to reset it on the calling thread
// to ensure that the event handler is not called once DeAllocate() returns.
@@ -80,9 +84,6 @@
// Frame rate specified to Allocate().
int frame_rate_;
- // The underlying ScreenCapturer instance used to capture frames.
- scoped_ptr<webrtc::ScreenCapturer> screen_capturer_;
-
// Empty until the first frame has been captured, and the output dimensions
// chosen based on the capture frame's size, and any caller-supplied
// size constraints.
@@ -104,25 +105,27 @@
// |task_runner_|.
bool capture_task_posted_;
- // True when waiting for |screen_capturer_| to capture current frame.
+ // True when waiting for |desktop_capturer_| to capture current frame.
bool capture_in_progress_;
DISALLOW_COPY_AND_ASSIGN(Core);
};
-ScreenCaptureDevice::Core::Core(
- scoped_refptr<base::SequencedTaskRunner> task_runner)
+DesktopCaptureDevice::Core::Core(
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ scoped_ptr<webrtc::DesktopCapturer> capturer)
: task_runner_(task_runner),
+ desktop_capturer_(capturer.Pass()),
event_handler_(NULL),
started_(false),
capture_task_posted_(false),
capture_in_progress_(false) {
}
-ScreenCaptureDevice::Core::~Core() {
+DesktopCaptureDevice::Core::~Core() {
}
-void ScreenCaptureDevice::Core::Allocate(int width, int height,
+void DesktopCaptureDevice::Core::Allocate(int width, int height,
int frame_rate,
EventHandler* event_handler) {
DCHECK_GT(width, 0);
@@ -139,17 +142,17 @@
base::Bind(&Core::DoAllocate, this, width, height, frame_rate));
}
-void ScreenCaptureDevice::Core::Start() {
+void DesktopCaptureDevice::Core::Start() {
task_runner_->PostTask(
FROM_HERE, base::Bind(&Core::DoStart, this));
}
-void ScreenCaptureDevice::Core::Stop() {
+void DesktopCaptureDevice::Core::Stop() {
task_runner_->PostTask(
FROM_HERE, base::Bind(&Core::DoStop, this));
}
-void ScreenCaptureDevice::Core::DeAllocate() {
+void DesktopCaptureDevice::Core::DeAllocate() {
{
base::AutoLock auto_lock(event_handler_lock_);
event_handler_ = NULL;
@@ -158,11 +161,11 @@
}
webrtc::SharedMemory*
-ScreenCaptureDevice::Core::CreateSharedMemory(size_t size) {
+DesktopCaptureDevice::Core::CreateSharedMemory(size_t size) {
return NULL;
}
-void ScreenCaptureDevice::Core::OnCaptureCompleted(
+void DesktopCaptureDevice::Core::OnCaptureCompleted(
webrtc::DesktopFrame* frame) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
DCHECK(capture_in_progress_);
@@ -257,41 +260,23 @@
}
}
-void ScreenCaptureDevice::Core::DoAllocate(int width,
- int height,
- int frame_rate) {
+void DesktopCaptureDevice::Core::DoAllocate(int width,
+ int height,
+ int frame_rate) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(desktop_capturer_);
requested_size_.set(width, height);
output_size_.set(0, 0);
frame_rate_ = frame_rate;
- // Create and start frame capturer.
- if (!screen_capturer_) {
-#if defined(OS_CHROMEOS) && !defined(ARCH_CPU_ARMEL) && defined(USE_X11)
- // ScreenCapturerX11 polls by default, due to poor driver support for
- // DAMAGE. ChromeOS' drivers [can be patched to] support DAMAGE properly, so
- // use it. However ARM driver seems to not support this properly, so disable
- // it for ARM. See http://crbug.com/230105.
- screen_capturer_.reset(webrtc::ScreenCapturer::CreateWithXDamage(true));
-#elif defined(OS_WIN)
- // ScreenCapturerWin disables Aero by default. We don't want it disabled for
- // WebRTC screen capture, though.
- screen_capturer_.reset(
- webrtc::ScreenCapturer::CreateWithDisableAero(false));
-#else
- screen_capturer_.reset(webrtc::ScreenCapturer::Create());
-#endif
- }
-
- if (screen_capturer_)
- screen_capturer_->Start(this);
+ desktop_capturer_->Start(this);
// Capture first frame, so that we can call OnFrameInfo() callback.
DoCapture();
}
-void ScreenCaptureDevice::Core::DoStart() {
+void DesktopCaptureDevice::Core::DoStart() {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
started_ = true;
if (!capture_task_posted_) {
@@ -300,20 +285,20 @@
}
}
-void ScreenCaptureDevice::Core::DoStop() {
+void DesktopCaptureDevice::Core::DoStop() {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
started_ = false;
scaled_frame_.reset();
}
-void ScreenCaptureDevice::Core::DoDeAllocate() {
+void DesktopCaptureDevice::Core::DoDeAllocate() {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
DoStop();
- screen_capturer_.reset();
+ desktop_capturer_.reset();
output_size_.set(0, 0);
}
-void ScreenCaptureDevice::Core::ScheduleCaptureTimer() {
+void DesktopCaptureDevice::Core::ScheduleCaptureTimer() {
DCHECK(!capture_task_posted_);
capture_task_posted_ = true;
task_runner_->PostDelayedTask(
@@ -321,7 +306,7 @@
base::TimeDelta::FromSeconds(1) / frame_rate_);
}
-void ScreenCaptureDevice::Core::OnCaptureTimer() {
+void DesktopCaptureDevice::Core::OnCaptureTimer() {
DCHECK(capture_task_posted_);
capture_task_posted_ = false;
@@ -333,33 +318,81 @@
DoCapture();
}
-void ScreenCaptureDevice::Core::DoCapture() {
+void DesktopCaptureDevice::Core::DoCapture() {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
DCHECK(!capture_in_progress_);
capture_in_progress_ = true;
- screen_capturer_->Capture(webrtc::DesktopRegion());
+ desktop_capturer_->Capture(webrtc::DesktopRegion());
// Currently only synchronous implementations of DesktopCapturer are
// supported.
DCHECK(!capture_in_progress_);
}
-ScreenCaptureDevice::ScreenCaptureDevice(
- scoped_refptr<base::SequencedTaskRunner> task_runner)
- : core_(new Core(task_runner)), name_("Screen", "Screen") {
+// static
+scoped_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
+ const DesktopMediaID& source) {
+ scoped_refptr<base::SequencedWorkerPool> blocking_pool =
+ BrowserThread::GetBlockingPool();
+ scoped_refptr<base::SequencedTaskRunner> task_runner =
+ blocking_pool->GetSequencedTaskRunner(
+ blocking_pool->GetSequenceToken());
+
+ switch (source.type) {
+ case DesktopMediaID::TYPE_SCREEN: {
+ scoped_ptr<webrtc::DesktopCapturer> capturer;
+
+#if defined(OS_CHROMEOS) && !defined(ARCH_CPU_ARMEL) && defined(USE_X11)
+ // ScreenCapturerX11 polls by default, due to poor driver support for
+ // DAMAGE. ChromeOS' drivers [can be patched to] support DAMAGE properly,
+ // so use it. However ARM driver seems to not support this properly, so
+ // disable it for ARM. See http://crbug.com/230105 .
+ capturer.reset(webrtc::ScreenCapturer::CreateWithXDamage(true));
+#elif defined(OS_WIN)
+ // ScreenCapturerWin disables Aero by default. We don't want it disabled
+ // for WebRTC screen capture, though.
+ capturer.reset(
+ webrtc::ScreenCapturer::CreateWithDisableAero(false));
+#else
+ capturer.reset(webrtc::ScreenCapturer::Create());
+#endif
+
+ return scoped_ptr<media::VideoCaptureDevice>(new DesktopCaptureDevice(
+ task_runner, capturer.Pass()));
+ }
+
+ case DesktopMediaID::TYPE_WINDOW: {
+ scoped_ptr<webrtc::WindowCapturer> capturer(
+ webrtc::WindowCapturer::Create());
+
+ if (!capturer || !capturer->SelectWindow(source.id)) {
+ return scoped_ptr<media::VideoCaptureDevice>();
+ }
+
+ return scoped_ptr<media::VideoCaptureDevice>(new DesktopCaptureDevice(
+ task_runner, capturer.PassAs<webrtc::DesktopCapturer>()));
+ }
+
+ default: {
+ NOTREACHED();
+ return scoped_ptr<media::VideoCaptureDevice>();
+ }
+ }
}
-ScreenCaptureDevice::~ScreenCaptureDevice() {
+DesktopCaptureDevice::DesktopCaptureDevice(
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ scoped_ptr<webrtc::DesktopCapturer> capturer)
+ : core_(new Core(task_runner, capturer.Pass())),
+ name_("", "") {
+}
+
+DesktopCaptureDevice::~DesktopCaptureDevice() {
DeAllocate();
}
-void ScreenCaptureDevice::SetScreenCapturerForTest(
- scoped_ptr<webrtc::ScreenCapturer> capturer) {
- core_->SetScreenCapturerForTest(capturer.Pass());
-}
-
-void ScreenCaptureDevice::Allocate(
+void DesktopCaptureDevice::Allocate(
const media::VideoCaptureCapability& capture_format,
EventHandler* observer) {
core_->Allocate(capture_format.width,
@@ -368,19 +401,19 @@
observer);
}
-void ScreenCaptureDevice::Start() {
+void DesktopCaptureDevice::Start() {
core_->Start();
}
-void ScreenCaptureDevice::Stop() {
+void DesktopCaptureDevice::Stop() {
core_->Stop();
}
-void ScreenCaptureDevice::DeAllocate() {
+void DesktopCaptureDevice::DeAllocate() {
core_->DeAllocate();
}
-const media::VideoCaptureDevice::Name& ScreenCaptureDevice::device_name() {
+const media::VideoCaptureDevice::Name& DesktopCaptureDevice::device_name() {
return name_;
}
diff --git a/content/browser/renderer_host/media/desktop_capture_device.h b/content/browser/renderer_host/media/desktop_capture_device.h
new file mode 100644
index 0000000..84422d3
--- /dev/null
+++ b/content/browser/renderer_host/media/desktop_capture_device.h
@@ -0,0 +1,58 @@
+// 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 CONTENT_BROWSER_RENDERER_HOST_MEDIA_DESKTOP_CAPTURE_DEVICE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_DESKTOP_CAPTURE_DEVICE_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "media/video/capture/video_capture_device.h"
+
+namespace base {
+class SequencedTaskRunner;
+} // namespace base
+
+namespace webrtc {
+class DesktopCapturer;
+} // namespace webrtc
+
+namespace content {
+
+struct DesktopMediaID;
+
+// DesktopCaptureDevice implements VideoCaptureDevice for screens and windows.
+// It's essentially an adapter between webrtc::DesktopCapturer and
+// VideoCaptureDevice.
+class CONTENT_EXPORT DesktopCaptureDevice : public media::VideoCaptureDevice {
+ public:
+ // Creates capturer for the specified |source| and then creates
+ // DesktopCaptureDevice for it. May return NULL in case of a failure (e.g. if
+ // requested window was destroyed).
+ static scoped_ptr<media::VideoCaptureDevice> Create(
+ const DesktopMediaID& source);
+
+ DesktopCaptureDevice(scoped_refptr<base::SequencedTaskRunner> task_runner,
+ scoped_ptr<webrtc::DesktopCapturer> desktop_capturer);
+ virtual ~DesktopCaptureDevice();
+
+ // VideoCaptureDevice interface.
+ virtual void Allocate(const media::VideoCaptureCapability& capture_format,
+ EventHandler* observer) OVERRIDE;
+ virtual void Start() OVERRIDE;
+ virtual void Stop() OVERRIDE;
+ virtual void DeAllocate() OVERRIDE;
+ virtual const Name& device_name() OVERRIDE;
+
+ private:
+ class Core;
+ scoped_refptr<Core> core_;
+ Name name_;
+
+ DISALLOW_COPY_AND_ASSIGN(DesktopCaptureDevice);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_DESKTOP_CAPTURE_DEVICE_H_
diff --git a/content/browser/renderer_host/media/screen_capture_device_unittest.cc b/content/browser/renderer_host/media/desktop_capture_device_unittest.cc
similarity index 91%
rename from content/browser/renderer_host/media/screen_capture_device_unittest.cc
rename to content/browser/renderer_host/media/desktop_capture_device_unittest.cc
index c3ca06f..0f14585 100644
--- a/content/browser/renderer_host/media/screen_capture_device_unittest.cc
+++ b/content/browser/renderer_host/media/desktop_capture_device_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/renderer_host/media/screen_capture_device.h"
+#include "content/browser/renderer_host/media/desktop_capture_device.h"
#include "base/basictypes.h"
#include "base/sequenced_task_runner.h"
@@ -83,7 +83,7 @@
int frame_index_;
};
-class ScreenCaptureDeviceTest : public testing::Test {
+class DesktopCaptureDeviceTest : public testing::Test {
public:
virtual void SetUp() OVERRIDE {
worker_pool_ = new base::SequencedWorkerPool(3, "TestCaptureThread");
@@ -103,9 +103,12 @@
#else
#define MAYBE_Capture Capture
#endif
-TEST_F(ScreenCaptureDeviceTest, MAYBE_Capture) {
- ScreenCaptureDevice capture_device(
- worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()));
+TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
+ scoped_ptr<webrtc::DesktopCapturer> capturer(
+ webrtc::ScreenCapturer::Create());
+ DesktopCaptureDevice capture_device(
+ worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()),
+ capturer.Pass());
media::VideoCaptureCapability caps;
base::WaitableEvent done_event(false, false);
int frame_size;
@@ -121,12 +124,7 @@
InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)));
media::VideoCaptureCapability capture_format(
- 640,
- 480,
- kFrameRate,
- media::VideoCaptureCapability::kI420,
- 0,
- false,
+ 640, 480, kFrameRate, media::VideoCaptureCapability::kI420, 0, false,
media::ConstantResolutionVideoCaptureDevice);
capture_device.Allocate(capture_format, &frame_observer);
capture_device.Start();
@@ -144,13 +142,12 @@
}
// Test that screen capturer can handle resolution change without crashing.
-TEST_F(ScreenCaptureDeviceTest, ScreenResolutionChange) {
+TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChange) {
FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();
- ScreenCaptureDevice capture_device(
- worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()));
- capture_device.SetScreenCapturerForTest(
- scoped_ptr<webrtc::ScreenCapturer>(mock_capturer));
+ DesktopCaptureDevice capture_device(
+ worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()),
+ scoped_ptr<webrtc::DesktopCapturer>(mock_capturer));
media::VideoCaptureCapability caps;
base::WaitableEvent done_event(false, false);
diff --git a/content/browser/renderer_host/media/device_request_message_filter.cc b/content/browser/renderer_host/media/device_request_message_filter.cc
index fba074b..770e800 100644
--- a/content/browser/renderer_host/media/device_request_message_filter.cc
+++ b/content/browser/renderer_host/media/device_request_message_filter.cc
@@ -71,6 +71,11 @@
NOTIMPLEMENTED();
}
+void DeviceRequestMessageFilter::StopGeneratedStream(
+ const std::string& label) {
+ NOTIMPLEMENTED();
+}
+
void DeviceRequestMessageFilter::DevicesEnumerated(
const std::string& label,
const StreamDeviceInfoArray& new_devices) {
diff --git a/content/browser/renderer_host/media/device_request_message_filter.h b/content/browser/renderer_host/media/device_request_message_filter.h
index 2ae1e77..048e215 100644
--- a/content/browser/renderer_host/media/device_request_message_filter.h
+++ b/content/browser/renderer_host/media/device_request_message_filter.h
@@ -34,6 +34,7 @@
const std::string& label, const StreamDeviceInfoArray& audio_devices,
const StreamDeviceInfoArray& video_devices) OVERRIDE;
virtual void StreamGenerationFailed(const std::string& label) OVERRIDE;
+ virtual void StopGeneratedStream(const std::string& label) OVERRIDE;
virtual void DeviceOpened(const std::string& label,
const StreamDeviceInfo& video_device) OVERRIDE;
// DevicesEnumerated() is the only callback we're interested in.
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
index abd4cd3..ebc4d89 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
@@ -62,6 +62,20 @@
request.page_request_id));
}
+void MediaStreamDispatcherHost::StopGeneratedStream(
+ const std::string& label) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DVLOG(1) << "MediaStreamDispatcherHost::StopGeneratedStream("
+ << ", {label = " << label << "})";
+
+ StreamMap::iterator it = streams_.find(label);
+ DCHECK(it != streams_.end());
+ StreamRequest request = it->second;
+ streams_.erase(it);
+
+ Send(new MediaStreamMsg_StopGeneratedStream(request.render_view_id, label));
+}
+
void MediaStreamDispatcherHost::DevicesEnumerated(
const std::string& label,
const StreamDeviceInfoArray& devices) {
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.h b/content/browser/renderer_host/media/media_stream_dispatcher_host.h
index 4b94496..ec1dd15 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host.h
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.h
@@ -33,6 +33,7 @@
const StreamDeviceInfoArray& audio_devices,
const StreamDeviceInfoArray& video_devices) OVERRIDE;
virtual void StreamGenerationFailed(const std::string& label) OVERRIDE;
+ virtual void StopGeneratedStream(const std::string& label) OVERRIDE;
virtual void DevicesEnumerated(const std::string& label,
const StreamDeviceInfoArray& devices) OVERRIDE;
virtual void DeviceOpened(const std::string& label,
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index 5325155..05804266 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -52,6 +52,8 @@
void(int routing_id, int request_id, int audio_array_size,
int video_array_size));
MOCK_METHOD2(OnStreamGenerationFailed, void(int routing_id, int request_id));
+ MOCK_METHOD1(OnStopGeneratedStreamFromBrowser,
+ void(int routing_id));
// Accessor to private functions.
void OnGenerateStream(int page_request_id,
@@ -91,6 +93,8 @@
IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated, OnStreamGenerated)
IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed,
OnStreamGenerationFailed)
+ IPC_MESSAGE_HANDLER(MediaStreamMsg_StopGeneratedStream,
+ OnStopGeneratedStreamFromBrowser)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
EXPECT_TRUE(handled);
@@ -122,6 +126,15 @@
label_= "";
}
+ void OnStopGeneratedStreamFromBrowser(const IPC::Message& msg,
+ const std::string& label) {
+ OnStopGeneratedStreamFromBrowser(msg.routing_id());
+ // Notify that the event have occured.
+ if (!quit_closure_.is_null())
+ message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure_));
+ label_ = "";
+ }
+
scoped_refptr<base::MessageLoopProxy> message_loop_;
base::Closure quit_closure_;
};
@@ -323,8 +336,7 @@
media_stream_manager_->UseFakeUI(stream_ui.PassAs<FakeMediaStreamUIProxy>());
EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
- EXPECT_CALL(*host_.get(),
- OnStreamGenerationFailed(kRenderId, kPageRequestId));
+ EXPECT_CALL(*host_.get(), OnStopGeneratedStreamFromBrowser(kRenderId));
GenerateStreamAndWaitForResult(kPageRequestId, options);
EXPECT_EQ(host_->audio_devices_.size(), 0u);
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index b5151bc..4493311 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -263,18 +263,19 @@
DCHECK(found_match || translated_video_device_id.empty());
}
- if (options.video_type == MEDIA_SCREEN_VIDEO_CAPTURE ||
+ if (options.video_type == MEDIA_DESKTOP_VIDEO_CAPTURE ||
options.audio_type == MEDIA_SYSTEM_AUDIO_CAPTURE) {
// For screen capture we only support two valid combinations:
// (1) screen video capture only, or
// (2) screen video capture with system audio capture.
- if (options.video_type != MEDIA_SCREEN_VIDEO_CAPTURE ||
+ if (options.video_type != MEDIA_DESKTOP_VIDEO_CAPTURE ||
(options.audio_type != MEDIA_NO_SERVICE &&
options.audio_type != MEDIA_SYSTEM_AUDIO_CAPTURE)) {
// TODO(sergeyu): Surface error message to the calling JS code.
LOG(ERROR) << "Invalid screen capture request.";
return std::string();
}
+ translated_video_device_id = options.video_device_id;
}
// Create a new request based on options.
@@ -624,11 +625,11 @@
audio_type == MEDIA_TAB_AUDIO_CAPTURE ||
video_type == MEDIA_TAB_VIDEO_CAPTURE;
- bool is_screen_capure =
- video_type == MEDIA_SCREEN_VIDEO_CAPTURE;
+ bool is_screen_capture =
+ video_type == MEDIA_DESKTOP_VIDEO_CAPTURE;
if (!is_web_contents_capture &&
- !is_screen_capure &&
+ !is_screen_capture &&
((IsAudioMediaType(audio_type) && !audio_enumeration_cache_.valid) ||
(IsVideoMediaType(video_type) && !video_enumeration_cache_.valid))) {
// Enumerate the devices if there is no valid device lists to be used.
@@ -987,7 +988,7 @@
// Notify renderers that the stream has been stopped.
if (it->second->requester)
- it->second->requester->StreamGenerationFailed(label);
+ it->second->requester->StopGeneratedStream(label);
StopGeneratedStream(label);
}
diff --git a/content/browser/renderer_host/media/media_stream_requester.h b/content/browser/renderer_host/media/media_stream_requester.h
index 6d8736e..50858fa 100644
--- a/content/browser/renderer_host/media/media_stream_requester.h
+++ b/content/browser/renderer_host/media/media_stream_requester.h
@@ -21,11 +21,12 @@
virtual void StreamGenerated(const std::string& label,
const StreamDeviceInfoArray& audio_devices,
const StreamDeviceInfoArray& video_devices) = 0;
- // Called if GenerateStream failed or if stream has been stopped by the user.
- // TODO(sergeyu): Rename this method and corresponding IPC message or maybe
- // add a separate IPC message.
+ // Called if GenerateStream failed.
virtual void StreamGenerationFailed(const std::string& label) = 0;
+ // Called if stream has been stopped by user request.
+ virtual void StopGeneratedStream(const std::string& label) = 0;
+
// Called as a reply of a successful call to EnumerateDevices.
virtual void DevicesEnumerated(const std::string& label,
const StreamDeviceInfoArray& devices) = 0;
diff --git a/content/browser/renderer_host/media/screen_capture_device.h b/content/browser/renderer_host/media/screen_capture_device.h
deleted file mode 100644
index df338d7..0000000
--- a/content/browser/renderer_host/media/screen_capture_device.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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 CONTENT_BROWSER_RENDERER_HOST_MEDIA_SCREEN_CAPTURE_DEVICE_H_
-#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_SCREEN_CAPTURE_DEVICE_H_
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "media/video/capture/video_capture_device.h"
-
-namespace base {
-class SequencedTaskRunner;
-} // namespace base
-
-namespace webrtc {
-class ScreenCapturer;
-} // namespace webrtc
-
-namespace content {
-
-// ScreenCaptureDevice implements VideoCaptureDevice for the screen. It's
-// essentially an adapter between ScreenCapturer and VideoCaptureDevice.
-class CONTENT_EXPORT ScreenCaptureDevice : public media::VideoCaptureDevice {
- public:
- explicit ScreenCaptureDevice(
- scoped_refptr<base::SequencedTaskRunner> task_runner);
- virtual ~ScreenCaptureDevice();
-
- // Helper used in tests to supply a fake capturer.
- void SetScreenCapturerForTest(
- scoped_ptr<webrtc::ScreenCapturer> capturer);
-
- // VideoCaptureDevice interface.
- virtual void Allocate(const media::VideoCaptureCapability& capture_format,
- EventHandler* observer) OVERRIDE;
- virtual void Start() OVERRIDE;
- virtual void Stop() OVERRIDE;
- virtual void DeAllocate() OVERRIDE;
- virtual const Name& device_name() OVERRIDE;
-
- private:
- class Core;
- scoped_refptr<Core> core_;
- Name name_;
-
- DISALLOW_COPY_AND_ASSIGN(ScreenCaptureDevice);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_SCREEN_CAPTURE_DEVICE_H_
diff --git a/content/browser/renderer_host/media/video_capture_buffer_pool.cc b/content/browser/renderer_host/media/video_capture_buffer_pool.cc
index ae29c75..207f86a 100644
--- a/content/browser/renderer_host/media/video_capture_buffer_pool.cc
+++ b/content/browser/renderer_host/media/video_capture_buffer_pool.cc
@@ -144,21 +144,15 @@
Buffer* buffer = buffers_[buffer_id];
// Wrap the buffer in a VideoFrame container.
- uint8* base_ptr = static_cast<uint8*>(buffer->shared_memory.memory());
- size_t u_offset = size.GetArea();
- size_t v_offset = u_offset + u_offset / 4;
scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::WrapExternalYuvData(
- media::VideoFrame::YV12, // Actually it's I420, but equivalent here.
- size, gfx::Rect(size), size,
- size.width(), // y stride
- size.width() / 2, // u stride
- size.width() / 2, // v stride
- base_ptr, // y address
- base_ptr + u_offset, // u address
- base_ptr + v_offset, // v address
- base::TimeDelta(), // timestamp (unused).
+ media::VideoFrame::WrapExternalSharedMemory(
+ media::VideoFrame::I420,
+ size,
+ gfx::Rect(size),
+ size,
+ static_cast<uint8*>(buffer->shared_memory.memory()),
buffer->shared_memory.handle(),
+ base::TimeDelta(),
disposal_handler);
if (buffer->rotation != rotation) {
diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc
index aa27e12..79da412 100644
--- a/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -16,13 +16,14 @@
#include "content/browser/renderer_host/media/web_contents_video_capture_device.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/desktop_media_id.h"
#include "content/public/common/media_stream_request.h"
#include "media/base/scoped_histogram_timer.h"
#include "media/video/capture/fake_video_capture_device.h"
#include "media/video/capture/video_capture_device.h"
#if defined(ENABLE_SCREEN_CAPTURE)
-#include "content/browser/renderer_host/media/screen_capture_device.h"
+#include "content/browser/renderer_host/media/desktop_capture_device.h"
#endif
namespace content {
@@ -157,17 +158,19 @@
// Check if another session has already opened this device. If so, just
// use that opened device.
- media::VideoCaptureDevice* video_capture_device = GetOpenedDevice(device);
- if (video_capture_device) {
+ media::VideoCaptureDevice* opened_video_capture_device =
+ GetOpenedDevice(device);
+ if (opened_video_capture_device) {
DeviceEntry& new_entry = devices_[capture_session_id];
new_entry.stream_type = device.device.type;
- new_entry.capture_device = video_capture_device;
+ new_entry.capture_device = opened_video_capture_device;
PostOnOpened(device.device.type, capture_session_id);
return;
}
- // Open the device.
+ scoped_ptr<media::VideoCaptureDevice> video_capture_device;
+ // Open the device.
switch (device.device.type) {
case MEDIA_DEVICE_VIDEO_CAPTURE: {
// We look up the device id from the renderer in our local enumeration
@@ -176,24 +179,23 @@
media::VideoCaptureDevice::Name* found =
video_capture_devices_.FindById(device.device.id);
if (found) {
- video_capture_device = use_fake_device_ ?
+ video_capture_device.reset(use_fake_device_ ?
media::FakeVideoCaptureDevice::Create(*found) :
- media::VideoCaptureDevice::Create(*found);
+ media::VideoCaptureDevice::Create(*found));
}
break;
}
case MEDIA_TAB_VIDEO_CAPTURE: {
- video_capture_device = WebContentsVideoCaptureDevice::Create(
- device.device.id);
+ video_capture_device.reset(
+ WebContentsVideoCaptureDevice::Create(device.device.id));
break;
}
- case MEDIA_SCREEN_VIDEO_CAPTURE: {
+ case MEDIA_DESKTOP_VIDEO_CAPTURE: {
#if defined(ENABLE_SCREEN_CAPTURE)
- scoped_refptr<base::SequencedWorkerPool> blocking_pool =
- BrowserThread::GetBlockingPool();
- video_capture_device = new ScreenCaptureDevice(
- blocking_pool->GetSequencedTaskRunner(
- blocking_pool->GetSequenceToken()));
+ DesktopMediaID id = DesktopMediaID::Parse(device.device.id);
+ if (id.type != DesktopMediaID::TYPE_NONE) {
+ video_capture_device = DesktopCaptureDevice::Create(id);
+ }
#endif // defined(ENABLE_SCREEN_CAPTURE)
break;
}
@@ -210,7 +212,7 @@
DeviceEntry& new_entry = devices_[capture_session_id];
new_entry.stream_type = device.device.type;
- new_entry.capture_device = video_capture_device;
+ new_entry.capture_device = video_capture_device.release();
PostOnOpened(device.device.type, capture_session_id);
}
@@ -434,7 +436,7 @@
*device_names = video_capture_devices_;
break;
- case MEDIA_SCREEN_VIDEO_CAPTURE:
+ case MEDIA_DESKTOP_VIDEO_CAPTURE:
device_names->clear();
break;
diff --git a/content/browser/renderer_host/media/web_contents_video_capture_device.cc b/content/browser/renderer_host/media/web_contents_video_capture_device.cc
index 2e63e94..e27b703 100644
--- a/content/browser/renderer_host/media/web_contents_video_capture_device.cc
+++ b/content/browser/renderer_host/media/web_contents_video_capture_device.cc
@@ -648,7 +648,7 @@
}
// Sanity-check the output buffer.
- if (output->format() != media::VideoFrame::YV12) {
+ if (output->format() != media::VideoFrame::I420) {
NOTREACHED();
return;
}
diff --git a/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc b/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
index 7eb28ea..d88d553 100644
--- a/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
+++ b/content/browser/renderer_host/media/web_contents_video_capture_device_unittest.cc
@@ -374,7 +374,7 @@
const scoped_refptr<media::VideoFrame>& frame,
base::Time timestamp) OVERRIDE {
EXPECT_EQ(gfx::Size(kTestWidth, kTestHeight), frame->coded_size());
- EXPECT_EQ(media::VideoFrame::YV12, frame->format());
+ EXPECT_EQ(media::VideoFrame::I420, frame->format());
EXPECT_LE(
0,
buffer_pool_->RecognizeReservedBuffer(frame->shared_memory_handle()));
diff --git a/content/browser/renderer_host/media/webrtc_identity_service_host.cc b/content/browser/renderer_host/media/webrtc_identity_service_host.cc
index cce3c74..0230b26 100644
--- a/content/browser/renderer_host/media/webrtc_identity_service_host.cc
+++ b/content/browser/renderer_host/media/webrtc_identity_service_host.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/media/webrtc_identity_store.h"
#include "content/common/media/webrtc_identity_messages.h"
#include "net/base/net_errors.h"
@@ -13,8 +14,10 @@
namespace content {
WebRTCIdentityServiceHost::WebRTCIdentityServiceHost(
+ int renderer_process_id,
WebRTCIdentityStore* identity_store)
- : identity_store_(identity_store) {}
+ : renderer_process_id_(renderer_process_id),
+ identity_store_(identity_store) {}
WebRTCIdentityServiceHost::~WebRTCIdentityServiceHost() {
if (!cancel_callback_.is_null())
@@ -42,6 +45,15 @@
SendErrorMessage(net::ERR_INSUFFICIENT_RESOURCES);
return;
}
+
+ ChildProcessSecurityPolicyImpl* policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+ if (!policy->CanAccessCookiesForOrigin(renderer_process_id_, origin)) {
+ DLOG(WARNING) << "Request rejected because origin access is denied.";
+ SendErrorMessage(net::ERR_ACCESS_DENIED);
+ return;
+ }
+
cancel_callback_ = identity_store_->RequestIdentity(
origin,
identity_name,
diff --git a/content/browser/renderer_host/media/webrtc_identity_service_host.h b/content/browser/renderer_host/media/webrtc_identity_service_host.h
index 4c53056..3676223 100644
--- a/content/browser/renderer_host/media/webrtc_identity_service_host.h
+++ b/content/browser/renderer_host/media/webrtc_identity_service_host.h
@@ -26,7 +26,8 @@
// ERR_INSUFFICIENT_RESOURCES will be sent back to the renderer.
class CONTENT_EXPORT WebRTCIdentityServiceHost : public BrowserMessageFilter {
public:
- explicit WebRTCIdentityServiceHost(WebRTCIdentityStore* identity_store);
+ explicit WebRTCIdentityServiceHost(int renderer_process_id,
+ WebRTCIdentityStore* identity_store);
protected:
virtual ~WebRTCIdentityServiceHost();
@@ -50,6 +51,7 @@
void SendErrorMessage(int error);
+ int renderer_process_id_;
base::Closure cancel_callback_;
WebRTCIdentityStore* identity_store_;
diff --git a/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc b/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc
index 058e15b..341378d 100644
--- a/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc
+++ b/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc
@@ -4,9 +4,11 @@
#include <deque>
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/media/webrtc_identity_store.h"
#include "content/browser/renderer_host/media/webrtc_identity_service_host.h"
#include "content/common/media/webrtc_identity_messages.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "ipc/ipc_message.h"
#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -21,9 +23,12 @@
static const char FAKE_CERTIFICATE[] = "fake cert";
static const char FAKE_PRIVATE_KEY[] = "fake private key";
static const int FAKE_ERROR = 100;
+static const int FAKE_RENDERER_ID = 10;
class MockWebRTCIdentityStore : public WebRTCIdentityStore {
public:
+ MockWebRTCIdentityStore() : WebRTCIdentityStore(base::FilePath(), NULL) {}
+
virtual base::Closure RequestIdentity(
const GURL& origin,
const std::string& identity_name,
@@ -46,6 +51,8 @@
}
private:
+ virtual ~MockWebRTCIdentityStore() {}
+
void OnCancel() { callback_.Reset(); }
CompletionCallback callback_;
@@ -54,7 +61,11 @@
class WebRTCIdentityServiceHostForTest : public WebRTCIdentityServiceHost {
public:
explicit WebRTCIdentityServiceHostForTest(WebRTCIdentityStore* identity_store)
- : WebRTCIdentityServiceHost(identity_store) {}
+ : WebRTCIdentityServiceHost(FAKE_RENDERER_ID, identity_store) {
+ ChildProcessSecurityPolicyImpl* policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+ policy->Add(FAKE_RENDERER_ID);
+ }
virtual bool Send(IPC::Message* message) OVERRIDE {
messages_.push_back(*message);
@@ -75,7 +86,11 @@
void ClearMessages() { messages_.clear(); }
private:
- virtual ~WebRTCIdentityServiceHostForTest() {}
+ virtual ~WebRTCIdentityServiceHostForTest() {
+ ChildProcessSecurityPolicyImpl* policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+ policy->Remove(FAKE_RENDERER_ID);
+ }
std::deque<IPC::Message> messages_;
};
@@ -83,7 +98,8 @@
class WebRTCIdentityServiceHostTest : public ::testing::Test {
public:
WebRTCIdentityServiceHostTest()
- : store_(new MockWebRTCIdentityStore()),
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
+ store_(new MockWebRTCIdentityStore()),
host_(new WebRTCIdentityServiceHostForTest(store_.get())) {}
void SendRequestToHost() {
@@ -124,7 +140,8 @@
}
protected:
- scoped_ptr<MockWebRTCIdentityStore> store_;
+ TestBrowserThreadBundle browser_thread_bundle_;
+ scoped_refptr<MockWebRTCIdentityStore> store_;
scoped_refptr<WebRTCIdentityServiceHostForTest> host_;
};
@@ -158,4 +175,13 @@
VerifyRequestFailedMessage(net::ERR_KEY_GENERATION_FAILED);
}
+TEST_F(WebRTCIdentityServiceHostTest, TestOriginAccessDenied) {
+ ChildProcessSecurityPolicyImpl* policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+ policy->Remove(FAKE_RENDERER_ID);
+
+ SendRequestToHost();
+ VerifyRequestFailedMessage(net::ERR_ACCESS_DENIED);
+}
+
} // namespace content
diff --git a/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc b/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
index 27ba37d..2bd44c1 100644
--- a/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
+++ b/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
@@ -90,7 +90,10 @@
ppapi::host::ReplyMessageContext reply_context) {
host_->SendReply(reply_context,
PpapiPluginMsg_FileRef_GetAbsolutePathReply(path_.AsUTF8Unsafe()));
- return PP_OK;
+
+ // Use PP_OK_COMPLETIONPENDING instead of PP_OK since we've already sent our
+ // reply above.
+ return PP_OK_COMPLETIONPENDING;
}
fileapi::FileSystemURL PepperExternalFileRefBackend::GetFileSystemURL() const {
diff --git a/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc b/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
index 337807d..2d93123 100644
--- a/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
+++ b/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
@@ -221,7 +221,7 @@
context.params.set_result(ppapi::PlatformFileErrorToPepperError(error));
- std::vector<ppapi::FileRef_CreateInfo> infos;
+ std::vector<ppapi::FileRefCreateInfo> infos;
std::vector<PP_FileType> file_types;
if (error == base::PLATFORM_FILE_OK && fs_host_.get()) {
std::string dir_path = path_;
@@ -235,7 +235,7 @@
else
file_types.push_back(PP_FILETYPE_REGULAR);
- ppapi::FileRef_CreateInfo info;
+ ppapi::FileRefCreateInfo info;
info.file_system_type = fs_type_;
info.file_system_plugin_resource = fs_host_->pp_resource();
std::string path =
diff --git a/content/browser/renderer_host/pepper/pepper_renderer_connection.cc b/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
index a5b95ce..7e3428a 100644
--- a/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
+++ b/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
@@ -16,7 +16,9 @@
#include "ppapi/host/resource_host.h"
#include "ppapi/proxy/ppapi_message_utils.h"
#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_message_utils.h"
#include "ppapi/proxy/resource_message_params.h"
+#include "ppapi/shared_impl/file_ref_detailed_info.h"
namespace content {
@@ -76,6 +78,8 @@
OnMsgCreateResourceHostFromHost)
IPC_MESSAGE_HANDLER(PpapiHostMsg_FileRef_GetInfoForRenderer,
OnMsgFileRefGetInfoForRenderer)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_FileRef_SyncGetInfoForRenderer,
+ OnMsgFileRefSyncGetInfoForRenderer)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidCreateInProcessInstance,
OnMsgDidCreateInProcessInstance)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidDeleteInProcessInstance,
@@ -132,12 +136,20 @@
int child_process_id,
int32_t sequence,
const std::vector<PP_Resource>& resources) {
- std::vector<PP_Resource> out_resources;
- std::vector<PP_FileSystemType> fs_types;
- std::vector<std::string> file_system_url_specs;
- std::vector<base::FilePath> external_paths;
+ std::vector<ppapi::FileRefDetailedInfo> infos;
+ OnMsgFileRefSyncGetInfoForRenderer(child_process_id, resources, &infos);
+ Send(new PpapiHostMsg_FileRef_GetInfoForRendererReply(
+ routing_id,
+ sequence,
+ infos));
+}
+void PepperRendererConnection::OnMsgFileRefSyncGetInfoForRenderer(
+ int child_process_id,
+ const std::vector<PP_Resource>& resources,
+ std::vector<ppapi::FileRefDetailedInfo>* out_infos) {
BrowserPpapiHostImpl* host = GetHostForChildProcess(child_process_id);
+
if (host) {
for (size_t i = 0; i < resources.size(); ++i) {
ppapi::host::ResourceHost* resource_host =
@@ -145,20 +157,15 @@
if (resource_host && resource_host->IsFileRefHost()) {
PepperFileRefHost* file_ref_host =
static_cast<PepperFileRefHost*>(resource_host);
- out_resources.push_back(resources[i]);
- fs_types.push_back(file_ref_host->GetFileSystemType());
- file_system_url_specs.push_back(file_ref_host->GetFileSystemURLSpec());
- external_paths.push_back(file_ref_host->GetExternalPath());
+ ppapi::FileRefDetailedInfo info;
+ info.resource = resources[i];
+ info.file_system_type = file_ref_host->GetFileSystemType();
+ info.file_system_url_spec = file_ref_host->GetFileSystemURLSpec();
+ info.external_path = file_ref_host->GetExternalPath();
+ out_infos->push_back(info);
}
}
}
- Send(new PpapiHostMsg_FileRef_GetInfoForRendererReply(
- routing_id,
- sequence,
- out_resources,
- fs_types,
- file_system_url_specs,
- external_paths));
}
void PepperRendererConnection::OnMsgDidCreateInProcessInstance(
diff --git a/content/browser/renderer_host/pepper/pepper_renderer_connection.h b/content/browser/renderer_host/pepper/pepper_renderer_connection.h
index 4392346..074bef6 100644
--- a/content/browser/renderer_host/pepper/pepper_renderer_connection.h
+++ b/content/browser/renderer_host/pepper/pepper_renderer_connection.h
@@ -11,6 +11,7 @@
#include "content/public/browser/browser_message_filter.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_resource.h"
+#include "ppapi/shared_impl/file_ref_detailed_info.h"
class GURL;
@@ -58,6 +59,11 @@
int32_t sequence_num,
const std::vector<PP_Resource>& resources);
+ void OnMsgFileRefSyncGetInfoForRenderer(
+ int child_process_id,
+ const std::vector<PP_Resource>& resources,
+ std::vector<ppapi::FileRefDetailedInfo>* out_infos);
+
void OnMsgDidCreateInProcessInstance(
PP_Instance instance,
const PepperRendererInstanceData& instance_data);
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index e4cb17c..fc84eab 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -43,6 +43,7 @@
#include "content/public/browser/plugin_service_filter.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/user_metrics.h"
+#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/context_menu_params.h"
#include "content/public/common/url_constants.h"
@@ -65,7 +66,6 @@
#include "ppapi/shared_impl/file_type_conversion.h"
#include "third_party/WebKit/public/web/WebNotificationPresenter.h"
#include "ui/gfx/color_profile.h"
-#include "webkit/plugins/plugin_constants.h"
#if defined(OS_MACOSX)
#include "content/common/mac/font_descriptor.h"
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index d3ba06e..1f6492b 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -132,7 +132,6 @@
#include "ui/gl/gl_switches.h"
#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
#include "webkit/common/resource_type.h"
-#include "webkit/plugins/plugin_switches.h"
#if defined(OS_ANDROID)
#include "content/browser/android/vibration_message_filter.h"
@@ -652,7 +651,7 @@
channel_->AddFilter(gpu_message_filter_);
#if defined(ENABLE_WEBRTC)
channel_->AddFilter(new WebRTCIdentityServiceHost(
- storage_partition_impl_->GetWebRTCIdentityStore()));
+ GetID(), storage_partition_impl_->GetWebRTCIdentityStore()));
peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID());
channel_->AddFilter(peer_connection_tracker_host_.get());
channel_->AddFilter(new MediaStreamDispatcherHost(
@@ -1028,6 +1027,7 @@
switches::kVModule,
switches::kWebCoreLogChannels,
switches::kEnableWebGLDraftExtensions,
+ switches::kEnableHTMLImports,
switches::kTraceToConsole,
switches::kEnableDeviceMotion,
#if defined(OS_ANDROID)
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 53a05f2..59822b2 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -403,13 +403,13 @@
void RenderWidgetHostViewAndroid::OnTextInputStateChanged(
const ViewHostMsg_TextInputState_Params& params) {
-#if defined(OS_ANDROID)
- if (params.require_ack) {
- // Regardless of how we exit from this method, we must acknowledge that we
- // processed the input state change.
- base::ScopedClosureRunner ack_caller(base::Bind(&SendImeEventAck, host_));
- }
-#endif
+ // If an acknowledgement is required for this event, regardless of how we exit
+ // from this method, we must acknowledge that we processed the input state
+ // change.
+ base::ScopedClosureRunner ack_caller(base::Bind(&SendImeEventAck, host_));
+ if (!params.require_ack)
+ ack_caller.Release();
+
if (!IsShowing())
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 10ce7ce..8c52017 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -2165,6 +2165,10 @@
return text_input_type_;
}
+ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
+ return ui::TEXT_INPUT_MODE_DEFAULT;
+}
+
bool RenderWidgetHostViewAura::CanComposeInline() const {
return can_compose_inline_;
}
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 dafe42f..c4a1627 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -259,6 +259,7 @@
virtual void InsertChar(char16 ch, int flags) OVERRIDE;
virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
virtual ui::TextInputType GetTextInputType() const OVERRIDE;
+ virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
virtual bool CanComposeInline() const OVERRIDE;
virtual gfx::Rect GetCaretBounds() OVERRIDE;
virtual bool GetCompositionCharacterBounds(uint32 index,
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index b35d5b3..d6b1e78 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -171,8 +171,8 @@
gfx::Rect* rect = reinterpret_cast<gfx::Rect*>(lparam);
gfx::Rect rect_in_pixels = ui::win::DIPToScreenRect(*rect);
static UINT msg = RegisterWindowMessage(kPaintMessageName);
- WPARAM wparam = rect_in_pixels.x() << 16 | rect_in_pixels.y();
- lparam = rect_in_pixels.width() << 16 | rect_in_pixels.height();
+ WPARAM wparam = MAKEWPARAM(rect_in_pixels.x(), rect_in_pixels.y());
+ lparam = MAKELPARAM(rect_in_pixels.width(), rect_in_pixels.height());
// SendMessage gets the message across much quicker than PostMessage, since it
// doesn't get queued. When the plugin thread calls PeekMessage or other
@@ -218,6 +218,10 @@
return;
}
+#if defined(USE_AURA)
+ std::vector<RECT> invalidate_rects;
+#endif
+
for (size_t i = 0; i < moves.size(); ++i) {
unsigned long flags = 0;
const WebPluginGeometry& move = moves[i];
@@ -290,6 +294,19 @@
// Note: System will own the hrgn after we call SetWindowRgn,
// so we don't need to call DeleteObject(hrgn)
::SetWindowRgn(window, hrgn, !move.clip_rect.IsEmpty());
+
+#if defined(USE_AURA)
+ // When using the software compositor, if the clipping rectangle is empty
+ // then DeferWindowPos won't redraw the newly uncovered area under the
+ // plugin.
+ if (clip_rect_in_pixel.IsEmpty() &&
+ !GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
+ RECT r;
+ GetClientRect(window, &r);
+ MapWindowPoints(window, parent, reinterpret_cast<POINT*>(&r), 2);
+ invalidate_rects.push_back(r);
+ }
+#endif
} else {
flags |= SWP_NOMOVE;
flags |= SWP_NOSIZE;
@@ -322,6 +339,13 @@
gfx::Rect gr(r);
PaintEnumChildProc(move.window, reinterpret_cast<LPARAM>(&gr));
}
+ } else {
+ for (size_t i = 0; i < invalidate_rects.size(); ++i) {
+ ::RedrawWindow(
+ parent, &invalidate_rects[i], NULL,
+ // These flags are from WebPluginDelegateImpl::NativeWndProc.
+ RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_FRAME | RDW_UPDATENOW);
+ }
}
#endif
}
diff --git a/content/browser/renderer_host/render_widget_host_view_win.cc b/content/browser/renderer_host/render_widget_host_view_win.cc
index 9096e37..dcf3873 100644
--- a/content/browser/renderer_host/render_widget_host_view_win.cc
+++ b/content/browser/renderer_host/render_widget_host_view_win.cc
@@ -404,6 +404,7 @@
weak_factory_(this),
is_loading_(false),
text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
+ text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
can_compose_inline_(true),
is_fullscreen_(false),
ignore_mouse_movement_(true),
@@ -692,9 +693,12 @@
bool can_compose_inline,
ui::TextInputMode input_mode) {
if (text_input_type_ != type ||
+ text_input_mode_ != input_mode ||
can_compose_inline_ != can_compose_inline) {
- const bool text_input_type_changed = (text_input_type_ != type);
+ const bool text_input_type_changed = (text_input_type_ != type) ||
+ (text_input_mode_ != input_mode);
text_input_type_ = type;
+ text_input_mode_ = input_mode;
can_compose_inline_ = can_compose_inline;
UpdateIMEState();
if (text_input_type_changed)
@@ -1038,6 +1042,14 @@
return text_input_type_;
}
+ui::TextInputMode RenderWidgetHostViewWin::GetTextInputMode() const {
+ if (!base::win::IsTSFAwareRequired()) {
+ NOTREACHED();
+ return ui::TEXT_INPUT_MODE_DEFAULT;
+ }
+ return ui::TEXT_INPUT_MODE_DEFAULT;
+}
+
bool RenderWidgetHostViewWin::CanComposeInline() const {
if (!base::win::IsTSFAwareRequired()) {
NOTREACHED();
@@ -3155,6 +3167,8 @@
} else {
imm32_manager_->DisableIME(m_hWnd);
}
+
+ imm32_manager_->SetTextInputMode(m_hWnd, text_input_mode_);
}
void RenderWidgetHostViewWin::UpdateInputScopeIfNecessary(
diff --git a/content/browser/renderer_host/render_widget_host_view_win.h b/content/browser/renderer_host/render_widget_host_view_win.h
index d613f3a..52030d7 100644
--- a/content/browser/renderer_host/render_widget_host_view_win.h
+++ b/content/browser/renderer_host/render_widget_host_view_win.h
@@ -12,6 +12,7 @@
#include <vector>
#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
@@ -270,6 +271,7 @@
virtual void InsertChar(char16 ch, int flags) OVERRIDE;
virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
virtual ui::TextInputType GetTextInputType() const OVERRIDE;
+ virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
virtual bool CanComposeInline() const OVERRIDE;
virtual gfx::Rect GetCaretBounds() OVERRIDE;
virtual bool GetCompositionCharacterBounds(uint32 index,
@@ -360,6 +362,9 @@
void OnFinalMessage(HWND window);
private:
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewWinBrowserTest,
+ TextInputTypeChanged);
+
// Updates the display cursor to the current cursor if the cursor is over this
// render view.
void UpdateCursorIfOverSelf();
@@ -533,6 +538,7 @@
// Stores the current text input type received by TextInputStateChanged()
// method.
ui::TextInputType text_input_type_;
+ ui::TextInputMode text_input_mode_;
bool can_compose_inline_;
ScopedVector<ui::ViewProp> props_;
diff --git a/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc
index 77763ab..76070bc 100644
--- a/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_win_browsertest.cc
@@ -2,8 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <vector>
+
#include "base/command_line.h"
#include "base/win/metro.h"
+#include "content/browser/renderer_host/render_widget_host_view_win.h"
+#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_utils.h"
@@ -11,14 +15,94 @@
#include "content/shell/shell.h"
#include "content/test/content_browser_test_utils.h"
#include "content/test/content_browser_test.h"
+#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/text_input_type.h"
+#include "ui/base/ime/win/imm32_manager.h"
#include "ui/base/ime/win/mock_tsf_bridge.h"
#include "ui/base/ime/win/tsf_bridge.h"
namespace content {
-class RenderWidgetHostViewWinTest : public ContentBrowserTest {
+namespace {
+
+class MockIMM32Manager : public ui::IMM32Manager {
public:
- RenderWidgetHostViewWinTest() {}
+ MockIMM32Manager()
+ : window_handle_(NULL),
+ input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
+ call_count_(0) {
+ }
+ virtual ~MockIMM32Manager() {}
+
+ virtual void SetTextInputMode(HWND window_handle,
+ ui::TextInputMode input_mode) OVERRIDE {
+ ++call_count_;
+ window_handle_ = window_handle;
+ input_mode_ = input_mode;
+ }
+
+ void Reset() {
+ window_handle_ = NULL;
+ input_mode_ = ui::TEXT_INPUT_MODE_DEFAULT;
+ call_count_ = 0;
+ }
+
+ HWND window_handle() const { return window_handle_; }
+ ui::TextInputMode input_mode() const { return input_mode_; }
+ size_t call_count() const { return call_count_; }
+
+ private:
+ HWND window_handle_;
+ ui::TextInputMode input_mode_;
+ size_t call_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockIMM32Manager);
+};
+
+// Testing class serving initialized RenderWidgetHostViewWin instance;
+class RenderWidgetHostViewWinBrowserTest : public ContentBrowserTest {
+ public:
+ RenderWidgetHostViewWinBrowserTest() {}
+
+ virtual void SetUpOnMainThread() OVERRIDE {
+ ContentBrowserTest::SetUpOnMainThread();
+
+ NavigateToURL(shell(), GURL("about:blank"));
+
+ view_ = static_cast<RenderWidgetHostViewWin*>(
+ RenderWidgetHostViewPort::FromRWHV(
+ shell()->web_contents()->GetRenderViewHost()->GetView()));
+ CHECK(view_);
+ }
+
+ protected:
+ RenderWidgetHostViewWin* view_;
+};
+
+} // namespace
+
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinBrowserTest,
+ TextInputTypeChanged) {
+ ASSERT_TRUE(view_->m_hWnd);
+
+ MockIMM32Manager* mock = new MockIMM32Manager();
+ mock->Reset();
+ view_->imm32_manager_.reset(mock);
+ view_->TextInputTypeChanged(ui::TEXT_INPUT_TYPE_NONE, false,
+ ui::TEXT_INPUT_MODE_EMAIL);
+
+ EXPECT_EQ(1, mock->call_count());
+ EXPECT_EQ(view_->m_hWnd, mock->window_handle());
+ EXPECT_EQ(ui::TEXT_INPUT_MODE_EMAIL, mock->input_mode());
+
+ mock->Reset();
+ view_->TextInputTypeChanged(ui::TEXT_INPUT_TYPE_NONE, false,
+ ui::TEXT_INPUT_MODE_EMAIL);
+ EXPECT_EQ(0, mock->call_count());
+}
+
+class RenderWidgetHostViewWinTSFTest : public ContentBrowserTest {
+ public:
+ RenderWidgetHostViewWinTSFTest() {}
virtual void SetUpCommandLine(CommandLine* command_line) {
command_line->AppendSwitch(switches::kEnableTextServicesFramework);
@@ -26,7 +110,7 @@
};
// crbug.com/151798
-IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinTest,
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinTSFTest,
DISABLED_SwichToPasswordField) {
ui::MockTSFBridge mock_bridge;
ui::TSFBridge* old_bridge = ui::TSFBridge::ReplaceForTesting(&mock_bridge);
@@ -64,7 +148,7 @@
}
// crbug.com/151798
-IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinTest,
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinTSFTest,
DISABLED_SwitchToSameField) {
ui::MockTSFBridge mock_bridge;
ui::TSFBridge* old_bridge = ui::TSFBridge::ReplaceForTesting(&mock_bridge);
@@ -102,7 +186,7 @@
}
// crbug.com/151798
-IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinTest,
+IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewWinTSFTest,
DISABLED_SwitchToSamePasswordField) {
ui::MockTSFBridge mock_bridge;
ui::TSFBridge* old_bridge = ui::TSFBridge::ReplaceForTesting(&mock_bridge);
diff --git a/content/browser/renderer_host/test_render_view_host.cc b/content/browser/renderer_host/test_render_view_host.cc
index 56be05c..129591c 100644
--- a/content/browser/renderer_host/test_render_view_host.cc
+++ b/content/browser/renderer_host/test_render_view_host.cc
@@ -311,8 +311,12 @@
void TestRenderViewHost::SendNavigateWithTransitionAndResponseCode(
int page_id, const GURL& url, PageTransition transition,
int response_code) {
- OnDidStartProvisionalLoadForFrame(kFrameId, -1, true, url);
- SendNavigateWithParameters(page_id, url, transition, url, response_code, 0);
+ // DidStartProvisionalLoad may delete the pending entry that holds |url|,
+ // so we keep a copy of it to use in SendNavigateWithParameters.
+ GURL url_copy(url);
+ OnDidStartProvisionalLoadForFrame(kFrameId, -1, true, url_copy);
+ SendNavigateWithParameters(page_id, url_copy, transition, url_copy,
+ response_code, 0);
}
void TestRenderViewHost::SendNavigateWithParameters(
diff --git a/content/browser/safe_util_win.cc b/content/browser/safe_util_win.cc
index 2dce2ca..ac077f1 100644
--- a/content/browser/safe_util_win.cc
+++ b/content/browser/safe_util_win.cc
@@ -19,12 +19,6 @@
namespace content {
namespace {
-// This GUID is associated with any 'don't ask me again' settings that the
-// user can select for different file types.
-// {2676A9A2-D919-4fee-9187-152100393AB2}
-static const GUID kClientID = { 0x2676a9a2, 0xd919, 0x4fee,
- { 0x91, 0x87, 0x15, 0x21, 0x0, 0x39, 0x3a, 0xb2 } };
-
// Sets the Zone Identifier on the file to "Internet" (3). Returns true if the
// function succeeds, false otherwise. A failure is expected on system where
// the Zone Identifier is not supported, like a machine with a FAT32 filesystem.
@@ -55,72 +49,11 @@
return true;
}
-}
+} // namespace
-// This function implementation is based on the attachment execution
-// services functionally deployed with IE6 or Service pack 2. This
-// functionality is exposed in the IAttachmentExecute COM interface.
-// more information at:
-// http://msdn2.microsoft.com/en-us/library/ms647048.aspx
-bool SaferOpenItemViaShell(HWND hwnd, const std::wstring& window_title,
- const base::FilePath& full_path,
- const std::wstring& source_url) {
- base::win::ScopedComPtr<IAttachmentExecute> attachment_services;
- HRESULT hr = attachment_services.CreateInstance(CLSID_AttachmentServices);
- if (FAILED(hr)) {
- // We don't have Attachment Execution Services, it must be a pre-XP.SP2
- // Windows installation, or the thread does not have COM initialized.
- if (hr == CO_E_NOTINITIALIZED) {
- NOTREACHED();
- return false;
- }
- return ui::win::OpenItemViaShell(full_path);
- }
-
- attachment_services->SetClientGuid(kClientID);
-
- if (!window_title.empty())
- attachment_services->SetClientTitle(window_title.c_str());
-
- // To help windows decide if the downloaded file is dangerous we can provide
- // what the documentation calls evidence. Which we provide now:
- //
- // Set the file itself as evidence.
- hr = attachment_services->SetLocalPath(full_path.value().c_str());
- if (FAILED(hr))
- return false;
- // Set the origin URL as evidence.
- hr = attachment_services->SetSource(source_url.c_str());
- if (FAILED(hr))
- return false;
-
- // Now check the windows policy.
- if (attachment_services->CheckPolicy() != S_OK) {
- // It is possible that the above call returns an undocumented result
- // equal to 0x800c000e which seems to indicate that the URL failed the
- // the security check. If you proceed with the Prompt() call the
- // Shell might show a dialog that says:
- // "windows found that this file is potentially harmful. To help protect
- // your computer, Windows has blocked access to this file."
- // Upon dismissal of the dialog windows will delete the file (!!).
- // So, we can 'return' in that case but maybe is best to let it happen to
- // fail on the safe side.
-
- ATTACHMENT_ACTION action;
- // We cannot control what the prompt says or does directly but it
- // is a pretty decent dialog; for example, if an executable is signed it can
- // decode and show the publisher and the certificate.
- hr = attachment_services->Prompt(hwnd, ATTACHMENT_PROMPT_EXEC, &action);
- if (FAILED(hr) || (ATTACHMENT_ACTION_CANCEL == action)) {
- // The user has declined opening the item.
- return false;
- }
- }
- return ui::win::OpenItemViaShellNoZoneCheck(full_path);
-}
-
-HRESULT ScanAndSaveDownloadedFile(const base::FilePath& full_path,
- const GURL& source_url) {
+HRESULT AVScanFile(const base::FilePath& full_path,
+ const std::string& source_url,
+ const GUID& client_guid) {
base::win::ScopedComPtr<IAttachmentExecute> attachment_services;
HRESULT hr = attachment_services.CreateInstance(CLSID_AttachmentServices);
@@ -135,15 +68,20 @@
return hr;
}
- hr = attachment_services->SetClientGuid(kClientID);
- if (FAILED(hr))
- return hr;
+ if (!IsEqualGUID(client_guid, GUID_NULL)) {
+ hr = attachment_services->SetClientGuid(client_guid);
+ if (FAILED(hr))
+ return hr;
+ }
hr = attachment_services->SetLocalPath(full_path.value().c_str());
if (FAILED(hr))
return hr;
- hr = attachment_services->SetSource(UTF8ToWide(source_url.spec()).c_str());
+ // Note: SetSource looks like it needs to be called, even if empty.
+ // Docs say it is optional, but it appears not calling it at all sets
+ // a zone that is too restrictive.
+ hr = attachment_services->SetSource(UTF8ToWide(source_url).c_str());
if (FAILED(hr))
return hr;
diff --git a/content/browser/safe_util_win.h b/content/browser/safe_util_win.h
index 1636748..3860429 100644
--- a/content/browser/safe_util_win.h
+++ b/content/browser/safe_util_win.h
@@ -16,34 +16,6 @@
namespace content {
-// Open or run a downloaded file via the Windows shell, possibly showing first
-// a consent dialog if the the file is deemed dangerous. This function is an
-// enhancement over the OpenItemViaShell() function of win_util.h.
-//
-// The user consent dialog will be shown or not according to the windows
-// execution policy defined in the registry which can be overridden per user.
-// The mechanics of the policy are explained in the Microsoft Knowledge base
-// number 883260: http://support.microsoft.com/kb/883260
-//
-// The 'hwnd' is the handle to the parent window. In case a dialog is displayed
-// the parent window will be disabled since the dialog is meant to be modal.
-// The 'window_title' is the text displayed on the title bar of the dialog. If
-// you pass an empty string the dialog will have a generic 'windows security'
-// name on the title bar.
-//
-// You must provide a valid 'full_path' to the file to be opened and a well
-// formed url in 'source_url'. The url should identify the source of the file
-// but does not have to be network-reachable. If the url is malformed a
-// dialog will be shown telling the user that the file will be blocked.
-//
-// In the event that there is no default application registered for the file
-// specified by 'full_path' it ask the user, via the Windows "Open With"
-// dialog.
-// Returns 'true' on successful open, 'false' otherwise.
-bool SaferOpenItemViaShell(HWND hwnd, const std::wstring& window_title,
- const base::FilePath& full_path,
- const std::wstring& source_url);
-
// Invokes IAttachmentExecute::Save to validate the downloaded file. The call
// may scan the file for viruses and if necessary, annotate it with evidence. As
// a result of the validation, the file may be deleted. See:
@@ -67,10 +39,15 @@
// Any other return value indicates an unexpected error during the scan.
//
// |full_path| : is the path to the downloaded file. This should be the final
-// path of the download.
-// |source_url|: the source URL for the download.
-HRESULT ScanAndSaveDownloadedFile(const base::FilePath& full_path,
- const GURL& source_url);
+// path of the download. Must be present.
+// |source_url|: the source URL for the download. If empty, the source will
+// not be set.
+// |client_guid|: the GUID to be set in the IAttachmentExecute client slot.
+// Used to identify the app to the system AV function.
+// If GUID_NULL is passed, no client GUID is set.
+HRESULT AVScanFile(const base::FilePath& full_path,
+ const std::string& source_url,
+ const GUID& client_guid);
} // namespace content
#endif // CONTENT_COMMON_SAFE_UTIL_WIN_H_
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index 1775b5f..361b4d1 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -252,6 +252,7 @@
net::URLRequestContextGetter* rq_context,
DOMStorageContextWrapper* dom_storage_context,
quota::QuotaManager* quota_manager,
+ WebRTCIdentityStore* webrtc_identity_store,
const base::Time begin,
const base::Time end);
@@ -284,7 +285,7 @@
webkit_database::DatabaseTracker* database_tracker,
DOMStorageContextWrapper* dom_storage_context,
IndexedDBContextImpl* indexed_db_context,
- scoped_ptr<WebRTCIdentityStore> webrtc_identity_store)
+ WebRTCIdentityStore* webrtc_identity_store)
: partition_path_(partition_path),
quota_manager_(quota_manager),
appcache_service_(appcache_service),
@@ -292,7 +293,7 @@
database_tracker_(database_tracker),
dom_storage_context_(dom_storage_context),
indexed_db_context_(indexed_db_context),
- webrtc_identity_store_(webrtc_identity_store.Pass()) {}
+ webrtc_identity_store_(webrtc_identity_store) {}
StoragePartitionImpl::~StoragePartitionImpl() {
// These message loop checks are just to avoid leaks in unittests.
@@ -367,8 +368,8 @@
scoped_refptr<ChromeAppCacheService> appcache_service =
new ChromeAppCacheService(quota_manager->proxy());
- scoped_ptr<WebRTCIdentityStore> webrtc_identity_store(
- new WebRTCIdentityStore());
+ scoped_refptr<WebRTCIdentityStore> webrtc_identity_store(
+ new WebRTCIdentityStore(path, context->GetSpecialStoragePolicy()));
return new StoragePartitionImpl(partition_path,
quota_manager.get(),
@@ -377,7 +378,7 @@
database_tracker.get(),
dom_storage_context.get(),
indexed_db_context.get(),
- webrtc_identity_store.Pass());
+ webrtc_identity_store.get());
}
base::FilePath StoragePartitionImpl::GetPath() {
@@ -431,7 +432,8 @@
// DataDeletionHelper::DecrementTaskCountOnUI().
helper->ClearDataOnUIThread(
remove_mask, quota_storage_remove_mask, remove_origin,
- GetPath(), rq_context, dom_storage_context_, quota_manager_, begin, end);
+ GetPath(), rq_context, dom_storage_context_, quota_manager_,
+ webrtc_identity_store_, begin, end);
}
void StoragePartitionImpl::
@@ -546,6 +548,7 @@
net::URLRequestContextGetter* rq_context,
DOMStorageContextWrapper* dom_storage_context,
quota::QuotaManager* quota_manager,
+ WebRTCIdentityStore* webrtc_identity_store,
const base::Time begin,
const base::Time end) {
DCHECK_NE(remove_mask, 0u);
@@ -602,6 +605,18 @@
path, begin, end, decrement_callback));
}
+ if (remove_mask & REMOVE_DATA_MASK_WEBRTC_IDENTITY) {
+ IncrementTaskCountOnUI();
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&WebRTCIdentityStore::DeleteBetween,
+ webrtc_identity_store,
+ begin,
+ end,
+ decrement_callback));
+ }
+
DecrementTaskCountOnUI();
}
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index 8665a74..e59347c 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -77,7 +77,7 @@
webkit_database::DatabaseTracker* database_tracker,
DOMStorageContextWrapper* dom_storage_context,
IndexedDBContextImpl* indexed_db_context,
- scoped_ptr<WebRTCIdentityStore> webrtc_identity_store);
+ WebRTCIdentityStore* webrtc_identity_store);
void ClearDataImpl(uint32 remove_mask,
uint32 quota_storage_remove_mask,
@@ -112,7 +112,7 @@
scoped_refptr<webkit_database::DatabaseTracker> database_tracker_;
scoped_refptr<DOMStorageContextWrapper> dom_storage_context_;
scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
- scoped_ptr<WebRTCIdentityStore> webrtc_identity_store_;
+ scoped_refptr<WebRTCIdentityStore> webrtc_identity_store_;
DISALLOW_COPY_AND_ASSIGN(StoragePartitionImpl);
};
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
index 2207837..a8b47bc 100644
--- a/content/browser/storage_partition_impl_unittest.cc
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -109,14 +109,8 @@
EXPECT_EQ(1u, Size());
TestClosureCallback clear_cb;
- StoragePartitionImpl sp(cache_path(),
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- scoped_ptr<WebRTCIdentityStore>());
+ StoragePartitionImpl sp(
+ cache_path(), NULL, NULL, NULL, NULL, NULL, NULL, NULL);
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(&ClearData, &sp, clear_cb.callback()));
clear_cb.WaitForResult();
diff --git a/content/browser/utility_process_host_impl.cc b/content/browser/utility_process_host_impl.cc
index db062c5..2e56218 100644
--- a/content/browser/utility_process_host_impl.cc
+++ b/content/browser/utility_process_host_impl.cc
@@ -27,7 +27,6 @@
#include "content/utility/utility_thread_impl.h"
#include "ipc/ipc_switches.h"
#include "ui/base/ui_base_switches.h"
-#include "webkit/plugins/plugin_switches.h"
#if defined(OS_WIN)
#include "content/public/common/sandboxed_process_launcher_delegate.h"
diff --git a/content/browser/web_contents/debug_urls.cc b/content/browser/web_contents/debug_urls.cc
index b554eca..1f1222c 100644
--- a/content/browser/web_contents/debug_urls.cc
+++ b/content/browser/web_contents/debug_urls.cc
@@ -10,10 +10,10 @@
#include "content/browser/gpu/gpu_process_host_ui_shim.h"
#include "content/browser/ppapi_plugin_process_host.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_constants.h"
#include "content/public/common/url_constants.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "url/gurl.h"
-#include "webkit/plugins/plugin_constants.h"
namespace content {
diff --git a/content/browser/web_contents/navigation_controller_impl_unittest.cc b/content/browser/web_contents/navigation_controller_impl_unittest.cc
index c86e3a5..c3e9b19 100644
--- a/content/browser/web_contents/navigation_controller_impl_unittest.cc
+++ b/content/browser/web_contents/navigation_controller_impl_unittest.cc
@@ -2611,6 +2611,52 @@
EXPECT_EQ(controller.GetEntryAtIndex(1)->GetURL(), transient_url);
}
+// Ensure that renderer initiated pending entries get replaced, so that we
+// don't show a stale virtual URL when a navigation commits.
+// See http://crbug.com/266922.
+TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
+ NavigationControllerImpl& controller = controller_impl();
+
+ const GURL url1("nonexistent:12121");
+ const GURL url1_fixed("http://nonexistent:12121/");
+ const GURL url2("http://foo");
+
+ // We create pending entries for renderer-initiated navigations so that we
+ // can show them in new tabs when it is safe.
+ contents()->DidStartProvisionalLoadForFrame(
+ test_rvh(), 1, -1, true, url1);
+
+ // Simulate what happens if a BrowserURLHandler rewrites the URL, causing
+ // the virtual URL to differ from the URL.
+ controller.GetPendingEntry()->SetURL(url1_fixed);
+ controller.GetPendingEntry()->SetVirtualURL(url1);
+
+ EXPECT_EQ(url1_fixed, controller.GetPendingEntry()->GetURL());
+ EXPECT_EQ(url1, controller.GetPendingEntry()->GetVirtualURL());
+ EXPECT_TRUE(
+ NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())->
+ is_renderer_initiated());
+
+ // If the user clicks another link, we should replace the pending entry.
+ contents()->DidStartProvisionalLoadForFrame(
+ test_rvh(), 1, -1, true, url2);
+ EXPECT_EQ(url2, controller.GetPendingEntry()->GetURL());
+ EXPECT_EQ(url2, controller.GetPendingEntry()->GetVirtualURL());
+
+ // Once it commits, the URL and virtual URL should reflect the actual page.
+ test_rvh()->SendNavigate(0, url2);
+ EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL());
+ EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetVirtualURL());
+
+ // We should not replace the pending entry for an error URL.
+ contents()->DidStartProvisionalLoadForFrame(
+ test_rvh(), 1, -1, true, url1);
+ EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL());
+ contents()->DidStartProvisionalLoadForFrame(
+ test_rvh(), 1, -1, true, GURL(kUnreachableWebDataURL));
+ EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL());
+}
+
// Tests that the URLs for renderer-initiated navigations are not displayed to
// the user until the navigation commits, to prevent URL spoof attacks.
// See http://crbug.com/99016.
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 66e110e..551be51 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2133,24 +2133,31 @@
render_view_host->GetProcess();
RenderViewHost::FilterURL(render_process_host, false, &validated_url);
- if (is_main_frame)
+ if (is_main_frame) {
DidChangeLoadProgress(0);
- // Create a pending entry for this provisional load (if none exists) using the
- // current SiteInstance, and ensure the address bar updates accordingly.
- // We don't know the referrer or extra headers at this point, but the referrer
- // will be set properly upon commit.
- if (is_main_frame && !controller_.GetPendingEntry()) {
- NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
- controller_.CreateNavigationEntry(validated_url,
- content::Referrer(),
- content::PAGE_TRANSITION_LINK,
- true /* is_renderer_initiated */,
- std::string(), GetBrowserContext()));
- entry->set_site_instance(
- static_cast<SiteInstanceImpl*>(GetSiteInstance()));
- controller_.SetPendingEntry(entry);
- NotifyNavigationStateChanged(content::INVALIDATE_TYPE_URL);
+ // If there is no browser-initiated pending entry for this navigation and it
+ // is not for the error URL, create a pending entry using the current
+ // SiteInstance, and ensure the address bar updates accordingly. We don't
+ // know the referrer or extra headers at this point, but the referrer will
+ // be set properly upon commit.
+ NavigationEntry* pending_entry = controller_.GetPendingEntry();
+ bool has_browser_initiated_pending_entry = pending_entry &&
+ !NavigationEntryImpl::FromNavigationEntry(pending_entry)->
+ is_renderer_initiated();
+ if (!has_browser_initiated_pending_entry && !is_error_page) {
+ NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
+ controller_.CreateNavigationEntry(validated_url,
+ content::Referrer(),
+ content::PAGE_TRANSITION_LINK,
+ true /* is_renderer_initiated */,
+ std::string(),
+ GetBrowserContext()));
+ entry->set_site_instance(
+ static_cast<SiteInstanceImpl*>(GetSiteInstance()));
+ controller_.SetPendingEntry(entry);
+ NotifyNavigationStateChanged(content::INVALIDATE_TYPE_URL);
+ }
}
// Notify observers about the start of the provisional load.
@@ -2603,7 +2610,7 @@
"Playing video");
#if defined(OS_ANDROID)
static_cast<PowerSaveBlockerImpl*>(blocker.get())->
- InitDisplaySleepBlocker(GetView()->GetTopLevelNativeWindow());
+ InitDisplaySleepBlocker(GetView()->GetNativeView());
#endif
} else if (has_audio) {
blocker = PowerSaveBlocker::Create(
diff --git a/content/child/appcache/OWNERS b/content/child/appcache/OWNERS
new file mode 100644
index 0000000..3723f40
--- /dev/null
+++ b/content/child/appcache/OWNERS
@@ -0,0 +1 @@
+michaeln@chromium.org
diff --git a/content/child/appcache_backend_proxy.cc b/content/child/appcache/appcache_backend_proxy.cc
similarity index 95%
rename from content/child/appcache_backend_proxy.cc
rename to content/child/appcache/appcache_backend_proxy.cc
index 8323751..8f9d06a 100644
--- a/content/child/appcache_backend_proxy.cc
+++ b/content/child/appcache/appcache_backend_proxy.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/child/appcache_backend_proxy.h"
+#include "content/child/appcache/appcache_backend_proxy.h"
#include "content/common/appcache_messages.h"
diff --git a/content/child/appcache_backend_proxy.h b/content/child/appcache/appcache_backend_proxy.h
similarity index 87%
rename from content/child/appcache_backend_proxy.h
rename to content/child/appcache/appcache_backend_proxy.h
index 943990a..467d385 100644
--- a/content/child/appcache_backend_proxy.h
+++ b/content/child/appcache/appcache_backend_proxy.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_CHILD_APPCACHE_BACKEND_PROXY_H_
-#define CONTENT_CHILD_APPCACHE_BACKEND_PROXY_H_
+#ifndef CONTENT_CHILD_APPCACHE_APPCACHE_BACKEND_PROXY_H_
+#define CONTENT_CHILD_APPCACHE_APPCACHE_BACKEND_PROXY_H_
#include <vector>
@@ -51,4 +51,4 @@
} // namespace content
-#endif // CONTENT_CHILD_APPCACHE_BACKEND_PROXY_H_
\ No newline at end of file
+#endif // CONTENT_CHILD_APPCACHE_APPCACHE_BACKEND_PROXY_H_
\ No newline at end of file
diff --git a/content/child/appcache_dispatcher.cc b/content/child/appcache/appcache_dispatcher.cc
similarity index 95%
rename from content/child/appcache_dispatcher.cc
rename to content/child/appcache/appcache_dispatcher.cc
index 96adc89..c3b4ec6 100644
--- a/content/child/appcache_dispatcher.cc
+++ b/content/child/appcache/appcache_dispatcher.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/child/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_dispatcher.h"
#include "content/common/appcache_messages.h"
diff --git a/content/child/appcache_dispatcher.h b/content/child/appcache/appcache_dispatcher.h
similarity index 85%
rename from content/child/appcache_dispatcher.h
rename to content/child/appcache/appcache_dispatcher.h
index 0ce2acb..0b62563 100644
--- a/content/child/appcache_dispatcher.h
+++ b/content/child/appcache/appcache_dispatcher.h
@@ -1,15 +1,15 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_CHILD_APPCACHE_DISPATCHER_H_
-#define CONTENT_CHILD_APPCACHE_DISPATCHER_H_
+#ifndef CONTENT_CHILD_APPCACHE_APPCACHE_DISPATCHER_H_
+#define CONTENT_CHILD_APPCACHE_APPCACHE_DISPATCHER_H_
#include <string>
#include <vector>
#include "base/memory/scoped_ptr.h"
-#include "content/child/appcache_backend_proxy.h"
+#include "content/child/appcache/appcache_backend_proxy.h"
#include "ipc/ipc_listener.h"
#include "webkit/common/appcache/appcache_interfaces.h"
@@ -50,4 +50,4 @@
} // namespace content
-#endif // CONTENT_CHILD_APPCACHE_DISPATCHER_H_
+#endif // CONTENT_CHILD_APPCACHE_APPCACHE_DISPATCHER_H_
diff --git a/webkit/renderer/appcache/appcache_frontend_impl.cc b/content/child/appcache/appcache_frontend_impl.cc
similarity index 61%
rename from webkit/renderer/appcache/appcache_frontend_impl.cc
rename to content/child/appcache/appcache_frontend_impl.cc
index 519bcd5..0163df2 100644
--- a/webkit/renderer/appcache/appcache_frontend_impl.cc
+++ b/content/child/appcache/appcache_frontend_impl.cc
@@ -1,33 +1,33 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/renderer/appcache/appcache_frontend_impl.h"
+#include "content/child/appcache/appcache_frontend_impl.h"
#include "base/logging.h"
+#include "content/child/appcache/web_application_cache_host_impl.h"
#include "third_party/WebKit/public/web/WebApplicationCacheHost.h"
#include "third_party/WebKit/public/web/WebConsoleMessage.h"
-#include "webkit/renderer/appcache/web_application_cache_host_impl.h"
using WebKit::WebApplicationCacheHost;
using WebKit::WebConsoleMessage;
-namespace appcache {
+namespace content {
// Inline helper to keep the lines shorter and unwrapped.
inline WebApplicationCacheHostImpl* GetHost(int id) {
return WebApplicationCacheHostImpl::FromId(id);
}
-void AppCacheFrontendImpl::OnCacheSelected(
- int host_id, const AppCacheInfo& info) {
+void AppCacheFrontendImpl::OnCacheSelected(int host_id,
+ const appcache::AppCacheInfo& info) {
WebApplicationCacheHostImpl* host = GetHost(host_id);
if (host)
host->OnCacheSelected(info);
}
void AppCacheFrontendImpl::OnStatusChanged(const std::vector<int>& host_ids,
- Status status) {
+ appcache::Status status) {
for (std::vector<int>::const_iterator i = host_ids.begin();
i != host_ids.end(); ++i) {
WebApplicationCacheHostImpl* host = GetHost(*i);
@@ -37,9 +37,9 @@
}
void AppCacheFrontendImpl::OnEventRaised(const std::vector<int>& host_ids,
- EventID event_id) {
- DCHECK(event_id != PROGRESS_EVENT); // See OnProgressEventRaised.
- DCHECK(event_id != ERROR_EVENT); // See OnErrorEventRaised.
+ appcache::EventID event_id) {
+ DCHECK(event_id != appcache::PROGRESS_EVENT); // See OnProgressEventRaised.
+ DCHECK(event_id != appcache::ERROR_EVENT); // See OnErrorEventRaised.
for (std::vector<int>::const_iterator i = host_ids.begin();
i != host_ids.end(); ++i) {
WebApplicationCacheHostImpl* host = GetHost(*i);
@@ -50,7 +50,9 @@
void AppCacheFrontendImpl::OnProgressEventRaised(
const std::vector<int>& host_ids,
- const GURL& url, int num_total, int num_complete) {
+ const GURL& url,
+ int num_total,
+ int num_complete) {
for (std::vector<int>::const_iterator i = host_ids.begin();
i != host_ids.end(); ++i) {
WebApplicationCacheHostImpl* host = GetHost(*i);
@@ -59,9 +61,8 @@
}
}
-void AppCacheFrontendImpl::OnErrorEventRaised(
- const std::vector<int>& host_ids,
- const std::string& message) {
+void AppCacheFrontendImpl::OnErrorEventRaised(const std::vector<int>& host_ids,
+ const std::string& message) {
for (std::vector<int>::const_iterator i = host_ids.begin();
i != host_ids.end(); ++i) {
WebApplicationCacheHostImpl* host = GetHost(*i);
@@ -70,7 +71,8 @@
}
}
-void AppCacheFrontendImpl::OnLogMessage(int host_id, LogLevel log_level,
+void AppCacheFrontendImpl::OnLogMessage(int host_id,
+ appcache::LogLevel log_level,
const std::string& message) {
WebApplicationCacheHostImpl* host = GetHost(host_id);
if (host)
@@ -87,40 +89,40 @@
// Ensure that enum values never get out of sync with the
// ones declared for use within the WebKit api
COMPILE_ASSERT((int)WebApplicationCacheHost::Uncached ==
- (int)UNCACHED, Uncached);
+ (int)appcache::UNCACHED, Uncached);
COMPILE_ASSERT((int)WebApplicationCacheHost::Idle ==
- (int)IDLE, Idle);
+ (int)appcache::IDLE, Idle);
COMPILE_ASSERT((int)WebApplicationCacheHost::Checking ==
- (int)CHECKING, Checking);
+ (int)appcache::CHECKING, Checking);
COMPILE_ASSERT((int)WebApplicationCacheHost::Downloading ==
- (int)DOWNLOADING, Downloading);
+ (int)appcache::DOWNLOADING, Downloading);
COMPILE_ASSERT((int)WebApplicationCacheHost::UpdateReady ==
- (int)UPDATE_READY, UpdateReady);
+ (int)appcache::UPDATE_READY, UpdateReady);
COMPILE_ASSERT((int)WebApplicationCacheHost::Obsolete ==
- (int)OBSOLETE, Obsolete);
+ (int)appcache::OBSOLETE, Obsolete);
COMPILE_ASSERT((int)WebApplicationCacheHost::CheckingEvent ==
- (int)CHECKING_EVENT, CheckingEvent);
+ (int)appcache::CHECKING_EVENT, CheckingEvent);
COMPILE_ASSERT((int)WebApplicationCacheHost::ErrorEvent ==
- (int)ERROR_EVENT, ErrorEvent);
+ (int)appcache::ERROR_EVENT, ErrorEvent);
COMPILE_ASSERT((int)WebApplicationCacheHost::NoUpdateEvent ==
- (int)NO_UPDATE_EVENT, NoUpdateEvent);
+ (int)appcache::NO_UPDATE_EVENT, NoUpdateEvent);
COMPILE_ASSERT((int)WebApplicationCacheHost::DownloadingEvent ==
- (int)DOWNLOADING_EVENT, DownloadingEvent);
+ (int)appcache::DOWNLOADING_EVENT, DownloadingEvent);
COMPILE_ASSERT((int)WebApplicationCacheHost::ProgressEvent ==
- (int)PROGRESS_EVENT, ProgressEvent);
+ (int)appcache::PROGRESS_EVENT, ProgressEvent);
COMPILE_ASSERT((int)WebApplicationCacheHost::UpdateReadyEvent ==
- (int)UPDATE_READY_EVENT, UpdateReadyEvent);
+ (int)appcache::UPDATE_READY_EVENT, UpdateReadyEvent);
COMPILE_ASSERT((int)WebApplicationCacheHost::CachedEvent ==
- (int)CACHED_EVENT, CachedEvent);
+ (int)appcache::CACHED_EVENT, CachedEvent);
COMPILE_ASSERT((int)WebApplicationCacheHost::ObsoleteEvent ==
- (int)OBSOLETE_EVENT, ObsoleteEvent);
+ (int)appcache::OBSOLETE_EVENT, ObsoleteEvent);
COMPILE_ASSERT((int)WebConsoleMessage::LevelDebug ==
- (int)LOG_DEBUG, LevelDebug);
+ (int)appcache::LOG_DEBUG, LevelDebug);
COMPILE_ASSERT((int)WebConsoleMessage::LevelLog ==
- (int)LOG_INFO, LevelLog);
+ (int)appcache::LOG_INFO, LevelLog);
COMPILE_ASSERT((int)WebConsoleMessage::LevelWarning ==
- (int)LOG_WARNING, LevelWarning);
+ (int)appcache::LOG_WARNING, LevelWarning);
COMPILE_ASSERT((int)WebConsoleMessage::LevelError ==
- (int)LOG_ERROR, LevelError);
+ (int)appcache::LOG_ERROR, LevelError);
-} // namespace appcache
+} // namespace content
diff --git a/content/child/appcache/appcache_frontend_impl.h b/content/child/appcache/appcache_frontend_impl.h
new file mode 100644
index 0000000..90774fa
--- /dev/null
+++ b/content/child/appcache/appcache_frontend_impl.h
@@ -0,0 +1,34 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_CHILD_APPCACHE_APPCACHE_FRONTEND_IMPL_H_
+#define CONTENT_CHILD_APPCACHE_APPCACHE_FRONTEND_IMPL_H_
+
+#include "webkit/common/appcache/appcache_interfaces.h"
+
+namespace content {
+
+class AppCacheFrontendImpl : public appcache::AppCacheFrontend {
+ public:
+ virtual void OnCacheSelected(int host_id,
+ const appcache::AppCacheInfo& info) OVERRIDE;
+ virtual void OnStatusChanged(const std::vector<int>& host_ids,
+ appcache::Status status) OVERRIDE;
+ virtual void OnEventRaised(const std::vector<int>& host_ids,
+ appcache::EventID event_id) OVERRIDE;
+ virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
+ const GURL& url,
+ int num_total,
+ int num_complete) OVERRIDE;
+ virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
+ const std::string& message) OVERRIDE;
+ virtual void OnLogMessage(int host_id,
+ appcache::LogLevel log_level,
+ const std::string& message) OVERRIDE;
+ virtual void OnContentBlocked(int host_id, const GURL& manifest_url) OVERRIDE;
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_APPCACHE_APPCACHE_FRONTEND_IMPL_H_
diff --git a/webkit/renderer/appcache/web_application_cache_host_impl.cc b/content/child/appcache/web_application_cache_host_impl.cc
similarity index 81%
rename from webkit/renderer/appcache/web_application_cache_host_impl.cc
rename to content/child/appcache/web_application_cache_host_impl.cc
index db67df5..b4a15f3 100644
--- a/webkit/renderer/appcache/web_application_cache_host_impl.cc
+++ b/content/child/appcache/web_application_cache_host_impl.cc
@@ -1,18 +1,18 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/renderer/appcache/web_application_cache_host_impl.h"
+#include "content/child/appcache/web_application_cache_host_impl.h"
#include "base/compiler_specific.h"
#include "base/id_map.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "third_party/WebKit/public/web/WebDataSource.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
+#include "third_party/WebKit/public/web/WebDataSource.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
using WebKit::WebApplicationCacheHost;
using WebKit::WebApplicationCacheHostClient;
@@ -22,8 +22,10 @@
using WebKit::WebURL;
using WebKit::WebURLResponse;
using WebKit::WebVector;
+using appcache::AppCacheBackend;
+using appcache::AppCacheResourceInfo;
-namespace appcache {
+namespace content {
namespace {
@@ -72,12 +74,12 @@
: client_(client),
backend_(backend),
host_id_(all_hosts()->Add(this)),
- status_(UNCACHED),
+ status_(appcache::UNCACHED),
is_scheme_supported_(false),
is_get_method_(false),
is_new_master_entry_(MAYBE),
was_select_cache_called_(false) {
- DCHECK(client && backend && (host_id_ != kNoHostId));
+ DCHECK(client && backend && (host_id_ != appcache::kNoHostId));
backend_->RegisterHost(host_id_);
}
@@ -98,32 +100,32 @@
}
void WebApplicationCacheHostImpl::OnEventRaised(appcache::EventID event_id) {
- DCHECK(event_id != PROGRESS_EVENT); // See OnProgressEventRaised.
- DCHECK(event_id != ERROR_EVENT); // See OnErrorEventRaised.
+ DCHECK(event_id != appcache::PROGRESS_EVENT); // See OnProgressEventRaised.
+ DCHECK(event_id != appcache::ERROR_EVENT); // See OnErrorEventRaised.
// Emit logging output prior to calling out to script as we can get
// deleted within the script event handler.
const char* kFormatString = "Application Cache %s event";
std::string message = base::StringPrintf(kFormatString,
kEventNames[event_id]);
- OnLogMessage(LOG_INFO, message);
+ OnLogMessage(appcache::LOG_INFO, message);
switch (event_id) {
- case CHECKING_EVENT:
- status_ = CHECKING;
+ case appcache::CHECKING_EVENT:
+ status_ = appcache::CHECKING;
break;
- case DOWNLOADING_EVENT:
- status_ = DOWNLOADING;
+ case appcache::DOWNLOADING_EVENT:
+ status_ = appcache::DOWNLOADING;
break;
- case UPDATE_READY_EVENT:
- status_ = UPDATE_READY;
+ case appcache::UPDATE_READY_EVENT:
+ status_ = appcache::UPDATE_READY;
break;
- case CACHED_EVENT:
- case NO_UPDATE_EVENT:
- status_ = IDLE;
+ case appcache::CACHED_EVENT:
+ case appcache::NO_UPDATE_EVENT:
+ status_ = appcache::IDLE;
break;
- case OBSOLETE_EVENT:
- status_ = OBSOLETE;
+ case appcache::OBSOLETE_EVENT:
+ status_ = appcache::OBSOLETE;
break;
default:
NOTREACHED();
@@ -140,8 +142,8 @@
const char* kFormatString = "Application Cache Progress event (%d of %d) %s";
std::string message = base::StringPrintf(kFormatString, num_complete,
num_total, url.spec().c_str());
- OnLogMessage(LOG_INFO, message);
- status_ = DOWNLOADING;
+ OnLogMessage(appcache::LOG_INFO, message);
+ status_ = appcache::DOWNLOADING;
client_->notifyProgressEventListener(url, num_total, num_complete);
}
@@ -152,10 +154,10 @@
const char* kFormatString = "Application Cache Error event: %s";
std::string full_message = base::StringPrintf(kFormatString,
message.c_str());
- OnLogMessage(LOG_ERROR, full_message);
+ OnLogMessage(appcache::LOG_ERROR, full_message);
- status_ = cache_info_.is_complete ? IDLE : UNCACHED;
- client_->notifyEventListener(static_cast<EventID>(ERROR_EVENT));
+ status_ = cache_info_.is_complete ? appcache::IDLE : appcache::UNCACHED;
+ client_->notifyEventListener(static_cast<EventID>(appcache::ERROR_EVENT));
}
void WebApplicationCacheHostImpl::willStartMainResourceRequest(
@@ -165,7 +167,7 @@
original_main_resource_url_ = ClearUrlRef(request.url());
std::string method = request.httpMethod().utf8();
- is_get_method_ = (method == kHttpGETMethod);
+ is_get_method_ = (method == appcache::kHttpGETMethod);
DCHECK(method == StringToUpperASCII(method));
if (frame) {
@@ -177,7 +179,7 @@
WebApplicationCacheHostImpl* spawning_host = FromFrame(spawning_frame);
if (spawning_host && (spawning_host != this) &&
- (spawning_host->status_ != UNCACHED)) {
+ (spawning_host->status_ != appcache::UNCACHED)) {
backend_->SetSpawningHostId(host_id_, spawning_host->host_id());
}
}
@@ -193,8 +195,8 @@
return;
was_select_cache_called_ = true;
- status_ = (document_response_.appCacheID() == kNoCacheId) ?
- UNCACHED : CHECKING;
+ status_ = (document_response_.appCacheID() == appcache::kNoCacheId) ?
+ appcache::UNCACHED : appcache::CHECKING;
is_new_master_entry_ = NO;
backend_->SelectCache(host_id_, document_url_,
document_response_.appCacheID(),
@@ -211,18 +213,18 @@
// 6.9.6 The application cache selection algorithm
// Check for new 'master' entries.
- if (document_response_.appCacheID() == kNoCacheId) {
+ if (document_response_.appCacheID() == appcache::kNoCacheId) {
if (is_scheme_supported_ && is_get_method_ &&
(manifest_gurl.GetOrigin() == document_url_.GetOrigin())) {
- status_ = CHECKING;
+ status_ = appcache::CHECKING;
is_new_master_entry_ = YES;
} else {
- status_ = UNCACHED;
+ status_ = appcache::UNCACHED;
is_new_master_entry_ = NO;
manifest_gurl = GURL();
}
- backend_->SelectCache(host_id_, document_url_,
- kNoCacheId, manifest_gurl);
+ backend_->SelectCache(
+ host_id_, document_url_, appcache::kNoCacheId, manifest_gurl);
return true;
}
@@ -234,11 +236,11 @@
if (document_manifest_gurl != manifest_gurl) {
backend_->MarkAsForeignEntry(host_id_, document_url_,
document_response_.appCacheID());
- status_ = UNCACHED;
+ status_ = appcache::UNCACHED;
return false; // the navigation will be restarted
}
- status_ = CHECKING;
+ status_ = appcache::CHECKING;
// Its a 'master' entry thats already in the cache.
backend_->SelectCache(host_id_, document_url_,
@@ -255,8 +257,8 @@
is_get_method_ = true; // A redirect was involved.
original_main_resource_url_ = GURL();
- is_scheme_supported_ = IsSchemeSupported(document_url_);
- if ((document_response_.appCacheID() != kNoCacheId) ||
+ is_scheme_supported_ = appcache::IsSchemeSupported(document_url_);
+ if ((document_response_.appCacheID() != appcache::kNoCacheId) ||
!is_scheme_supported_ || !is_get_method_)
is_new_master_entry_ = NO;
}
@@ -281,8 +283,8 @@
bool WebApplicationCacheHostImpl::startUpdate() {
if (!backend_->StartUpdate(host_id_))
return false;
- if (status_ == IDLE || status_ == UPDATE_READY)
- status_ = CHECKING;
+ if (status_ == appcache::IDLE || status_ == appcache::UPDATE_READY)
+ status_ = appcache::CHECKING;
else
status_ = backend_->GetStatus(host_id_);
return true;
@@ -325,4 +327,4 @@
resources->swap(web_resources);
}
-} // appcache namespace
+} // namespace content
diff --git a/webkit/renderer/appcache/web_application_cache_host_impl.h b/content/child/appcache/web_application_cache_host_impl.h
similarity index 78%
rename from webkit/renderer/appcache/web_application_cache_host_impl.h
rename to content/child/appcache/web_application_cache_host_impl.h
index 752ad83..c0cdea9 100644
--- a/webkit/renderer/appcache/web_application_cache_host_impl.h
+++ b/content/child/appcache/web_application_cache_host_impl.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef WEBKIT_RENDERER_APPCACHE_WEB_APPLICATION_CACHE_HOST_IMPL_H_
-#define WEBKIT_RENDERER_APPCACHE_WEB_APPLICATION_CACHE_HOST_IMPL_H_
+#ifndef CONTENT_CHILD_APPCACHE_WEB_APPLICATION_CACHE_HOST_IMPL_H_
+#define CONTENT_CHILD_APPCACHE_WEB_APPLICATION_CACHE_HOST_IMPL_H_
#include <string>
@@ -12,15 +12,14 @@
#include "third_party/WebKit/public/web/WebApplicationCacheHostClient.h"
#include "url/gurl.h"
#include "webkit/common/appcache/appcache_interfaces.h"
-#include "webkit/renderer/webkit_storage_renderer_export.h"
namespace WebKit {
class WebFrame;
}
-namespace appcache {
+namespace content {
-class WEBKIT_STORAGE_RENDERER_EXPORT WebApplicationCacheHostImpl
+class WebApplicationCacheHostImpl
: NON_EXPORTED_BASE(public WebKit::WebApplicationCacheHost) {
public:
// Returns the host having given id or NULL if there is no such host.
@@ -30,11 +29,11 @@
static WebApplicationCacheHostImpl* FromFrame(const WebKit::WebFrame* frame);
WebApplicationCacheHostImpl(WebKit::WebApplicationCacheHostClient* client,
- AppCacheBackend* backend);
+ appcache::AppCacheBackend* backend);
virtual ~WebApplicationCacheHostImpl();
int host_id() const { return host_id_; }
- AppCacheBackend* backend() const { return backend_; }
+ appcache::AppCacheBackend* backend() const { return backend_; }
WebKit::WebApplicationCacheHostClient* client() const { return client_; }
virtual void OnCacheSelected(const appcache::AppCacheInfo& info);
@@ -42,10 +41,11 @@
void OnEventRaised(appcache::EventID);
void OnProgressEventRaised(const GURL& url, int num_total, int num_complete);
void OnErrorEventRaised(const std::string& message);
- virtual void OnLogMessage(LogLevel log_level, const std::string& message) {}
+ virtual void OnLogMessage(appcache::LogLevel log_level,
+ const std::string& message) {}
virtual void OnContentBlocked(const GURL& manifest_url) {}
- // WebApplicationCacheHost methods
+ // WebKit::WebApplicationCacheHost:
virtual void willStartMainResourceRequest(WebKit::WebURLRequest&,
const WebKit::WebFrame*);
virtual void willStartSubResourceRequest(WebKit::WebURLRequest&);
@@ -68,7 +68,7 @@
};
WebKit::WebApplicationCacheHostClient* client_;
- AppCacheBackend* backend_;
+ appcache::AppCacheBackend* backend_;
int host_id_;
appcache::Status status_;
WebKit::WebURLResponse document_response_;
@@ -81,6 +81,6 @@
bool was_select_cache_called_;
};
-} // namespace
+} // namespace content
-#endif // WEBKIT_RENDERER_APPCACHE_WEB_APPLICATION_CACHE_HOST_IMPL_H_
+#endif // CONTENT_CHILD_APPCACHE_WEB_APPLICATION_CACHE_HOST_IMPL_H_
diff --git a/content/child/npapi/plugin_instance.cc b/content/child/npapi/plugin_instance.cc
index ac4c8b4..c279b9b 100644
--- a/content/child/npapi/plugin_instance.cc
+++ b/content/child/npapi/plugin_instance.cc
@@ -16,8 +16,8 @@
#include "content/child/npapi/plugin_string_stream.h"
#include "content/child/npapi/webplugin.h"
#include "content/child/npapi/webplugin_delegate.h"
+#include "content/public/common/content_constants.h"
#include "net/base/escape.h"
-#include "webkit/plugins/plugin_constants.h"
#if defined(OS_MACOSX)
#include <ApplicationServices/ApplicationServices.h>
diff --git a/content/child/npapi/webplugin_delegate_impl_gtk.cc b/content/child/npapi/webplugin_delegate_impl_gtk.cc
index 9b608b9..36906c5 100644
--- a/content/child/npapi/webplugin_delegate_impl_gtk.cc
+++ b/content/child/npapi/webplugin_delegate_impl_gtk.cc
@@ -13,12 +13,12 @@
#include "base/metrics/stats_counters.h"
#include "content/child/npapi/plugin_instance.h"
#include "content/child/npapi/webplugin.h"
+#include "content/public/common/content_constants.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/base/gtk/gtk_compat.h"
#include "ui/gfx/blit.h"
#include "webkit/common/cursors/webcursor.h"
-#include "webkit/plugins/plugin_constants.h"
#include "third_party/npapi/bindings/npapi_x11.h"
diff --git a/content/child/npapi/webplugin_delegate_impl_win.cc b/content/child/npapi/webplugin_delegate_impl_win.cc
index 1ac124f..01f2100 100644
--- a/content/child/npapi/webplugin_delegate_impl_win.cc
+++ b/content/child/npapi/webplugin_delegate_impl_win.cc
@@ -28,12 +28,12 @@
#include "content/child/npapi/webplugin.h"
#include "content/child/npapi/webplugin_ime_win.h"
#include "content/common/plugin_constants_win.h"
+#include "content/public/common/content_constants.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/base/win/dpi.h"
#include "ui/base/win/hwnd_util.h"
#include "webkit/common/cursors/webcursor.h"
-#include "webkit/plugins/plugin_constants.h"
using WebKit::WebKeyboardEvent;
using WebKit::WebInputEvent;
@@ -947,10 +947,10 @@
// Get the invalid rect which is in screen coordinates and convert to
// window coordinates.
gfx::Rect invalid_rect;
- invalid_rect.set_x(wparam >> 16);
- invalid_rect.set_y(wparam & 0xFFFF);
- invalid_rect.set_width(lparam >> 16);
- invalid_rect.set_height(lparam & 0xFFFF);
+ invalid_rect.set_x(static_cast<short>(LOWORD(wparam)));
+ invalid_rect.set_y(static_cast<short>(HIWORD(wparam)));
+ invalid_rect.set_width(static_cast<short>(LOWORD(lparam)));
+ invalid_rect.set_height(static_cast<short>(HIWORD(lparam)));
RECT window_rect;
GetWindowRect(hwnd, &window_rect);
diff --git a/content/child/power_monitor_broadcast_source_unittest.cc b/content/child/power_monitor_broadcast_source_unittest.cc
index 0d09f60..b665e90 100644
--- a/content/child/power_monitor_broadcast_source_unittest.cc
+++ b/content/child/power_monitor_broadcast_source_unittest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "base/message_loop/message_loop.h"
-#include "base/power_monitor/power_monitor_test_base.h"
+#include "base/test/power_monitor_test_base.h"
#include "content/child/power_monitor_broadcast_source.h"
#include "content/common/power_monitor_messages.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index ec8f617..5c74ca6 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -132,6 +132,9 @@
if (command_line.HasSwitch(switches::kEnableWebGLDraftExtensions))
WebRuntimeFeatures::enableWebGLDraftExtensions(true);
+
+ if (command_line.HasSwitch(switches::kEnableHTMLImports))
+ WebRuntimeFeatures::enableHTMLImports(true);
}
} // namespace content
diff --git a/content/common/browser_plugin/browser_plugin_constants.cc b/content/common/browser_plugin/browser_plugin_constants.cc
index bd20b85..691366b 100644
--- a/content/common/browser_plugin/browser_plugin_constants.cc
+++ b/content/common/browser_plugin/browser_plugin_constants.cc
@@ -47,16 +47,13 @@
const char kEventDialog[] = "dialog";
const char kEventNewWindow[] = "newwindow";
const char kEventRequestPermission[] = "permissionrequest";
-const char kEventResponsive[] = "responsive";
const char kEventSizeChanged[] = "sizechanged";
-const char kEventUnresponsive[] = "unresponsive";
// Parameters/properties on events.
const char kDefaultPromptText[] = "defaultPromptText";
const char kId[] = "id";
const char kInitialHeight[] = "initialHeight";
const char kInitialWidth[] = "initialWidth";
-const char kIsTopLevel[] = "isTopLevel";
const char kLastUnlockedBySelf[] = "lastUnlockedBySelf";
const char kMessageText[] = "messageText";
const char kMessageType[] = "messageType";
diff --git a/content/common/browser_plugin/browser_plugin_constants.h b/content/common/browser_plugin/browser_plugin_constants.h
index ba8dd06..a411741 100644
--- a/content/common/browser_plugin/browser_plugin_constants.h
+++ b/content/common/browser_plugin/browser_plugin_constants.h
@@ -56,7 +56,6 @@
extern const char kId[];
extern const char kInitialHeight[];
extern const char kInitialWidth[];
-extern const char kIsTopLevel[];
extern const char kLastUnlockedBySelf[];
extern const char kMessageText[];
extern const char kMessageType[];
diff --git a/content/common/content_constants_internal.cc b/content/common/content_constants_internal.cc
index c2bcaff..f5da70e 100644
--- a/content/common/content_constants_internal.cc
+++ b/content/common/content_constants_internal.cc
@@ -8,6 +8,10 @@
const int kHungRendererDelayMs = 30000;
+const uint16 kMaxPluginSideLength = 1 << 15;
+// 8m pixels.
+const uint32 kMaxPluginSize = 8 << 20;
+
const int kTraceEventBrowserProcessSortIndex = -6;
const int kTraceEventRendererProcessSortIndex = -5;
const int kTraceEventPluginProcessSortIndex = -4;
diff --git a/content/common/content_constants_internal.h b/content/common/content_constants_internal.h
index ddb082f..55a2ade 100644
--- a/content/common/content_constants_internal.h
+++ b/content/common/content_constants_internal.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_COMMON_CONTENT_CONSTANTS_INTERNAL_H_
#define CONTENT_COMMON_CONTENT_CONSTANTS_INTERNAL_H_
+#include "base/basictypes.h"
#include "content/common/content_export.h"
namespace content {
@@ -12,6 +13,12 @@
// How long to wait before we consider a renderer hung.
CONTENT_EXPORT extern const int kHungRendererDelayMs;
+// The maximum plugin width and height.
+extern const uint16 kMaxPluginSideLength;
+// The maximum plugin size, defined as the number of pixels occupied by the
+// plugin.
+extern const uint32 kMaxPluginSize;
+
// Constants used to organize content processes in about:tracing.
CONTENT_EXPORT extern const int kTraceEventBrowserProcessSortIndex;
CONTENT_EXPORT extern const int kTraceEventRendererProcessSortIndex;
diff --git a/content/common/gpu/media/exynos_video_decode_accelerator.cc b/content/common/gpu/media/exynos_video_decode_accelerator.cc
index 6817ca9..677df9c 100644
--- a/content/common/gpu/media/exynos_video_decode_accelerator.cc
+++ b/content/common/gpu/media/exynos_video_decode_accelerator.cc
@@ -50,6 +50,11 @@
namespace {
+// TODO(posciak): remove once we update linux-headers.
+#ifndef V4L2_EVENT_RESOLUTION_CHANGE
+#define V4L2_EVENT_RESOLUTION_CHANGE 5
+#endif
+
const char kExynosMfcDevice[] = "/dev/mfc-dec";
const char kExynosGscDevice[] = "/dev/gsc1";
const char kMaliDriver[] = "libmali.so";
@@ -212,6 +217,8 @@
decoder_decode_buffer_tasks_scheduled_(0),
decoder_frames_at_client_(0),
decoder_flushing_(false),
+ resolution_change_pending_(false),
+ resolution_change_reset_pending_(false),
decoder_partial_frame_pending_(false),
mfc_fd_(-1),
mfc_input_streamon_(false),
@@ -379,6 +386,12 @@
format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16;
IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_S_FMT, &format);
+ // Subscribe to the resolution change event.
+ struct v4l2_event_subscription sub;
+ memset(&sub, 0, sizeof(sub));
+ sub.type = V4L2_EVENT_RESOLUTION_CHANGE;
+ IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_SUBSCRIBE_EVENT, &sub);
+
// Initialize format-specific bits.
if (video_profile_ >= media::H264PROFILE_MIN &&
video_profile_ <= media::H264PROFILE_MAX) {
@@ -637,6 +650,9 @@
} else if (decoder_state_ == kError) {
DVLOG(2) << "DecodeBufferTask(): early out: kError state";
return;
+ } else if (decoder_state_ == kChangingResolution) {
+ DVLOG(2) << "DecodeBufferTask(): early out: resolution change pending";
+ return;
}
if (decoder_current_bitstream_buffer_ == NULL) {
@@ -862,35 +878,21 @@
// Check and see if we have format info yet.
struct v4l2_format format;
- format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- if (ioctl(mfc_fd_, VIDIOC_G_FMT, &format) != 0) {
- if (errno == EINVAL) {
- // We will get EINVAL if we haven't seen sufficient stream to decode the
- // format. Return true and schedule the next buffer.
- *endpos = size;
- return true;
- } else {
- DPLOG(ERROR) << "DecodeBufferInitial(): ioctl() failed: VIDIOC_G_FMT";
- NOTIFY_ERROR(PLATFORM_FAILURE);
- return false;
- }
+ bool again = false;
+ if (!GetFormatInfo(&format, &again))
+ return false;
+
+ if (again) {
+ // Need more stream to decode format, return true and schedule next buffer.
+ *endpos = size;
+ return true;
}
// Run this initialization only on first startup.
if (decoder_state_ == kInitialized) {
- DVLOG(3) << "DecodeBufferInitial(): running one-time initialization";
+ DVLOG(3) << "DecodeBufferInitial(): running initialization";
// Success! Setup our parameters.
- CHECK_EQ(format.fmt.pix_mp.num_planes, 2);
- frame_buffer_size_.SetSize(
- format.fmt.pix_mp.width, format.fmt.pix_mp.height);
- mfc_output_buffer_size_[0] = format.fmt.pix_mp.plane_fmt[0].sizeimage;
- mfc_output_buffer_size_[1] = format.fmt.pix_mp.plane_fmt[1].sizeimage;
- mfc_output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat;
- DCHECK_EQ(mfc_output_buffer_pixelformat_, V4L2_PIX_FMT_NV12MT_16X16);
-
- // Create our other buffers.
- if (!CreateMfcOutputBuffers() || !CreateGscInputBuffers() ||
- !CreateGscOutputBuffers())
+ if (!CreateBuffersForFormat(format))
return false;
// MFC expects to process the initial buffer once during stream init to
@@ -1064,9 +1066,12 @@
// We got buffers! Kick the GSC.
EnqueueGsc();
+
+ if (decoder_state_ == kChangingResolution)
+ ResumeAfterResolutionChange();
}
-void ExynosVideoDecodeAccelerator::ServiceDeviceTask() {
+void ExynosVideoDecodeAccelerator::ServiceDeviceTask(bool mfc_event_pending) {
DVLOG(3) << "ServiceDeviceTask()";
DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
DCHECK_NE(decoder_state_, kUninitialized);
@@ -1080,8 +1085,13 @@
} else if (decoder_state_ == kError) {
DVLOG(2) << "ServiceDeviceTask(): early out: kError state";
return;
+ } else if (decoder_state_ == kChangingResolution) {
+ DVLOG(2) << "ServiceDeviceTask(): early out: kChangingResolution state";
+ return;
}
+ if (mfc_event_pending)
+ DequeueMfcEvents();
DequeueMfc();
DequeueGsc();
EnqueueMfc();
@@ -1133,6 +1143,7 @@
<< decoder_frames_at_client_ << "]";
ScheduleDecodeBufferTaskIfNeeded();
+ StartResolutionChangeIfNeeded();
}
void ExynosVideoDecodeAccelerator::EnqueueMfc() {
@@ -1180,6 +1191,26 @@
}
}
+void ExynosVideoDecodeAccelerator::DequeueMfcEvents() {
+ DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ DCHECK_EQ(decoder_state_, kDecoding);
+ DVLOG(3) << "DequeueMfcEvents()";
+
+ struct v4l2_event ev;
+ memset(&ev, 0, sizeof(ev));
+
+ while (ioctl(mfc_fd_, VIDIOC_DQEVENT, &ev) == 0) {
+ if (ev.type == V4L2_EVENT_RESOLUTION_CHANGE) {
+ DVLOG(3) << "DequeueMfcEvents(): got resolution change event.";
+ DCHECK(!resolution_change_pending_);
+ resolution_change_pending_ = true;
+ } else {
+ DLOG(FATAL) << "DequeueMfcEvents(): got an event (" << ev.type
+ << ") we haven't subscribed to.";
+ }
+ }
+}
+
void ExynosVideoDecodeAccelerator::DequeueMfc() {
DVLOG(3) << "DequeueMfc()";
DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
@@ -1538,6 +1569,11 @@
return;
}
+ if (decoder_state_ == kChangingResolution) {
+ DVLOG(2) << "ReusePictureBufferTask(): early out: kChangingResolution";
+ return;
+ }
+
size_t index;
for (index = 0; index < gsc_output_buffer_map_.size(); ++index)
if (gsc_output_buffer_map_[index].picture_id == picture_buffer_id)
@@ -1619,6 +1655,21 @@
gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ ) != 0)
return;
+ // TODO(posciak): crbug.com/270039. MFC requires a streamoff-streamon
+ // sequence after flush to continue, even if we are not resetting. This would
+ // make sense, because we don't really want to resume from a non-resume point
+ // (e.g. not from an IDR) if we are flushed.
+ // MSE player however triggers a Flush() on chunk end, but never Reset(). One
+ // could argue either way, or even say that Flush() is not needed/harmful when
+ // transitioning to next chunk.
+ // For now, do the streamoff-streamon cycle to satisfy MFC and not freeze when
+ // doing MSE. This should be harmless otherwise.
+ if (!StopDevicePoll(false))
+ return;
+
+ if (!StartDevicePoll())
+ return;
+
decoder_delay_bitstream_buffer_id_ = -1;
decoder_flushing_ = false;
DVLOG(3) << "NotifyFlushDoneIfNeeded(): returning flush";
@@ -1639,10 +1690,25 @@
return;
}
- // We stop streaming, but we _don't_ destroy our buffers.
- if (!StopDevicePoll())
+ // If we are in the middle of switching resolutions, postpone reset until
+ // it's done. We don't have to worry about timing of this wrt to decoding,
+ // because MFC input pipe is already stopped if we are changing resolution.
+ // We will come back here after we are done with the resolution change.
+ DCHECK(!resolution_change_reset_pending_);
+ if (resolution_change_pending_ || decoder_state_ == kChangingResolution) {
+ resolution_change_reset_pending_ = true;
+ return;
+ }
+
+ // We stop streaming and clear buffer tracking info (not preserving
+ // MFC inputs).
+ // StopDevicePoll() unconditionally does _not_ destroy buffers, however.
+ if (!StopDevicePoll(false))
return;
+ DequeueMfcEvents();
+
+ resolution_change_pending_ = false;
decoder_current_bitstream_buffer_.reset();
decoder_input_queue_.clear();
@@ -1694,7 +1760,7 @@
// DestroyTask() should run regardless of decoder_state_.
// Stop streaming and the device_poll_thread_.
- StopDevicePoll();
+ StopDevicePoll(false);
decoder_current_bitstream_buffer_.reset();
decoder_current_input_buffer_ = -1;
@@ -1726,7 +1792,7 @@
return true;
}
-bool ExynosVideoDecodeAccelerator::StopDevicePoll() {
+bool ExynosVideoDecodeAccelerator::StopDevicePoll(bool keep_mfc_input_state) {
DVLOG(3) << "StopDevicePoll()";
DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
@@ -1739,11 +1805,13 @@
return false;
// Stop streaming.
- if (mfc_input_streamon_) {
- __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
- IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type);
+ if (!keep_mfc_input_state) {
+ if (mfc_input_streamon_) {
+ __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+ IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type);
+ }
+ mfc_input_streamon_ = false;
}
- mfc_input_streamon_ = false;
if (mfc_output_streamon_) {
__u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
IOCTL_OR_ERROR_RETURN_FALSE(mfc_fd_, VIDIOC_STREAMOFF, &type);
@@ -1761,15 +1829,17 @@
gsc_output_streamon_ = false;
// Reset all our accounting info.
- mfc_input_ready_queue_.clear();
- mfc_free_input_buffers_.clear();
- for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) {
- mfc_free_input_buffers_.push_back(i);
- mfc_input_buffer_map_[i].at_device = false;
- mfc_input_buffer_map_[i].bytes_used = 0;
- mfc_input_buffer_map_[i].input_id = -1;
+ if (!keep_mfc_input_state) {
+ mfc_input_ready_queue_.clear();
+ mfc_free_input_buffers_.clear();
+ for (size_t i = 0; i < mfc_input_buffer_map_.size(); ++i) {
+ mfc_free_input_buffers_.push_back(i);
+ mfc_input_buffer_map_[i].at_device = false;
+ mfc_input_buffer_map_[i].bytes_used = 0;
+ mfc_input_buffer_map_[i].input_id = -1;
+ }
+ mfc_input_buffer_queued_count_ = 0;
}
- mfc_input_buffer_queued_count_ = 0;
mfc_free_output_buffers_.clear();
for (size_t i = 0; i < mfc_output_buffer_map_.size(); ++i) {
mfc_free_output_buffers_.push_back(i);
@@ -1830,6 +1900,84 @@
return true;
}
+void ExynosVideoDecodeAccelerator::StartResolutionChangeIfNeeded() {
+ DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ DCHECK_EQ(decoder_state_, kDecoding);
+
+ if (!resolution_change_pending_)
+ return;
+
+ if (!mfc_output_gsc_input_queue_.empty() ||
+ gsc_input_buffer_queued_count_ + gsc_output_buffer_queued_count_ > 0) {
+ DVLOG(3) << "StartResolutionChangeIfNeeded(): waiting for GSC to finish.";
+ return;
+ }
+
+ DVLOG(3) << "No more work for GSC, initiate resolution change";
+
+ // Keep MFC input queue.
+ if (!StopDevicePoll(true))
+ return;
+
+ decoder_state_ = kChangingResolution;
+ DCHECK(resolution_change_pending_);
+ resolution_change_pending_ = false;
+
+ // Post a task to clean up buffers on child thread. This will also ensure
+ // that we won't accept ReusePictureBuffer() anymore after that.
+ child_message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
+ &ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers,
+ weak_this_));
+}
+
+void ExynosVideoDecodeAccelerator::FinishResolutionChange() {
+ DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ DVLOG(3) << "FinishResolutionChange()";
+
+ if (decoder_state_ == kError) {
+ DVLOG(2) << "FinishResolutionChange(): early out: kError state";
+ return;
+ }
+
+ struct v4l2_format format;
+ bool again;
+ bool ret = GetFormatInfo(&format, &again);
+ if (!ret || again) {
+ DVLOG(3) << "Couldn't get format information after resolution change";
+ NOTIFY_ERROR(PLATFORM_FAILURE);
+ return;
+ }
+
+ if (!CreateBuffersForFormat(format)) {
+ DVLOG(3) << "Couldn't reallocate buffers after resolution change";
+ NOTIFY_ERROR(PLATFORM_FAILURE);
+ return;
+ }
+
+ // From here we stay in kChangingResolution and wait for
+ // AssignPictureBuffers() before we can resume.
+}
+
+void ExynosVideoDecodeAccelerator::ResumeAfterResolutionChange() {
+ DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ DVLOG(3) << "ResumeAfterResolutionChange()";
+
+ decoder_state_ = kDecoding;
+
+ if (resolution_change_reset_pending_) {
+ resolution_change_reset_pending_ = false;
+ ResetTask();
+ return;
+ }
+
+ if (!StartDevicePoll())
+ return;
+
+ EnqueueMfc();
+ // Gsc will get enqueued in AssignPictureBuffersTask().
+ ScheduleDecodeBufferTaskIfNeeded();
+}
+
void ExynosVideoDecodeAccelerator::DevicePollTask(unsigned int poll_fds) {
DVLOG(3) << "DevicePollTask()";
DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current());
@@ -1841,6 +1989,7 @@
// device_poll_interrupt_fd_.
struct pollfd pollfds[3];
nfds_t nfds;
+ int mfc_pollfd = -1;
// Add device_poll_interrupt_fd_;
pollfds[0].fd = device_poll_interrupt_fd_;
@@ -1850,7 +1999,8 @@
if (poll_fds & kPollMfc) {
DVLOG(3) << "DevicePollTask(): adding MFC to poll() set";
pollfds[nfds].fd = mfc_fd_;
- pollfds[nfds].events = POLLIN | POLLOUT | POLLERR;
+ pollfds[nfds].events = POLLIN | POLLOUT | POLLERR | POLLPRI;
+ mfc_pollfd = nfds;
nfds++;
}
// Add GSC fd, if we should poll on it.
@@ -1869,11 +2019,14 @@
return;
}
+ bool mfc_event_pending = (mfc_pollfd != -1 &&
+ pollfds[mfc_pollfd].revents & POLLPRI);
+
// All processing should happen on ServiceDeviceTask(), since we shouldn't
// touch decoder state from this thread.
decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
&ExynosVideoDecodeAccelerator::ServiceDeviceTask,
- base::Unretained(this)));
+ base::Unretained(this), mfc_event_pending));
}
void ExynosVideoDecodeAccelerator::NotifyError(Error error) {
@@ -1906,6 +2059,48 @@
}
}
+bool ExynosVideoDecodeAccelerator::GetFormatInfo(struct v4l2_format* format,
+ bool* again) {
+ DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+
+ *again = false;
+ memset(format, 0, sizeof(*format));
+ format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ if (HANDLE_EINTR(ioctl(mfc_fd_, VIDIOC_G_FMT, format)) != 0) {
+ if (errno == EINVAL) {
+ // EINVAL means we haven't seen sufficient stream to decode the format.
+ *again = true;
+ return true;
+ } else {
+ DPLOG(ERROR) << "DecodeBufferInitial(): ioctl() failed: VIDIOC_G_FMT";
+ NOTIFY_ERROR(PLATFORM_FAILURE);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ExynosVideoDecodeAccelerator::CreateBuffersForFormat(
+ const struct v4l2_format& format) {
+ DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
+ CHECK_EQ(format.fmt.pix_mp.num_planes, 2);
+ frame_buffer_size_.SetSize(
+ format.fmt.pix_mp.width, format.fmt.pix_mp.height);
+ mfc_output_buffer_size_[0] = format.fmt.pix_mp.plane_fmt[0].sizeimage;
+ mfc_output_buffer_size_[1] = format.fmt.pix_mp.plane_fmt[1].sizeimage;
+ mfc_output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat;
+ DCHECK_EQ(mfc_output_buffer_pixelformat_, V4L2_PIX_FMT_NV12MT_16X16);
+ DVLOG(3) << "CreateBuffersForFormat(): new resolution: "
+ << frame_buffer_size_.ToString();
+
+ if (!CreateMfcOutputBuffers() || !CreateGscInputBuffers() ||
+ !CreateGscOutputBuffers())
+ return false;
+
+ return true;
+}
+
bool ExynosVideoDecodeAccelerator::CreateMfcInputBuffers() {
DVLOG(3) << "CreateMfcInputBuffers()";
// We always run this as we prepare to initialize.
@@ -1969,7 +2164,8 @@
bool ExynosVideoDecodeAccelerator::CreateMfcOutputBuffers() {
DVLOG(3) << "CreateMfcOutputBuffers()";
- DCHECK_EQ(decoder_state_, kInitialized);
+ DCHECK(decoder_state_ == kInitialized ||
+ decoder_state_ == kChangingResolution);
DCHECK(!mfc_output_streamon_);
DCHECK(mfc_output_buffer_map_.empty());
@@ -2026,7 +2222,8 @@
bool ExynosVideoDecodeAccelerator::CreateGscInputBuffers() {
DVLOG(3) << "CreateGscInputBuffers()";
- DCHECK_EQ(decoder_state_, kInitialized);
+ DCHECK(decoder_state_ == kInitialized ||
+ decoder_state_ == kChangingResolution);
DCHECK(!gsc_input_streamon_);
DCHECK(gsc_input_buffer_map_.empty());
@@ -2089,7 +2286,8 @@
bool ExynosVideoDecodeAccelerator::CreateGscOutputBuffers() {
DVLOG(3) << "CreateGscOutputBuffers()";
- DCHECK_EQ(decoder_state_, kInitialized);
+ DCHECK(decoder_state_ == kInitialized ||
+ decoder_state_ == kChangingResolution);
DCHECK(!gsc_output_streamon_);
DCHECK(gsc_output_buffer_map_.empty());
@@ -2216,8 +2414,11 @@
eglDestroyImageKHR(egl_display_, output_record.egl_image);
if (output_record.egl_sync != EGL_NO_SYNC_KHR)
eglDestroySyncKHR(egl_display_, output_record.egl_sync);
- if (client_)
+ if (client_) {
+ DVLOG(1) << "DestroyGscOutputBuffers(): "
+ << "dismissing PictureBuffer id=" << output_record.picture_id;
client_->DismissPictureBuffer(output_record.picture_id);
+ }
++i;
} while (i < gsc_output_buffer_map_.size());
}
@@ -2234,4 +2435,18 @@
gsc_free_output_buffers_.clear();
}
+void ExynosVideoDecodeAccelerator::ResolutionChangeDestroyBuffers() {
+ DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
+ DVLOG(3) << "ResolutionChangeDestroyBuffers()";
+
+ DestroyGscInputBuffers();
+ DestroyGscOutputBuffers();
+ DestroyMfcOutputBuffers();
+
+ // Finish resolution change on decoder thread.
+ decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ &ExynosVideoDecodeAccelerator::FinishResolutionChange,
+ base::Unretained(this)));
+}
+
} // namespace content
diff --git a/content/common/gpu/media/exynos_video_decode_accelerator.h b/content/common/gpu/media/exynos_video_decode_accelerator.h
index b1b9375..77471402 100644
--- a/content/common/gpu/media/exynos_video_decode_accelerator.h
+++ b/content/common/gpu/media/exynos_video_decode_accelerator.h
@@ -102,6 +102,8 @@
kDecoding, // DecodeBufferInitial() successful; decoding frames.
kResetting, // Presently resetting.
kAfterReset, // After Reset(), ready to start decoding again.
+ kChangingResolution, // Performing resolution change, all remaining
+ // pre-change frames decoded and processed.
kError, // Error in kDecoding state.
};
@@ -204,13 +206,16 @@
void AssignPictureBuffersTask(scoped_ptr<PictureBufferArrayRef> pic_buffers);
// Service I/O on the V4L2 devices. This task should only be scheduled from
- // DevicePollTask().
- void ServiceDeviceTask();
+ // DevicePollTask(). If |mfc_event_pending| is true, one or more events
+ // on MFC file descriptor are pending.
+ void ServiceDeviceTask(bool mfc_event_pending);
// Handle the various device queues.
void EnqueueMfc();
void DequeueMfc();
void EnqueueGsc();
void DequeueGsc();
+ // Handle incoming MFC events.
+ void DequeueMfcEvents();
// Enqueue a buffer on the corresponding queue.
bool EnqueueMfcInputRecord();
bool EnqueueMfcOutputRecord();
@@ -245,11 +250,23 @@
// Attempt to start/stop device_poll_thread_.
bool StartDevicePoll();
- bool StopDevicePoll();
+ // If |keep_mfc_input_state| is true, don't reset MFC input state; used during
+ // resolution change.
+ bool StopDevicePoll(bool keep_mfc_input_state);
// Set/clear the device poll interrupt (using device_poll_interrupt_fd_).
bool SetDevicePollInterrupt();
bool ClearDevicePollInterrupt();
+ void StartResolutionChangeIfNeeded();
+ void FinishResolutionChange();
+ void ResumeAfterResolutionChange();
+
+ // Try to get output format from MFC, detected after parsing the beginning
+ // of the stream. Sets |again| to true if more parsing is needed.
+ bool GetFormatInfo(struct v4l2_format* format, bool* again);
+ // Create MFC output and GSC input and output buffers for the given |format|.
+ bool CreateBuffersForFormat(const struct v4l2_format& format);
+
//
// Device tasks, to be run on device_poll_thread_.
//
@@ -280,11 +297,16 @@
bool CreateGscInputBuffers();
bool CreateGscOutputBuffers();
- // Destroy these buffers.
+ //
+ // Methods run on child thread.
+ //
+
+ // Destroy buffers.
void DestroyMfcInputBuffers();
void DestroyMfcOutputBuffers();
void DestroyGscInputBuffers();
void DestroyGscOutputBuffers();
+ void ResolutionChangeDestroyBuffers();
// Our original calling message loop for the child thread.
scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_;
@@ -331,6 +353,11 @@
int decoder_frames_at_client_;
// Are we flushing?
bool decoder_flushing_;
+ // Got a notification from driver that it reached resolution change point
+ // in the stream.
+ bool resolution_change_pending_;
+ // Got a reset request while we were performing resolution change.
+ bool resolution_change_reset_pending_;
// Input queue for decoder_thread_: BitstreamBuffers in.
std::list<linked_ptr<BitstreamBufferRef> > decoder_input_queue_;
// For H264 decode, hardware requires that we send it frame-sized chunks.
diff --git a/content/common/media/media_stream_messages.h b/content/common/media/media_stream_messages.h
index a388f85..8edd0e0 100644
--- a/content/common/media/media_stream_messages.h
+++ b/content/common/media/media_stream_messages.h
@@ -49,6 +49,12 @@
IPC_MESSAGE_ROUTED1(MediaStreamMsg_StreamGenerationFailed,
int /* request id */)
+// The browser requests to stop streaming.
+// Note that this differs from MediaStreamHostMsg_StopGeneratedStream below
+// which is a request from the renderer.
+IPC_MESSAGE_ROUTED1(MediaStreamMsg_StopGeneratedStream,
+ std::string /* label */)
+
// The browser has enumerated devices successfully.
// Used by Pepper.
// TODO(vrk,wjia): Move this to pepper code.
diff --git a/content/common/plugin_list.cc b/content/common/plugin_list.cc
index 79f8cc5..69102c5 100644
--- a/content/common/plugin_list.cc
+++ b/content/common/plugin_list.cc
@@ -13,9 +13,9 @@
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/public/common/content_switches.h"
#include "net/base/mime_util.h"
#include "url/gurl.h"
-#include "webkit/plugins/plugin_switches.h"
#if defined(OS_WIN)
#include "content/common/plugin_constants_win.h"
diff --git a/content/common/sandbox_seccomp_bpf_linux.cc b/content/common/sandbox_seccomp_bpf_linux.cc
index 8216549..5d8c42a 100644
--- a/content/common/sandbox_seccomp_bpf_linux.cc
+++ b/content/common/sandbox_seccomp_bpf_linux.cc
@@ -1781,6 +1781,10 @@
return true;
}
+// Files needed by the ARM GPU userspace.
+static const char kLibGlesPath[] = "/usr/lib/libGLESv2.so.2";
+static const char kLibEglPath[] = "/usr/lib/libEGL.so.1";
+
void AddArmMaliGpuWhitelist(std::vector<std::string>* read_whitelist,
std::vector<std::string>* write_whitelist) {
// Device file needed by the ARM GPU userspace.
@@ -1831,13 +1835,11 @@
std::vector<std::string>* write_whitelist) {
// On ARM we're enabling the sandbox before the X connection is made,
// so we need to allow access to |.Xauthority|.
- static const char kXAutorityPath[] = "/home/chronos/.Xauthority";
+ static const char kXAuthorityPath[] = "/home/chronos/.Xauthority";
+ static const char kLdSoCache[] = "/etc/ld.so.cache";
- // Files needed by the ARM GPU userspace.
- static const char kLibGlesPath[] = "/usr/lib/libGLESv2.so.2";
- static const char kLibEglPath[] = "/usr/lib/libEGL.so.1";
-
- read_whitelist->push_back(kXAutorityPath);
+ read_whitelist->push_back(kXAuthorityPath);
+ read_whitelist->push_back(kLdSoCache);
read_whitelist->push_back(kLibGlesPath);
read_whitelist->push_back(kLibEglPath);
@@ -1911,6 +1913,11 @@
// Create a new broker process.
InitGpuBrokerProcess(policy, broker_process);
+ // Preload the GL libraries. These are in the read whitelist but we have to
+ // preload them anyways to work around ld.so bugs. See crbug.com/268439.
+ dlopen(kLibGlesPath, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
+ dlopen(kLibEglPath, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
+
// Preload the Tegra libraries.
dlopen("/usr/lib/libnvrm.so", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
dlopen("/usr/lib/libnvrm_graphics.so", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
diff --git a/content/common/url_schemes.cc b/content/common/url_schemes.cc
index c7446a3..ac8dbf4 100644
--- a/content/common/url_schemes.cc
+++ b/content/common/url_schemes.cc
@@ -38,8 +38,8 @@
// the new tab page.
url_util::AddStandardScheme(chrome::kChromeDevToolsScheme);
url_util::AddStandardScheme(chrome::kChromeUIScheme);
- url_util::AddStandardScheme(chrome::kMetadataScheme);
url_util::AddStandardScheme(chrome::kGuestScheme);
+ url_util::AddStandardScheme(kMetadataScheme);
std::for_each(additional_standard_schemes.begin(),
additional_standard_schemes.end(),
AddStandardSchemeHelper);
diff --git a/content/content_app_both.target.darwin-arm.mk b/content/content_app_both.target.darwin-arm.mk
index e90575c..21c2dca 100644
--- a/content/content_app_both.target.darwin-arm.mk
+++ b/content/content_app_both.target.darwin-arm.mk
@@ -91,6 +91,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -201,6 +202,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/content/content_app_both.target.darwin-mips.mk b/content/content_app_both.target.darwin-mips.mk
index 292cfa3..d3ccd15 100644
--- a/content/content_app_both.target.darwin-mips.mk
+++ b/content/content_app_both.target.darwin-mips.mk
@@ -90,6 +90,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -199,6 +200,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/content/content_app_both.target.darwin-x86.mk b/content/content_app_both.target.darwin-x86.mk
index 5be1f6c..1272873 100644
--- a/content/content_app_both.target.darwin-x86.mk
+++ b/content/content_app_both.target.darwin-x86.mk
@@ -92,6 +92,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -204,6 +205,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/content/content_app_both.target.linux-arm.mk b/content/content_app_both.target.linux-arm.mk
index e90575c..21c2dca 100644
--- a/content/content_app_both.target.linux-arm.mk
+++ b/content/content_app_both.target.linux-arm.mk
@@ -91,6 +91,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -201,6 +202,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/content/content_app_both.target.linux-mips.mk b/content/content_app_both.target.linux-mips.mk
index 292cfa3..d3ccd15 100644
--- a/content/content_app_both.target.linux-mips.mk
+++ b/content/content_app_both.target.linux-mips.mk
@@ -90,6 +90,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -199,6 +200,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/content/content_app_both.target.linux-x86.mk b/content/content_app_both.target.linux-x86.mk
index 5be1f6c..1272873 100644
--- a/content/content_app_both.target.linux-x86.mk
+++ b/content/content_app_both.target.linux-x86.mk
@@ -92,6 +92,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -204,6 +205,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index b3751ac..3396cf9 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -707,6 +707,8 @@
'browser/media/media_internals_ui.h',
'browser/media/webrtc_identity_store.cc',
'browser/media/webrtc_identity_store.h',
+ 'browser/media/webrtc_identity_store_backend.cc',
+ 'browser/media/webrtc_identity_store_backend.h',
'browser/media/webrtc_internals.cc',
'browser/media/webrtc_internals.h',
'browser/media/webrtc_internals_message_handler.cc',
@@ -1290,8 +1292,8 @@
}],
['enable_webrtc==1 and (OS=="linux" or OS=="mac" or OS=="win")', {
'sources': [
- 'browser/renderer_host/media/screen_capture_device.cc',
- 'browser/renderer_host/media/screen_capture_device.h',
+ 'browser/renderer_host/media/desktop_capture_device.cc',
+ 'browser/renderer_host/media/desktop_capture_device.h',
],
'dependencies': [
'../third_party/webrtc/modules/modules.gyp:desktop_capture',
@@ -1349,14 +1351,6 @@
'../build/linux/system.gyp:udev',
'../sandbox/sandbox.gyp:libc_urandom_override',
],
- # Set LINUX_SANDBOX_PATH for Linux, including Chrome OS
- 'conditions': [
- ['linux_sandbox_path != ""', {
- 'defines': [
- 'LINUX_SANDBOX_PATH="<(linux_sandbox_path)"',
- ],
- }],
- ],
}],
['OS=="linux" and use_aura==1', {
'dependencies': [
diff --git a/content/content_browser.target.darwin-arm.mk b/content/content_browser.target.darwin-arm.mk
index 1b6db5c..6a78080 100644
--- a/content/content_browser.target.darwin-arm.mk
+++ b/content/content_browser.target.darwin-arm.mk
@@ -273,6 +273,7 @@
content/browser/media/media_internals_proxy.cc \
content/browser/media/media_internals_ui.cc \
content/browser/media/webrtc_identity_store.cc \
+ content/browser/media/webrtc_identity_store_backend.cc \
content/browser/media/webrtc_internals.cc \
content/browser/media/webrtc_internals_message_handler.cc \
content/browser/media/webrtc_internals_ui.cc \
@@ -476,6 +477,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMEDIA_DISABLE_LIBVPX' \
'-D__STDC_CONSTANT_MACROS' \
@@ -605,6 +607,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMEDIA_DISABLE_LIBVPX' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_browser.target.darwin-mips.mk b/content/content_browser.target.darwin-mips.mk
index ee0dac8..44495ca 100644
--- a/content/content_browser.target.darwin-mips.mk
+++ b/content/content_browser.target.darwin-mips.mk
@@ -273,6 +273,7 @@
content/browser/media/media_internals_proxy.cc \
content/browser/media/media_internals_ui.cc \
content/browser/media/webrtc_identity_store.cc \
+ content/browser/media/webrtc_identity_store_backend.cc \
content/browser/media/webrtc_internals.cc \
content/browser/media/webrtc_internals_message_handler.cc \
content/browser/media/webrtc_internals_ui.cc \
@@ -475,6 +476,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMEDIA_DISABLE_LIBVPX' \
'-D__STDC_CONSTANT_MACROS' \
@@ -603,6 +605,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMEDIA_DISABLE_LIBVPX' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_browser.target.darwin-x86.mk b/content/content_browser.target.darwin-x86.mk
index bac157c..cf3658e 100644
--- a/content/content_browser.target.darwin-x86.mk
+++ b/content/content_browser.target.darwin-x86.mk
@@ -273,6 +273,7 @@
content/browser/media/media_internals_proxy.cc \
content/browser/media/media_internals_ui.cc \
content/browser/media/webrtc_identity_store.cc \
+ content/browser/media/webrtc_identity_store_backend.cc \
content/browser/media/webrtc_internals.cc \
content/browser/media/webrtc_internals_message_handler.cc \
content/browser/media/webrtc_internals_ui.cc \
@@ -477,6 +478,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMEDIA_DISABLE_LIBVPX' \
'-D__STDC_CONSTANT_MACROS' \
@@ -608,6 +610,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMEDIA_DISABLE_LIBVPX' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_browser.target.linux-arm.mk b/content/content_browser.target.linux-arm.mk
index 1b6db5c..6a78080 100644
--- a/content/content_browser.target.linux-arm.mk
+++ b/content/content_browser.target.linux-arm.mk
@@ -273,6 +273,7 @@
content/browser/media/media_internals_proxy.cc \
content/browser/media/media_internals_ui.cc \
content/browser/media/webrtc_identity_store.cc \
+ content/browser/media/webrtc_identity_store_backend.cc \
content/browser/media/webrtc_internals.cc \
content/browser/media/webrtc_internals_message_handler.cc \
content/browser/media/webrtc_internals_ui.cc \
@@ -476,6 +477,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMEDIA_DISABLE_LIBVPX' \
'-D__STDC_CONSTANT_MACROS' \
@@ -605,6 +607,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMEDIA_DISABLE_LIBVPX' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_browser.target.linux-mips.mk b/content/content_browser.target.linux-mips.mk
index ee0dac8..44495ca 100644
--- a/content/content_browser.target.linux-mips.mk
+++ b/content/content_browser.target.linux-mips.mk
@@ -273,6 +273,7 @@
content/browser/media/media_internals_proxy.cc \
content/browser/media/media_internals_ui.cc \
content/browser/media/webrtc_identity_store.cc \
+ content/browser/media/webrtc_identity_store_backend.cc \
content/browser/media/webrtc_internals.cc \
content/browser/media/webrtc_internals_message_handler.cc \
content/browser/media/webrtc_internals_ui.cc \
@@ -475,6 +476,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMEDIA_DISABLE_LIBVPX' \
'-D__STDC_CONSTANT_MACROS' \
@@ -603,6 +605,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMEDIA_DISABLE_LIBVPX' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_browser.target.linux-x86.mk b/content/content_browser.target.linux-x86.mk
index bac157c..cf3658e 100644
--- a/content/content_browser.target.linux-x86.mk
+++ b/content/content_browser.target.linux-x86.mk
@@ -273,6 +273,7 @@
content/browser/media/media_internals_proxy.cc \
content/browser/media/media_internals_ui.cc \
content/browser/media/webrtc_identity_store.cc \
+ content/browser/media/webrtc_identity_store_backend.cc \
content/browser/media/webrtc_internals.cc \
content/browser/media/webrtc_internals_message_handler.cc \
content/browser/media/webrtc_internals_ui.cc \
@@ -477,6 +478,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMEDIA_DISABLE_LIBVPX' \
'-D__STDC_CONSTANT_MACROS' \
@@ -608,6 +610,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMEDIA_DISABLE_LIBVPX' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_child.gypi b/content/content_child.gypi
index b0c18ed..dd980e3 100644
--- a/content/content_child.gypi
+++ b/content/content_child.gypi
@@ -19,10 +19,14 @@
'sources': [
'child/android/child_jni_registrar.cc',
'child/android/child_jni_registrar.h',
- 'child/appcache_backend_proxy.cc',
- 'child/appcache_backend_proxy.h',
- 'child/appcache_dispatcher.cc',
- 'child/appcache_dispatcher.h',
+ 'child/appcache/appcache_backend_proxy.cc',
+ 'child/appcache/appcache_backend_proxy.h',
+ 'child/appcache/appcache_dispatcher.cc',
+ 'child/appcache/appcache_dispatcher.h',
+ 'child/appcache/appcache_frontend_impl.cc',
+ 'child/appcache/appcache_frontend_impl.h',
+ 'child/appcache/web_application_cache_host_impl.cc',
+ 'child/appcache/web_application_cache_host_impl.h',
'child/browser_font_resource_trusted.cc',
'child/browser_font_resource_trusted.h',
'child/child_histogram_message_filter.cc',
diff --git a/content/content_child.target.darwin-arm.mk b/content/content_child.target.darwin-arm.mk
index 264be10..abeb044 100644
--- a/content/content_child.target.darwin-arm.mk
+++ b/content/content_child.target.darwin-arm.mk
@@ -31,8 +31,10 @@
LOCAL_SRC_FILES := \
content/child/android/child_jni_registrar.cc \
- content/child/appcache_backend_proxy.cc \
- content/child/appcache_dispatcher.cc \
+ content/child/appcache/appcache_backend_proxy.cc \
+ content/child/appcache/appcache_dispatcher.cc \
+ content/child/appcache/appcache_frontend_impl.cc \
+ content/child/appcache/web_application_cache_host_impl.cc \
content/child/child_histogram_message_filter.cc \
content/child/child_process.cc \
content/child/child_resource_message_filter.cc \
@@ -125,6 +127,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -239,6 +242,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_child.target.darwin-mips.mk b/content/content_child.target.darwin-mips.mk
index aea02dd..ef40461 100644
--- a/content/content_child.target.darwin-mips.mk
+++ b/content/content_child.target.darwin-mips.mk
@@ -31,8 +31,10 @@
LOCAL_SRC_FILES := \
content/child/android/child_jni_registrar.cc \
- content/child/appcache_backend_proxy.cc \
- content/child/appcache_dispatcher.cc \
+ content/child/appcache/appcache_backend_proxy.cc \
+ content/child/appcache/appcache_dispatcher.cc \
+ content/child/appcache/appcache_frontend_impl.cc \
+ content/child/appcache/web_application_cache_host_impl.cc \
content/child/child_histogram_message_filter.cc \
content/child/child_process.cc \
content/child/child_resource_message_filter.cc \
@@ -124,6 +126,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -237,6 +240,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_child.target.darwin-x86.mk b/content/content_child.target.darwin-x86.mk
index affffa7..8eb7fa0 100644
--- a/content/content_child.target.darwin-x86.mk
+++ b/content/content_child.target.darwin-x86.mk
@@ -31,8 +31,10 @@
LOCAL_SRC_FILES := \
content/child/android/child_jni_registrar.cc \
- content/child/appcache_backend_proxy.cc \
- content/child/appcache_dispatcher.cc \
+ content/child/appcache/appcache_backend_proxy.cc \
+ content/child/appcache/appcache_dispatcher.cc \
+ content/child/appcache/appcache_frontend_impl.cc \
+ content/child/appcache/web_application_cache_host_impl.cc \
content/child/child_histogram_message_filter.cc \
content/child/child_process.cc \
content/child/child_resource_message_filter.cc \
@@ -127,6 +129,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -243,6 +246,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_child.target.linux-arm.mk b/content/content_child.target.linux-arm.mk
index 264be10..abeb044 100644
--- a/content/content_child.target.linux-arm.mk
+++ b/content/content_child.target.linux-arm.mk
@@ -31,8 +31,10 @@
LOCAL_SRC_FILES := \
content/child/android/child_jni_registrar.cc \
- content/child/appcache_backend_proxy.cc \
- content/child/appcache_dispatcher.cc \
+ content/child/appcache/appcache_backend_proxy.cc \
+ content/child/appcache/appcache_dispatcher.cc \
+ content/child/appcache/appcache_frontend_impl.cc \
+ content/child/appcache/web_application_cache_host_impl.cc \
content/child/child_histogram_message_filter.cc \
content/child/child_process.cc \
content/child/child_resource_message_filter.cc \
@@ -125,6 +127,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -239,6 +242,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_child.target.linux-mips.mk b/content/content_child.target.linux-mips.mk
index aea02dd..ef40461 100644
--- a/content/content_child.target.linux-mips.mk
+++ b/content/content_child.target.linux-mips.mk
@@ -31,8 +31,10 @@
LOCAL_SRC_FILES := \
content/child/android/child_jni_registrar.cc \
- content/child/appcache_backend_proxy.cc \
- content/child/appcache_dispatcher.cc \
+ content/child/appcache/appcache_backend_proxy.cc \
+ content/child/appcache/appcache_dispatcher.cc \
+ content/child/appcache/appcache_frontend_impl.cc \
+ content/child/appcache/web_application_cache_host_impl.cc \
content/child/child_histogram_message_filter.cc \
content/child/child_process.cc \
content/child/child_resource_message_filter.cc \
@@ -124,6 +126,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -237,6 +240,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_child.target.linux-x86.mk b/content/content_child.target.linux-x86.mk
index affffa7..8eb7fa0 100644
--- a/content/content_child.target.linux-x86.mk
+++ b/content/content_child.target.linux-x86.mk
@@ -31,8 +31,10 @@
LOCAL_SRC_FILES := \
content/child/android/child_jni_registrar.cc \
- content/child/appcache_backend_proxy.cc \
- content/child/appcache_dispatcher.cc \
+ content/child/appcache/appcache_backend_proxy.cc \
+ content/child/appcache/appcache_dispatcher.cc \
+ content/child/appcache/appcache_frontend_impl.cc \
+ content/child/appcache/web_application_cache_host_impl.cc \
content/child/child_histogram_message_filter.cc \
content/child/child_process.cc \
content/child/child_resource_message_filter.cc \
@@ -127,6 +129,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -243,6 +246,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_common.gypi b/content/content_common.gypi
index 42a345b..f7413b5 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -37,6 +37,8 @@
'public/common/context_menu_params.cc',
'public/common/context_menu_params.h',
'public/common/console_message_level.h',
+ 'public/common/desktop_media_id.cc',
+ 'public/common/desktop_media_id.h',
'public/common/drop_data.cc',
'public/common/drop_data.h',
'public/common/favicon_url.cc',
diff --git a/content/content_common.target.darwin-arm.mk b/content/content_common.target.darwin-arm.mk
index d1a213b..9738bb5 100644
--- a/content/content_common.target.darwin-arm.mk
+++ b/content/content_common.target.darwin-arm.mk
@@ -37,6 +37,7 @@
content/public/common/content_constants.cc \
content/public/common/content_switches.cc \
content/public/common/context_menu_params.cc \
+ content/public/common/desktop_media_id.cc \
content/public/common/drop_data.cc \
content/public/common/favicon_url.cc \
content/public/common/file_chooser_params.cc \
@@ -193,6 +194,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
@@ -309,6 +311,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_common.target.darwin-mips.mk b/content/content_common.target.darwin-mips.mk
index ba84ef0..d2200cc 100644
--- a/content/content_common.target.darwin-mips.mk
+++ b/content/content_common.target.darwin-mips.mk
@@ -37,6 +37,7 @@
content/public/common/content_constants.cc \
content/public/common/content_switches.cc \
content/public/common/context_menu_params.cc \
+ content/public/common/desktop_media_id.cc \
content/public/common/drop_data.cc \
content/public/common/favicon_url.cc \
content/public/common/file_chooser_params.cc \
@@ -192,6 +193,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
@@ -307,6 +309,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_common.target.darwin-x86.mk b/content/content_common.target.darwin-x86.mk
index 9d0a842..c4449d0 100644
--- a/content/content_common.target.darwin-x86.mk
+++ b/content/content_common.target.darwin-x86.mk
@@ -37,6 +37,7 @@
content/public/common/content_constants.cc \
content/public/common/content_switches.cc \
content/public/common/context_menu_params.cc \
+ content/public/common/desktop_media_id.cc \
content/public/common/drop_data.cc \
content/public/common/favicon_url.cc \
content/public/common/file_chooser_params.cc \
@@ -194,6 +195,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
@@ -312,6 +314,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_common.target.linux-arm.mk b/content/content_common.target.linux-arm.mk
index d1a213b..9738bb5 100644
--- a/content/content_common.target.linux-arm.mk
+++ b/content/content_common.target.linux-arm.mk
@@ -37,6 +37,7 @@
content/public/common/content_constants.cc \
content/public/common/content_switches.cc \
content/public/common/context_menu_params.cc \
+ content/public/common/desktop_media_id.cc \
content/public/common/drop_data.cc \
content/public/common/favicon_url.cc \
content/public/common/file_chooser_params.cc \
@@ -193,6 +194,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
@@ -309,6 +311,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_common.target.linux-mips.mk b/content/content_common.target.linux-mips.mk
index ba84ef0..d2200cc 100644
--- a/content/content_common.target.linux-mips.mk
+++ b/content/content_common.target.linux-mips.mk
@@ -37,6 +37,7 @@
content/public/common/content_constants.cc \
content/public/common/content_switches.cc \
content/public/common/context_menu_params.cc \
+ content/public/common/desktop_media_id.cc \
content/public/common/drop_data.cc \
content/public/common/favicon_url.cc \
content/public/common/file_chooser_params.cc \
@@ -192,6 +193,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
@@ -307,6 +309,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_common.target.linux-x86.mk b/content/content_common.target.linux-x86.mk
index 9d0a842..c4449d0 100644
--- a/content/content_common.target.linux-x86.mk
+++ b/content/content_common.target.linux-x86.mk
@@ -37,6 +37,7 @@
content/public/common/content_constants.cc \
content/public/common/content_switches.cc \
content/public/common/context_menu_params.cc \
+ content/public/common/desktop_media_id.cc \
content/public/common/drop_data.cc \
content/public/common/favicon_url.cc \
content/public/common/file_chooser_params.cc \
@@ -194,6 +195,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
@@ -312,6 +314,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/content/content_gpu.target.darwin-arm.mk b/content/content_gpu.target.darwin-arm.mk
index b6b56ad..46eec2f 100644
--- a/content/content_gpu.target.darwin-arm.mk
+++ b/content/content_gpu.target.darwin-arm.mk
@@ -87,6 +87,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -196,6 +197,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_gpu.target.darwin-mips.mk b/content/content_gpu.target.darwin-mips.mk
index 2f69c62..248aea2 100644
--- a/content/content_gpu.target.darwin-mips.mk
+++ b/content/content_gpu.target.darwin-mips.mk
@@ -86,6 +86,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -194,6 +195,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_gpu.target.darwin-x86.mk b/content/content_gpu.target.darwin-x86.mk
index 868fb4e..b2e3430 100644
--- a/content/content_gpu.target.darwin-x86.mk
+++ b/content/content_gpu.target.darwin-x86.mk
@@ -89,6 +89,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -201,6 +202,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_gpu.target.linux-arm.mk b/content/content_gpu.target.linux-arm.mk
index b6b56ad..46eec2f 100644
--- a/content/content_gpu.target.linux-arm.mk
+++ b/content/content_gpu.target.linux-arm.mk
@@ -87,6 +87,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -196,6 +197,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_gpu.target.linux-mips.mk b/content/content_gpu.target.linux-mips.mk
index 2f69c62..248aea2 100644
--- a/content/content_gpu.target.linux-mips.mk
+++ b/content/content_gpu.target.linux-mips.mk
@@ -86,6 +86,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -194,6 +195,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_gpu.target.linux-x86.mk b/content/content_gpu.target.linux-x86.mk
index 868fb4e..b2e3430 100644
--- a/content/content_gpu.target.linux-x86.mk
+++ b/content/content_gpu.target.linux-x86.mk
@@ -89,6 +89,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -201,6 +202,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/content/content_plugin.gypi b/content/content_plugin.gypi
index e00e563..7ff4221 100644
--- a/content/content_plugin.gypi
+++ b/content/content_plugin.gypi
@@ -9,9 +9,7 @@
'../skia/skia.gyp:skia',
'../third_party/npapi/npapi.gyp:npapi',
'../third_party/WebKit/public/blink.gyp:blink',
- '../webkit/plugins/webkit_plugins.gyp:plugins_common',
'../webkit/support/webkit_support.gyp:glue',
- '../webkit/support/webkit_support.gyp:plugins',
],
'include_dirs': [
'<(INTERMEDIATE_DIR)',
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index 25ad0ea..4b011ab 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -19,7 +19,6 @@
'../v8/tools/gyp/v8.gyp:v8',
'../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu',
'../webkit/common/webkit_common.gyp:webkit_common',
- '../webkit/plugins/webkit_plugins.gyp:plugins_common',
'../webkit/renderer/compositor_bindings/compositor_bindings.gyp:webkit_compositor_bindings',
'../webkit/renderer/compositor_bindings/compositor_bindings.gyp:webkit_compositor_support',
'../webkit/renderer/webkit_renderer.gyp:webkit_renderer',
@@ -27,7 +26,6 @@
'../webkit/storage_renderer.gyp:webkit_storage_renderer',
'../webkit/support/webkit_support.gyp:glue',
'../webkit/support/webkit_support.gyp:glue_child',
- '../webkit/support/webkit_support.gyp:plugins',
],
'include_dirs': [
'..',
@@ -69,8 +67,6 @@
'renderer/accessibility/renderer_accessibility_focus_only.h',
'renderer/active_notification_tracker.cc',
'renderer/active_notification_tracker.h',
- 'renderer/all_rendering_benchmarks.cc',
- 'renderer/all_rendering_benchmarks.h',
'renderer/android/address_detector.cc',
'renderer/android/address_detector.h',
'renderer/android/content_detector.cc',
@@ -167,8 +163,11 @@
'renderer/media/android/proxy_media_keys.h',
'renderer/media/android/renderer_media_player_manager.cc',
'renderer/media/android/renderer_media_player_manager.h',
- 'renderer/media/android/stream_texture_factory_android.cc',
'renderer/media/android/stream_texture_factory_android.h',
+ 'renderer/media/android/stream_texture_factory_android_impl.cc',
+ 'renderer/media/android/stream_texture_factory_android_impl.h',
+ 'renderer/media/android/stream_texture_factory_android_synchronous_impl.cc',
+ 'renderer/media/android/stream_texture_factory_android_synchronous_impl.h',
'renderer/media/android/webmediaplayer_android.cc',
'renderer/media/android/webmediaplayer_android.h',
'renderer/media/android/webmediaplayer_proxy_android.cc',
@@ -356,8 +355,6 @@
'renderer/pepper/ppb_broker_impl.h',
'renderer/pepper/ppb_buffer_impl.cc',
'renderer/pepper/ppb_buffer_impl.h',
- 'renderer/pepper/ppb_file_ref_impl.cc',
- 'renderer/pepper/ppb_file_ref_impl.h',
'renderer/pepper/ppb_flash_message_loop_impl.cc',
'renderer/pepper/ppb_flash_message_loop_impl.h',
'renderer/pepper/ppb_gpu_blacklist_private_impl.cc',
@@ -478,6 +475,8 @@
'renderer/renderer_webkitplatformsupport_impl.h',
'renderer/rendering_benchmark.cc',
'renderer/rendering_benchmark.h',
+ 'renderer/sad_plugin.cc',
+ 'renderer/sad_plugin.h',
'renderer/savable_resources.cc',
'renderer/savable_resources.h',
'renderer/scoped_clipboard_writer_glue.cc',
diff --git a/content/content_renderer.target.darwin-arm.mk b/content/content_renderer.target.darwin-arm.mk
index 4fb613c..8679aad 100644
--- a/content/content_renderer.target.darwin-arm.mk
+++ b/content/content_renderer.target.darwin-arm.mk
@@ -48,7 +48,6 @@
content/renderer/accessibility/renderer_accessibility.cc \
content/renderer/accessibility/renderer_accessibility_complete.cc \
content/renderer/accessibility/renderer_accessibility_focus_only.cc \
- content/renderer/all_rendering_benchmarks.cc \
content/renderer/android/address_detector.cc \
content/renderer/android/content_detector.cc \
content/renderer/android/email_detector.cc \
@@ -95,7 +94,8 @@
content/renderer/media/android/media_source_delegate.cc \
content/renderer/media/android/proxy_media_keys.cc \
content/renderer/media/android/renderer_media_player_manager.cc \
- content/renderer/media/android/stream_texture_factory_android.cc \
+ content/renderer/media/android/stream_texture_factory_android_impl.cc \
+ content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc \
content/renderer/media/android/webmediaplayer_android.cc \
content/renderer/media/android/webmediaplayer_proxy_android.cc \
content/renderer/media/audio_decoder.cc \
@@ -171,6 +171,7 @@
content/renderer/renderer_webcolorchooser_impl.cc \
content/renderer/renderer_webkitplatformsupport_impl.cc \
content/renderer/rendering_benchmark.cc \
+ content/renderer/sad_plugin.cc \
content/renderer/savable_resources.cc \
content/renderer/scoped_clipboard_writer_glue.cc \
content/renderer/shared_memory_seqlock_reader.cc \
@@ -244,6 +245,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -385,6 +387,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/content/content_renderer.target.darwin-mips.mk b/content/content_renderer.target.darwin-mips.mk
index 5ccec42..09fe76f 100644
--- a/content/content_renderer.target.darwin-mips.mk
+++ b/content/content_renderer.target.darwin-mips.mk
@@ -48,7 +48,6 @@
content/renderer/accessibility/renderer_accessibility.cc \
content/renderer/accessibility/renderer_accessibility_complete.cc \
content/renderer/accessibility/renderer_accessibility_focus_only.cc \
- content/renderer/all_rendering_benchmarks.cc \
content/renderer/android/address_detector.cc \
content/renderer/android/content_detector.cc \
content/renderer/android/email_detector.cc \
@@ -95,7 +94,8 @@
content/renderer/media/android/media_source_delegate.cc \
content/renderer/media/android/proxy_media_keys.cc \
content/renderer/media/android/renderer_media_player_manager.cc \
- content/renderer/media/android/stream_texture_factory_android.cc \
+ content/renderer/media/android/stream_texture_factory_android_impl.cc \
+ content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc \
content/renderer/media/android/webmediaplayer_android.cc \
content/renderer/media/android/webmediaplayer_proxy_android.cc \
content/renderer/media/audio_decoder.cc \
@@ -171,6 +171,7 @@
content/renderer/renderer_webcolorchooser_impl.cc \
content/renderer/renderer_webkitplatformsupport_impl.cc \
content/renderer/rendering_benchmark.cc \
+ content/renderer/sad_plugin.cc \
content/renderer/savable_resources.cc \
content/renderer/scoped_clipboard_writer_glue.cc \
content/renderer/shared_memory_seqlock_reader.cc \
@@ -243,6 +244,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -383,6 +385,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/content/content_renderer.target.darwin-x86.mk b/content/content_renderer.target.darwin-x86.mk
index 1db78f3..ad20f15 100644
--- a/content/content_renderer.target.darwin-x86.mk
+++ b/content/content_renderer.target.darwin-x86.mk
@@ -48,7 +48,6 @@
content/renderer/accessibility/renderer_accessibility.cc \
content/renderer/accessibility/renderer_accessibility_complete.cc \
content/renderer/accessibility/renderer_accessibility_focus_only.cc \
- content/renderer/all_rendering_benchmarks.cc \
content/renderer/android/address_detector.cc \
content/renderer/android/content_detector.cc \
content/renderer/android/email_detector.cc \
@@ -95,7 +94,8 @@
content/renderer/media/android/media_source_delegate.cc \
content/renderer/media/android/proxy_media_keys.cc \
content/renderer/media/android/renderer_media_player_manager.cc \
- content/renderer/media/android/stream_texture_factory_android.cc \
+ content/renderer/media/android/stream_texture_factory_android_impl.cc \
+ content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc \
content/renderer/media/android/webmediaplayer_android.cc \
content/renderer/media/android/webmediaplayer_proxy_android.cc \
content/renderer/media/audio_decoder.cc \
@@ -171,6 +171,7 @@
content/renderer/renderer_webcolorchooser_impl.cc \
content/renderer/renderer_webkitplatformsupport_impl.cc \
content/renderer/rendering_benchmark.cc \
+ content/renderer/sad_plugin.cc \
content/renderer/savable_resources.cc \
content/renderer/scoped_clipboard_writer_glue.cc \
content/renderer/shared_memory_seqlock_reader.cc \
@@ -245,6 +246,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -388,6 +390,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/content/content_renderer.target.linux-arm.mk b/content/content_renderer.target.linux-arm.mk
index 4fb613c..8679aad 100644
--- a/content/content_renderer.target.linux-arm.mk
+++ b/content/content_renderer.target.linux-arm.mk
@@ -48,7 +48,6 @@
content/renderer/accessibility/renderer_accessibility.cc \
content/renderer/accessibility/renderer_accessibility_complete.cc \
content/renderer/accessibility/renderer_accessibility_focus_only.cc \
- content/renderer/all_rendering_benchmarks.cc \
content/renderer/android/address_detector.cc \
content/renderer/android/content_detector.cc \
content/renderer/android/email_detector.cc \
@@ -95,7 +94,8 @@
content/renderer/media/android/media_source_delegate.cc \
content/renderer/media/android/proxy_media_keys.cc \
content/renderer/media/android/renderer_media_player_manager.cc \
- content/renderer/media/android/stream_texture_factory_android.cc \
+ content/renderer/media/android/stream_texture_factory_android_impl.cc \
+ content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc \
content/renderer/media/android/webmediaplayer_android.cc \
content/renderer/media/android/webmediaplayer_proxy_android.cc \
content/renderer/media/audio_decoder.cc \
@@ -171,6 +171,7 @@
content/renderer/renderer_webcolorchooser_impl.cc \
content/renderer/renderer_webkitplatformsupport_impl.cc \
content/renderer/rendering_benchmark.cc \
+ content/renderer/sad_plugin.cc \
content/renderer/savable_resources.cc \
content/renderer/scoped_clipboard_writer_glue.cc \
content/renderer/shared_memory_seqlock_reader.cc \
@@ -244,6 +245,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -385,6 +387,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/content/content_renderer.target.linux-mips.mk b/content/content_renderer.target.linux-mips.mk
index 5ccec42..09fe76f 100644
--- a/content/content_renderer.target.linux-mips.mk
+++ b/content/content_renderer.target.linux-mips.mk
@@ -48,7 +48,6 @@
content/renderer/accessibility/renderer_accessibility.cc \
content/renderer/accessibility/renderer_accessibility_complete.cc \
content/renderer/accessibility/renderer_accessibility_focus_only.cc \
- content/renderer/all_rendering_benchmarks.cc \
content/renderer/android/address_detector.cc \
content/renderer/android/content_detector.cc \
content/renderer/android/email_detector.cc \
@@ -95,7 +94,8 @@
content/renderer/media/android/media_source_delegate.cc \
content/renderer/media/android/proxy_media_keys.cc \
content/renderer/media/android/renderer_media_player_manager.cc \
- content/renderer/media/android/stream_texture_factory_android.cc \
+ content/renderer/media/android/stream_texture_factory_android_impl.cc \
+ content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc \
content/renderer/media/android/webmediaplayer_android.cc \
content/renderer/media/android/webmediaplayer_proxy_android.cc \
content/renderer/media/audio_decoder.cc \
@@ -171,6 +171,7 @@
content/renderer/renderer_webcolorchooser_impl.cc \
content/renderer/renderer_webkitplatformsupport_impl.cc \
content/renderer/rendering_benchmark.cc \
+ content/renderer/sad_plugin.cc \
content/renderer/savable_resources.cc \
content/renderer/scoped_clipboard_writer_glue.cc \
content/renderer/shared_memory_seqlock_reader.cc \
@@ -243,6 +244,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -383,6 +385,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/content/content_renderer.target.linux-x86.mk b/content/content_renderer.target.linux-x86.mk
index 1db78f3..ad20f15 100644
--- a/content/content_renderer.target.linux-x86.mk
+++ b/content/content_renderer.target.linux-x86.mk
@@ -48,7 +48,6 @@
content/renderer/accessibility/renderer_accessibility.cc \
content/renderer/accessibility/renderer_accessibility_complete.cc \
content/renderer/accessibility/renderer_accessibility_focus_only.cc \
- content/renderer/all_rendering_benchmarks.cc \
content/renderer/android/address_detector.cc \
content/renderer/android/content_detector.cc \
content/renderer/android/email_detector.cc \
@@ -95,7 +94,8 @@
content/renderer/media/android/media_source_delegate.cc \
content/renderer/media/android/proxy_media_keys.cc \
content/renderer/media/android/renderer_media_player_manager.cc \
- content/renderer/media/android/stream_texture_factory_android.cc \
+ content/renderer/media/android/stream_texture_factory_android_impl.cc \
+ content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc \
content/renderer/media/android/webmediaplayer_android.cc \
content/renderer/media/android/webmediaplayer_proxy_android.cc \
content/renderer/media/audio_decoder.cc \
@@ -171,6 +171,7 @@
content/renderer/renderer_webcolorchooser_impl.cc \
content/renderer/renderer_webkitplatformsupport_impl.cc \
content/renderer/rendering_benchmark.cc \
+ content/renderer/sad_plugin.cc \
content/renderer/savable_resources.cc \
content/renderer/scoped_clipboard_writer_glue.cc \
content/renderer/shared_memory_seqlock_reader.cc \
@@ -245,6 +246,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
@@ -388,6 +390,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DFEATURE_ENABLE_SSL' \
'-DFEATURE_ENABLE_VOICEMAIL' \
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index bbd785c..115ba8a 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -175,7 +175,7 @@
'../ppapi/ppapi_internal.gyp:ppapi_shared',
'../ppapi/ppapi_internal.gyp:ppapi_unittest_shared',
'../third_party/WebKit/public/blink.gyp:blink',
- '../third_party/WebKit/Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp:TestRunner',
+ '../third_party/WebKit/public/blink_test_runner.gyp:blink_test_runner',
'../ui/surface/surface.gyp:surface',
'../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu',
'../webkit/renderer/compositor_bindings/compositor_bindings.gyp:webkit_compositor_support',
@@ -586,15 +586,12 @@
'../ui/gl/gl.gyp:gl',
'../v8/tools/gyp/v8.gyp:v8',
'../webkit/common/webkit_common.gyp:webkit_common',
- '../webkit/plugins/webkit_plugins.gyp:plugins_common',
'../webkit/renderer/webkit_renderer.gyp:webkit_renderer',
'../webkit/storage_browser.gyp:webkit_storage_browser',
'../webkit/storage_common.gyp:webkit_storage_common',
'../webkit/storage_renderer.gyp:webkit_storage_renderer',
'../webkit/support/webkit_support.gyp:glue',
'../webkit/support/webkit_support.gyp:glue_child',
- '../webkit/support/webkit_support.gyp:plugins',
- '../webkit/plugins/webkit_plugins.gyp:plugins_common',
],
}],
['enable_plugins==0', {
@@ -640,7 +637,7 @@
}],
['enable_webrtc==1 and (OS=="linux" or OS=="mac" or OS=="win")', {
'sources': [
- 'browser/renderer_host/media/screen_capture_device_unittest.cc',
+ 'browser/renderer_host/media/desktop_capture_device_unittest.cc',
],
'dependencies': [
'../third_party/webrtc/modules/modules.gyp:desktop_capture',
@@ -776,7 +773,6 @@
'../webkit/renderer/webkit_renderer.gyp:webkit_renderer',
'../webkit/support/webkit_support.gyp:glue',
'../webkit/support/webkit_support.gyp:glue_child',
- '../webkit/plugins/webkit_plugins.gyp:plugins_common',
],
'include_dirs': [
'..',
@@ -955,6 +951,7 @@
'browser/accessibility/accessibility_win_browsertest.cc',
'browser/accessibility/dump_accessibility_tree_browsertest.cc',
'browser/plugin_browsertest.cc',
+ 'browser/renderer_host/render_widget_host_view_win_browsertest.cc',
],
}],
['OS!="android" and OS!="ios"', {
@@ -982,7 +979,7 @@
'dependencies': [
# Runtime dependencies.
'../third_party/widevine/cdm/widevine_cdm.gyp:widevinecdmadapter',
- '../webkit/support/webkit_support.gyp:clearkeycdmadapter',
+ '../media/media.gyp:clearkeycdmadapter',
],
}],
['input_speech==0', {
diff --git a/content/plugin/DEPS b/content/plugin/DEPS
index 71cb2f3..a87bacc 100644
--- a/content/plugin/DEPS
+++ b/content/plugin/DEPS
@@ -6,6 +6,5 @@
"+skia/ext",
"+third_party/npapi",
"+webkit/glue",
- "+webkit/plugins",
]
diff --git a/content/ppapi_plugin/ppapi_thread.cc b/content/ppapi_plugin/ppapi_thread.cc
index 2315729..73d51ad 100644
--- a/content/ppapi_plugin/ppapi_thread.cc
+++ b/content/ppapi_plugin/ppapi_thread.cc
@@ -23,6 +23,7 @@
#include "content/ppapi_plugin/plugin_process_dispatcher.h"
#include "content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/pepper_plugin_info.h"
#include "content/public/common/sandbox_init.h"
#include "content/public/plugin/content_plugin_client.h"
@@ -39,7 +40,6 @@
#include "ppapi/shared_impl/api_id.h"
#include "third_party/WebKit/public/web/WebKit.h"
#include "ui/base/ui_base_switches.h"
-#include "webkit/plugins/plugin_switches.h"
#if defined(OS_WIN)
#include "base/win/win_util.h"
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
index de71a63..db41c53 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java
@@ -116,26 +116,26 @@
// Service class for child process. As the default value it uses SandboxedProcessService0 and
// PrivilegedProcessService0.
- private static final ChildConnectionAllocator mSandboxedChildConnectionAllocator =
+ private static final ChildConnectionAllocator sSandboxedChildConnectionAllocator =
new ChildConnectionAllocator(true);
- private static final ChildConnectionAllocator mPrivilegedChildConnectionAllocator =
+ private static final ChildConnectionAllocator sPrivilegedChildConnectionAllocator =
new ChildConnectionAllocator(false);
- private static boolean mConnectionAllocated = false;
+ private static boolean sConnectionAllocated = false;
// Sets service class for sandboxed service and privileged service.
public static void setChildProcessClass(
Class<? extends SandboxedProcessService> sandboxedServiceClass,
Class<? extends PrivilegedProcessService> privilegedServiceClass) {
// We should guarantee this is called before allocating connection.
- assert !mConnectionAllocated;
- mSandboxedChildConnectionAllocator.setServiceClass(sandboxedServiceClass);
- mPrivilegedChildConnectionAllocator.setServiceClass(privilegedServiceClass);
+ assert !sConnectionAllocated;
+ sSandboxedChildConnectionAllocator.setServiceClass(sandboxedServiceClass);
+ sPrivilegedChildConnectionAllocator.setServiceClass(privilegedServiceClass);
}
private static ChildConnectionAllocator getConnectionAllocator(boolean inSandbox) {
return inSandbox ?
- mSandboxedChildConnectionAllocator : mPrivilegedChildConnectionAllocator;
+ sSandboxedChildConnectionAllocator : sPrivilegedChildConnectionAllocator;
}
private static ChildProcessConnection allocateConnection(Context context,
@@ -147,7 +147,7 @@
stop(pid);
}
};
- mConnectionAllocated = true;
+ sConnectionAllocated = true;
return getConnectionAllocator(inSandbox).allocate(context, deathCallback);
}
@@ -172,7 +172,7 @@
private static final int NULL_PROCESS_HANDLE = 0;
// Map from pid to ChildService connection.
- private static Map<Integer, ChildProcessConnection> mServiceMap =
+ private static Map<Integer, ChildProcessConnection> sServiceMap =
new ConcurrentHashMap<Integer, ChildProcessConnection>();
// Map from pid to the count of oom bindings. "Oom binding" is a binding that raises the process
@@ -181,7 +181,7 @@
private static SparseIntArray sOomBindingCount = new SparseIntArray();
// A pre-allocated and pre-bound connection ready for connection setup, or null.
- static ChildProcessConnection mSpareSandboxedConnection = null;
+ private static ChildProcessConnection sSpareSandboxedConnection = null;
/**
* Returns the child process service interface for the given pid. This may be called on
@@ -192,7 +192,7 @@
* @return The IChildProcessService or null if the service no longer exists.
*/
public static IChildProcessService getChildService(int pid) {
- ChildProcessConnection connection = mServiceMap.get(pid);
+ ChildProcessConnection connection = sServiceMap.get(pid);
if (connection != null) {
return connection.getService();
}
@@ -208,8 +208,8 @@
public static void warmUp(Context context) {
synchronized (ChildProcessLauncher.class) {
assert !ThreadUtils.runningOnUiThread();
- if (mSpareSandboxedConnection == null) {
- mSpareSandboxedConnection = allocateBoundConnection(context, null, true);
+ if (sSpareSandboxedConnection == null) {
+ sSpareSandboxedConnection = allocateBoundConnection(context, null, true);
}
}
}
@@ -272,8 +272,8 @@
ChildProcessConnection allocatedConnection = null;
synchronized (ChildProcessLauncher.class) {
if (inSandbox) {
- allocatedConnection = mSpareSandboxedConnection;
- mSpareSandboxedConnection = null;
+ allocatedConnection = sSpareSandboxedConnection;
+ sSpareSandboxedConnection = null;
}
}
if (allocatedConnection == null) {
@@ -293,7 +293,7 @@
Log.d(TAG, "on connect callback, pid=" + pid + " context=" + clientContext);
if (pid != NULL_PROCESS_HANDLE) {
sOomBindingCount.put(pid, oomBindingCount);
- mServiceMap.put(pid, connection);
+ sServiceMap.put(pid, connection);
} else {
freeConnection(connection);
}
@@ -335,7 +335,7 @@
@CalledByNative
static void stop(int pid) {
Log.d(TAG, "stopping child connection: pid=" + pid);
- ChildProcessConnection connection = mServiceMap.remove(pid);
+ ChildProcessConnection connection = sServiceMap.remove(pid);
if (connection == null) {
LogPidWarning(pid, "Tried to stop non-existent connection");
return;
@@ -350,7 +350,7 @@
* binding once it is no longer needed.
*/
static void removeInitialBinding(int pid) {
- ChildProcessConnection connection = mServiceMap.get(pid);
+ ChildProcessConnection connection = sServiceMap.get(pid);
if (connection == null) {
LogPidWarning(pid, "Tried to remove a binding for a non-existent connection");
return;
@@ -366,7 +366,7 @@
* @param pid The process handle of the service connection obtained from {@link #start}.
*/
static void bindAsHighPriority(int pid) {
- ChildProcessConnection connection = mServiceMap.get(pid);
+ ChildProcessConnection connection = sServiceMap.get(pid);
if (connection == null) {
LogPidWarning(pid, "Tried to bind a non-existent connection");
return;
@@ -380,7 +380,7 @@
* @param pid The process handle of the service obtained from {@link #start}.
*/
static void unbindAsHighPriority(int pid) {
- ChildProcessConnection connection = mServiceMap.get(pid);
+ ChildProcessConnection connection = sServiceMap.get(pid);
if (connection == null) {
LogPidWarning(pid, "Tried to unbind non-existent connection");
return;
@@ -392,7 +392,7 @@
* @return True iff the given service process is protected from the out-of-memory killing, or it
* was protected from it when it died.
*/
- public static boolean isOomProtected(int pid) {
+ static boolean isOomProtected(int pid) {
return sOomBindingCount.get(pid) > 0;
}
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentView.java b/content/public/android/java/src/org/chromium/content/browser/ContentView.java
index 135cb26..9a19f97 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentView.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentView.java
@@ -96,6 +96,11 @@
AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ if (getScrollBarStyle() == View.SCROLLBARS_INSIDE_OVERLAY) {
+ setHorizontalScrollBarEnabled(false);
+ setVerticalScrollBarEnabled(false);
+ }
+
mContentViewCore = new ContentViewCore(context);
mContentViewCore.initialize(this, this, nativeWebContents, windowAndroid,
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN ?
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
index 95ed270..b6e5580 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -531,9 +531,16 @@
lp.topMargin = topMargin;
view.setLayoutParams(lp);
} else if (mContainerView instanceof AbsoluteLayout) {
+ // This fixes the offset due to a difference in
+ // scrolling model of WebView vs. Chrome.
+ // TODO(sgurun) fix this to use mContainerView.getScroll[X/Y]()
+ // as it naturally accounts for scroll differences between
+ // these models.
+ leftMargin += mRenderCoordinates.getScrollXPixInt();
+ topMargin += mRenderCoordinates.getScrollYPixInt();
android.widget.AbsoluteLayout.LayoutParams lp =
new android.widget.AbsoluteLayout.LayoutParams((int)width,
- (int)height, leftMargin, topMargin);
+ (int)(height * scale), leftMargin, topMargin);
view.setLayoutParams(lp);
} else {
Log.e(TAG, "Unknown layout " + mContainerView.getClass().getName());
@@ -754,11 +761,6 @@
mContainerView.setFocusableInTouchMode(true);
mContainerView.setClickable(true);
- if (mContainerView.getScrollBarStyle() == View.SCROLLBARS_INSIDE_OVERLAY) {
- mContainerView.setHorizontalScrollBarEnabled(false);
- mContainerView.setVerticalScrollBarEnabled(false);
- }
-
mZoomManager = new ZoomManager(mContext, this);
mContentViewGestureHandler = new ContentViewGestureHandler(mContext, this, mZoomManager,
inputEventDeliveryMode);
diff --git a/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java b/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java
index 26a9d62..548c66d 100644
--- a/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java
+++ b/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java
@@ -5,16 +5,16 @@
package org.chromium.content.browser;
import org.chromium.base.CalledByNative;
-import org.chromium.ui.WindowAndroid;
+import org.chromium.ui.ViewAndroid;
class PowerSaveBlocker {
@CalledByNative
- private static void applyBlock(WindowAndroid windowAndroid) {
- windowAndroid.keepScreenOn(true);
+ private static void applyBlock(ViewAndroid view) {
+ view.incrementKeepScreenOnCount();
}
@CalledByNative
- private static void removeBlock(WindowAndroid windowAndroid) {
- windowAndroid.keepScreenOn(false);
+ private static void removeBlock(ViewAndroid view) {
+ view.decrementKeepScreenOnCount();
}
}
\ No newline at end of file
diff --git a/content/public/android/java/src/org/chromium/content/browser/ResourceExtractor.java b/content/public/android/java/src/org/chromium/content/browser/ResourceExtractor.java
index 2b650ce..8a943f7 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ResourceExtractor.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ResourceExtractor.java
@@ -52,11 +52,6 @@
@Override
protected Void doInBackground(Void... unused) {
- if (sMandatoryPaks == null) {
- assert false : "No pak files specified. Call setMandatoryPaksToExtract before "
- + "beginning the resource extractions";
- return null;
- }
if (!mOutputDir.exists() && !mOutputDir.mkdirs()) {
Log.e(LOGTAG, "Unable to create pak resources directory!");
return null;
@@ -242,7 +237,8 @@
/**
* Specifies the .pak files that should be extracted from the APK's asset resources directory
* and moved to {@link #getOutputDirFromContext(Context)}.
- * @param mandatoryPaks The list of pak files to be loaded.
+ * @param mandatoryPaks The list of pak files to be loaded. If no pak files are
+ * required, pass a single empty string.
*/
public static void setMandatoryPaksToExtract(String... mandatoryPaks) {
assert (sInstance == null || sInstance.mExtractTask == null)
@@ -271,6 +267,10 @@
}
public void waitForCompletion() {
+ if (shouldSkipPakExtraction()) {
+ return;
+ }
+
assert mExtractTask != null;
try {
@@ -296,6 +296,10 @@
return;
}
+ if (shouldSkipPakExtraction()) {
+ return;
+ }
+
mExtractTask = new ExtractTask();
mExtractTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
@@ -315,4 +319,14 @@
}
}
}
+
+ /**
+ * Pak extraction not necessarily required by the embedder; we allow them to skip
+ * this process if they call setMandatoryPaksToExtract with a single empty String.
+ */
+ private static boolean shouldSkipPakExtraction() {
+ // Must call setMandatoryPaksToExtract before beginning resource extraction.
+ assert sMandatoryPaks != null;
+ return sMandatoryPaks.length == 1 && "".equals(sMandatoryPaks[0]);
+ }
}
diff --git a/content/public/browser/browser_thread.h b/content/public/browser/browser_thread.h
index 5f9fc22..ab44eda 100644
--- a/content/public/browser/browser_thread.h
+++ b/content/public/browser/browser_thread.h
@@ -179,9 +179,9 @@
// Windows registry.
static base::SequencedWorkerPool* GetBlockingPool();
- // Callable on any thread. Returns whether the given ID corresponds to a well
- // known thread.
- static bool IsWellKnownThread(ID identifier);
+ // Callable on any thread. Returns whether the given well-known thread is
+ // initialized.
+ static bool IsThreadInitialized(ID identifier);
// Callable on any thread. Returns whether you're currently on a particular
// thread.
diff --git a/content/public/browser/download_manager.h b/content/public/browser/download_manager.h
index 35f191b..37c6d09 100644
--- a/content/public/browser/download_manager.h
+++ b/content/public/browser/download_manager.h
@@ -52,7 +52,6 @@
class DownloadQuery;
class DownloadRequestHandle;
struct DownloadCreateInfo;
-struct DownloadRetrieveInfo;
// Browser's download manager: manages all downloads and destination view.
class CONTENT_EXPORT DownloadManager : public base::SupportsUserData::Data {
@@ -145,6 +144,8 @@
const GURL& referrer_url,
const base::Time& start_time,
const base::Time& end_time,
+ const std::string& etag,
+ const std::string& last_modified,
int64 received_bytes,
int64 total_bytes,
DownloadItem::DownloadState state,
diff --git a/content/public/browser/download_manager_delegate.cc b/content/public/browser/download_manager_delegate.cc
index c33fcd4..9351ce2 100644
--- a/content/public/browser/download_manager_delegate.cc
+++ b/content/public/browser/download_manager_delegate.cc
@@ -38,6 +38,11 @@
return false;
}
+std::string
+DownloadManagerDelegate::ApplicationClientIdForFileScanning() const {
+ return std::string();
+}
+
DownloadManagerDelegate::~DownloadManagerDelegate() {}
} // namespace content
diff --git a/content/public/browser/download_manager_delegate.h b/content/public/browser/download_manager_delegate.h
index 98bad43..89be2df 100644
--- a/content/public/browser/download_manager_delegate.h
+++ b/content/public/browser/download_manager_delegate.h
@@ -129,6 +129,12 @@
DownloadItem* download,
const CheckForFileExistenceCallback& callback) {}
+ // Return a GUID string used for identifying the application to the
+ // system AV function for scanning downloaded files. If an empty
+ // or invalid GUID string is returned, no client identification
+ // will be given to the AV function.
+ virtual std::string ApplicationClientIdForFileScanning() const;
+
protected:
virtual ~DownloadManagerDelegate();
};
diff --git a/content/public/browser/storage_partition.h b/content/public/browser/storage_partition.h
index f69feaa..b30ca42 100644
--- a/content/public/browser/storage_partition.h
+++ b/content/public/browser/storage_partition.h
@@ -64,7 +64,7 @@
REMOVE_DATA_MASK_LOCAL_STORAGE = 1 << 4,
REMOVE_DATA_MASK_SHADER_CACHE = 1 << 5,
REMOVE_DATA_MASK_WEBSQL = 1 << 6,
-
+ REMOVE_DATA_MASK_WEBRTC_IDENTITY = 1 << 7,
REMOVE_DATA_MASK_ALL = -1
};
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index 35a6eac..86b51a2 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -79,7 +79,12 @@
CreateParams(BrowserContext* context, SiteInstance* site);
BrowserContext* browser_context;
+
+ // Specifying a SiteInstance here is optional. It can be set to avoid an
+ // extra process swap if the first navigation is expected to require a
+ // privileged process.
SiteInstance* site_instance;
+
WebContents* opener;
int routing_id;
int main_frame_routing_id;
diff --git a/content/public/common/content_constants.cc b/content/public/common/content_constants.cc
index 5c73ecd..75e9273 100644
--- a/content/public/common/content_constants.cc
+++ b/content/public/common/content_constants.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "content/public/common/content_constants.h"
+
namespace content {
const base::FilePath::CharType kAppCacheDirname[] =
@@ -12,6 +13,14 @@
const char kBrowserPluginMimeType[] = "application/browser-plugin";
+const char kFlashPluginName[] = "Shockwave Flash";
+const char kFlashPluginSwfMimeType[] = "application/x-shockwave-flash";
+const char kFlashPluginSwfExtension[] = "swf";
+const char kFlashPluginSwfDescription[] = "Shockwave Flash";
+const char kFlashPluginSplMimeType[] = "application/futuresplash";
+const char kFlashPluginSplExtension[] = "spl";
+const char kFlashPluginSplDescription[] = "FutureSplash Player";
+
// This number used to be limited to 32 in the past (see b/535234).
const size_t kMaxRendererProcessCount = 82;
const int kMaxSessionHistoryEntries = 50;
diff --git a/content/public/common/content_constants.h b/content/public/common/content_constants.h
index c6d3dd5..012b00f 100644
--- a/content/public/common/content_constants.h
+++ b/content/public/common/content_constants.h
@@ -24,6 +24,14 @@
// The MIME type used for the browser plugin.
CONTENT_EXPORT extern const char kBrowserPluginMimeType[];
+CONTENT_EXPORT extern const char kFlashPluginName[];
+CONTENT_EXPORT extern const char kFlashPluginSwfMimeType[];
+CONTENT_EXPORT extern const char kFlashPluginSwfExtension[];
+CONTENT_EXPORT extern const char kFlashPluginSwfDescription[];
+CONTENT_EXPORT extern const char kFlashPluginSplMimeType[];
+CONTENT_EXPORT extern const char kFlashPluginSplExtension[];
+CONTENT_EXPORT extern const char kFlashPluginSplDescription[];
+
CONTENT_EXPORT extern const size_t kMaxRendererProcessCount;
// The maximum number of session history entries per tab.
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 40e932b..07c6ff3f 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -10,18 +10,33 @@
// override for developers who need the old behavior for testing.
const char kAllowFileAccessFromFiles[] = "allow-file-access-from-files";
+// Enables the sandboxed processes to run without a job object assigned to them.
+// This flag is required to allow Chrome to run in RemoteApps or Citrix. This
+// flag can reduce the security of the sandboxed processes and allow them to do
+// certain API calls like shut down Windows or access the clipboard. Also we
+// lose the chance to kill some processes until the outer job that owns them
+// finishes.
+const char kAllowNoSandboxJob[] = "allow-no-sandbox-job";
+
// Allows debugging of sandboxed processes (see zygote_main_linux.cc).
const char kAllowSandboxDebugging[] = "allow-sandbox-debugging";
// Allow compositing on chrome:// pages.
const char kAllowWebUICompositing[] = "allow-webui-compositing";
+// The same as kAuditHandles except all handles are enumerated.
+const char kAuditAllHandles[] = "enable-handle-auditing-all";
+
// Enumerates and prints a child process' most dangerous handles when it
// is terminated.
const char kAuditHandles[] = "enable-handle-auditing";
-// The same as kAuditHandles except all handles are enumerated.
-const char kAuditAllHandles[] = "enable-handle-auditing-all";
+// Blacklist the GPU for accelerated compositing.
+const char kBlacklistAcceleratedCompositing[] =
+ "blacklist-accelerated-compositing";
+
+// Blacklist the GPU for WebGL.
+const char kBlacklistWebGL[] = "blacklist-webgl";
// Causes the browser process to throw an assertion on startup.
const char kBrowserAssertTest[] = "assert-test";
@@ -32,6 +47,16 @@
// Path to the exe to run for the renderer and plugin subprocesses.
const char kBrowserSubprocessPath[] = "browser-subprocess-path";
+// Dumps extra logging about plugin loading to the log file.
+const char kDebugPluginLoading[] = "debug-plugin-loading";
+
+// Sets the tile size used by composited layers.
+const char kDefaultTileWidth[] = "default-tile-width";
+const char kDefaultTileHeight[] = "default-tile-height";
+
+// Disable antialiasing on 2d canvas.
+const char kDisable2dCanvasAntialiasing[] = "disable-canvas-aa";
+
// Disables client-visible 3D APIs, in particular WebGL and Pepper 3D.
// This is controlled by policy and is kept separate from the other
// enable/disable switches to avoid accidentally regressing the policy
@@ -41,25 +66,31 @@
// Disable gpu-accelerated 2d canvas.
const char kDisableAccelerated2dCanvas[] = "disable-accelerated-2d-canvas";
-// Disable antialiasing on 2d canvas.
-const char kDisable2dCanvasAntialiasing[] = "disable-canvas-aa";
-
-// Enable experimental canvas features, e.g. canvas 2D context attributes
-const char kEnableExperimentalCanvasFeatures[]
- = "enable-experimental-canvas-features";
-
// Disables accelerated compositing.
const char kDisableAcceleratedCompositing[] = "disable-accelerated-compositing";
+// Disables accelerated compositing for backgrounds of root layers with
+// background-attachment: fixed.
+const char kDisableAcceleratedFixedRootBackground[] =
+ "disable-accelerated-fixed-root-background";
+
// Disables the hardware acceleration of 3D CSS and animation.
const char kDisableAcceleratedLayers[] = "disable-accelerated-layers";
+// Disables accelerated compositing for overflow scroll.
+const char kDisableAcceleratedOverflowScroll[] =
+ "disable-accelerated-overflow-scroll";
+
// Disables the hardware acceleration of plugins.
const char kDisableAcceleratedPlugins[] = "disable-accelerated-plugins";
// Disables GPU accelerated video display.
const char kDisableAcceleratedVideo[] = "disable-accelerated-video";
+// Disables hardware acceleration of video decode, where available.
+const char kDisableAcceleratedVideoDecode[] =
+ "disable-accelerated-video-decode";
+
// Disables the alternate window station for the renderer.
const char kDisableAltWinstation[] = "disable-winsta";
@@ -74,9 +105,24 @@
// users with many windows/tabs and lots of memory.
const char kDisableBackingStoreLimit[] = "disable-backing-store-limit";
+// Enables browser plugin compositing experiment.
+const char kDisableBrowserPluginCompositing[] =
+ "disable-browser-plugin-compositing";
+
+// See comment for kEnableCompositingForFixedPosition.
+const char kDisableCompositingForFixedPosition[] =
+ "disable-fixed-position-compositing";
+
+// See comment for kEnableCompositingForTransition.
+const char kDisableCompositingForTransition[] =
+ "disable-transition-compositing";
+
// Disables HTML5 DB support.
const char kDisableDatabases[] = "disable-databases";
+// Disables delegated renderer.
+const char kDisableDelegatedRenderer[] = "disable-delegated-renderer";
+
// Disables desktop notifications (default enabled on windows).
const char kDisableDesktopNotifications[] = "disable-desktop-notifications";
@@ -86,28 +132,40 @@
// Disable experimental WebGL support.
const char kDisableExperimentalWebGL[] = "disable-webgl";
-// Blacklist the GPU for accelerated compositing.
-const char kBlacklistAcceleratedCompositing[] =
- "blacklist-accelerated-compositing";
-
-// Blacklist the GPU for WebGL.
-const char kBlacklistWebGL[] = "blacklist-webgl";
-
// Disable FileSystem API.
const char kDisableFileSystem[] = "disable-file-system";
+const char kDisableFixedPositionCreatesStackingContext[]
+ = "disable-fixed-position-creates-stacking-context";
+
// Disable 3D inside of flapper.
const char kDisableFlash3d[] = "disable-flash-3d";
// Disable Stage3D inside of flapper.
const char kDisableFlashStage3d[] = "disable-flash-stage3d";
+// This flag disables force compositing mode and prevents it from being enabled
+// via field trials.
+const char kDisableForceCompositingMode[] = "disable-force-compositing-mode";
+
+// Disable the JavaScript Full Screen API.
+const char kDisableFullScreen[] = "disable-fullscreen";
+
// Suppresses support for the Geolocation javascript API.
const char kDisableGeolocation[] = "disable-geolocation";
+const char kDisableGestureTapHighlight[] = "disable-gesture-tap-highlight";
+
// Disable GL multisampling.
const char kDisableGLMultisampling[] = "disable-gl-multisampling";
+// Disables GPU hardware acceleration. If software renderer is not in place,
+// then the GPU process won't launch.
+const char kDisableGpu[] = "disable-gpu";
+
+// Prevent the compositor from using its GPU implementation.
+const char kDisableGpuCompositing[] = "disable-gpu-compositing";
+
// Do not launch the GPU process shortly after browser process launch. Instead
// launch it when it is first needed.
const char kDisableGpuProcessPrelaunch[] = "disable-gpu-process-prelaunch";
@@ -115,41 +173,34 @@
// Disable the GPU process sandbox.
const char kDisableGpuSandbox[] = "disable-gpu-sandbox";
-// Reduces the GPU process sandbox to be less strict.
-const char kReduceGpuSandbox[] = "reduce-gpu-sandbox";
+// Disable the thread that crashes the GPU process if it stops responding to
+// messages.
+const char kDisableGpuWatchdog[] = "disable-gpu-watchdog";
// Suppresses hang monitor dialogs in renderer processes. This may allow slow
// unload handlers on a page to prevent the tab from closing, but the Task
// Manager can be used to terminate the offending process in this case.
const char kDisableHangMonitor[] = "disable-hang-monitor";
-// Disables HTML-based desktop notifications.
-const char kDisableHTMLNotifications[] = "disable-html-notifications";
-
// Disable the RenderThread's HistogramCustomizer.
const char kDisableHistogramCustomizer[] = "disable-histogram-customizer";
+// Disables HTML-based desktop notifications.
+const char kDisableHTMLNotifications[] = "disable-html-notifications";
+
// Disable the use of an ImageTransportSurface. This means the GPU process
// will present the rendered page rather than the browser process.
const char kDisableImageTransportSurface[] = "disable-image-transport-surface";
-// Use hardware gpu, if available, for tests.
-const char kUseGpuInTests[] = "use-gpu-in-tests";
-
-// Disables GPU hardware acceleration. If software renderer is not in place,
-// then the GPU process won't launch.
-const char kDisableGpu[] = "disable-gpu";
-
-// Disable the thread that crashes the GPU process if it stops responding to
-// messages.
-const char kDisableGpuWatchdog[] = "disable-gpu-watchdog";
-
// Prevent Java from running.
const char kDisableJava[] = "disable-java";
// Don't execute JavaScript (browser JS like the new tab page still runs).
const char kDisableJavaScript[] = "disable-javascript";
+// Disables prefixed Encrypted Media API (e.g. webkitGenerateKeyRequest()).
+const char kDisableLegacyEncryptedMedia[] = "disable-legacy-encrypted-media";
+
// Disable LocalStorage.
const char kDisableLocalStorage[] = "disable-local-storage";
@@ -157,13 +208,20 @@
// builds.
const char kDisableLogging[] = "disable-logging";
-// Enables displaying net log events on the command line, or writing the events
-// to a separate file if a file name is given.
-const char kLogNetLog[] = "log-net-log";
+// Disable Pepper3D.
+const char kDisablePepper3d[] = "disable-pepper-3d";
+
+// Disables compositor-accelerated touch-screen pinch gestures.
+const char kDisablePinch[] = "disable-pinch";
// Prevent plugins from running.
const char kDisablePlugins[] = "disable-plugins";
+// Disable discovering third-party plug-ins. Effectively loading only
+// ones shipped with the browser plus third-party ones as specified by
+// --extra-plugin-dir and --load-plugin switches.
+const char kDisablePluginsDiscovery[] = "disable-plugins-discovery";
+
// Disables remote web font support. SVG font should always work whether this
// option is specified or not.
const char kDisableRemoteFonts[] = "disable-remote-fonts";
@@ -171,12 +229,6 @@
// Turns off the accessibility in the renderer.
const char kDisableRendererAccessibility[] = "disable-renderer-accessibility";
-// Disable False Start in SSL and TLS connections.
-const char kDisableSSLFalseStart[] = "disable-ssl-false-start";
-
-// Disable smooth scrolling for testing.
-const char kDisableSmoothScrolling[] = "disable-smooth-scrolling";
-
// Disable the seccomp filter sandbox (seccomp-bpf) (Linux only).
const char kDisableSeccompFilterSandbox[] = "disable-seccomp-filter-sandbox";
@@ -192,60 +244,33 @@
// Disables site-specific tailoring to compatibility issues in WebKit.
const char kDisableSiteSpecificQuirks[] = "disable-site-specific-quirks";
+// Disable smooth scrolling for testing.
+const char kDisableSmoothScrolling[] = "disable-smooth-scrolling";
+
+// Disables the use of a 3D software rasterizer.
+const char kDisableSoftwareRasterizer[] = "disable-software-rasterizer";
+
// Disables speech input.
const char kDisableSpeechInput[] = "disable-speech-input";
-// Specifies the request key for the continuous speech recognition webservice.
-const char kSpeechRecognitionWebserviceKey[] = "speech-service-key";
+// Disable False Start in SSL and TLS connections.
+const char kDisableSSLFalseStart[] = "disable-ssl-false-start";
-// Enables the synthesis part of the Web Speech API.
-const char kEnableSpeechSynthesis[] = "enable-speech-synthesis";
+// Disable multithreaded GPU compositing of web content.
+const char kDisableThreadedCompositing[] = "disable-threaded-compositing";
-#if defined(OS_ANDROID)
-// WebRTC is enabled by default on Android.
-const char kDisableWebRTC[] = "disable-webrtc";
-
-// Enable the recognition part of the Web Speech API.
-const char kEnableSpeechRecognition[] = "enable-speech-recognition";
-
-#endif
+// Disables the threaded HTML parser in WebKit
+const char kDisableThreadedHTMLParser[] = "disable-threaded-html-parser";
// Disable web audio API.
const char kDisableWebAudio[] = "disable-webaudio";
-#if defined(ENABLE_WEBRTC)
-// Enables WebRTC AEC recordings.
-const char kEnableWebRtcAecRecordings[] = "enable-webrtc-aec-recordings";
-
-// Enable WebRTC DataChannels SCTP wire protocol support.
-const char kEnableSCTPDataChannels[] = "enable-sctp-data-channels";
-
-// Disable WebRTC device enumeration.
-const char kDisableDeviceEnumeration[] = "disable-device-enumeration";
-
-#endif
-
-// Enable WebRTC to open TCP server sockets.
-const char kEnableWebRtcTcpServerSocket[] = "enable-webrtc-tcp-server-socket";
-
-// Enables HW decode acceleration for WebRTC.
-const char kEnableWebRtcHWDecoding[] = "enable-webrtc-hw-decoding";
-
-// Enable CSS Transitions / Animations on the Web Animations model.
-const char kEnableWebAnimationsCSS[] = "enable-web-animations-css";
-
-// Enable SVG Animations on the Web Animations model.
-const char kEnableWebAnimationsSVG[] = "enable-web-animations-svg";
-
-// Enables Web MIDI API.
-const char kEnableWebMIDI[] = "enable-web-midi";
+// Disables prefixed Media Source API (i.e., the WebKitMediaSource object).
+const char kDisableWebKitMediaSource[] = "disable-webkit-media-source";
// Don't enforce the same-origin policy. (Used by people testing their sites.)
const char kDisableWebSecurity[] = "disable-web-security";
-// Enable an experimental WebSocket implementation.
-const char kEnableExperimentalWebSocket[] = "enable-experimental-websocket";
-
// Disables WebKit's XSSAuditor. The XSSAuditor mitigates reflective XSS.
const char kDisableXSSAuditor[] = "disable-xss-auditor";
@@ -255,16 +280,24 @@
// based tests.
const char kDomAutomationController[] = "dom-automation";
-// Specifies if the |StatsCollectionController| needs to be bound in the
-// renderer. This binding happens on per-frame basis and hence can potentially
-// be a performance bottleneck. One should only enable it when running a test
-// that needs to access the provided statistics.
-const char kStatsCollectionController[] =
- "enable-stats-collection-bindings";
-
// Enable gpu-accelerated SVG/W3C filters.
const char kEnableAcceleratedFilters[] = "enable-accelerated-filters";
+// Enables accelerated compositing for backgrounds of root layers with
+// background-attachment: fixed. Requires kForceCompositingMode.
+const char kEnableAcceleratedFixedRootBackground[] =
+ "enable-accelerated-fixed-root-background";
+
+// Enables accelerated compositing for overflow scroll. Promotes eligible
+// overflow:scroll elements to layers to enable accelerated scrolling for them.
+const char kEnableAcceleratedOverflowScroll[] =
+ "enable-accelerated-overflow-scroll";
+
+// Enables accelerated compositing for scrollable frames for accelerated
+// scrolling for them. Requires kForceCompositingMode.
+const char kEnableAcceleratedScrollableFrames[] =
+ "enable-accelerated-scrollable-frames";
+
// Turns on extremely verbose logging of accessibility events.
const char kEnableAccessibilityLogging[] = "enable-accessibility-logging";
@@ -272,11 +305,13 @@
//
// TODO(miu): Remove --enable-audible-notifications once the feature goes
// live. http://crbug.com/178934
-const char kEnableAudibleNotifications[] = "enable-audible-notifications";
+const char kEnableAudibleNotifications[] = "enable-audible-notifications";
-// Enables browser plugin compositing experiment.
-const char kDisableBrowserPluginCompositing[] =
- "disable-browser-plugin-compositing";
+// Use a begin frame signal from browser to renderer to schedule rendering.
+const char kEnableBeginFrameScheduling[] = "enable-begin-frame-scheduling";
+
+// Synchronize delivery and response of input events to and from the renderer.
+const char kEnableBrowserInputController[] = "enable-browser-input-controller";
// Enables browser plugin for all types of pages.
const char kEnableBrowserPluginForAllViewTypes[] =
@@ -286,7 +321,12 @@
// kEnableBrowserPluginGuestViews must also be set at this time.
const char kEnableBrowserPluginDragDrop[] = "enable-browser-plugin-drag-drop";
-// Enable/Disable the creation of compositing layers for fixed position
+// Enables accelerated scrolling by the compositor for frames. Requires
+// kForceCompositingMode and kEnableAcceleratedScrollableFrames.
+const char kEnableCompositedScrollingForFrames[] =
+ "enable-composited-scrolling-for-frames";
+
+// Enable the creation of compositing layers for fixed position
// elements. Three options are needed to support four possible scenarios:
// 1. Default (disabled)
// 2. Enabled always (to allow dogfooding)
@@ -298,10 +338,6 @@
// override Option #4.
const char kEnableCompositingForFixedPosition[] =
"enable-fixed-position-compositing";
-const char kDisableCompositingForFixedPosition[] =
- "disable-fixed-position-compositing";
-const char kEnableHighDpiCompositingForFixedPosition[] =
- "enable-high-dpi-fixed-position-compositing";
// Enable/Disable the creation of compositing layers for RenderLayers with a
// transition on a property that supports accelerated animation (that is,
@@ -312,14 +348,12 @@
// 3. Disabled always.
const char kEnableCompositingForTransition[] =
"enable-transition-compositing";
-const char kDisableCompositingForTransition[] =
- "disable-transition-compositing";
// Enables CSS3 custom filters
const char kEnableCssShaders[] = "enable-css-shaders";
-// Disables delegated renderer.
-const char kDisableDelegatedRenderer[] = "disable-delegated-renderer";
+// Defer image decoding in WebKit until painting.
+const char kEnableDeferredImageDecoding[] = "enable-deferred-image-decoding";
// Enables delegated renderer.
const char kEnableDelegatedRenderer[] = "enable-delegated-renderer";
@@ -327,40 +361,33 @@
// Enables device motion events.
const char kEnableDeviceMotion[] = "enable-device-motion";
-#if defined(OS_ANDROID)
-// Disables device motion events.
-const char kDisableDeviceMotion[] = "disable-device-motion";
-#endif
-
// 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";
+
+// Enable experimental canvas features, e.g. canvas 2D context attributes
+const char kEnableExperimentalCanvasFeatures[] =
+ "enable-experimental-canvas-features";
+
// Enables Web Platform features that are in development.
const char kEnableExperimentalWebPlatformFeatures[] =
"enable-experimental-web-platform-features";
-// Enables the CSS multicol implementation that uses the regions implementation.
-const char kEnableRegionBasedColumns[] =
- "enable-region-based-columns";
-
-// Disables the threaded HTML parser in WebKit
-const char kDisableThreadedHTMLParser[] = "disable-threaded-html-parser";
+// Enable an experimental WebSocket implementation.
+const char kEnableExperimentalWebSocket[] = "enable-experimental-websocket";
// By default, a page is laid out to fill the entire width of the window.
// This flag fixes the layout of the page to a default of 980 CSS pixels,
// or to a specified width and height using --enable-fixed-layout=w,h
const char kEnableFixedLayout[] = "enable-fixed-layout";
-// Disable the JavaScript Full Screen API.
-const char kDisableFullScreen[] = "disable-fullscreen";
-
-// Enable Text Service Framework(TSF) for text inputting instead of IMM32. This
-// flag is ignored on Metro environment.
-const char kEnableTextServicesFramework[] = "enable-text-services-framework";
+const char kEnableFixedPositionCreatesStackingContext[]
+ = "enable-fixed-position-creates-stacking-context";
// Enable Gesture Tap Highlight
-const char kEnableGestureTapHighlight[] = "enable-gesture-tap-highlight";
-const char kDisableGestureTapHighlight[] = "disable-gesture-tap-highlight";
+const char kEnableGestureTapHighlight[] = "enable-gesture-tap-highlight";
// Enables the GPU benchmarking extension
const char kEnableGpuBenchmarking[] = "enable-gpu-benchmarking";
@@ -368,34 +395,22 @@
// Enables TRACE for GL calls in the renderer.
const char kEnableGpuClientTracing[] = "enable-gpu-client-tracing";
+// See comment for kEnableCompositingForFixedPosition.
+const char kEnableHighDpiCompositingForFixedPosition[] =
+ "enable-high-dpi-fixed-position-compositing";
+
+// Enable HTML Imports
+extern const char kEnableHTMLImports[] = "enable-html-imports";
+
// Enables support for inband text tracks in media content.
-const char kEnableInbandTextTracks[] = "enable-inband-text-tracks";
-
-// Enables the memory benchmarking extension
-const char kEnableMemoryBenchmarking[] = "enable-memory-benchmarking";
-
-// Enables the Skia benchmarking extension
-const char kEnableSkiaBenchmarking[] = "enable-skia-benchmarking";
+const char kEnableInbandTextTracks[] = "enable-inband-text-tracks";
// Force logging to be enabled. Logging is disabled by default in release
// builds.
const char kEnableLogging[] = "enable-logging";
-// Disables prefixed Media Source API (i.e., the WebKitMediaSource object).
-const char kDisableWebKitMediaSource[] = "disable-webkit-media-source";
-
-// Enables support for Encrypted Media Extensions (e.g. MediaKeys).
-const char kEnableEncryptedMedia[] = "enable-encrypted-media";
-
-// Disables prefixed Encrypted Media API (e.g. webkitGenerateKeyRequest()).
-const char kDisableLegacyEncryptedMedia[] = "disable-legacy-encrypted-media";
-
-// Use fake device for MediaStream to replace actual camera and microphone.
-const char kUseFakeDeviceForMediaStream[] = "use-fake-device-for-media-stream";
-
-// Bypass the media stream infobar by selecting the default device for media
-// streams (e.g. WebRTC). Works with --use-fake-device-for-media-stream.
-const char kUseFakeUIForMediaStream[] = "use-fake-ui-for-media-stream";
+// Enables the memory benchmarking extension
+const char kEnableMemoryBenchmarking[] = "enable-memory-benchmarking";
// On Windows, converts the page to the currently-installed monitor profile.
// This does NOT enable color management for images. The source is still
@@ -406,13 +421,15 @@
// http://crbug.com/260005
const char kEnableNewMediaInternals[] = "enable-new-media-internals";
-// Enables compositor-accelerated touch-screen pinch gestures.
-const char kEnablePinch[] = "enable-pinch";
-const char kDisablePinch[] = "disable-pinch";
-
// Enables use of cache if offline, even if it's stale
const char kEnableOfflineCacheAccess[] = "enable-offline-cache-access";
+// Forward overscroll event data from the renderer to the browser.
+const char kEnableOverscrollNotifications[] = "enable-overscroll-notifications";
+
+// Enables compositor-accelerated touch-screen pinch gestures.
+const char kEnablePinch[] = "enable-pinch";
+
// Enable caching of pre-parsed JS script data. See http://crbug.com/32407.
const char kEnablePreparsedJsCaching[] = "enable-preparsed-js-caching";
@@ -425,23 +442,32 @@
const char kEnablePruneGpuCommandBuffers[] =
"enable-prune-gpu-command-buffers";
-// Enable screen capturing support for MediaStream API.
-const char kEnableUserMediaScreenCapturing[] =
- "enable-usermedia-screen-capturing";
-
-// Enables TLS cached info extension.
-const char kEnableSSLCachedInfo[] = "enable-ssl-cached-info";
+// Enables the CSS multicol implementation that uses the regions implementation.
+const char kEnableRegionBasedColumns[] =
+ "enable-region-based-columns";
// Cause the OS X sandbox write to syslog every time an access to a resource
// is denied by the sandbox.
const char kEnableSandboxLogging[] = "enable-sandbox-logging";
-// Enable spatial navigation
-const char kEnableSpatialNavigation[] = "enable-spatial-navigation";
+// Enables the Skia benchmarking extension
+const char kEnableSkiaBenchmarking[] = "enable-skia-benchmarking";
// On platforms that support it, enables smooth scroll animation.
const char kEnableSmoothScrolling[] = "enable-smooth-scrolling";
+// Allow the compositor to use its software implementation if GL fails.
+const char kEnableSoftwareCompositing[] = "enable-software-compositing";
+
+// Enable spatial navigation
+const char kEnableSpatialNavigation[] = "enable-spatial-navigation";
+
+// Enables the synthesis part of the Web Speech API.
+const char kEnableSpeechSynthesis[] = "enable-speech-synthesis";
+
+// Enables TLS cached info extension.
+const char kEnableSSLCachedInfo[] = "enable-ssl-cached-info";
+
// Enables StatsTable, logging statistics to a global named shared memory table.
const char kEnableStatsTable[] = "enable-stats-table";
@@ -457,29 +483,51 @@
// cookies on cross-site requests.
const char kEnableStrictSiteIsolation[] = "enable-strict-site-isolation";
-// Enable multithreaded GPU compositing of web content.
-const char kEnableThreadedCompositing[] = "enable-threaded-compositing";
-
-// Allow GL contexts to be automatically virtualized (shared between command
-// buffer clients) if they are compatible.
-const char kEnableVirtualGLContexts[] = "enable-virtual-gl-contexts";
-
-// Disable multithreaded GPU compositing of web content.
-const char kDisableThreadedCompositing[] = "disable-threaded-compositing";
-
// Enable use of experimental TCP sockets API for sending data in the
// SYN packet.
const char kEnableTcpFastOpen[] = "enable-tcp-fastopen";
-// Disables hardware acceleration of video decode, where available.
-const char kDisableAcceleratedVideoDecode[] =
- "disable-accelerated-video-decode";
+// Enable Text Service Framework(TSF) for text inputting instead of IMM32. This
+// flag is ignored on Metro environment.
+const char kEnableTextServicesFramework[] = "enable-text-services-framework";
+
+// Enable multithreaded GPU compositing of web content.
+const char kEnableThreadedCompositing[] = "enable-threaded-compositing";
+
+// Enable screen capturing support for MediaStream API.
+const char kEnableUserMediaScreenCapturing[] =
+ "enable-usermedia-screen-capturing";
// Enables the use of the viewport meta tag, which allows
// pages to control aspects of their own layout. This also turns on touch-screen
// pinch gestures.
const char kEnableViewport[] = "enable-viewport";
+// Allow GL contexts to be automatically virtualized (shared between command
+// buffer clients) if they are compatible.
+const char kEnableVirtualGLContexts[] = "enable-virtual-gl-contexts";
+
+// Enables moving cursor by word in visual order.
+const char kEnableVisualWordMovement[] = "enable-visual-word-movement";
+
+// Enable the Vtune profiler support.
+const char kEnableVtune[] = "enable-vtune-support";
+
+// Enable CSS Transitions / Animations on the Web Animations model.
+const char kEnableWebAnimationsCSS[] = "enable-web-animations-css";
+
+// Enable SVG Animations on the Web Animations model.
+const char kEnableWebAnimationsSVG[] = "enable-web-animations-svg";
+
+// Enables WebGL extensions not yet approved by the community.
+const char kEnableWebGLDraftExtensions[] = "enable-webgl-draft-extensions";
+
+// Enables Web MIDI API.
+const char kEnableWebMIDI[] = "enable-web-midi";
+
+// Enable WebRTC to open TCP server sockets.
+const char kEnableWebRtcTcpServerSocket[] = "enable-webrtc-tcp-server-socket";
+
// Enables experimental features for the geolocation API.
// Current features:
// - CoreLocation support for Mac OS X 10.6
@@ -487,14 +535,13 @@
// - Location platform support for Windows 7
const char kExperimentalLocationFeatures[] = "experimental-location-features";
+// Load NPAPI plugins from the specified directory.
+const char kExtraPluginDir[] = "extra-plugin-dir";
+
// If accelerated compositing is supported, always enter compositing mode for
// the base layer even when compositing is not strictly required.
const char kForceCompositingMode[] = "force-compositing-mode";
-// This flag disables force compositing mode and prevents it from being enabled
-// via field trials.
-const char kDisableForceCompositingMode[] = "disable-force-compositing-mode";
-
// Some field trials may be randomized in the browser, and the randomly selected
// outcome needs to be propagated to the renderer. For instance, this is used
// to modify histograms recorded in the renderer, or to get the renderer to
@@ -510,12 +557,6 @@
// overrides this if present.
const char kForceRendererAccessibility[] = "force-renderer-accessibility";
-// Allow the compositor to use its software implementation if GL fails.
-const char kEnableSoftwareCompositing[] = "enable-software-compositing";
-
-// Prevent the compositor from using its GPU implementation.
-const char kDisableGpuCompositing[] = "disable-gpu-compositing";
-
// Passes gpu device_id from browser process to GPU process.
const char kGpuDeviceID[] = "gpu-device-id";
@@ -541,12 +582,6 @@
// Passes gpu vendor_id from browser process to GPU process.
const char kGpuVendorID[] = "gpu-vendor-id";
-#if defined(OS_ANDROID)
-// Don't display any scrollbars. This is useful for Android WebView where
-// the system manages the scrollbars instead.
-const char kHideScrollbars[] = "hide-scrollbars";
-#endif
-
// These mappings only apply to the host resolver.
const char kHostResolverRules[] = "host-resolver-rules";
@@ -565,24 +600,24 @@
// Specifies the flags passed to JS engine
const char kJavaScriptFlags[] = "js-flags";
-// Load NPAPI plugins from the specified directory.
-const char kExtraPluginDir[] = "extra-plugin-dir";
-
// Load an NPAPI plugin from the specified path.
const char kLoadPlugin[] = "load-plugin";
-// Disable discovering third-party plug-ins. Effectively loading only
-// ones shipped with the browser plus third-party ones as specified by
-// --extra-plugin-dir and --load-plugin switches.
-const char kDisablePluginsDiscovery[] = "disable-plugins-discovery";
-
// Sets the minimum log level. Valid values are from 0 to 3:
// INFO = 0, WARNING = 1, LOG_ERROR = 2, LOG_FATAL = 3.
const char kLoggingLevel[] = "log-level";
+// Enables displaying net log events on the command line, or writing the events
+// to a separate file if a file name is given.
+const char kLogNetLog[] = "log-net-log";
+
// Make plugin processes log their sent and received messages to VLOG(1).
const char kLogPluginMessages[] = "log-plugin-messages";
+// Sets the width and height above which a composited layer will get tiled.
+const char kMaxUntiledLayerHeight[] = "max-untiled-layer-height";
+const char kMaxUntiledLayerWidth[] = "max-untiled-layer-width";
+
// Sample memory usage with high frequency and store the results to the
// Renderer.Memory histogram. Used in memory tests.
const char kMemoryMetrics[] = "memory-metrics";
@@ -597,13 +632,11 @@
// Disables the sandbox for all process types that are normally sandboxed.
const char kNoSandbox[] = "no-sandbox";
-// Enables the sandboxed processes to run without a job object assigned to them.
-// This flag is required to allow Chrome to run in RemoteApps or Citrix. This
-// flag can reduce the security of the sandboxed processes and allow them to do
-// certain API calls like shut down Windows or access the clipboard. Also we
-// lose the chance to kill some processes until the outer job that owns them
-// finishes.
-const char kAllowNoSandboxJob[] = "allow-no-sandbox-job";
+// Enables or disables history navigation in response to horizontal overscroll.
+// Set the value to '1' to enable the feature, and set to '0' to disable.
+// Defaults to enabled.
+const char kOverscrollHistoryNavigation[] =
+ "overscroll-history-navigation";
// Specifies a command that should be used to launch the plugin process. Useful
// for running the plugin process through purify or quantify. Ex:
@@ -622,6 +655,9 @@
// Argument to the process type that indicates a PPAPI broker process type.
const char kPpapiBrokerProcess[] = "ppapi-broker";
+// "Command-line" arguments for the PPAPI Flash; used for debugging options.
+const char kPpapiFlashArgs[] = "ppapi-flash-args";
+
// Runs PPAPI (Pepper) plugins in-process.
const char kPpapiInProcess[] = "ppapi-in-process";
@@ -651,17 +687,16 @@
// renderer or plugin host. If it's empty, it's the browser.
const char kProcessType[] = "type";
+// Reduces the GPU process sandbox to be less strict.
+const char kReduceGpuSandbox[] = "reduce-gpu-sandbox";
+
// Register Pepper plugins (see pepper_plugin_registry.cc for its format).
const char kRegisterPepperPlugins[] = "register-pepper-plugins";
+
// Enables remote debug over HTTP on the specified port.
const char kRemoteDebuggingPort[] = "remote-debugging-port";
-#if defined(OS_ANDROID)
-// Enables remote debug over HTTP on the specified socket name.
-const char kRemoteDebuggingSocketName[] = "remote-debugging-socket-name";
-#endif
-
// Causes the renderer process to throw an assertion on launch.
const char kRendererAssertTest[] = "renderer-assert-test";
@@ -672,9 +707,6 @@
// Causes the process to run as renderer instead of as browser.
const char kRendererProcess[] = "renderer";
-// Enable the Vtune profiler support.
-const char kEnableVtune[] = "enable-vtune-support";
-
// Overrides the default/calculated limit to the number of renderer processes.
// Very high values for this setting can lead to high memory/resource usage
// or instability.
@@ -683,24 +715,10 @@
// Causes the renderer process to display a dialog on launch.
const char kRendererStartupDialog[] = "renderer-startup-dialog";
-// Enables accelerated compositing for overflow scroll. Promotes eligible
-// overflow:scroll elements to layers to enable accelerated scrolling for them.
-const char kEnableAcceleratedOverflowScroll[] =
- "enable-accelerated-overflow-scroll";
-
-// Disables accelerated compositing for overflow scroll.
-const char kDisableAcceleratedOverflowScroll[] =
- "disable-accelerated-overflow-scroll";
-
-// Enables accelerated compositing for scrollable frames for accelerated
-// scrolling for them. Requires kForceCompositingMode.
-const char kEnableAcceleratedScrollableFrames[] =
- "enable-accelerated-scrollable-frames";
-
-// Enables accelerated scrolling by the compositor for frames. Requires
-// kForceCompositingMode and kEnableAcceleratedScrollableFrames.
-const char kEnableCompositedScrollingForFrames[] =
- "enable-composited-scrolling-for-frames";
+// Enables or disables scroll end effect in response to vertical overscroll.
+// Set the value to '1' to enable the feature, and set to '0' to disable.
+// Defaults to disabled.
+const char kScrollEndEffect[] = "scroll-end-effect";
// Visibly render a border around paint rects in the web page to help debug
// and study painting behavior.
@@ -734,24 +752,35 @@
// content. The switch is intended only for tests.
const char kSkipGpuDataLoading[] = "skip-gpu-data-loading";
+// Specifies the request key for the continuous speech recognition webservice.
+const char kSpeechRecognitionWebserviceKey[] = "speech-service-key";
+
+// Specifies if the |StatsCollectionController| needs to be bound in the
+// renderer. This binding happens on per-frame basis and hence can potentially
+// be a performance bottleneck. One should only enable it when running a test
+// that needs to access the provided statistics.
+const char kStatsCollectionController[] =
+ "enable-stats-collection-bindings";
+
+// Upscale defaults to "good".
+const char kTabCaptureDownscaleQuality[] = "tab-capture-downscale-quality";
+
// Scaling quality for capturing tab. Should be one of "fast", "good" or "best".
// One flag for upscaling, one for downscaling.
// Upscale defaults to "best".
const char kTabCaptureUpscaleQuality[] = "tab-capture-upscale-quality";
-// Upscale defaults to "good".
-const char kTabCaptureDownscaleQuality[] = "tab-capture-downscale-quality";
// GestureTapDown events are deferred by this many miillseconds before
// sending them to the renderer.
const char kTapDownDeferralTimeMs[] = "tap-down-deferral-time";
-// Runs the security test for the renderer sandbox.
-const char kTestSandbox[] = "test-sandbox";
-
// Allows for forcing socket connections to http/https to use fixed ports.
const char kTestingFixedHttpPort[] = "testing-fixed-http-port";
const char kTestingFixedHttpsPort[] = "testing-fixed-https-port";
+// Runs the security test for the renderer sandbox.
+const char kTestSandbox[] = "test-sandbox";
+
// Causes TRACE_EVENT flags to be recorded from startup. Optionally, can
// specify the specific trace categories to include (e.g.
// --trace-startup=base,net) otherwise, all events are recorded. Setting this
@@ -761,6 +790,11 @@
// supported in the base-only TraceLog component).
const char kTraceStartup[] = "trace-startup";
+// Sets the time in seconds until startup tracing ends. If omitted a default of
+// 5 seconds is used. Has no effect without --trace-startup, or if
+// --startup-trace-file=none was supplied.
+const char kTraceStartupDuration[] = "trace-startup-duration";
+
// If supplied, sets the file which startup tracing will be stored into, if
// omitted the default will be used "chrometrace.log" in the current directory.
// Has no effect unless --trace-startup is also supplied.
@@ -770,15 +804,25 @@
// all events since startup.
const char kTraceStartupFile[] = "trace-startup-file";
-// Sets the time in seconds until startup tracing ends. If omitted a default of
-// 5 seconds is used. Has no effect without --trace-startup, or if
-// --startup-trace-file=none was supplied.
-const char kTraceStartupDuration[] = "trace-startup-duration";
+
// Prioritizes the UI's command stream in the GPU process
extern const char kUIPrioritizeInGpuProcess[] =
"ui-prioritize-in-gpu-process";
+// Use fake device for MediaStream to replace actual camera and microphone.
+const char kUseFakeDeviceForMediaStream[] = "use-fake-device-for-media-stream";
+
+// Bypass the media stream infobar by selecting the default device for media
+// streams (e.g. WebRTC). Works with --use-fake-device-for-media-stream.
+const char kUseFakeUIForMediaStream[] = "use-fake-ui-for-media-stream";
+
+// Use hardware gpu, if available, for tests.
+const char kUseGpuInTests[] = "use-gpu-in-tests";
+
+// Set when Chromium should use a mobile user agent.
+const char kUseMobileUserAgent[] = "use-mobile-user-agent";
+
// A string used to override the default user agent with a custom one.
const char kUserAgent[] = "user-agent";
@@ -815,25 +859,50 @@
// Causes the process to run as a renderer zygote.
const char kZygoteProcess[] = "zygote";
-// Enables moving cursor by word in visual order.
-const char kEnableVisualWordMovement[] = "enable-visual-word-movement";
+#if defined(ENABLE_WEBRTC)
+// Disable WebRTC device enumeration.
+const char kDisableDeviceEnumeration[] = "disable-device-enumeration";
-// Set when Chromium should use a mobile user agent.
-const char kUseMobileUserAgent[] = "use-mobile-user-agent";
+// Enable WebRTC DataChannels SCTP wire protocol support.
+const char kEnableSCTPDataChannels[] = "enable-sctp-data-channels";
+
+// Enables WebRTC AEC recordings.
+const char kEnableWebRtcAecRecordings[] = "enable-webrtc-aec-recordings";
+
+// Enables HW decode acceleration for WebRTC.
+const char kEnableWebRtcHWDecoding[] = "enable-webrtc-hw-decoding";
+
+#endif
#if defined(OS_ANDROID)
-// Disable history logging for media elements.
-const char kDisableMediaHistoryLogging[] = "disable-media-history";
+// Disables device motion events.
+const char kDisableDeviceMotion[] = "disable-device-motion";
// Disable user gesture requirement for media playback.
const char kDisableGestureRequirementForMediaPlayback[] =
"disable-gesture-requirement-for-media-playback";
-// The telephony region (ISO country code) to use in phone number detection.
-const char kNetworkCountryIso[] = "network-country-iso";
+// Disable history logging for media elements.
+const char kDisableMediaHistoryLogging[] = "disable-media-history";
// Disable overscroll edge effects like those found in Android views.
const char kDisableOverscrollEdgeEffect[] = "disable-overscroll-edge-effect";
+
+// WebRTC is enabled by default on Android.
+const char kDisableWebRTC[] = "disable-webrtc";
+
+// Enable the recognition part of the Web Speech API.
+const char kEnableSpeechRecognition[] = "enable-speech-recognition";
+
+// Don't display any scrollbars. This is useful for Android WebView where
+// the system manages the scrollbars instead.
+const char kHideScrollbars[] = "hide-scrollbars";
+
+// The telephony region (ISO country code) to use in phone number detection.
+const char kNetworkCountryIso[] = "network-country-iso";
+
+// Enables remote debug over HTTP on the specified socket name.
+const char kRemoteDebuggingSocketName[] = "remote-debugging-socket-name";
#endif
#if defined(OS_CHROMEOS)
@@ -841,11 +910,6 @@
const char kDisablePanelFitting[] = "disable-panel-fitting";
#endif
-#if defined(OS_POSIX)
-// Causes the child processes to cleanly exit via calling exit().
-const char kChildCleanExit[] = "child-clean-exit";
-#endif
-
#if defined(OS_MACOSX) && !defined(OS_IOS)
const char kDisableCarbonInterposing[] = "disable-carbon-interposing";
@@ -853,58 +917,16 @@
const char kUseCoreAnimation[] = "use-core-animation";
#endif
-// Disables the use of a 3D software rasterizer.
-const char kDisableSoftwareRasterizer[] = "disable-software-rasterizer";
+#if defined(OS_POSIX)
+// Causes the child processes to cleanly exit via calling exit().
+const char kChildCleanExit[] = "child-clean-exit";
+#endif
#if defined(USE_AURA)
// Forces usage of the test compositor. Needed to run ui tests on bots.
extern const char kTestCompositor[] = "test-compositor";
#endif
-// Sets the tile size used by composited layers.
-const char kDefaultTileWidth[] = "default-tile-width";
-const char kDefaultTileHeight[] = "default-tile-height";
-
-// Sets the width and height above which a composited layer will get tiled.
-const char kMaxUntiledLayerWidth[] = "max-untiled-layer-width";
-const char kMaxUntiledLayerHeight[] = "max-untiled-layer-height";
-
-const char kEnableFixedPositionCreatesStackingContext[]
- = "enable-fixed-position-creates-stacking-context";
-const char kDisableFixedPositionCreatesStackingContext[]
- = "disable-fixed-position-creates-stacking-context";
-
-// Defer image decoding in WebKit until painting.
-const char kEnableDeferredImageDecoding[] = "enable-deferred-image-decoding";
-
-// Use a begin frame signal from browser to renderer to schedule rendering.
-const char kEnableBeginFrameScheduling[] = "enable-begin-frame-scheduling";
-
-// Synchronize delivery and response of input events to and from the renderer.
-const char kEnableBrowserInputController[] = "enable-browser-input-controller";
-
-// Enables or disables history navigation in response to horizontal overscroll.
-// Set the value to '1' to enable the feature, and set to '0' to disable.
-// Defaults to enabled.
-const char kOverscrollHistoryNavigation[] =
- "overscroll-history-navigation";
-
-// Enables or disables scroll end effect in response to vertical overscroll.
-// Set the value to '1' to enable the feature, and set to '0' to disable.
-// Defaults to disabled.
-const char kScrollEndEffect[] = "scroll-end-effect";
-
-// Forward overscroll event data from the renderer to the browser.
-const char kEnableOverscrollNotifications[] = "enable-overscroll-notifications";
-
-// Enables WebGL extensions not yet approved by the community.
-const char kEnableWebGLDraftExtensions[] = "enable-webgl-draft-extensions";
-
-// Enables/disables accelerated compositing for backgrounds of root layers with
-// background-attachment: fixed. Requires kForceCompositingMode.
-const char kDisableAcceleratedFixedRootBackground[] =
- "disable-accelerated-fixed-root-background";
-const char kEnableAcceleratedFixedRootBackground[] =
- "enable-accelerated-fixed-root-background";
+// Don't dump stuff here, follow the same order as the header.
} // namespace switches
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 9124de1..a4852d5 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -12,148 +12,154 @@
namespace switches {
+// All switches in alphabetical order. The switches should be documented
+// alongside the definition of their values in the .cc file.
CONTENT_EXPORT extern const char kAllowFileAccessFromFiles[];
+CONTENT_EXPORT extern const char kAllowNoSandboxJob[];
extern const char kAllowSandboxDebugging[];
extern const char kAllowWebUICompositing[];
-extern const char kAuditHandles[];
extern const char kAuditAllHandles[];
+extern const char kAuditHandles[];
+CONTENT_EXPORT extern const char kBlacklistAcceleratedCompositing[];
+CONTENT_EXPORT extern const char kBlacklistWebGL[];
CONTENT_EXPORT extern const char kBrowserAssertTest[];
CONTENT_EXPORT extern const char kBrowserCrashTest[];
CONTENT_EXPORT extern const char kBrowserSubprocessPath[];
+extern const char kDebugPluginLoading[];
+extern const char kDefaultTileWidth[];
+extern const char kDefaultTileHeight[];
CONTENT_EXPORT extern const char kDisable2dCanvasAntialiasing[];
-CONTENT_EXPORT extern const char kEnableExperimentalCanvasFeatures[];
CONTENT_EXPORT extern const char kDisable3DAPIs[];
CONTENT_EXPORT extern const char kDisableAccelerated2dCanvas[];
CONTENT_EXPORT extern const char kDisableAcceleratedCompositing[];
+CONTENT_EXPORT extern const char kDisableAcceleratedFixedRootBackground[];
CONTENT_EXPORT extern const char kDisableAcceleratedLayers[];
+extern const char kDisableAcceleratedOverflowScroll[];
CONTENT_EXPORT extern const char kDisableAcceleratedPlugins[];
CONTENT_EXPORT extern const char kDisableAcceleratedVideo[];
+CONTENT_EXPORT extern const char kDisableAcceleratedVideoDecode[];
CONTENT_EXPORT extern const char kDisableAltWinstation[];
CONTENT_EXPORT extern const char kDisableApplicationCache[];
CONTENT_EXPORT extern const char kDisableAudio[];
extern const char kDisableBackingStoreLimit[];
+CONTENT_EXPORT extern const char kDisableBrowserPluginCompositing[];
+CONTENT_EXPORT extern const char kDisableCompositingForFixedPosition[];
+CONTENT_EXPORT extern const char kDisableCompositingForTransition[];
CONTENT_EXPORT extern const char kDisableDatabases[];
+CONTENT_EXPORT extern const char kDisableDelegatedRenderer[];
extern const char kDisableDesktopNotifications[];
CONTENT_EXPORT extern const char kDisableDeviceOrientation[];
CONTENT_EXPORT extern const char kDisableExperimentalWebGL[];
-CONTENT_EXPORT extern const char kBlacklistAcceleratedCompositing[];
-CONTENT_EXPORT extern const char kBlacklistWebGL[];
extern const char kDisableFileSystem[];
+CONTENT_EXPORT extern const char kDisableFixedPositionCreatesStackingContext[];
CONTENT_EXPORT extern const char kDisableFlash3d[];
CONTENT_EXPORT extern const char kDisableFlashStage3d[];
CONTENT_EXPORT extern const char kDisableForceCompositingMode[];
+CONTENT_EXPORT extern const char kDisableFullScreen[];
extern const char kDisableGeolocation[];
-CONTENT_EXPORT extern const char kUseGpuInTests[];
-extern const char kDisableGpu[];
+CONTENT_EXPORT extern const char kDisableGestureTapHighlight[];
CONTENT_EXPORT extern const char kDisableGLMultisampling[];
+extern const char kDisableGpu[];
+CONTENT_EXPORT extern const char kDisableGpuCompositing[];
CONTENT_EXPORT extern const char kDisableGpuProcessPrelaunch[];
extern const char kDisableGpuSandbox[];
-extern const char kReduceGpuSandbox[];
-CONTENT_EXPORT extern const char kDisableGpuCompositing[];
extern const char kDisableGpuWatchdog[];
CONTENT_EXPORT extern const char kDisableHangMonitor[];
-CONTENT_EXPORT extern const char kDisableHTMLNotifications[];
extern const char kDisableHistogramCustomizer[];
+CONTENT_EXPORT extern const char kDisableHTMLNotifications[];
extern const char kDisableImageTransportSurface[];
CONTENT_EXPORT extern const char kDisableJava[];
CONTENT_EXPORT extern const char kDisableJavaScript[];
+extern const char kDisableLegacyEncryptedMedia[];
CONTENT_EXPORT extern const char kDisableLocalStorage[];
CONTENT_EXPORT extern const char kDisableLogging[];
-CONTENT_EXPORT extern const char kLogNetLog[];
-CONTENT_EXPORT extern const char kDisableSmoothScrolling[];
+extern const char kDisablePepper3d[];
+extern const char kDisablePinch[];
CONTENT_EXPORT extern const char kDisablePlugins[];
+CONTENT_EXPORT extern const char kDisablePluginsDiscovery[];
extern const char kDisableRemoteFonts[];
extern const char kDisableRendererAccessibility[];
-extern const char kDisableSSLFalseStart[];
extern const char kDisableSeccompFilterSandbox[];
extern const char kDisableSessionStorage[];
extern const char kDisableSetuidSandbox[];
extern const char kDisableSharedWorkers[];
extern const char kDisableSiteSpecificQuirks[];
+CONTENT_EXPORT extern const char kDisableSmoothScrolling[];
+CONTENT_EXPORT extern const char kDisableSoftwareRasterizer[];
CONTENT_EXPORT extern const char kDisableSpeechInput[];
-extern const char kSpeechRecognitionWebserviceKey[];
-CONTENT_EXPORT extern const char kEnableSpeechSynthesis[];
-#if defined(OS_ANDROID)
-CONTENT_EXPORT extern const char kDisableWebRTC[];
-CONTENT_EXPORT extern const char kEnableSpeechRecognition[];
-#endif
+extern const char kDisableSSLFalseStart[];
+CONTENT_EXPORT extern const char kDisableThreadedCompositing[];
+CONTENT_EXPORT extern const char kDisableThreadedHTMLParser[];
CONTENT_EXPORT extern const char kDisableWebAudio[];
-#if defined(ENABLE_WEBRTC)
-CONTENT_EXPORT extern const char kDisableDeviceEnumeration[];
-CONTENT_EXPORT extern const char kEnableSCTPDataChannels[];
-extern const char kEnableWebRtcAecRecordings[];
-extern const char kEnableWebRtcHWDecoding[];
-#endif
-extern const char kEnableWebRtcTcpServerSocket[];
-extern const char kEnableWebAnimationsCSS[];
-extern const char kEnableWebAnimationsSVG[];
-extern const char kEnableWebMIDI[];
+extern const char kDisableWebKitMediaSource[];
extern const char kDisableWebSecurity[];
-extern const char kEnableExperimentalWebSocket[];
extern const char kDisableXSSAuditor[];
CONTENT_EXPORT extern const char kDomAutomationController[];
-CONTENT_EXPORT extern const char kStatsCollectionController[];
CONTENT_EXPORT extern const char kEnableAcceleratedFilters[];
+CONTENT_EXPORT extern const char kEnableAcceleratedFixedRootBackground[];
+extern const char kEnableAcceleratedOverflowScroll[];
+extern const char kEnableAcceleratedScrollableFrames[];
extern const char kEnableAccessibilityLogging[];
extern const char kEnableAudibleNotifications[];
-CONTENT_EXPORT extern const char kDisableBrowserPluginCompositing[];
+CONTENT_EXPORT extern const char kEnableBeginFrameScheduling[];
+CONTENT_EXPORT extern const char kEnableBrowserInputController[];
CONTENT_EXPORT extern const char kEnableBrowserPluginForAllViewTypes[];
CONTENT_EXPORT extern const char kEnableBrowserPluginDragDrop[];
+extern const char kEnableCompositedScrollingForFrames[];
CONTENT_EXPORT extern const char kEnableCompositingForFixedPosition[];
-CONTENT_EXPORT extern const char kEnableHighDpiCompositingForFixedPosition[];
-CONTENT_EXPORT extern const char kDisableCompositingForFixedPosition[];
CONTENT_EXPORT extern const char kEnableCompositingForTransition[];
-CONTENT_EXPORT extern const char kDisableCompositingForTransition[];
CONTENT_EXPORT extern const char kEnableCssShaders[];
-CONTENT_EXPORT extern const char kDisableDelegatedRenderer[];
+CONTENT_EXPORT extern const char kEnableDeferredImageDecoding[];
CONTENT_EXPORT extern const char kEnableDelegatedRenderer[];
CONTENT_EXPORT extern const char kEnableDeviceMotion[];
-#if defined(OS_ANDROID)
-CONTENT_EXPORT extern const char kDisableDeviceMotion[];
-#endif
CONTENT_EXPORT extern const char kEnableDownloadResumption[];
+extern const char kEnableEncryptedMedia[];
+CONTENT_EXPORT extern const char kEnableExperimentalCanvasFeatures[];
CONTENT_EXPORT extern const char kEnableExperimentalWebPlatformFeatures[];
-CONTENT_EXPORT extern const char kEnableRegionBasedColumns[];
-CONTENT_EXPORT extern const char kDisableThreadedHTMLParser[];
+extern const char kEnableExperimentalWebSocket[];
CONTENT_EXPORT extern const char kEnableFixedLayout[];
-CONTENT_EXPORT extern const char kDisableFullScreen[];
-CONTENT_EXPORT extern const char kEnableTextServicesFramework[];
+CONTENT_EXPORT extern const char kEnableFixedPositionCreatesStackingContext[];
CONTENT_EXPORT extern const char kEnableGestureTapHighlight[];
-CONTENT_EXPORT extern const char kDisableGestureTapHighlight[];
extern const char kEnableGpuBenchmarking[];
extern const char kEnableGpuClientTracing[];
+CONTENT_EXPORT extern const char kEnableHighDpiCompositingForFixedPosition[];
+extern const char kEnableHTMLImports[];
CONTENT_EXPORT extern const char kEnableInbandTextTracks[];
-extern const char kEnableMemoryBenchmarking[];
-extern const char kEnableSkiaBenchmarking[];
CONTENT_EXPORT extern const char kEnableLogging[];
-extern const char kDisableWebKitMediaSource[];
-extern const char kEnableEncryptedMedia[];
-extern const char kDisableLegacyEncryptedMedia[];
-CONTENT_EXPORT extern const char kUseFakeDeviceForMediaStream[];
-CONTENT_EXPORT extern const char kUseFakeUIForMediaStream[];
+extern const char kEnableMemoryBenchmarking[];
extern const char kEnableMonitorProfile[];
extern const char kEnableNewMediaInternals[];
-extern const char kEnableUserMediaScreenCapturing[];
-extern const char kEnablePinch[];
CONTENT_EXPORT extern const char kEnableOfflineCacheAccess[];
-extern const char kDisablePinch[];
+CONTENT_EXPORT extern const char kEnableOverscrollNotifications[];
+extern const char kEnablePinch[];
extern const char kEnablePreparsedJsCaching[];
CONTENT_EXPORT extern const char kEnablePrivilegedWebGLExtensions[];
extern const char kEnablePruneGpuCommandBuffers[];
-extern const char kEnableSSLCachedInfo[];
+CONTENT_EXPORT extern const char kEnableRegionBasedColumns[];
extern const char kEnableSandboxLogging[];
-extern const char kEnableSpatialNavigation[];
-CONTENT_EXPORT extern const char kEnableSoftwareCompositing[];
+extern const char kEnableSkiaBenchmarking[];
CONTENT_EXPORT extern const char kEnableSmoothScrolling[];
+CONTENT_EXPORT extern const char kEnableSoftwareCompositing[];
+extern const char kEnableSpatialNavigation[];
+CONTENT_EXPORT extern const char kEnableSpeechSynthesis[];
+extern const char kEnableSSLCachedInfo[];
CONTENT_EXPORT extern const char kEnableStatsTable[];
extern const char kEnableStrictSiteIsolation[];
-CONTENT_EXPORT extern const char kEnableThreadedCompositing[];
-CONTENT_EXPORT extern const char kDisableThreadedCompositing[];
-extern const char kEnableVirtualGLContexts[];
CONTENT_EXPORT extern const char kEnableTcpFastOpen[];
-CONTENT_EXPORT extern const char kDisableAcceleratedVideoDecode[];
+CONTENT_EXPORT extern const char kEnableTextServicesFramework[];
+CONTENT_EXPORT extern const char kEnableThreadedCompositing[];
+extern const char kEnableUserMediaScreenCapturing[];
extern const char kEnableViewport[];
+extern const char kEnableVirtualGLContexts[];
+extern const char kEnableVisualWordMovement[];
+CONTENT_EXPORT extern const char kEnableVtune[];
+extern const char kEnableWebAnimationsCSS[];
+extern const char kEnableWebAnimationsSVG[];
+CONTENT_EXPORT extern const char kEnableWebGLDraftExtensions[];
+extern const char kEnableWebMIDI[];
+extern const char kEnableWebRtcTcpServerSocket[];
CONTENT_EXPORT extern const char kExperimentalLocationFeatures[];
+CONTENT_EXPORT extern const char kExtraPluginDir[];
CONTENT_EXPORT extern const char kForceCompositingMode[];
extern const char kForceFieldTrials[];
CONTENT_EXPORT extern const char kForceRendererAccessibility[];
@@ -165,30 +171,29 @@
extern const char kGpuSandboxAllowSysVShm[];
extern const char kGpuStartupDialog[];
extern const char kGpuVendorID[];
-#if defined(OS_ANDROID)
-CONTENT_EXPORT extern const char kHideScrollbars[];
-#endif
CONTENT_EXPORT extern const char kHostResolverRules[];
CONTENT_EXPORT extern const char kIgnoreCertificateErrors[];
CONTENT_EXPORT extern const char kIgnoreGpuBlacklist[];
extern const char kInProcessGPU[];
extern const char kInProcessPlugins[];
CONTENT_EXPORT extern const char kJavaScriptFlags[];
-CONTENT_EXPORT extern const char kExtraPluginDir[];
extern const char kLoadPlugin[];
-CONTENT_EXPORT extern const char kDisablePluginsDiscovery[];
CONTENT_EXPORT extern const char kLoggingLevel[];
+CONTENT_EXPORT extern const char kLogNetLog[];
extern const char kLogPluginMessages[];
+extern const char kMaxUntiledLayerHeight[];
+extern const char kMaxUntiledLayerWidth[];
extern const char kMemoryMetrics[];
CONTENT_EXPORT extern const char kMuteAudio[];
CONTENT_EXPORT extern const char kNoReferrers[];
CONTENT_EXPORT extern const char kNoSandbox[];
-CONTENT_EXPORT extern const char kAllowNoSandboxJob[];
+CONTENT_EXPORT extern const char kOverscrollHistoryNavigation[];
extern const char kPluginLauncher[];
CONTENT_EXPORT extern const char kPluginPath[];
CONTENT_EXPORT extern const char kPluginProcess[];
extern const char kPluginStartupDialog[];
CONTENT_EXPORT extern const char kPpapiBrokerProcess[];
+extern const char kPpapiFlashArgs[];
CONTENT_EXPORT extern const char kPpapiInProcess[];
extern const char kPpapiPluginLauncher[];
CONTENT_EXPORT extern const char kPpapiPluginProcess[];
@@ -196,36 +201,36 @@
CONTENT_EXPORT extern const char kProcessPerSite[];
CONTENT_EXPORT extern const char kProcessPerTab[];
CONTENT_EXPORT extern const char kProcessType[];
+extern const char kReduceGpuSandbox[];
CONTENT_EXPORT extern const char kRegisterPepperPlugins[];
CONTENT_EXPORT extern const char kRemoteDebuggingPort[];
-#if defined(OS_ANDROID)
-CONTENT_EXPORT extern const char kRemoteDebuggingSocketName[];
-#endif
CONTENT_EXPORT extern const char kRendererAssertTest[];
extern const char kRendererCmdPrefix[];
CONTENT_EXPORT extern const char kRendererProcess[];
-CONTENT_EXPORT extern const char kEnableVtune[];
extern const char kRendererProcessLimit[];
extern const char kRendererStartupDialog[];
-extern const char kEnableAcceleratedOverflowScroll[];
-extern const char kDisableAcceleratedOverflowScroll[];
-extern const char kEnableAcceleratedScrollableFrames[];
-extern const char kEnableCompositedScrollingForFrames[];
+CONTENT_EXPORT extern const char kScrollEndEffect[];
extern const char kShowPaintRects[];
CONTENT_EXPORT extern const char kSimulateTouchScreenWithMouse[];
CONTENT_EXPORT extern const char kSingleProcess[];
CONTENT_EXPORT extern const char kSitePerProcess[];
CONTENT_EXPORT extern const char kSkipGpuDataLoading[];
-extern const char kTabCaptureUpscaleQuality[];
+extern const char kSpeechRecognitionWebserviceKey[];
+CONTENT_EXPORT extern const char kStatsCollectionController[];
extern const char kTabCaptureDownscaleQuality[];
+extern const char kTabCaptureUpscaleQuality[];
extern const char kTapDownDeferralTimeMs[];
-CONTENT_EXPORT extern const char kTestSandbox[];
CONTENT_EXPORT extern const char kTestingFixedHttpPort[];
CONTENT_EXPORT extern const char kTestingFixedHttpsPort[];
+CONTENT_EXPORT extern const char kTestSandbox[];
extern const char kTraceStartup[];
-extern const char kTraceStartupFile[];
extern const char kTraceStartupDuration[];
+extern const char kTraceStartupFile[];
CONTENT_EXPORT extern const char kUIPrioritizeInGpuProcess[];
+CONTENT_EXPORT extern const char kUseFakeDeviceForMediaStream[];
+CONTENT_EXPORT extern const char kUseFakeUIForMediaStream[];
+CONTENT_EXPORT extern const char kUseGpuInTests[];
+CONTENT_EXPORT extern const char kUseMobileUserAgent[];
CONTENT_EXPORT extern const char kUserAgent[];
extern const char kUtilityCmdPrefix[];
CONTENT_EXPORT extern const char kUtilityProcess[];
@@ -236,51 +241,45 @@
CONTENT_EXPORT extern const char kWorkerProcess[];
CONTENT_EXPORT extern const char kZygoteCmdPrefix[];
CONTENT_EXPORT extern const char kZygoteProcess[];
-CONTENT_EXPORT extern const char kDisableSoftwareRasterizer[];
-extern const char kDefaultTileWidth[];
-extern const char kDefaultTileHeight[];
-extern const char kMaxUntiledLayerWidth[];
-extern const char kMaxUntiledLayerHeight[];
-CONTENT_EXPORT extern const char kEnableFixedPositionCreatesStackingContext[];
-CONTENT_EXPORT extern const char kDisableFixedPositionCreatesStackingContext[];
-CONTENT_EXPORT extern const char kEnableDeferredImageDecoding[];
-CONTENT_EXPORT extern const char kEnableBeginFrameScheduling[];
-CONTENT_EXPORT extern const char kEnableBrowserInputController[];
-extern const char kEnableVisualWordMovement[];
-CONTENT_EXPORT extern const char kUseMobileUserAgent[];
+#if defined(ENABLE_WEBRTC)
+CONTENT_EXPORT extern const char kDisableDeviceEnumeration[];
+CONTENT_EXPORT extern const char kEnableSCTPDataChannels[];
+extern const char kEnableWebRtcAecRecordings[];
+extern const char kEnableWebRtcHWDecoding[];
+#endif
#if defined(OS_ANDROID)
-extern const char kDisableMediaHistoryLogging[];
+CONTENT_EXPORT extern const char kDisableDeviceMotion[];
CONTENT_EXPORT extern const char kDisableGestureRequirementForMediaPlayback[];
-extern const char kNetworkCountryIso[];
+extern const char kDisableMediaHistoryLogging[];
CONTENT_EXPORT extern const char kDisableOverscrollEdgeEffect[];
+CONTENT_EXPORT extern const char kDisableWebRTC[];
+CONTENT_EXPORT extern const char kEnableSpeechRecognition[];
+CONTENT_EXPORT extern const char kHideScrollbars[];
+extern const char kNetworkCountryIso[];
+CONTENT_EXPORT extern const char kRemoteDebuggingSocketName[];
#endif
#if defined(OS_CHROMEOS)
CONTENT_EXPORT extern const char kDisablePanelFitting[];
#endif
-#if defined(OS_POSIX)
-extern const char kChildCleanExit[];
-#endif
-
#if defined(OS_MACOSX) && !defined(OS_IOS)
extern const char kDisableCarbonInterposing[];
extern const char kUseCoreAnimation[];
#endif
+#if defined(OS_POSIX)
+extern const char kChildCleanExit[];
+#endif
+
#if defined(USE_AURA)
CONTENT_EXPORT extern const char kTestCompositor[];
#endif
-CONTENT_EXPORT extern const char kOverscrollHistoryNavigation[];
-CONTENT_EXPORT extern const char kScrollEndEffect[];
-CONTENT_EXPORT extern const char kEnableOverscrollNotifications[];
-CONTENT_EXPORT extern const char kEnableWebGLDraftExtensions[];
-
-CONTENT_EXPORT extern const char kDisableAcceleratedFixedRootBackground[];
-CONTENT_EXPORT extern const char kEnableAcceleratedFixedRootBackground[];
+// DON'T ADD RANDOM STUFF HERE. Put it in the main section above in
+// alphabetical order, or in one of the ifdefs (also in order in each section).
} // namespace switches
diff --git a/content/public/common/desktop_media_id.cc b/content/public/common/desktop_media_id.cc
new file mode 100644
index 0000000..82ebe9c
--- /dev/null
+++ b/content/public/common/desktop_media_id.cc
@@ -0,0 +1,41 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/common/desktop_media_id.h"
+
+namespace content {
+
+// static
+DesktopMediaID DesktopMediaID::Parse(const std::string& str) {
+ if (str == "screen")
+ return DesktopMediaID(TYPE_SCREEN, 0);
+
+ std::string window_prefix("window:");
+ if (StartsWithASCII(str, window_prefix, true)) {
+ int64 id;
+ if (!base::StringToInt64(str.substr(window_prefix.size()), &id))
+ return DesktopMediaID(TYPE_NONE, 0);
+ return DesktopMediaID(TYPE_WINDOW, id);
+ }
+
+ return DesktopMediaID(TYPE_NONE, 0);
+}
+
+std::string DesktopMediaID::ToString() {
+ switch (type) {
+ case TYPE_NONE:
+ NOTREACHED();
+ return std::string();
+
+ case TYPE_SCREEN:
+ return "screen";
+
+ case TYPE_WINDOW:
+ return "window:" + base::Int64ToString(id);
+ }
+ NOTREACHED();
+ return std::string();
+}
+
+} // namespace content
diff --git a/content/public/common/desktop_media_id.h b/content/public/common/desktop_media_id.h
new file mode 100644
index 0000000..a863872
--- /dev/null
+++ b/content/public/common/desktop_media_id.h
@@ -0,0 +1,57 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_COMMON_DESKTOP_MEDIA_ID_H_
+#define CONTENT_PUBLIC_COMMON_DESKTOP_MEDIA_ID_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Type used to identify desktop media sources. It's converted to string and
+// stored in MediaStreamRequest::requested_video_device_id .
+struct CONTENT_EXPORT DesktopMediaID {
+ public:
+ enum Type {
+ TYPE_NONE,
+ TYPE_SCREEN,
+ TYPE_WINDOW,
+ };
+ typedef intptr_t Id;
+
+ static DesktopMediaID Parse(const std::string& str);
+
+ DesktopMediaID()
+ : type(TYPE_NONE),
+ id(0) {
+ }
+ DesktopMediaID(Type type, Id id)
+ : type(type),
+ id(id) {
+ }
+
+ // Operators so that DesktopMediaID can be used with STL containers.
+ bool operator<(const DesktopMediaID& other) const {
+ return type < other.type || (type == other.type && id < other.id);
+ }
+ bool operator==(const DesktopMediaID& other) const {
+ return type == other.type && id == other.id;
+ }
+
+ bool is_null() { return type == TYPE_NONE; }
+
+ std::string ToString();
+
+ Type type;
+ Id id;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_DESKTOP_MEDIA_ID_H_
diff --git a/content/public/common/media_stream_request.cc b/content/public/common/media_stream_request.cc
index 2c2f9d8..e3ad35b 100644
--- a/content/public/common/media_stream_request.cc
+++ b/content/public/common/media_stream_request.cc
@@ -17,8 +17,7 @@
bool IsVideoMediaType(MediaStreamType type) {
return (type == content::MEDIA_DEVICE_VIDEO_CAPTURE ||
type == content::MEDIA_TAB_VIDEO_CAPTURE ||
- type == content::MEDIA_SCREEN_VIDEO_CAPTURE ||
- type == content::MEDIA_WINDOW_VIDEO_CAPTURE);
+ type == content::MEDIA_DESKTOP_VIDEO_CAPTURE);
}
MediaStreamDevice::MediaStreamDevice() : type(MEDIA_NO_SERVICE) {}
diff --git a/content/public/common/media_stream_request.h b/content/public/common/media_stream_request.h
index d01e7a8..cbbf232d1 100644
--- a/content/public/common/media_stream_request.h
+++ b/content/public/common/media_stream_request.h
@@ -26,14 +26,18 @@
MEDIA_DEVICE_VIDEO_CAPTURE,
// Mirroring of a browser tab.
+ //
+ // TODO(serygeu): Remove these values and use MEDIA_DESKTOP_VIDEO_CAPTURE and
+ // MEDIA_DESKTOP_AUDIO_CAPTURE.
MEDIA_TAB_AUDIO_CAPTURE,
MEDIA_TAB_VIDEO_CAPTURE,
// Desktop media sources.
- MEDIA_SCREEN_VIDEO_CAPTURE,
- MEDIA_WINDOW_VIDEO_CAPTURE,
+ MEDIA_DESKTOP_VIDEO_CAPTURE,
// Capture system audio (post-mix loopback stream).
+ //
+ // TODO(sergeyu): Replace with MEDIA_DESKTOP_AUDIO_CAPTURE.
MEDIA_SYSTEM_AUDIO_CAPTURE,
NUM_MEDIA_TYPES
diff --git a/content/public/common/url_constants.cc b/content/public/common/url_constants.cc
index d8936c5..71ab648 100644
--- a/content/public/common/url_constants.cc
+++ b/content/public/common/url_constants.cc
@@ -22,12 +22,12 @@
const char kHttpScheme[] = "http";
const char kHttpsScheme[] = "https";
const char kJavaScriptScheme[] = "javascript";
-const char kMailToScheme[] = "mailto";
-const char kMetadataScheme[] = "metadata";
} // namespace chrome
namespace content {
+const char kMailToScheme[] = "mailto";
+const char kMetadataScheme[] = "metadata";
const char kSwappedOutScheme[] = "swappedout";
const char kViewSourceScheme[] = "view-source";
diff --git a/content/public/common/url_constants.h b/content/public/common/url_constants.h
index 541f4c6..ef17684 100644
--- a/content/public/common/url_constants.h
+++ b/content/public/common/url_constants.h
@@ -28,12 +28,12 @@
CONTENT_EXPORT extern const char kHttpScheme[];
CONTENT_EXPORT extern const char kHttpsScheme[];
CONTENT_EXPORT extern const char kJavaScriptScheme[];
-CONTENT_EXPORT extern const char kMailToScheme[];
-CONTENT_EXPORT extern const char kMetadataScheme[];
} // namespace chrome
namespace content {
+CONTENT_EXPORT extern const char kMailToScheme[];
+CONTENT_EXPORT extern const char kMetadataScheme[];
CONTENT_EXPORT extern const char kSwappedOutScheme[];
CONTENT_EXPORT extern const char kViewSourceScheme[];
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc
index a94fb2d..c190f09 100644
--- a/content/public/renderer/content_renderer_client.cc
+++ b/content/public/renderer/content_renderer_client.cc
@@ -138,7 +138,7 @@
bool ContentRendererClient::ShouldOverridePageVisibilityState(
const RenderView* render_view,
- WebKit::WebPageVisibilityState* override_state) const {
+ WebKit::WebPageVisibilityState* override_state) {
return false;
}
@@ -163,17 +163,22 @@
return NULL;
}
+bool ContentRendererClient::IsExternalPepperPlugin(
+ const std::string& module_name) {
+ return false;
+}
+
bool ContentRendererClient::IsPluginAllowedToCallRequestOSFileHandle(
- WebKit::WebPluginContainer* container) const {
+ WebKit::WebPluginContainer* container) {
return false;
}
bool ContentRendererClient::AllowBrowserPlugin(
- WebKit::WebPluginContainer* container) const {
+ WebKit::WebPluginContainer* container) {
return false;
}
-bool ContentRendererClient::AllowPepperMediaStreamAPI(const GURL& url) const {
+bool ContentRendererClient::AllowPepperMediaStreamAPI(const GURL& url) {
return false;
}
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index 7730927..a00e1a9 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -209,7 +209,7 @@
virtual WebKit::WebPrescientNetworking* GetPrescientNetworking();
virtual bool ShouldOverridePageVisibilityState(
const RenderView* render_view,
- WebKit::WebPageVisibilityState* override_state) const;
+ WebKit::WebPageVisibilityState* override_state);
// Return true if the GetCookie request will be handled by the embedder.
// Cookies are returned in the cookie parameter.
@@ -229,16 +229,20 @@
virtual const void* CreatePPAPIInterface(
const std::string& interface_name);
+ // Returns true if the given Pepper plugin is external (requiring special
+ // startup steps).
+ virtual bool IsExternalPepperPlugin(const std::string& module_name);
+
// Returns true if plugin living in the container can use
// pp::FileIO::RequestOSFileHandle.
virtual bool IsPluginAllowedToCallRequestOSFileHandle(
- WebKit::WebPluginContainer* container) const;
+ WebKit::WebPluginContainer* container);
// Returns whether BrowserPlugin should be allowed within the |container|.
- virtual bool AllowBrowserPlugin(WebKit::WebPluginContainer* container) const;
+ virtual bool AllowBrowserPlugin(WebKit::WebPluginContainer* container);
// Returns true if the page at |url| can use Pepper MediaStream APIs.
- virtual bool AllowPepperMediaStreamAPI(const GURL& url) const;
+ virtual bool AllowPepperMediaStreamAPI(const GURL& url);
};
} // namespace content
diff --git a/content/public/renderer/pepper_plugin_instance.h b/content/public/renderer/pepper_plugin_instance.h
index 211752d..c7741a2 100644
--- a/content/public/renderer/pepper_plugin_instance.h
+++ b/content/public/renderer/pepper_plugin_instance.h
@@ -56,11 +56,6 @@
// Returns the location of this module.
virtual base::FilePath GetModulePath() = 0;
- // Returns a reference to a file with the given path.
- // The returned object will have a refcount of 0 (just like "new").
- virtual PP_Resource CreateExternalFileReference(
- const base::FilePath& external_file_path) = 0;
-
// Creates a PPB_ImageData given a Skia image.
virtual PP_Resource CreateImage(gfx::ImageSkia* source_image,
float scale) = 0;
@@ -92,7 +87,6 @@
virtual int32_t Navigate(const ppapi::URLRequestInfoData& request,
const char* target,
bool from_user_action) = 0;
-
};
} // namespace content
diff --git a/content/public/renderer/renderer_ppapi_host.h b/content/public/renderer/renderer_ppapi_host.h
index 329961e..36d6273 100644
--- a/content/public/renderer/renderer_ppapi_host.h
+++ b/content/public/renderer/renderer_ppapi_host.h
@@ -47,6 +47,11 @@
public:
// Returns the RendererPpapiHost associated with the given PP_Instance,
// or NULL if the instance is invalid.
+ //
+ // Do NOT use this when dealing with the "NaCl trusted plugin". That plugin
+ // and the "untrusted plugin" (the NaCl application) that will be loaded
+ // share a PP_Instance, and the RendererPpapiHost* for the "untrusted plugin"
+ // will be returned after we switch the proxy on.
CONTENT_EXPORT static RendererPpapiHost* GetForPPInstance(
PP_Instance instance);
diff --git a/content/public/test/mock_download_manager.cc b/content/public/test/mock_download_manager.cc
index 12485b2..ef5a9f5 100644
--- a/content/public/test/mock_download_manager.cc
+++ b/content/public/test/mock_download_manager.cc
@@ -17,6 +17,8 @@
const GURL& referrer_url,
const base::Time& start_time,
const base::Time& end_time,
+ const std::string& etag,
+ const std::string& last_modified,
int64 received_bytes,
int64 total_bytes,
DownloadItem::DownloadState state,
@@ -46,6 +48,8 @@
referrer_url(rhs.referrer_url),
start_time(rhs.start_time),
end_time(rhs.end_time),
+ etag(rhs.etag),
+ last_modified(rhs.last_modified),
received_bytes(rhs.received_bytes),
total_bytes(rhs.total_bytes),
state(rhs.state),
@@ -64,6 +68,8 @@
referrer_url == rhs.referrer_url &&
start_time == rhs.start_time &&
end_time == rhs.end_time &&
+ etag == rhs.etag &&
+ last_modified == rhs.last_modified &&
received_bytes == rhs.received_bytes &&
total_bytes == rhs.total_bytes &&
state == rhs.state &&
@@ -91,6 +97,8 @@
const GURL& referrer_url,
const base::Time& start_time,
const base::Time& end_time,
+ const std::string& etag,
+ const std::string& last_modified,
int64 received_bytes,
int64 total_bytes,
DownloadItem::DownloadState state,
@@ -99,8 +107,8 @@
bool opened) {
CreateDownloadItemAdapter adapter(
id, current_path, target_path, url_chain, referrer_url, start_time,
- end_time, received_bytes, total_bytes, state, danger_type,
- interrupt_reason, opened);
+ end_time, etag, last_modified, received_bytes, total_bytes, state,
+ danger_type, interrupt_reason, opened);
return MockCreateDownloadItem(adapter);
}
diff --git a/content/public/test/mock_download_manager.h b/content/public/test/mock_download_manager.h
index 9f090a9..fdcf9d6 100644
--- a/content/public/test/mock_download_manager.h
+++ b/content/public/test/mock_download_manager.h
@@ -33,6 +33,8 @@
GURL referrer_url;
base::Time start_time;
base::Time end_time;
+ std::string etag;
+ std::string last_modified;
int64 received_bytes;
int64 total_bytes;
DownloadItem::DownloadState state;
@@ -48,6 +50,8 @@
const GURL& referrer_url,
const base::Time& start_time,
const base::Time& end_time,
+ const std::string& etag,
+ const std::string& last_modified,
int64 received_bytes,
int64 total_bytes,
DownloadItem::DownloadState state,
@@ -99,6 +103,8 @@
const GURL& referrer_url,
const base::Time& start_time,
const base::Time& end_time,
+ const std::string& etag,
+ const std::string& last_modified,
int64 received_bytes,
int64 total_bytes,
DownloadItem::DownloadState state,
diff --git a/content/renderer/all_rendering_benchmarks.cc b/content/renderer/all_rendering_benchmarks.cc
deleted file mode 100644
index 14280f3..0000000
--- a/content/renderer/all_rendering_benchmarks.cc
+++ /dev/null
@@ -1,290 +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 "content/renderer/all_rendering_benchmarks.h"
-
-#include <algorithm>
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/time/time.h"
-#include "content/renderer/rendering_benchmark.h"
-#include "skia/ext/platform_canvas.h"
-#include "third_party/skia/include/core/SkPicture.h"
-#include "third_party/skia/include/utils/SkNullCanvas.h"
-#include "third_party/WebKit/public/platform/WebRect.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-#include "third_party/WebKit/public/web/WebViewBenchmarkSupport.h"
-
-using base::TimeDelta;
-using base::TimeTicks;
-using WebKit::WebSize;
-using WebKit::WebCanvas;
-using WebKit::WebViewBenchmarkSupport;
-using WebKit::WebRect;
-using std::vector;
-
-namespace {
-
-// This is a base class for timing the painting of the current webpage to
-// custom WebCanvases.
-class CustomPaintBenchmark
- : public content::RenderingBenchmark,
- public WebViewBenchmarkSupport::PaintClient {
- public:
- CustomPaintBenchmark(const std::string& name,
- WebViewBenchmarkSupport::PaintMode paint_mode)
- : content::RenderingBenchmark(name),
- paint_mode_(paint_mode) { }
-
- virtual WebCanvas* willPaint(const WebSize& size) OVERRIDE {
- WebCanvas* canvas = createCanvas(size);
- before_time_ = TimeTicks::HighResNow();
- return canvas;
- }
-
- virtual void didPaint(WebCanvas* canvas) OVERRIDE {
- paint_time_total_ += (TimeTicks::HighResNow() - before_time_);
- delete canvas;
- }
-
- virtual double Run(WebViewBenchmarkSupport* support) OVERRIDE {
- paint_time_total_ = TimeDelta();
- support->paint(this, paint_mode_);
- return paint_time_total_.InMillisecondsF();
- }
-
- private:
- virtual WebCanvas* createCanvas(const WebSize& size) = 0;
-
- TimeTicks before_time_;
- TimeDelta paint_time_total_;
- const WebViewBenchmarkSupport::PaintMode paint_mode_;
-};
-
-class BitmapCanvasPaintBenchmark : public CustomPaintBenchmark {
- public:
- BitmapCanvasPaintBenchmark(const std::string& name,
- WebViewBenchmarkSupport::PaintMode paint_mode)
- : CustomPaintBenchmark(name, paint_mode) { }
-
- private:
- virtual WebCanvas* createCanvas(const WebSize& size) OVERRIDE {
- return skia::CreateBitmapCanvas(size.width, size.height, false);
- }
-};
-
-class CanvasCountBenchmark
- : public content::RenderingBenchmark,
- public WebViewBenchmarkSupport::PaintClient {
- public:
- CanvasCountBenchmark(const std::string& name,
- WebViewBenchmarkSupport::PaintMode paint_mode)
- : content::RenderingBenchmark(name),
- canvas_count_(0),
- paint_mode_(paint_mode) { }
-
- virtual WebCanvas* willPaint(const WebSize& size) OVERRIDE {
- ++canvas_count_;
- return SkCreateNullCanvas();
- }
-
- virtual void didPaint(WebCanvas* canvas) OVERRIDE {
- delete canvas;
- }
-
- virtual double Run(WebViewBenchmarkSupport* support) OVERRIDE {
- canvas_count_ = 0;
- support->paint(this, paint_mode_);
- return canvas_count_;
- }
- private:
- int canvas_count_;
- const WebViewBenchmarkSupport::PaintMode paint_mode_;
-};
-
-class NullCanvasPaintBenchmark : public CustomPaintBenchmark {
- public:
- NullCanvasPaintBenchmark(const std::string& name,
- WebViewBenchmarkSupport::PaintMode paint_mode)
- : CustomPaintBenchmark(name, paint_mode) { }
-
- private:
- virtual WebCanvas* createCanvas(const WebSize& size) OVERRIDE {
- return SkCreateNullCanvas();
- }
-};
-
-class SkPicturePaintBenchmark : public CustomPaintBenchmark {
- public:
- SkPicturePaintBenchmark(const std::string& name,
- WebViewBenchmarkSupport::PaintMode paint_mode)
- : CustomPaintBenchmark(name, paint_mode) { }
-
- virtual void didPaint(WebCanvas* canvas) OVERRIDE {
- DCHECK(picture_.getRecordingCanvas() == canvas);
- picture_.endRecording();
- CustomPaintBenchmark::didPaint(NULL);
- }
-
- private:
- virtual WebCanvas* createCanvas(const WebSize& size) OVERRIDE {
- return picture_.beginRecording(size.width, size.height);
- }
-
- SkPicture picture_;
-};
-
-// Base class for timing the replaying of the SkPicture into canvases.
-class TiledReplayBenchmark
- : public content::RenderingBenchmark,
- public WebViewBenchmarkSupport::PaintClient {
- public:
- TiledReplayBenchmark(const std::string& name,
- WebViewBenchmarkSupport::PaintMode paint_mode)
- : RenderingBenchmark(name),
- paint_mode_(paint_mode) {}
-
- virtual WebCanvas* willPaint(const WebSize& size) OVERRIDE {
- return picture_.beginRecording(size.width, size.height);
- }
-
- virtual void didPaint(WebCanvas* canvas) OVERRIDE {
- DCHECK(picture_.getRecordingCanvas() == canvas);
- picture_.endRecording();
-
- const vector<WebRect> repaint_tiles = GetRepaintTiles(
- WebSize(picture_.width(), picture_.height()));
-
- vector<WebRect>::const_iterator it;
- for (it = repaint_tiles.begin(); it != repaint_tiles.end(); ++it) {
- WebRect tile = *it;
- scoped_ptr<WebCanvas> canvas(
- skia::CreateBitmapCanvas(tile.width, tile.height, false));
- TimeTicks before_time = TimeTicks::HighResNow();
- canvas->translate(-tile.x, -tile.y);
- picture_.draw(canvas.get());
- paint_time_total_ += (TimeTicks::HighResNow() - before_time);
- }
- }
-
- virtual double Run(WebViewBenchmarkSupport* support) OVERRIDE {
- paint_time_total_ = TimeDelta();
- support->paint(this, paint_mode_);
- return paint_time_total_.InMillisecondsF();
- }
-
- private:
- virtual vector<WebRect> GetRepaintTiles(const WebSize& layer_size) const = 0;
-
- TimeDelta paint_time_total_;
- SkPicture picture_;
- const WebViewBenchmarkSupport::PaintMode paint_mode_;
-};
-
-class SquareTiledReplayBenchmark : public TiledReplayBenchmark {
- public:
- SquareTiledReplayBenchmark(const std::string& name,
- WebViewBenchmarkSupport::PaintMode paint_mode,
- int tile_size)
- : TiledReplayBenchmark(name, paint_mode),
- tile_size_(tile_size) {
- CHECK_GT(tile_size, 0);
- }
-
- private:
- virtual vector<WebRect> GetRepaintTiles(
- const WebSize& layer_size) const OVERRIDE {
- vector<WebRect> tiles;
- for (int x = 0; x < layer_size.width; x += tile_size_) {
- for (int y = 0; y < layer_size.height; y += tile_size_) {
- int width = std::min(layer_size.width - x, tile_size_);
- int height = std::min(layer_size.height - y, tile_size_);
- tiles.push_back(WebRect(x, y, width, height));
- }
- }
- return tiles;
- }
-
- int tile_size_;
-};
-
-class LayerWidthTiledReplayBenchmark : public TiledReplayBenchmark {
- public:
- LayerWidthTiledReplayBenchmark(const std::string& name,
- WebViewBenchmarkSupport::PaintMode paint_mode,
- int tile_height)
- : TiledReplayBenchmark(name, paint_mode),
- tile_height_(tile_height) {
- CHECK_GT(tile_height, 0);
- }
-
- private:
- virtual vector<WebRect> GetRepaintTiles(
- const WebSize& layer_size) const OVERRIDE {
- vector<WebRect> tiles;
- for (int y = 0; y < layer_size.height; y += tile_height_) {
- int height = std::min(layer_size.height - y, tile_height_);
- tiles.push_back(WebRect(0, y, layer_size.width, height));
- }
- return tiles;
- }
-
- int tile_height_;
-};
-
-} // anonymous namespace
-
-namespace content {
-
-ScopedVector<RenderingBenchmark> AllRenderingBenchmarks() {
- ScopedVector<RenderingBenchmark> benchmarks;
- benchmarks.push_back(new BitmapCanvasPaintBenchmark(
- "PaintEverythingToBitmapMs",
- WebViewBenchmarkSupport::PaintModeEverything));
- benchmarks.push_back(new NullCanvasPaintBenchmark(
- "PaintEverythingToNullCanvasMs",
- WebViewBenchmarkSupport::PaintModeEverything));
- benchmarks.push_back(new CanvasCountBenchmark(
- "LayerCount",
- WebViewBenchmarkSupport::PaintModeEverything));
- benchmarks.push_back(new SkPicturePaintBenchmark(
- "PaintEverythingToSkPictureMs",
- WebViewBenchmarkSupport::PaintModeEverything));
- benchmarks.push_back(new SquareTiledReplayBenchmark(
- "RepaintEverythingTo256x256BitmapMs",
- WebViewBenchmarkSupport::PaintModeEverything,
- 256));
- benchmarks.push_back(new SquareTiledReplayBenchmark(
- "RepaintEverythingTo128x128BitmapMs",
- WebViewBenchmarkSupport::PaintModeEverything,
- 128));
- benchmarks.push_back(new SquareTiledReplayBenchmark(
- "RepaintEverythingTo512x512BitmapMs",
- WebViewBenchmarkSupport::PaintModeEverything,
- 512));
- benchmarks.push_back(new LayerWidthTiledReplayBenchmark(
- "RepaintEverythingToLayerWidthx256BitmapMs",
- WebViewBenchmarkSupport::PaintModeEverything,
- 256));
- benchmarks.push_back(new LayerWidthTiledReplayBenchmark(
- "RepaintEverythingToLayerWidthx128BitmapMs",
- WebViewBenchmarkSupport::PaintModeEverything,
- 128));
- benchmarks.push_back(new LayerWidthTiledReplayBenchmark(
- "RepaintEverythingToLayerWidthx64BitmapMs",
- WebViewBenchmarkSupport::PaintModeEverything,
- 64));
- benchmarks.push_back(new LayerWidthTiledReplayBenchmark(
- "RepaintEverythingToLayerWidthx512BitmapMs",
- WebViewBenchmarkSupport::PaintModeEverything,
- 512));
- return benchmarks.Pass();
-}
-
-} // namespace content
diff --git a/content/renderer/all_rendering_benchmarks.h b/content/renderer/all_rendering_benchmarks.h
deleted file mode 100644
index b19dca3..0000000
--- a/content/renderer/all_rendering_benchmarks.h
+++ /dev/null
@@ -1,19 +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 CONTENT_RENDERER_ALL_RENDERING_BENCHMARKS_H_
-#define CONTENT_RENDERER_ALL_RENDERING_BENCHMARKS_H_
-
-#include <vector>
-
-#include "base/memory/scoped_vector.h"
-
-namespace content {
-class RenderingBenchmark;
-
-ScopedVector<RenderingBenchmark> AllRenderingBenchmarks();
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_ALL_RENDERING_BENCHMARKS_H_
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc
index 186743e..f0483dd 100644
--- a/content/renderer/browser_plugin/browser_plugin.cc
+++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -23,6 +23,7 @@
#include "content/renderer/drop_data_builder.h"
#include "content/renderer/render_process_impl.h"
#include "content/renderer/render_thread_impl.h"
+#include "content/renderer/sad_plugin.h"
#include "content/renderer/v8_value_converter_impl.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebRect.h"
@@ -37,7 +38,6 @@
#include "third_party/WebKit/public/web/WebScriptSource.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "ui/base/keycodes/keyboard_codes.h"
-#include "webkit/plugins/sad_plugin.h"
#if defined (OS_WIN)
#include "base/sys_info.h"
@@ -1091,7 +1091,7 @@
// content_shell does not have the sad plugin bitmap, so we'll paint black
// instead to make it clear that something went wrong.
if (sad_guest_) {
- webkit::PaintSadPlugin(canvas, plugin_rect_, *sad_guest_);
+ PaintSadPlugin(canvas, plugin_rect_, *sad_guest_);
return;
}
}
diff --git a/content/renderer/browser_plugin/browser_plugin_browsertest.cc b/content/renderer/browser_plugin/browser_plugin_browsertest.cc
index c8e5123..1ad07e9 100644
--- a/content/renderer/browser_plugin/browser_plugin_browsertest.cc
+++ b/content/renderer/browser_plugin/browser_plugin_browsertest.cc
@@ -60,8 +60,8 @@
}
virtual ~TestContentRendererClient() {
}
- virtual bool AllowBrowserPlugin(WebKit::WebPluginContainer* container) const
- OVERRIDE {
+ virtual bool AllowBrowserPlugin(
+ WebKit::WebPluginContainer* container) OVERRIDE {
// Allow BrowserPlugin for tests.
return true;
}
diff --git a/content/renderer/gpu/gpu_benchmarking_extension.cc b/content/renderer/gpu/gpu_benchmarking_extension.cc
index 43d557d..a274d0d 100644
--- a/content/renderer/gpu/gpu_benchmarking_extension.cc
+++ b/content/renderer/gpu/gpu_benchmarking_extension.cc
@@ -14,7 +14,6 @@
#include "content/common/browser_rendering_stats.h"
#include "content/common/gpu/gpu_rendering_stats.h"
#include "content/public/renderer/render_thread.h"
-#include "content/renderer/all_rendering_benchmarks.h"
#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/render_view_impl.h"
#include "content/renderer/rendering_benchmark.h"
@@ -213,10 +212,6 @@
" native function SmoothScrollSendsTouch();"
" return SmoothScrollSendsTouch();"
"};"
- "chrome.gpuBenchmarking.runRenderingBenchmarks = function(filter) {"
- " native function RunRenderingBenchmarks();"
- " return RunRenderingBenchmarks(filter);"
- "};"
"chrome.gpuBenchmarking.beginWindowSnapshotPNG = function(callback) {"
" native function BeginWindowSnapshotPNG();"
" BeginWindowSnapshotPNG(callback);"
@@ -240,8 +235,6 @@
return v8::FunctionTemplate::New(BeginSmoothScroll);
if (name->Equals(v8::String::New("SmoothScrollSendsTouch")))
return v8::FunctionTemplate::New(SmoothScrollSendsTouch);
- if (name->Equals(v8::String::New("RunRenderingBenchmarks")))
- return v8::FunctionTemplate::New(RunRenderingBenchmarks);
if (name->Equals(v8::String::New("BeginWindowSnapshotPNG")))
return v8::FunctionTemplate::New(BeginWindowSnapshotPNG);
if (name->Equals(v8::String::New("ClearImageCache")))
@@ -451,62 +444,6 @@
args.GetReturnValue().Set(true);
}
- static void RunRenderingBenchmarks(
- const v8::FunctionCallbackInfo<v8::Value>& args) {
- // For our name filter, the argument can be undefined or null to run
- // all benchmarks, or a string for filtering by name.
- if (!args.Length() ||
- (!args[0]->IsString() &&
- !(args[0]->IsNull() || args[0]->IsUndefined()))) {
- return;
- }
-
- std::string name_filter;
- if (args[0]->IsNull() || args[0]->IsUndefined()) {
- name_filter = "";
- } else {
- char filter[256];
- args[0]->ToString()->WriteUtf8(filter, sizeof(filter)-1);
- name_filter = std::string(filter);
- }
-
- WebFrame* web_frame = WebFrame::frameForCurrentContext();
- if (!web_frame)
- return;
-
- WebView* web_view = web_frame->view();
- if (!web_view)
- return;
-
- WebViewBenchmarkSupport* support = web_view->benchmarkSupport();
- if (!support)
- return;
-
- ScopedVector<RenderingBenchmark> benchmarks = AllRenderingBenchmarks();
-
- v8::Handle<v8::Array> results = v8::Array::New(0);
- ScopedVector<RenderingBenchmark>::const_iterator it;
- for (it = benchmarks.begin(); it != benchmarks.end(); it++) {
- RenderingBenchmark* benchmark = *it;
- const std::string& name = benchmark->name();
- if (name_filter != "" &&
- std::string::npos == name.find(name_filter)) {
- continue;
- }
- benchmark->SetUp(support);
- double result = benchmark->Run(support);
- benchmark->TearDown(support);
-
- v8::Handle<v8::Object> result_object = v8::Object::New();
- result_object->Set(v8::String::New("benchmark", 9),
- v8::String::New(name.c_str(), -1));
- result_object->Set(v8::String::New("result", 6), v8::Number::New(result));
- results->Set(results->Length(), result_object);
- }
-
- args.GetReturnValue().Set(results);
- }
-
static void OnSnapshotCompleted(CallbackAndContext* callback_and_context,
const gfx::Size& size,
const std::vector<unsigned char>& png) {
diff --git a/content/renderer/gpu/input_handler_proxy.cc b/content/renderer/gpu/input_handler_proxy.cc
index 1d9bb07..1f88e62 100644
--- a/content/renderer/gpu/input_handler_proxy.cc
+++ b/content/renderer/gpu/input_handler_proxy.cc
@@ -173,10 +173,11 @@
DCHECK(expect_scroll_update_end_);
expect_scroll_update_end_ = false;
#endif
+ input_handler_->ScrollEnd();
+
if (!gesture_scroll_on_impl_thread_)
return DID_NOT_HANDLE;
- input_handler_->ScrollEnd();
gesture_scroll_on_impl_thread_ = false;
return DID_HANDLE;
} else if (event.type == WebInputEvent::GesturePinchBegin) {
diff --git a/content/renderer/gpu/input_handler_proxy_unittest.cc b/content/renderer/gpu/input_handler_proxy_unittest.cc
index ca3e2cf..3e8b8c8 100644
--- a/content/renderer/gpu/input_handler_proxy_unittest.cc
+++ b/content/renderer/gpu/input_handler_proxy_unittest.cc
@@ -238,6 +238,7 @@
gesture_.type = WebInputEvent::GestureScrollEnd;
gesture_.data.scrollUpdate.deltaY = 0;
+ EXPECT_CALL(mock_input_handler_, ScrollEnd()).WillOnce(testing::Return());
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
}
@@ -246,7 +247,7 @@
// Instead, we should get a DROP_EVENT result, indicating
// that we could determine that there's nothing that could scroll or otherwise
// react to this gesture sequence and thus we should drop the whole gesture
- // sequence on the floor.
+ // sequence on the floor, except for the ScrollEnd.
expected_disposition_ = InputHandlerProxy::DROP_EVENT;
VERIFY_AND_RESET_MOCKS();
@@ -255,6 +256,11 @@
gesture_.type = WebInputEvent::GestureScrollBegin;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ gesture_.type = WebInputEvent::GestureScrollEnd;
+ EXPECT_CALL(mock_input_handler_, ScrollEnd()).WillOnce(testing::Return());
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
}
TEST_F(InputHandlerProxyTest, GesturePinch) {
@@ -359,6 +365,8 @@
gesture_.type = WebInputEvent::GestureScrollEnd;
gesture_.data.scrollUpdate.deltaY = 0;
+ EXPECT_CALL(mock_input_handler_, ScrollEnd())
+ .WillOnce(testing::Return());
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
}
diff --git a/content/renderer/media/android/stream_texture_factory_android.cc b/content/renderer/media/android/stream_texture_factory_android.cc
deleted file mode 100644
index a2e2c5f..0000000
--- a/content/renderer/media/android/stream_texture_factory_android.cc
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/android/stream_texture_factory_android.h"
-
-#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
-#include "ui/gfx/size.h"
-
-namespace content {
-
-StreamTextureProxy::StreamTextureProxy(StreamTextureHost* host)
- : host_(host), client_(NULL) {
- host->SetListener(this);
-}
-
-StreamTextureProxy::~StreamTextureProxy() {}
-
-void StreamTextureProxy::Release() {
- SetClient(NULL);
- if (loop_.get() && loop_.get() != base::MessageLoopProxy::current())
- loop_->DeleteSoon(FROM_HERE, this);
- else
- delete this;
-}
-
-void StreamTextureProxy::SetClient(cc::VideoFrameProvider::Client* client) {
- base::AutoLock lock(client_lock_);
- client_ = client;
-}
-
-void StreamTextureProxy::BindToCurrentThread(int stream_id) {
- loop_ = base::MessageLoopProxy::current();
- host_->Initialize(stream_id);
-}
-
-void StreamTextureProxy::OnFrameAvailable() {
- base::AutoLock lock(client_lock_);
- if (client_)
- client_->DidReceiveFrame();
-}
-
-void StreamTextureProxy::OnMatrixChanged(const float matrix[16]) {
- base::AutoLock lock(client_lock_);
- if (client_)
- client_->DidUpdateMatrix(matrix);
-}
-
-StreamTextureFactory::StreamTextureFactory(
- WebKit::WebGraphicsContext3D* context,
- GpuChannelHost* channel,
- int view_id)
- : context_(context), channel_(channel), view_id_(view_id) {
- DCHECK(context_);
- DCHECK(channel);
-}
-
-StreamTextureFactory::~StreamTextureFactory() {}
-
-StreamTextureProxy* StreamTextureFactory::CreateProxy() {
- DCHECK(channel_.get());
- StreamTextureHost* host = new StreamTextureHost(channel_.get());
- return new StreamTextureProxy(host);
-}
-
-void StreamTextureFactory::EstablishPeer(int32 stream_id, int player_id) {
- DCHECK(channel_.get());
- channel_->Send(
- new GpuChannelMsg_EstablishStreamTexture(stream_id, view_id_, player_id));
-}
-
-unsigned StreamTextureFactory::CreateStreamTexture(
- unsigned texture_target,
- unsigned* texture_id,
- gpu::Mailbox* texture_mailbox,
- unsigned* texture_mailbox_sync_point) {
- unsigned stream_id = 0;
- if (context_->makeContextCurrent()) {
- *texture_id = context_->createTexture();
- stream_id = context_->createStreamTextureCHROMIUM(*texture_id);
-
- context_->genMailboxCHROMIUM(texture_mailbox->name);
- context_->bindTexture(texture_target, *texture_id);
- context_->produceTextureCHROMIUM(texture_target, texture_mailbox->name);
-
- context_->flush();
- *texture_mailbox_sync_point = context_->insertSyncPoint();
- }
- return stream_id;
-}
-
-void StreamTextureFactory::DestroyStreamTexture(unsigned texture_id) {
- if (context_->makeContextCurrent()) {
- // TODO(sievers): Make the destroyStreamTexture implicit when the last
- // texture referencing it is lost.
- context_->destroyStreamTextureCHROMIUM(texture_id);
- context_->deleteTexture(texture_id);
- context_->flush();
- }
-}
-
-void StreamTextureFactory::SetStreamTextureSize(
- int32 stream_id, const gfx::Size& size) {
- channel_->Send(new GpuChannelMsg_SetStreamTextureSize(stream_id, size));
-}
-
-} // namespace content
diff --git a/content/renderer/media/android/stream_texture_factory_android.h b/content/renderer/media/android/stream_texture_factory_android.h
index f496348..d41d857 100644
--- a/content/renderer/media/android/stream_texture_factory_android.h
+++ b/content/renderer/media/android/stream_texture_factory_android.h
@@ -7,51 +7,33 @@
#include "base/memory/scoped_ptr.h"
#include "cc/layers/video_frame_provider.h"
-#include "content/renderer/gpu/stream_texture_host_android.h"
#include "gpu/command_buffer/common/mailbox.h"
-
-namespace WebKit {
-class WebGraphicsContext3D;
-}
+#include "ui/gfx/size.h"
namespace content {
// The proxy class for the gpu thread to notify the compositor thread
// when a new video frame is available.
-class StreamTextureProxy : public StreamTextureHost::Listener {
+class StreamTextureProxy {
public:
- explicit StreamTextureProxy(StreamTextureHost* host);
- virtual ~StreamTextureProxy();
+ virtual ~StreamTextureProxy() {}
// Initialize and bind to the current thread, which becomes the thread that
// a connected client will receive callbacks on.
- void BindToCurrentThread(int32 stream_id);
+ virtual void BindToCurrentThread(int32 stream_id) = 0;
- bool IsBoundToThread() { return loop_.get() != NULL; }
+ virtual bool IsBoundToThread() = 0;
// Setting the target for callback when a frame is available. This function
// could be called on both the main thread and the compositor thread.
- void SetClient(cc::VideoFrameProvider::Client* client);
+ virtual void SetClient(cc::VideoFrameProvider::Client* client) = 0;
- // StreamTextureHost::Listener implementation:
- virtual void OnFrameAvailable() OVERRIDE;
- virtual void OnMatrixChanged(const float matrix[16]) OVERRIDE;
+ // Causes this instance to be deleted on the thread it is bound to.
+ virtual void Release() = 0;
struct Deleter {
inline void operator()(StreamTextureProxy* ptr) const { ptr->Release(); }
};
-
- private:
- // Causes this instance to be deleted on the thread it is bound to.
- void Release();
-
- scoped_ptr<StreamTextureHost> host_;
- scoped_refptr<base::MessageLoopProxy> loop_;
-
- base::Lock client_lock_;
- cc::VideoFrameProvider::Client* client_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureProxy);
};
typedef scoped_ptr<StreamTextureProxy, StreamTextureProxy::Deleter>
@@ -60,43 +42,34 @@
// Factory class for managing stream textures.
class StreamTextureFactory {
public:
- StreamTextureFactory(WebKit::WebGraphicsContext3D* context,
- GpuChannelHost* channel,
- int view_id);
- ~StreamTextureFactory();
+ virtual ~StreamTextureFactory() {}
// Create the StreamTextureProxy object.
- StreamTextureProxy* CreateProxy();
+ virtual StreamTextureProxy* CreateProxy() = 0;
// Send an IPC message to the browser process to request a java surface
// object for the given stream_id. After the the surface is created,
// it will be passed back to the WebMediaPlayerAndroid object identified by
// the player_id.
- void EstablishPeer(int32 stream_id, int player_id);
+ virtual void EstablishPeer(int32 stream_id, int player_id) = 0;
// Create the streamTexture and return the stream Id and create a client-side
// texture id to refer to the streamTexture. The texture id is produced into
// a mailbox so it can be used to ship in a VideoFrame, with a sync point for
// when the mailbox can be accessed.
- unsigned CreateStreamTexture(
+ virtual unsigned CreateStreamTexture(
unsigned texture_target,
unsigned* texture_id,
gpu::Mailbox* texture_mailbox,
- unsigned* texture_mailbox_sync_point);
+ unsigned* texture_mailbox_sync_point) = 0;
// Destroy the streamTexture for the given texture id, as well as the
// client side texture.
- void DestroyStreamTexture(unsigned texture_id);
+ virtual void DestroyStreamTexture(unsigned texture_id) = 0;
// Set the streamTexture size for the given stream Id.
- void SetStreamTextureSize(int32 texture_id, const gfx::Size& size);
-
- private:
- WebKit::WebGraphicsContext3D* context_;
- scoped_refptr<GpuChannelHost> channel_;
- int view_id_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureFactory);
+ virtual void SetStreamTextureSize(int32 texture_id,
+ const gfx::Size& size) = 0;
};
} // namespace content
diff --git a/content/renderer/media/android/stream_texture_factory_android_impl.cc b/content/renderer/media/android/stream_texture_factory_android_impl.cc
new file mode 100644
index 0000000..721b680
--- /dev/null
+++ b/content/renderer/media/android/stream_texture_factory_android_impl.cc
@@ -0,0 +1,140 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/android/stream_texture_factory_android_impl.h"
+
+#include "content/common/gpu/client/gpu_channel_host.h"
+#include "content/common/gpu/gpu_messages.h"
+#include "content/renderer/gpu/stream_texture_host_android.h"
+#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+#include "ui/gfx/size.h"
+
+namespace content {
+
+namespace {
+
+class StreamTextureProxyImpl : public StreamTextureProxy,
+ public StreamTextureHost::Listener {
+ public:
+ explicit StreamTextureProxyImpl(StreamTextureHost* host);
+ virtual ~StreamTextureProxyImpl();
+
+ // StreamTextureProxy implementation:
+ virtual void BindToCurrentThread(int32 stream_id) OVERRIDE;
+ virtual bool IsBoundToThread() OVERRIDE { return loop_.get() != NULL; }
+ virtual void SetClient(cc::VideoFrameProvider::Client* client) OVERRIDE;
+ virtual void Release() OVERRIDE;
+
+ // StreamTextureHost::Listener implementation:
+ virtual void OnFrameAvailable() OVERRIDE;
+ virtual void OnMatrixChanged(const float matrix[16]) OVERRIDE;
+
+ private:
+ scoped_ptr<StreamTextureHost> host_;
+ scoped_refptr<base::MessageLoopProxy> loop_;
+
+ base::Lock client_lock_;
+ cc::VideoFrameProvider::Client* client_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureProxyImpl);
+};
+
+StreamTextureProxyImpl::StreamTextureProxyImpl(StreamTextureHost* host)
+ : host_(host), client_(NULL) {
+ host->SetListener(this);
+}
+
+StreamTextureProxyImpl::~StreamTextureProxyImpl() {}
+
+void StreamTextureProxyImpl::Release() {
+ SetClient(NULL);
+ if (loop_.get() && loop_.get() != base::MessageLoopProxy::current())
+ loop_->DeleteSoon(FROM_HERE, this);
+ else
+ delete this;
+}
+
+void StreamTextureProxyImpl::SetClient(cc::VideoFrameProvider::Client* client) {
+ base::AutoLock lock(client_lock_);
+ client_ = client;
+}
+
+void StreamTextureProxyImpl::BindToCurrentThread(int stream_id) {
+ loop_ = base::MessageLoopProxy::current();
+ host_->Initialize(stream_id);
+}
+
+void StreamTextureProxyImpl::OnFrameAvailable() {
+ base::AutoLock lock(client_lock_);
+ if (client_)
+ client_->DidReceiveFrame();
+}
+
+void StreamTextureProxyImpl::OnMatrixChanged(const float matrix[16]) {
+ base::AutoLock lock(client_lock_);
+ if (client_)
+ client_->DidUpdateMatrix(matrix);
+}
+
+} // namespace
+
+StreamTextureFactoryImpl::StreamTextureFactoryImpl(
+ WebKit::WebGraphicsContext3D* context,
+ GpuChannelHost* channel,
+ int view_id)
+ : context_(context), channel_(channel), view_id_(view_id) {
+ DCHECK(context_);
+ DCHECK(channel);
+}
+
+StreamTextureFactoryImpl::~StreamTextureFactoryImpl() {}
+
+StreamTextureProxy* StreamTextureFactoryImpl::CreateProxy() {
+ DCHECK(channel_.get());
+ StreamTextureHost* host = new StreamTextureHost(channel_.get());
+ return new StreamTextureProxyImpl(host);
+}
+
+void StreamTextureFactoryImpl::EstablishPeer(int32 stream_id, int player_id) {
+ DCHECK(channel_.get());
+ channel_->Send(
+ new GpuChannelMsg_EstablishStreamTexture(stream_id, view_id_, player_id));
+}
+
+unsigned StreamTextureFactoryImpl::CreateStreamTexture(
+ unsigned texture_target,
+ unsigned* texture_id,
+ gpu::Mailbox* texture_mailbox,
+ unsigned* texture_mailbox_sync_point) {
+ unsigned stream_id = 0;
+ if (context_->makeContextCurrent()) {
+ *texture_id = context_->createTexture();
+ stream_id = context_->createStreamTextureCHROMIUM(*texture_id);
+
+ context_->genMailboxCHROMIUM(texture_mailbox->name);
+ context_->bindTexture(texture_target, *texture_id);
+ context_->produceTextureCHROMIUM(texture_target, texture_mailbox->name);
+
+ context_->flush();
+ *texture_mailbox_sync_point = context_->insertSyncPoint();
+ }
+ return stream_id;
+}
+
+void StreamTextureFactoryImpl::DestroyStreamTexture(unsigned texture_id) {
+ if (context_->makeContextCurrent()) {
+ // TODO(sievers): Make the destroyStreamTexture implicit when the last
+ // texture referencing it is lost.
+ context_->destroyStreamTextureCHROMIUM(texture_id);
+ context_->deleteTexture(texture_id);
+ context_->flush();
+ }
+}
+
+void StreamTextureFactoryImpl::SetStreamTextureSize(
+ int32 stream_id, const gfx::Size& size) {
+ channel_->Send(new GpuChannelMsg_SetStreamTextureSize(stream_id, size));
+}
+
+} // namespace content
diff --git a/content/renderer/media/android/stream_texture_factory_android_impl.h b/content/renderer/media/android/stream_texture_factory_android_impl.h
new file mode 100644
index 0000000..20aacdd
--- /dev/null
+++ b/content/renderer/media/android/stream_texture_factory_android_impl.h
@@ -0,0 +1,47 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_IMPL_H_
+#define CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_IMPL_H_
+
+#include "content/renderer/media/android/stream_texture_factory_android.h"
+
+namespace WebKit {
+class WebGraphicsContext3D;
+}
+
+namespace content {
+
+class GpuChannelHost;
+
+class StreamTextureFactoryImpl : public StreamTextureFactory {
+ public:
+ StreamTextureFactoryImpl(WebKit::WebGraphicsContext3D* context,
+ GpuChannelHost* channel,
+ int view_id);
+ virtual ~StreamTextureFactoryImpl();
+
+ // StreamTextureFactory implementation.
+ virtual StreamTextureProxy* CreateProxy() OVERRIDE;
+ virtual void EstablishPeer(int32 stream_id, int player_id) OVERRIDE;
+ virtual unsigned CreateStreamTexture(
+ unsigned texture_target,
+ unsigned* texture_id,
+ gpu::Mailbox* texture_mailbox,
+ unsigned* texture_mailbox_sync_point) OVERRIDE;
+ virtual void DestroyStreamTexture(unsigned texture_id) OVERRIDE;
+ virtual void SetStreamTextureSize(int32 texture_id,
+ const gfx::Size& size) OVERRIDE;
+
+ private:
+ WebKit::WebGraphicsContext3D* context_;
+ scoped_refptr<GpuChannelHost> channel_;
+ int view_id_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureFactoryImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_IMPL_H_
diff --git a/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc b/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc
new file mode 100644
index 0000000..88878d5
--- /dev/null
+++ b/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc
@@ -0,0 +1,34 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h"
+
+namespace content {
+
+StreamTextureFactorySynchronousImpl::StreamTextureFactorySynchronousImpl() {}
+StreamTextureFactorySynchronousImpl::~StreamTextureFactorySynchronousImpl() {}
+
+StreamTextureProxy* StreamTextureFactorySynchronousImpl::CreateProxy() {
+ return NULL;
+}
+
+void StreamTextureFactorySynchronousImpl::EstablishPeer(int32 stream_id,
+ int player_id) {}
+
+unsigned StreamTextureFactorySynchronousImpl::CreateStreamTexture(
+ unsigned texture_target,
+ unsigned* texture_id,
+ gpu::Mailbox* texture_mailbox,
+ unsigned* texture_mailbox_sync_point) {
+ return 0;
+}
+
+void StreamTextureFactorySynchronousImpl::DestroyStreamTexture(
+ unsigned texture_id) {}
+
+void StreamTextureFactorySynchronousImpl::SetStreamTextureSize(
+ int32 texture_id,
+ const gfx::Size& size) {}
+
+} // namespace content
diff --git a/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h b/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h
new file mode 100644
index 0000000..52fc65a
--- /dev/null
+++ b/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h
@@ -0,0 +1,35 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_SYNCHRONOUS_IMPL_H_
+#define CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_SYNCHRONOUS_IMPL_H_
+
+#include "content/renderer/media/android/stream_texture_factory_android.h"
+
+namespace content {
+
+// Factory for when using synchronous compositor in Android WebView.
+class StreamTextureFactorySynchronousImpl : public StreamTextureFactory {
+ public:
+ StreamTextureFactorySynchronousImpl();
+ virtual ~StreamTextureFactorySynchronousImpl();
+
+ virtual StreamTextureProxy* CreateProxy() OVERRIDE;
+ virtual void EstablishPeer(int32 stream_id, int player_id) OVERRIDE;
+ virtual unsigned CreateStreamTexture(
+ unsigned texture_target,
+ unsigned* texture_id,
+ gpu::Mailbox* texture_mailbox,
+ unsigned* texture_mailbox_sync_point) OVERRIDE;
+ virtual void DestroyStreamTexture(unsigned texture_id) OVERRIDE;
+ virtual void SetStreamTextureSize(int32 texture_id,
+ const gfx::Size& size) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(StreamTextureFactorySynchronousImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_SYNCHRONOUS_IMPL_H_
diff --git a/content/renderer/media/crypto/content_decryption_module_factory.cc b/content/renderer/media/crypto/content_decryption_module_factory.cc
index 3ce22f3..9310101 100644
--- a/content/renderer/media/crypto/content_decryption_module_factory.cc
+++ b/content/renderer/media/crypto/content_decryption_module_factory.cc
@@ -6,7 +6,7 @@
#include "base/logging.h"
#include "content/renderer/media/crypto/key_systems.h"
-#include "media/crypto/aes_decryptor.h"
+#include "media/cdm/aes_decryptor.h"
#if defined(ENABLE_PEPPER_CDMS)
#include "content/renderer/media/crypto/ppapi_decryptor.h"
diff --git a/content/renderer/media/media_stream_dependency_factory.cc b/content/renderer/media/media_stream_dependency_factory.cc
index 7f5e64a..304a818 100644
--- a/content/renderer/media/media_stream_dependency_factory.cc
+++ b/content/renderer/media/media_stream_dependency_factory.cc
@@ -286,7 +286,7 @@
source_data->device_info().device.type ==
content::MEDIA_TAB_VIDEO_CAPTURE ||
source_data->device_info().device.type ==
- content::MEDIA_SCREEN_VIDEO_CAPTURE;
+ content::MEDIA_DESKTOP_VIDEO_CAPTURE;
source_data->SetVideoSource(
CreateLocalVideoSource(source_data->device_info().session_id,
is_screencast,
@@ -551,8 +551,8 @@
web_frame);
PeerConnectionIdentityService* identity_service =
- new PeerConnectionIdentityService(GURL(web_frame->document().url().spec())
- .GetOrigin());
+ PeerConnectionIdentityService::Create(
+ GURL(web_frame->document().url().spec()).GetOrigin());
return pc_factory_->CreatePeerConnection(ice_servers,
constraints,
diff --git a/content/renderer/media/media_stream_dispatcher.cc b/content/renderer/media/media_stream_dispatcher.cc
index 80b3473..cc241fa 100644
--- a/content/renderer/media/media_stream_dispatcher.cc
+++ b/content/renderer/media/media_stream_dispatcher.cc
@@ -244,6 +244,8 @@
OnStreamGenerated)
IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed,
OnStreamGenerationFailed)
+ IPC_MESSAGE_HANDLER(MediaStreamMsg_StopGeneratedStream,
+ OnStopGeneratedStream)
IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated,
OnDevicesEnumerated)
IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerationFailed,
@@ -302,6 +304,20 @@
}
}
+void MediaStreamDispatcher::OnStopGeneratedStream(const std::string& label) {
+ DCHECK(main_loop_->BelongsToCurrentThread());
+ LabelStreamMap::iterator it = label_stream_map_.find(label);
+ if (it == label_stream_map_.end())
+ return;
+
+ if (it->second.handler.get()) {
+ it->second.handler->OnStopGeneratedStream(label);
+ DVLOG(1) << "MediaStreamDispatcher::OnStopGeneratedStream("
+ << label << ")\n";
+ }
+ label_stream_map_.erase(it);
+}
+
void MediaStreamDispatcher::OnDevicesEnumerated(
int request_id,
const std::string& label,
diff --git a/content/renderer/media/media_stream_dispatcher.h b/content/renderer/media/media_stream_dispatcher.h
index 3562a02..aa8f345 100644
--- a/content/renderer/media/media_stream_dispatcher.h
+++ b/content/renderer/media/media_stream_dispatcher.h
@@ -146,6 +146,7 @@
const StreamDeviceInfoArray& audio_array,
const StreamDeviceInfoArray& video_array);
void OnStreamGenerationFailed(int request_id);
+ void OnStopGeneratedStream(const std::string& label);
void OnDevicesEnumerated(
int request_id,
const std::string& label,
diff --git a/content/renderer/media/media_stream_dispatcher_eventhandler.h b/content/renderer/media/media_stream_dispatcher_eventhandler.h
index c489607..7a0803a 100644
--- a/content/renderer/media/media_stream_dispatcher_eventhandler.h
+++ b/content/renderer/media/media_stream_dispatcher_eventhandler.h
@@ -25,6 +25,9 @@
// to the requested devices or no device is available.
virtual void OnStreamGenerationFailed(int request_id) = 0;
+ // The user has requested to stop a media stream.
+ virtual void OnStopGeneratedStream(const std::string& label) = 0;
+
// A new list of devices have been enumerated.
virtual void OnDevicesEnumerated(
int request_id,
diff --git a/content/renderer/media/media_stream_dispatcher_unittest.cc b/content/renderer/media/media_stream_dispatcher_unittest.cc
index b5e46be..300bfe3 100644
--- a/content/renderer/media/media_stream_dispatcher_unittest.cc
+++ b/content/renderer/media/media_stream_dispatcher_unittest.cc
@@ -50,6 +50,10 @@
request_id_ = request_id;
}
+ virtual void OnStopGeneratedStream(const std::string& label) OVERRIDE {
+ label_ = label;
+ }
+
virtual void OnDevicesEnumerated(
int request_id,
const StreamDeviceInfoArray& device_array) OVERRIDE {
diff --git a/content/renderer/media/media_stream_impl.cc b/content/renderer/media/media_stream_impl.cc
index abe68a2..5edc4cc 100644
--- a/content/renderer/media/media_stream_impl.cc
+++ b/content/renderer/media/media_stream_impl.cc
@@ -10,6 +10,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/public/common/desktop_media_id.h"
#include "content/renderer/media/media_stream_audio_renderer.h"
#include "content/renderer/media/media_stream_dependency_factory.h"
#include "content/renderer/media/media_stream_dispatcher.h"
@@ -71,7 +72,9 @@
user_media_request.videoConstraints(),
kMediaStreamSourceId, true);
} else if (video_stream_source == kMediaStreamSourceScreen) {
- options->video_type = content::MEDIA_SCREEN_VIDEO_CAPTURE;
+ options->video_type = content::MEDIA_DESKTOP_VIDEO_CAPTURE;
+ options->video_device_id =
+ DesktopMediaID(DesktopMediaID::TYPE_SCREEN, 0).ToString();
}
}
}
@@ -373,6 +376,24 @@
DeleteUserMediaRequestInfo(request_info);
}
+// Callback from MediaStreamDispatcher.
+// The user has requested to stop the media stream.
+void MediaStreamImpl::OnStopGeneratedStream(const std::string& label) {
+ DCHECK(CalledOnValidThread());
+ DVLOG(1) << "MediaStreamImpl::OnStopGeneratedStream(" << label << ")";
+
+ UserMediaRequestInfo* user_media_request = FindUserMediaRequestInfo(label);
+ if (user_media_request) {
+ // No need to call media_stream_dispatcher_->StopStream() because the
+ // request has come from the browser process.
+ StopLocalAudioTrack(user_media_request->web_stream);
+ DeleteUserMediaRequestInfo(user_media_request);
+ } else {
+ DVLOG(1) << "MediaStreamImpl::OnStopGeneratedStream: the stream has "
+ << "already been stopped.";
+ }
+}
+
// Callback from MediaStreamDependencyFactory when the sources in |web_stream|
// have been generated.
void MediaStreamImpl::OnCreateNativeSourcesComplete(
diff --git a/content/renderer/media/media_stream_impl.h b/content/renderer/media/media_stream_impl.h
index ee506cc..1cd4479 100644
--- a/content/renderer/media/media_stream_impl.h
+++ b/content/renderer/media/media_stream_impl.h
@@ -73,6 +73,7 @@
const StreamDeviceInfoArray& audio_array,
const StreamDeviceInfoArray& video_array) OVERRIDE;
virtual void OnStreamGenerationFailed(int request_id) OVERRIDE;
+ virtual void OnStopGeneratedStream(const std::string& label) OVERRIDE;
virtual void OnDevicesEnumerated(
int request_id,
const StreamDeviceInfoArray& device_array) OVERRIDE;
diff --git a/content/renderer/media/peer_connection_identity_service.cc b/content/renderer/media/peer_connection_identity_service.cc
index f7bc856..904eb41 100644
--- a/content/renderer/media/peer_connection_identity_service.cc
+++ b/content/renderer/media/peer_connection_identity_service.cc
@@ -9,8 +9,17 @@
namespace content {
-PeerConnectionIdentityService::PeerConnectionIdentityService(const GURL& origin)
- : origin_(origin), pending_observer_(NULL), pending_request_id_(0) {}
+PeerConnectionIdentityService* PeerConnectionIdentityService::Create(
+ const GURL& origin) {
+// The crypto APIs needed for generating identities are not implenented for
+// OPENSSL yet (crbug/91512). So returning NULL in that case.
+// TODO(jiayl): remove the #if once the crypto APIs are implemented for OPENSSL.
+#if defined(USE_OPENSSL)
+ return NULL;
+#else
+ return new PeerConnectionIdentityService(origin);
+#endif // defined(USE_OPENSSL)
+}
PeerConnectionIdentityService::~PeerConnectionIdentityService() {
if (pending_observer_)
@@ -39,6 +48,9 @@
return true;
}
+PeerConnectionIdentityService::PeerConnectionIdentityService(const GURL& origin)
+ : origin_(origin), pending_observer_(NULL), pending_request_id_(0) {}
+
void PeerConnectionIdentityService::OnIdentityReady(
const std::string& certificate,
const std::string& private_key) {
diff --git a/content/renderer/media/peer_connection_identity_service.h b/content/renderer/media/peer_connection_identity_service.h
index a5092e3..fa0b16a 100644
--- a/content/renderer/media/peer_connection_identity_service.h
+++ b/content/renderer/media/peer_connection_identity_service.h
@@ -19,7 +19,8 @@
class PeerConnectionIdentityService
: public webrtc::DTLSIdentityServiceInterface {
public:
- explicit PeerConnectionIdentityService(const GURL& origin);
+ static PeerConnectionIdentityService* Create(const GURL& origin);
+
virtual ~PeerConnectionIdentityService();
// webrtc::DTLSIdentityServiceInterface implementation.
@@ -29,6 +30,8 @@
webrtc::DTLSIdentityRequestObserver* observer) OVERRIDE;
private:
+ explicit PeerConnectionIdentityService(const GURL& origin);
+
void OnIdentityReady(const std::string& certificate,
const std::string& private_key);
void OnRequestFailed(int error);
diff --git a/content/renderer/media/rtc_video_decoder.cc b/content/renderer/media/rtc_video_decoder.cc
index e89cad9..12904f1 100644
--- a/content/renderer/media/rtc_video_decoder.cc
+++ b/content/renderer/media/rtc_video_decoder.cc
@@ -95,11 +95,14 @@
RTCVideoDecoder::~RTCVideoDecoder() {
DVLOG(2) << "~RTCVideoDecoder";
- // Remove |this| from the observer if vda thread is alive.
- if (vda_loop_proxy_->BelongsToCurrentThread())
+ // Destroy VDA and remove |this| from the observer if this is vda thread.
+ if (vda_loop_proxy_->BelongsToCurrentThread()) {
base::MessageLoop::current()->RemoveDestructionObserver(this);
- // VDA should have been destroyed.
- DCHECK(!vda_);
+ DestroyVDA();
+ } else {
+ // VDA should have been destroyed in WillDestroyCurrentMessageLoop.
+ DCHECK(!vda_);
+ }
// Delete all shared memories.
STLDeleteElements(&available_shm_segments_);
@@ -231,19 +234,9 @@
int32_t RTCVideoDecoder::Release() {
DVLOG(2) << "Release";
- base::AutoLock auto_lock(lock_);
- if (state_ == UNINITIALIZED) {
- LOG(ERROR) << "Decoder not initialized.";
- return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
- }
- if (next_bitstream_buffer_id_ != 0)
- reset_bitstream_buffer_id_ = next_bitstream_buffer_id_ - 1;
- else
- reset_bitstream_buffer_id_ = ID_LAST;
- factories_->Abort();
- vda_loop_proxy_->PostTask(
- FROM_HERE, base::Bind(&RTCVideoDecoder::DestroyVDA, weak_this_));
- return WEBRTC_VIDEO_CODEC_OK;
+ // Do not destroy VDA because WebRTC can call InitDecode and start decoding
+ // again.
+ return Reset();
}
int32_t RTCVideoDecoder::Reset() {
@@ -367,7 +360,7 @@
width, height, width, (width + 1) / 2, (width + 1) / 2);
decoded_image.set_timestamp(timestamp);
- // Invoke decode callback. WebRTC expects no frame callback after Release.
+ // Invoke decode callback. WebRTC expects no callback after Reset or Release.
{
base::AutoLock auto_lock(lock_);
DCHECK(decode_complete_callback_ != NULL);
@@ -659,6 +652,8 @@
if (vda_)
vda_.release()->Destroy();
DestroyTextures();
+ base::AutoLock auto_lock(lock_);
+ state_ = UNINITIALIZED;
}
scoped_ptr<RTCVideoDecoder::SHMBuffer> RTCVideoDecoder::GetSHM_Locked(
diff --git a/content/renderer/media/rtc_video_decoder_unittest.cc b/content/renderer/media/rtc_video_decoder_unittest.cc
index e23e91b..2ffeb3e 100644
--- a/content/renderer/media/rtc_video_decoder_unittest.cc
+++ b/content/renderer/media/rtc_video_decoder_unittest.cc
@@ -20,6 +20,7 @@
namespace content {
+// TODO(wuchengli): add MockSharedMemroy so more functions can be tested.
class RTCVideoDecoderTest : public ::testing::Test,
webrtc::DecodedImageCallback {
public:
@@ -53,8 +54,6 @@
virtual void TearDown() OVERRIDE {
VLOG(2) << "TearDown";
if (vda_thread_.IsRunning()) {
- if (rtc_decoder_)
- rtc_decoder_->Release();
RunUntilIdle(); // Wait until all callbascks complete.
vda_loop_proxy_->DeleteSoon(FROM_HERE, rtc_decoder_.release());
// Make sure the decoder is released before stopping the thread.
@@ -152,6 +151,17 @@
TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) {
Initialize();
+ EXPECT_CALL(*mock_vda_, Reset())
+ .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
+ EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
+}
+
+TEST_F(RTCVideoDecoderTest, InitDecodeAfterRelease) {
+ EXPECT_CALL(*mock_vda_, Reset())
+ .WillRepeatedly(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
+ Initialize();
+ EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
+ Initialize();
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
}
diff --git a/content/renderer/media/webmediaplayer_impl.cc b/content/renderer/media/webmediaplayer_impl.cc
index 1343bc6..227d0cf 100644
--- a/content/renderer/media/webmediaplayer_impl.cc
+++ b/content/renderer/media/webmediaplayer_impl.cc
@@ -1061,8 +1061,8 @@
base::Bind(&LogMediaSourceError, media_log_));
demuxer_.reset(chunk_demuxer_);
-#if !defined(OS_CHROMEOS) || !defined(ARCH_CPU_X86_FAMILY)
- // Disable GpuVideoDecoder creation on platforms other than CrOS x86 until
+#if !defined(OS_CHROMEOS)
+ // Disable GpuVideoDecoder creation on platforms other than CrOS until
// they support codec config changes.
// TODO(acolwell): Remove this once http://crbug.com/151045 is fixed.
gpu_factories_ = NULL;
diff --git a/content/renderer/npapi/webplugin_delegate_proxy.cc b/content/renderer/npapi/webplugin_delegate_proxy.cc
index f1da1d8..fe807dd 100644
--- a/content/renderer/npapi/webplugin_delegate_proxy.cc
+++ b/content/renderer/npapi/webplugin_delegate_proxy.cc
@@ -30,11 +30,13 @@
#include "content/child/npapi/npobject_util.h"
#include "content/child/npapi/webplugin.h"
#include "content/child/plugin_messages.h"
+#include "content/common/content_constants_internal.h"
#include "content/common/view_messages.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/npapi/plugin_channel_host.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
+#include "content/renderer/sad_plugin.h"
#include "ipc/ipc_channel_handle.h"
#include "net/base/mime_util.h"
#include "skia/ext/platform_canvas.h"
@@ -51,8 +53,6 @@
#include "ui/gfx/skia_util.h"
#include "webkit/common/cursors/webcursor.h"
#include "webkit/glue/webkit_glue.h"
-#include "webkit/plugins/plugin_constants.h"
-#include "webkit/plugins/sad_plugin.h"
#if defined(OS_POSIX)
#include "ipc/ipc_channel_posix.h"
@@ -681,7 +681,11 @@
// If the plugin is no longer connected (channel crashed) draw a crashed
// plugin bitmap
if (!channel_host_.get() || !channel_host_->channel_valid()) {
- PaintSadPlugin(canvas, rect);
+ // Lazily load the sad plugin image.
+ if (!sad_plugin_)
+ sad_plugin_ = GetContentClient()->renderer()->GetSadPluginBitmap();
+ if (sad_plugin_)
+ PaintSadPlugin(canvas, plugin_rect_, *sad_plugin_);
return;
}
@@ -1011,15 +1015,6 @@
*cookies = plugin_->GetCookies(url, first_party_for_cookies);
}
-void WebPluginDelegateProxy::PaintSadPlugin(WebKit::WebCanvas* native_context,
- const gfx::Rect& rect) {
- // Lazily load the sad plugin image.
- if (!sad_plugin_)
- sad_plugin_ = GetContentClient()->renderer()->GetSadPluginBitmap();
- if (sad_plugin_)
- webkit::PaintSadPlugin(native_context, plugin_rect_, *sad_plugin_);
-}
-
void WebPluginDelegateProxy::CopyFromBackBufferToFrontBuffer(
const gfx::Rect& rect) {
#if defined(OS_MACOSX)
diff --git a/content/renderer/npapi/webplugin_delegate_proxy.h b/content/renderer/npapi/webplugin_delegate_proxy.h
index 7c7b0ae..a40da83 100644
--- a/content/renderer/npapi/webplugin_delegate_proxy.h
+++ b/content/renderer/npapi/webplugin_delegate_proxy.h
@@ -181,9 +181,6 @@
// Helper function that sends the UpdateGeometry message.
void SendUpdateGeometry(bool bitmaps_changed);
- // Draw a graphic indicating a crashed plugin.
- void PaintSadPlugin(WebKit::WebCanvas* canvas, const gfx::Rect& rect);
-
// Copies the given rectangle from the back-buffer transport_stores_ bitmap to
// the front-buffer transport_stores_ bitmap.
void CopyFromBackBufferToFrontBuffer(const gfx::Rect& rect);
diff --git a/content/renderer/npapi/webplugin_impl.cc b/content/renderer/npapi/webplugin_impl.cc
index ae71c44..21e80b6 100644
--- a/content/renderer/npapi/webplugin_impl.cc
+++ b/content/renderer/npapi/webplugin_impl.cc
@@ -13,10 +13,12 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "cc/layers/io_surface_layer.h"
+#include "content/child/appcache/web_application_cache_host_impl.h"
#include "content/child/npapi/plugin_host.h"
#include "content/child/npapi/plugin_instance.h"
#include "content/child/npapi/webplugin_delegate_impl.h"
#include "content/common/view_messages.h"
+#include "content/public/common/content_constants.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/npapi/webplugin_delegate_proxy.h"
#include "content/renderer/render_process.h"
@@ -49,11 +51,8 @@
#include "url/gurl.h"
#include "url/url_util.h"
#include "webkit/child/multipart_response_delegate.h"
-#include "webkit/plugins/plugin_constants.h"
-#include "webkit/renderer/appcache/web_application_cache_host_impl.h"
#include "webkit/renderer/compositor_bindings/web_layer_impl.h"
-using appcache::WebApplicationCacheHostImpl;
using WebKit::WebCanvas;
using WebKit::WebConsoleMessage;
using WebKit::WebCookieJar;
diff --git a/content/renderer/pepper/audio_helper.cc b/content/renderer/pepper/audio_helper.cc
index 2bbe991..0dae997 100644
--- a/content/renderer/pepper/audio_helper.cc
+++ b/content/renderer/pepper/audio_helper.cc
@@ -79,7 +79,7 @@
}
void AudioHelper::SetCreateCallback(
- scoped_refptr< ::ppapi::TrackedCallback> create_callback) {
+ scoped_refptr<ppapi::TrackedCallback> create_callback) {
DCHECK(!TrackedCallback::IsPending(create_callback_));
create_callback_ = create_callback;
}
diff --git a/content/renderer/pepper/audio_helper.h b/content/renderer/pepper/audio_helper.h
index 8b04c84..a111325 100644
--- a/content/renderer/pepper/audio_helper.h
+++ b/content/renderer/pepper/audio_helper.h
@@ -27,7 +27,7 @@
base::SyncSocket::Handle socket);
void SetCreateCallback(
- scoped_refptr< ::ppapi::TrackedCallback> create_callback);
+ scoped_refptr<ppapi::TrackedCallback> create_callback);
protected:
// TODO(viettrungluu): This is all very poorly thought out. Refactor.
@@ -42,7 +42,7 @@
base::SyncSocket::Handle socket_handle) = 0;
private:
- scoped_refptr< ::ppapi::TrackedCallback> create_callback_;
+ scoped_refptr<ppapi::TrackedCallback> create_callback_;
// When a create callback is being issued, these will save the info for
// querying from the callback. The proxy uses this to get the handles to the
diff --git a/content/renderer/pepper/content_decryptor_delegate.cc b/content/renderer/pepper/content_decryptor_delegate.cc
index 22c3aff..94d8928 100644
--- a/content/renderer/pepper/content_decryptor_delegate.cc
+++ b/content/renderer/pepper/content_decryptor_delegate.cc
@@ -823,7 +823,9 @@
scoped_refptr<media::VideoFrame> decoded_frame =
media::VideoFrame::WrapExternalYuvData(
media::VideoFrame::YV12,
- frame_size, gfx::Rect(frame_size), natural_size_,
+ frame_size,
+ gfx::Rect(frame_size),
+ natural_size_,
frame_info->strides[PP_DECRYPTEDFRAMEPLANES_Y],
frame_info->strides[PP_DECRYPTEDFRAMEPLANES_U],
frame_info->strides[PP_DECRYPTEDFRAMEPLANES_V],
@@ -832,10 +834,10 @@
frame_data + frame_info->plane_offsets[PP_DECRYPTEDFRAMEPLANES_V],
base::TimeDelta::FromMicroseconds(
frame_info->tracking_info.timestamp),
- ppb_buffer->shared_memory()->handle(),
media::BindToLoop(
base::MessageLoopProxy::current(),
- base::Bind(&BufferNoLongerNeeded, ppb_buffer,
+ base::Bind(&BufferNoLongerNeeded,
+ ppb_buffer,
base::Bind(&ContentDecryptorDelegate::FreeBuffer,
weak_this_,
frame_info->tracking_info.buffer_id))));
diff --git a/content/renderer/pepper/event_conversion.cc b/content/renderer/pepper/event_conversion.cc
index 8020d5a..6c02bd0 100644
--- a/content/renderer/pepper/event_conversion.cc
+++ b/content/renderer/pepper/event_conversion.cc
@@ -609,7 +609,7 @@
// Generate a coherent sequence of input events to simulate a user event.
// From src/third_party/WebKit/Tools/DumpRenderTree/chromium/EventSender.cpp.
std::vector<linked_ptr<WebInputEvent> > CreateSimulatedWebInputEvents(
- const ::ppapi::InputEventData& event,
+ const ppapi::InputEventData& event,
int plugin_x,
int plugin_y) {
std::vector<linked_ptr<WebInputEvent> > events;
diff --git a/content/renderer/pepper/event_conversion.h b/content/renderer/pepper/event_conversion.h
index 05bdda8..edaa730 100644
--- a/content/renderer/pepper/event_conversion.h
+++ b/content/renderer/pepper/event_conversion.h
@@ -28,18 +28,17 @@
// The generated events will be filled into the given vector. On failure, no
// events will ge generated and the vector will be empty.
void CreateInputEventData(const WebKit::WebInputEvent& event,
- std::vector< ::ppapi::InputEventData >* pp_events);
+ std::vector<ppapi::InputEventData >* pp_events);
// Creates a WebInputEvent from the given PP_InputEvent. If it fails, returns
// NULL. The caller owns the created object on success.
-WebKit::WebInputEvent* CreateWebInputEvent(
- const ::ppapi::InputEventData& event);
+WebKit::WebInputEvent* CreateWebInputEvent(const ppapi::InputEventData& event);
// Creates an array of WebInputEvents to make the given event look like a user
// input event on all platforms. |plugin_x| and |plugin_y| should be the
// coordinates of a point within the plugin's area on the page.
std::vector<linked_ptr<WebKit::WebInputEvent> > CreateSimulatedWebInputEvents(
- const ::ppapi::InputEventData& event,
+ const ppapi::InputEventData& event,
int plugin_x,
int plugin_y);
diff --git a/content/renderer/pepper/host_array_buffer_var.h b/content/renderer/pepper/host_array_buffer_var.h
index 9388c4e..9ba1d7c 100644
--- a/content/renderer/pepper/host_array_buffer_var.h
+++ b/content/renderer/pepper/host_array_buffer_var.h
@@ -14,7 +14,7 @@
namespace content {
// Represents a host-side ArrayBufferVar.
-class HostArrayBufferVar : public ::ppapi::ArrayBufferVar {
+class HostArrayBufferVar : public ppapi::ArrayBufferVar {
public:
explicit HostArrayBufferVar(uint32 size_in_bytes);
explicit HostArrayBufferVar(const WebKit::WebArrayBuffer& buffer);
diff --git a/content/renderer/pepper/host_globals.cc b/content/renderer/pepper/host_globals.cc
index dac943b..64a989c 100644
--- a/content/renderer/pepper/host_globals.cc
+++ b/content/renderer/pepper/host_globals.cc
@@ -11,6 +11,7 @@
#include "base/rand_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task_runner.h"
+#include "content/public/common/content_switches.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/plugin_module.h"
#include "content/renderer/render_thread_impl.h"
@@ -22,7 +23,6 @@
#include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
-#include "webkit/plugins/plugin_switches.h"
using ppapi::CheckIdType;
using ppapi::MakeTypedId;
@@ -77,15 +77,15 @@
HostGlobals* HostGlobals::host_globals_ = NULL;
HostGlobals::HostGlobals()
- : ::ppapi::PpapiGlobals(),
+ : ppapi::PpapiGlobals(),
resource_tracker_(ResourceTracker::SINGLE_THREADED) {
DCHECK(!host_globals_);
host_globals_ = this;
}
HostGlobals::HostGlobals(
- ::ppapi::PpapiGlobals::PerThreadForTest per_thread_for_test)
- : ::ppapi::PpapiGlobals(per_thread_for_test),
+ ppapi::PpapiGlobals::PerThreadForTest per_thread_for_test)
+ : ppapi::PpapiGlobals(per_thread_for_test),
resource_tracker_(ResourceTracker::SINGLE_THREADED) {
DCHECK(!host_globals_);
}
@@ -95,15 +95,15 @@
host_globals_ = NULL;
}
-::ppapi::ResourceTracker* HostGlobals::GetResourceTracker() {
+ppapi::ResourceTracker* HostGlobals::GetResourceTracker() {
return &resource_tracker_;
}
-::ppapi::VarTracker* HostGlobals::GetVarTracker() {
+ppapi::VarTracker* HostGlobals::GetVarTracker() {
return &host_var_tracker_;
}
-::ppapi::CallbackTracker* HostGlobals::GetCallbackTrackerForInstance(
+ppapi::CallbackTracker* HostGlobals::GetCallbackTrackerForInstance(
PP_Instance instance) {
InstanceMap::iterator found = instance_map_.find(instance);
if (found == instance_map_.end())
@@ -111,13 +111,13 @@
return found->second->module()->GetCallbackTracker().get();
}
-::ppapi::thunk::PPB_Instance_API* HostGlobals::GetInstanceAPI(
+ppapi::thunk::PPB_Instance_API* HostGlobals::GetInstanceAPI(
PP_Instance instance) {
// The InstanceAPI is just implemented by the PluginInstance object.
return GetInstance(instance);
}
-::ppapi::thunk::ResourceCreationAPI* HostGlobals::GetResourceCreationAPI(
+ppapi::thunk::ResourceCreationAPI* HostGlobals::GetResourceCreationAPI(
PP_Instance pp_instance) {
PepperPluginInstanceImpl* instance = GetInstance(pp_instance);
if (!instance)
@@ -189,7 +189,7 @@
return RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get();
}
-::ppapi::MessageLoopShared* HostGlobals::GetCurrentMessageLoop() {
+ppapi::MessageLoopShared* HostGlobals::GetCurrentMessageLoop() {
return NULL;
}
@@ -205,7 +205,7 @@
PP_Module new_module;
do {
new_module = MakeTypedId(static_cast<PP_Module>(base::RandUint64()),
- ::ppapi::PP_ID_TYPE_MODULE);
+ ppapi::PP_ID_TYPE_MODULE);
} while (!new_module ||
module_map_.find(new_module) != module_map_.end());
module_map_[new_module] = module;
@@ -213,7 +213,7 @@
}
void HostGlobals::ModuleDeleted(PP_Module module) {
- DLOG_IF(ERROR, !CheckIdType(module, ::ppapi::PP_ID_TYPE_MODULE))
+ DLOG_IF(ERROR, !CheckIdType(module, ppapi::PP_ID_TYPE_MODULE))
<< module << " is not a PP_Module.";
ModuleMap::iterator found = module_map_.find(module);
if (found == module_map_.end()) {
@@ -224,7 +224,7 @@
}
PluginModule* HostGlobals::GetModule(PP_Module module) {
- DLOG_IF(ERROR, !CheckIdType(module, ::ppapi::PP_ID_TYPE_MODULE))
+ DLOG_IF(ERROR, !CheckIdType(module, ppapi::PP_ID_TYPE_MODULE))
<< module << " is not a PP_Module.";
ModuleMap::iterator found = module_map_.find(module);
if (found == module_map_.end())
@@ -242,7 +242,7 @@
PP_Instance new_instance;
do {
new_instance = MakeTypedId(static_cast<PP_Instance>(base::RandUint64()),
- ::ppapi::PP_ID_TYPE_INSTANCE);
+ ppapi::PP_ID_TYPE_INSTANCE);
} while (!new_instance ||
instance_map_.find(new_instance) != instance_map_.end() ||
!instance->module()->ReserveInstanceID(new_instance));
@@ -265,7 +265,7 @@
}
PepperPluginInstanceImpl* HostGlobals::GetInstance(PP_Instance instance) {
- DLOG_IF(ERROR, !CheckIdType(instance, ::ppapi::PP_ID_TYPE_INSTANCE))
+ DLOG_IF(ERROR, !CheckIdType(instance, ppapi::PP_ID_TYPE_INSTANCE))
<< instance << " is not a PP_Instance.";
InstanceMap::iterator found = instance_map_.find(instance);
if (found == instance_map_.end())
diff --git a/content/renderer/pepper/host_globals.h b/content/renderer/pepper/host_globals.h
index f48eb05..2f67b9e 100644
--- a/content/renderer/pepper/host_globals.h
+++ b/content/renderer/pepper/host_globals.h
@@ -17,10 +17,10 @@
class PepperPluginInstanceImpl;
class PluginModule;
-class HostGlobals : public ::ppapi::PpapiGlobals {
+class HostGlobals : public ppapi::PpapiGlobals {
public:
HostGlobals();
- explicit HostGlobals(::ppapi::PpapiGlobals::PerThreadForTest);
+ explicit HostGlobals(ppapi::PpapiGlobals::PerThreadForTest);
virtual ~HostGlobals();
// Getter for the global singleton. Generally, you should use
@@ -32,13 +32,13 @@
}
// PpapiGlobals implementation.
- virtual ::ppapi::ResourceTracker* GetResourceTracker() OVERRIDE;
- virtual ::ppapi::VarTracker* GetVarTracker() OVERRIDE;
- virtual ::ppapi::CallbackTracker* GetCallbackTrackerForInstance(
+ virtual ppapi::ResourceTracker* GetResourceTracker() OVERRIDE;
+ virtual ppapi::VarTracker* GetVarTracker() OVERRIDE;
+ virtual ppapi::CallbackTracker* GetCallbackTrackerForInstance(
PP_Instance instance) OVERRIDE;
- virtual ::ppapi::thunk::PPB_Instance_API* GetInstanceAPI(
+ virtual ppapi::thunk::PPB_Instance_API* GetInstanceAPI(
PP_Instance instance) OVERRIDE;
- virtual ::ppapi::thunk::ResourceCreationAPI* GetResourceCreationAPI(
+ virtual ppapi::thunk::ResourceCreationAPI* GetResourceCreationAPI(
PP_Instance instance) OVERRIDE;
virtual PP_Module GetModuleForInstance(PP_Instance instance) OVERRIDE;
virtual std::string GetCmdLine() OVERRIDE;
@@ -52,7 +52,7 @@
PP_LogLevel level,
const std::string& source,
const std::string& value) OVERRIDE;
- virtual ::ppapi::MessageLoopShared* GetCurrentMessageLoop() OVERRIDE;
+ virtual ppapi::MessageLoopShared* GetCurrentMessageLoop() OVERRIDE;
virtual base::TaskRunner* GetFileTaskRunner(PP_Instance instance) OVERRIDE;
HostVarTracker* host_var_tracker() {
@@ -96,7 +96,7 @@
static HostGlobals* host_globals_;
- ::ppapi::ResourceTracker resource_tracker_;
+ ppapi::ResourceTracker resource_tracker_;
HostVarTracker host_var_tracker_;
// Tracks all live instances and their associated object.
diff --git a/content/renderer/pepper/host_var_tracker.cc b/content/renderer/pepper/host_var_tracker.cc
index 9b9ebda..71a568a 100644
--- a/content/renderer/pepper/host_var_tracker.cc
+++ b/content/renderer/pepper/host_var_tracker.cc
@@ -122,7 +122,7 @@
instance_map_.erase(found_instance);
}
-void HostVarTracker::ForceReleaseNPObject(::ppapi::NPObjectVar* object_var) {
+void HostVarTracker::ForceReleaseNPObject(ppapi::NPObjectVar* object_var) {
object_var->InstanceDeleted();
VarMap::iterator iter = live_vars_.find(object_var->GetExistingVarID());
if (iter == live_vars_.end()) {
diff --git a/content/renderer/pepper/host_var_tracker.h b/content/renderer/pepper/host_var_tracker.h
index 290e858..5abdbff 100644
--- a/content/renderer/pepper/host_var_tracker.h
+++ b/content/renderer/pepper/host_var_tracker.h
@@ -31,7 +31,7 @@
// Adds NPObject var tracking to the standard PPAPI VarTracker for use in the
// renderer.
-class HostVarTracker : public ::ppapi::VarTracker {
+class HostVarTracker : public ppapi::VarTracker {
public:
HostVarTracker();
virtual ~HostVarTracker();
@@ -40,14 +40,14 @@
// NPObject and get the NPObjectVar corresponding to it. This Add/Remove
// function is called by the NPObjectVar when it is created and
// destroyed.
- void AddNPObjectVar(::ppapi::NPObjectVar* object_var);
- void RemoveNPObjectVar(::ppapi::NPObjectVar* object_var);
+ void AddNPObjectVar(ppapi::NPObjectVar* object_var);
+ void RemoveNPObjectVar(ppapi::NPObjectVar* object_var);
// Looks up a previously registered NPObjectVar for the given NPObject and
// instance. Returns NULL if there is no NPObjectVar corresponding to the
// given NPObject for the given instance. See AddNPObjectVar above.
- ::ppapi::NPObjectVar* NPObjectVarForNPObject(PP_Instance instance,
- NPObject* np_object);
+ ppapi::NPObjectVar* NPObjectVarForNPObject(PP_Instance instance,
+ NPObject* np_object);
// Returns the number of NPObjectVar's associated with the given instance.
// Returns 0 if the instance isn't known.
@@ -67,17 +67,16 @@
private:
// VarTracker private implementation.
- virtual ::ppapi::ArrayBufferVar* CreateArrayBuffer(
+ virtual ppapi::ArrayBufferVar* CreateArrayBuffer(
uint32 size_in_bytes) OVERRIDE;
- virtual ::ppapi::ArrayBufferVar* CreateShmArrayBuffer(
+ virtual ppapi::ArrayBufferVar* CreateShmArrayBuffer(
uint32 size_in_bytes, base::SharedMemoryHandle handle) OVERRIDE;
// Clear the reference count of the given object and remove it from
// live_vars_.
- void ForceReleaseNPObject(::ppapi::NPObjectVar* object_var);
+ void ForceReleaseNPObject(ppapi::NPObjectVar* object_var);
- typedef std::map<NPObject*, ::ppapi::NPObjectVar*>
- NPObjectToNPObjectVarMap;
+ typedef std::map<NPObject*, ppapi::NPObjectVar*> NPObjectToNPObjectVarMap;
// Lists all known NPObjects, first indexed by the corresponding instance,
// then by the NPObject*. This allows us to look up an NPObjectVar given
diff --git a/content/renderer/pepper/host_var_tracker_unittest.cc b/content/renderer/pepper/host_var_tracker_unittest.cc
index 693d63f..0c4d00d 100644
--- a/content/renderer/pepper/host_var_tracker_unittest.cc
+++ b/content/renderer/pepper/host_var_tracker_unittest.cc
@@ -120,8 +120,8 @@
}
// Remove both of the refs we made above.
- ::ppapi::VarTracker* var_tracker =
- ::ppapi::PpapiGlobals::Get()->GetVarTracker();
+ ppapi::VarTracker* var_tracker =
+ ppapi::PpapiGlobals::Get()->GetVarTracker();
var_tracker->ReleaseVar(static_cast<int32_t>(pp_object2.value.as_id));
var_tracker->ReleaseVar(static_cast<int32_t>(pp_object1.value.as_id));
diff --git a/content/renderer/pepper/mock_resource.h b/content/renderer/pepper/mock_resource.h
index fc6d0a8..d7a09c3 100644
--- a/content/renderer/pepper/mock_resource.h
+++ b/content/renderer/pepper/mock_resource.h
@@ -12,10 +12,10 @@
// Tests can derive from this to implement special test-specific resources.
// It's assumed that a test will only need one mock resource, so it can
// static_cast to get its own implementation.
-class MockResource : public ::ppapi::Resource {
+class MockResource : public ppapi::Resource {
public:
MockResource(PP_Instance instance)
- : Resource(::ppapi::OBJECT_IS_IMPL, instance) {}
+ : Resource(ppapi::OBJECT_IS_IMPL, instance) {}
private:
virtual ~MockResource() {}
diff --git a/content/renderer/pepper/npapi_glue.cc b/content/renderer/pepper/npapi_glue.cc
index 96e0bb0..124d03d 100644
--- a/content/renderer/pepper/npapi_glue.cc
+++ b/content/renderer/pepper/npapi_glue.cc
@@ -292,7 +292,7 @@
}
PPVarArrayFromNPVariantArray::~PPVarArrayFromNPVariantArray() {
- ::ppapi::VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker();
+ ppapi::VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker();
for (size_t i = 0; i < size_; i++)
var_tracker->ReleaseVar(array_[i]);
}
@@ -343,7 +343,7 @@
if (!has_exception()) {
has_exception_ = true;
if (exception_) {
- *exception_ = ::ppapi::StringVar::StringToPPVar(message, strlen(message));
+ *exception_ = ppapi::StringVar::StringToPPVar(message, strlen(message));
}
}
}
diff --git a/content/renderer/pepper/pepper_browser_connection.cc b/content/renderer/pepper/pepper_browser_connection.cc
index 3032576..00c6cd6 100644
--- a/content/renderer/pepper/pepper_browser_connection.cc
+++ b/content/renderer/pepper/pepper_browser_connection.cc
@@ -34,9 +34,10 @@
IPC_BEGIN_MESSAGE_MAP(PepperBrowserConnection, msg)
IPC_MESSAGE_HANDLER(PpapiHostMsg_CreateResourceHostFromHostReply,
OnMsgCreateResourceHostFromHostReply)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_FileRef_GetInfoForRendererReply,
+ OnMsgFileRefGetInfoReply)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
-
return handled;
}
@@ -101,10 +102,7 @@
void PepperBrowserConnection::OnMsgFileRefGetInfoReply(
int32_t sequence_number,
- const std::vector<PP_Resource>& resources,
- const std::vector<PP_FileSystemType>& types,
- const std::vector<std::string>& file_system_url_specs,
- const std::vector<base::FilePath>& external_paths) {
+ const std::vector<ppapi::FileRefDetailedInfo>& infos) {
// Check that the message is destined for the plugin this object is associated
// with.
std::map<int32_t, FileRefGetInfoCallback>::iterator it =
@@ -112,7 +110,7 @@
if (it != get_info_map_.end()) {
FileRefGetInfoCallback callback = it->second;
get_info_map_.erase(it);
- callback.Run(resources, types, file_system_url_specs, external_paths);
+ callback.Run(infos);
} else {
NOTREACHED();
}
diff --git a/content/renderer/pepper/pepper_browser_connection.h b/content/renderer/pepper/pepper_browser_connection.h
index 9fde7d2..d058a32 100644
--- a/content/renderer/pepper/pepper_browser_connection.h
+++ b/content/renderer/pepper/pepper_browser_connection.h
@@ -15,6 +15,7 @@
#include "ppapi/c/pp_file_info.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_resource.h"
+#include "ppapi/shared_impl/file_ref_detailed_info.h"
namespace content {
@@ -28,10 +29,7 @@
public:
typedef base::Callback<void(int)> PendingResourceIDCallback;
typedef base::Callback<void(
- const std::vector<PP_Resource>&,
- const std::vector<PP_FileSystemType>&,
- const std::vector<std::string>&,
- const std::vector<base::FilePath>&)> FileRefGetInfoCallback;
+ const std::vector<ppapi::FileRefDetailedInfo>&)> FileRefGetInfoCallback;
explicit PepperBrowserConnection(RenderView* render_view);
virtual ~PepperBrowserConnection();
@@ -71,10 +69,7 @@
int pending_resource_host_id);
void OnMsgFileRefGetInfoReply(
int32_t sequence_number,
- const std::vector<PP_Resource>& resources,
- const std::vector<PP_FileSystemType>& types,
- const std::vector<std::string>& file_system_url_specs,
- const std::vector<base::FilePath>& external_paths);
+ const std::vector<ppapi::FileRefDetailedInfo>& infos);
// Return the next sequence number.
int32_t GetNextSequence();
diff --git a/content/renderer/pepper/pepper_device_enumeration_host_helper.h b/content/renderer/pepper/pepper_device_enumeration_host_helper.h
index 424475b..5773845 100644
--- a/content/renderer/pepper/pepper_device_enumeration_host_helper.h
+++ b/content/renderer/pepper/pepper_device_enumeration_host_helper.h
@@ -43,7 +43,7 @@
typedef base::Callback<
void (int /* request_id */,
bool /* succeeded */,
- const std::vector< ::ppapi::DeviceRefData>& /* devices */)>
+ const std::vector<ppapi::DeviceRefData>& /* devices */)>
EnumerateDevicesCallback;
// Enumerates devices of the specified type. The request ID passed into the
diff --git a/content/renderer/pepper/pepper_file_chooser_host.cc b/content/renderer/pepper/pepper_file_chooser_host.cc
index 1229d17..bdf9cd8 100644
--- a/content/renderer/pepper/pepper_file_chooser_host.cc
+++ b/content/renderer/pepper/pepper_file_chooser_host.cc
@@ -7,13 +7,11 @@
#include "base/files/file_path.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/renderer/renderer_ppapi_host.h"
-#include "content/renderer/pepper/ppb_file_ref_impl.h"
#include "content/renderer/render_view_impl.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
#include "third_party/WebKit/public/platform/WebCString.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebVector.h"
@@ -81,7 +79,9 @@
PP_Resource resource)
: ResourceHost(host->GetPpapiHost(), instance, resource),
renderer_ppapi_host_(host),
- handler_(NULL) {
+ num_pending_file_resources_(0),
+ handler_(NULL),
+ weak_factory_(this) {
}
PepperFileChooserHost::~PepperFileChooserHost() {
@@ -98,29 +98,30 @@
void PepperFileChooserHost::StoreChosenFiles(
const std::vector<ChosenFileInfo>& files) {
- std::vector<ppapi::PPB_FileRef_CreateInfo> chosen_files;
+ num_pending_file_resources_ = files.size();
for (size_t i = 0; i < files.size(); i++) {
#if defined(OS_WIN)
base::FilePath file_path(UTF8ToWide(files[i].path));
#else
base::FilePath file_path(files[i].path);
#endif
-
- PPB_FileRef_Impl* ref = PPB_FileRef_Impl::CreateExternal(
- pp_instance(), file_path, files[i].display_name);
- ppapi::PPB_FileRef_CreateInfo create_info;
- ppapi::proxy::PPB_FileRef_Proxy::SerializeFileRef(ref->GetReference(),
- &create_info);
- chosen_files.push_back(create_info);
+ renderer_ppapi_host_->CreateBrowserResourceHost(
+ pp_instance(),
+ PpapiHostMsg_FileRef_CreateExternal(file_path),
+ base::Bind(&PepperFileChooserHost::DidCreateResourceHost,
+ weak_factory_.GetWeakPtr(),
+ file_path,
+ files[i].display_name));
}
- reply_context_.params.set_result(
- (chosen_files.size() > 0) ? PP_OK : PP_ERROR_USERCANCEL);
- host()->SendReply(reply_context_,
- PpapiPluginMsg_FileChooser_ShowReply(chosen_files));
-
- reply_context_ = ppapi::host::ReplyMessageContext();
- handler_ = NULL; // Handler deletes itself.
+ if (files.empty()) {
+ reply_context_.params.set_result(PP_ERROR_USERCANCEL);
+ std::vector<ppapi::FileRefCreateInfo> chosen_files;
+ host()->SendReply(reply_context_,
+ PpapiPluginMsg_FileChooser_ShowReply(chosen_files));
+ reply_context_ = ppapi::host::ReplyMessageContext();
+ handler_ = NULL; // Handler deletes itself.
+ }
}
int32_t PepperFileChooserHost::OnShow(
@@ -167,5 +168,22 @@
return PP_OK_COMPLETIONPENDING;
}
+void PepperFileChooserHost::DidCreateResourceHost(
+ const base::FilePath& file_path,
+ const std::string& display_name,
+ int32_t id) {
+ num_pending_file_resources_--;
+ ppapi::FileRefCreateInfo info = ppapi::MakeExternalFileRefCreateInfo(
+ file_path, display_name, id);
+ chosen_files_.push_back(info);
+ if (num_pending_file_resources_ == 0) {
+ reply_context_.params.set_result(PP_OK);
+ host()->SendReply(reply_context_,
+ PpapiPluginMsg_FileChooser_ShowReply(chosen_files_));
+ reply_context_ = ppapi::host::ReplyMessageContext();
+ handler_ = NULL; // Handler deletes itself.
+ }
+}
+
} // namespace content
diff --git a/content/renderer/pepper/pepper_file_chooser_host.h b/content/renderer/pepper/pepper_file_chooser_host.h
index af27768..d837460 100644
--- a/content/renderer/pepper/pepper_file_chooser_host.h
+++ b/content/renderer/pepper/pepper_file_chooser_host.h
@@ -15,6 +15,10 @@
#include "ppapi/host/resource_host.h"
#include "ppapi/proxy/resource_message_params.h"
+namespace ppapi {
+struct FileRefCreateInfo;
+}
+
namespace content {
class RendererPpapiHost;
@@ -51,12 +55,21 @@
const std::string& suggested_file_name,
const std::vector<std::string>& accept_mime_types);
+ void DidCreateResourceHost(const base::FilePath& file_path,
+ const std::string& display_name,
+ int32_t id);
+
// Non-owning pointer.
RendererPpapiHost* renderer_ppapi_host_;
+ int num_pending_file_resources_;
+ std::vector<ppapi::FileRefCreateInfo> chosen_files_;
+
ppapi::host::ReplyMessageContext reply_context_;
CompletionHandler* handler_;
+ base::WeakPtrFactory<PepperFileChooserHost> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(PepperFileChooserHost);
};
diff --git a/content/renderer/pepper/pepper_file_chooser_host_unittest.cc b/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
index b228cd7..c8cf9f6 100644
--- a/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
+++ b/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
@@ -18,7 +18,6 @@
#include "ppapi/proxy/resource_message_params.h"
#include "ppapi/proxy/resource_message_test_sink.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
-#include "ppapi/shared_impl/ppb_file_ref_shared.h"
#include "ppapi/shared_impl/resource_tracker.h"
#include "ppapi/shared_impl/test_globals.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -65,70 +64,11 @@
} // namespace
-TEST_F(PepperFileChooserHostTest, Show) {
- PP_Resource pp_resource = 123;
-
- MockRendererPpapiHost host(view_, pp_instance());
- PepperFileChooserHost chooser(&host, pp_instance(), pp_resource);
-
- // Say there's a user gesture.
- host.set_has_user_gesture(true);
-
- std::vector<std::string> accept;
- accept.push_back("text/plain");
- PpapiHostMsg_FileChooser_Show show_msg(false, false, std::string(), accept);
-
- ppapi::proxy::ResourceMessageCallParams call_params(pp_resource, 0);
- ppapi::host::HostMessageContext context(call_params);
- int32 result = chooser.OnResourceMessageReceived(show_msg, &context);
- EXPECT_EQ(PP_OK_COMPLETIONPENDING, result);
-
- // The render view should have sent a chooser request to the browser
- // (caught by the render thread's test message sink).
- const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
- ViewHostMsg_RunFileChooser::ID);
- ASSERT_TRUE(msg);
- ViewHostMsg_RunFileChooser::Schema::Param call_msg_param;
- ASSERT_TRUE(ViewHostMsg_RunFileChooser::Read(msg, &call_msg_param));
- const FileChooserParams& chooser_params = call_msg_param.a;
-
- // Basic validation of request.
- EXPECT_EQ(FileChooserParams::Open, chooser_params.mode);
- ASSERT_EQ(1u, chooser_params.accept_types.size());
- EXPECT_EQ(accept[0], UTF16ToUTF8(chooser_params.accept_types[0]));
-
- // Send a chooser reply to the render view. Note our reply path has to have a
- // path separator so we include both a Unix and a Windows one.
- ui::SelectedFileInfo selected_info;
- selected_info.display_name = FILE_PATH_LITERAL("Hello, world");
- selected_info.local_path = base::FilePath(FILE_PATH_LITERAL("myp\\ath/foo"));
- std::vector<ui::SelectedFileInfo> selected_info_vector;
- selected_info_vector.push_back(selected_info);
- RenderViewImpl* view_impl = static_cast<RenderViewImpl*>(view_);
- ViewMsg_RunFileChooserResponse response(view_impl->routing_id(),
- selected_info_vector);
- EXPECT_TRUE(view_impl->OnMessageReceived(response));
-
- // This should have sent the Pepper reply to our test sink.
- ppapi::proxy::ResourceMessageReplyParams reply_params;
- IPC::Message reply_msg;
- ASSERT_TRUE(host.sink().GetFirstResourceReplyMatching(
- PpapiPluginMsg_FileChooser_ShowReply::ID, &reply_params, &reply_msg));
-
- // Basic validation of reply.
- EXPECT_EQ(call_params.sequence(), reply_params.sequence());
- EXPECT_EQ(PP_OK, reply_params.result());
- PpapiPluginMsg_FileChooser_ShowReply::Schema::Param reply_msg_param;
- ASSERT_TRUE(PpapiPluginMsg_FileChooser_ShowReply::Read(&reply_msg,
- &reply_msg_param));
- const std::vector<ppapi::PPB_FileRef_CreateInfo>& chooser_results =
- reply_msg_param.a;
- ASSERT_EQ(1u, chooser_results.size());
- // Note path is empty because this is an external filesystem.
- EXPECT_EQ(std::string(), chooser_results[0].path);
- EXPECT_EQ(FilePathToUTF8(selected_info.display_name),
- chooser_results[0].name);
-}
+// TODO(teravest): Write a good test for the "Show" interface of FileChooser.
+// We can't do this very easily today because we need direct access to the
+// RenderViewImpl, but also need renderer and browser instances fully set up.
+// This is was caused by the "new" FileRef refactor, which moved FileRef
+// hosting to the browser. http://crbug.com/270322
TEST_F(PepperFileChooserHostTest, NoUserGesture) {
PP_Resource pp_resource = 123;
diff --git a/content/renderer/pepper/pepper_file_io_host.cc b/content/renderer/pepper/pepper_file_io_host.cc
index 5a6d40c..0431b1c 100644
--- a/content/renderer/pepper/pepper_file_io_host.cc
+++ b/content/renderer/pepper/pepper_file_io_host.cc
@@ -17,11 +17,14 @@
#include "content/public/common/content_client.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/pepper/host_globals.h"
+#include "content/renderer/pepper/pepper_browser_connection.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
-#include "content/renderer/pepper/ppb_file_ref_impl.h"
+#include "content/renderer/pepper/plugin_module.h"
#include "content/renderer/pepper/quota_file_io.h"
+#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_file_io.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
@@ -36,17 +39,9 @@
using ppapi::PPTimeToTime;
using ppapi::host::ReplyMessageContext;
using ppapi::thunk::EnterResourceNoLock;
-using ppapi::thunk::PPB_FileRef_API;
namespace {
-// The maximum size we'll support reading in one chunk. The renderer process
-// must allocate a buffer sized according to the request of the plugin. To
-// keep things from getting out of control, we cap the read size to this value.
-// This should generally be OK since the API specifies that it may perform a
-// partial read.
-static const int32_t kMaxReadSize = 32 * 1024 * 1024; // 32MB
-
typedef base::Callback<void (base::PlatformFileError)> PlatformGeneralCallback;
int32_t ErrorOrByteNumber(int32_t pp_error, int32_t byte_number) {
@@ -142,6 +137,8 @@
PP_Instance instance,
PP_Resource resource)
: ResourceHost(host->GetPpapiHost(), instance, resource),
+ renderer_ppapi_host_(host),
+ plugin_instance_(HostGlobals::Get()->GetInstance(instance)),
file_(base::kInvalidPlatformFileValue),
file_system_type_(PP_FILESYSTEMTYPE_INVALID),
quota_policy_(quota::kQuotaLimitTypeUnknown),
@@ -163,12 +160,8 @@
IPC_BEGIN_MESSAGE_MAP(PepperFileIOHost, msg)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Open,
OnHostMsgOpen)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_FileIO_Query,
- OnHostMsgQuery)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Touch,
OnHostMsgTouch)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Read,
- OnHostMsgRead)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_Write,
OnHostMsgWrite)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FileIO_SetLength,
@@ -233,70 +226,71 @@
// FileSystemDispatcher so it can handle doing the security check.
int platform_file_flags = 0;
open_flags_ = open_flags;
- if (!::ppapi::PepperFileOpenFlagsToPlatformFileFlags(open_flags,
- &platform_file_flags)) {
+ if (!ppapi::PepperFileOpenFlagsToPlatformFileFlags(open_flags,
+ &platform_file_flags)) {
return PP_ERROR_BADARGUMENT;
}
- EnterResourceNoLock<PPB_FileRef_API> enter(file_ref_resource, true);
- if (enter.failed())
- return PP_ERROR_BADRESOURCE;
+ RenderView* render_view =
+ renderer_ppapi_host_->GetRenderViewForInstance(pp_instance());
+ PepperBrowserConnection* browser_connection =
+ PepperBrowserConnection::Get(render_view);
+ int child_process_id = plugin_instance_->module()->GetPluginChildId();
- PPB_FileRef_API* file_ref_api = enter.object();
- PP_FileSystemType type = file_ref_api->GetFileSystemType();
- if (type != PP_FILESYSTEMTYPE_LOCALPERSISTENT &&
- type != PP_FILESYSTEMTYPE_LOCALTEMPORARY &&
- type != PP_FILESYSTEMTYPE_EXTERNAL &&
- type != PP_FILESYSTEMTYPE_ISOLATED)
- return PP_ERROR_FAILED;
- file_system_type_ = type;
+ // Explicitly set child_process_id to 0 if we're running in process. This is
+ // necessary in the case where we're a host for a resource in "the trusted
+ // NaCl plugin". In that case, we may have already done work for the
+ // untrusted plugin, and the call above will give a non-zero
+ // child_process_id.
+ if (renderer_ppapi_host_->IsRunningInProcess())
+ child_process_id = 0;
- PPB_FileRef_Impl* file_ref = static_cast<PPB_FileRef_Impl*>(file_ref_api);
- if (file_ref->HasValidFileSystem()) {
- file_system_url_ = file_ref->GetFileSystemURL();
+ std::vector<PP_Resource> resources;
+ resources.push_back(file_ref_resource);
+ browser_connection->SendBrowserFileRefGetInfo(
+ child_process_id,
+ resources,
+ base::Bind(&PepperFileIOHost::DidGetFileRefInfo,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext(),
+ platform_file_flags));
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+void PepperFileIOHost::DidGetFileRefInfo(
+ ppapi::host::ReplyMessageContext reply_context,
+ int platform_file_flags,
+ const std::vector<ppapi::FileRefDetailedInfo>& infos) {
+ if (infos.size() != 1) {
+ reply_context.params.set_result(PP_ERROR_FAILED);
+ host()->SendReply(reply_context,
+ PpapiPluginMsg_FileIO_OpenReply());
+ return;
+ }
+
+ file_system_type_ = infos[0].file_system_type;
+ if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL) {
+ file_system_url_ = GURL(infos[0].file_system_url_spec);
FileSystemDispatcher* file_system_dispatcher =
ChildThread::current()->file_system_dispatcher();
+
AsyncOpenFileSystemURLCallback callback = base::Bind(
&PepperFileIOHost::ExecutePlatformOpenFileSystemURLCallback,
weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext());
+ reply_context);
file_system_dispatcher->OpenFile(
file_system_url_, platform_file_flags,
base::Bind(&DidOpenFileSystemURL, callback),
base::Bind(&DidFailOpenFileSystemURL, callback));
} else {
- if (file_system_type_ != PP_FILESYSTEMTYPE_EXTERNAL)
- return PP_ERROR_FAILED;
int message_id = pending_async_open_files_.Add(new AsyncOpenFileCallback(
base::Bind(&PepperFileIOHost::ExecutePlatformOpenFileCallback,
weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext())));
+ reply_context)));
RenderThreadImpl::current()->Send(new ViewHostMsg_AsyncOpenPepperFile(
- routing_id_, file_ref->GetSystemPath(), open_flags, message_id));
+ routing_id_, infos[0].external_path, open_flags_, message_id));
}
-
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperFileIOHost::OnHostMsgQuery(
- ppapi::host::HostMessageContext* context) {
- int32_t rv = state_manager_.CheckOperationState(
- FileIOStateManager::OPERATION_EXCLUSIVE, true);
- if (rv != PP_OK)
- return rv;
-
- if (!base::FileUtilProxy::GetFileInfoFromPlatformFile(
- RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
- file_,
- base::Bind(&PepperFileIOHost::ExecutePlatformQueryCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext())))
- return PP_ERROR_FAILED;
-
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
- return PP_OK_COMPLETIONPENDING;
}
int32_t PepperFileIOHost::OnHostMsgTouch(
@@ -338,39 +332,6 @@
return PP_OK_COMPLETIONPENDING;
}
-int32_t PepperFileIOHost::OnHostMsgRead(
- ppapi::host::HostMessageContext* context,
- int64_t offset,
- int32_t max_read_length) {
- int32_t rv = state_manager_.CheckOperationState(
- FileIOStateManager::OPERATION_READ, true);
- if (rv != PP_OK)
- return rv;
-
- // Validate max_read_length before allocating below. This value is coming from
- // the untrusted plugin.
- if (max_read_length < 0) {
- ReplyMessageContext reply_context = context->MakeReplyMessageContext();
- reply_context.params.set_result(PP_ERROR_FAILED);
- host()->SendReply(reply_context,
- PpapiPluginMsg_FileIO_ReadReply(std::string()));
- return PP_OK_COMPLETIONPENDING;
- }
-
- if (!base::FileUtilProxy::Read(
- RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
- file_,
- offset,
- max_read_length,
- base::Bind(&PepperFileIOHost::ExecutePlatformReadCallback,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext())))
- return PP_ERROR_FAILED;
-
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ);
- return PP_OK_COMPLETIONPENDING;
-}
-
int32_t PepperFileIOHost::OnHostMsgWrite(
ppapi::host::HostMessageContext* context,
int64_t offset,
@@ -520,16 +481,13 @@
quota_policy_ != quota::kQuotaLimitTypeUnlimited)
return PP_ERROR_FAILED;
- RendererPpapiHost* renderer_ppapi_host =
- RendererPpapiHost::GetForPPInstance(pp_instance());
-
// Whitelist to make it privately accessible.
if (!GetContentClient()->renderer()->IsPluginAllowedToCallRequestOSFileHandle(
- renderer_ppapi_host->GetContainerForInstance(pp_instance())))
+ renderer_ppapi_host_->GetContainerForInstance(pp_instance())))
return PP_ERROR_NOACCESS;
IPC::PlatformFileForTransit file =
- renderer_ppapi_host->ShareHandleWithRemote(file_, false);
+ renderer_ppapi_host_->ShareHandleWithRemote(file_, false);
if (file == IPC::InvalidPlatformFileForTransit())
return PP_ERROR_FAILED;
ppapi::host::ReplyMessageContext reply_context =
@@ -565,7 +523,7 @@
ppapi::host::ReplyMessageContext reply_context,
base::PlatformFileError error_code) {
reply_context.params.set_result(
- ::ppapi::PlatformFileErrorToPepperError(error_code));
+ ppapi::PlatformFileErrorToPepperError(error_code));
host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
state_manager_.SetOperationFinished();
}
@@ -574,7 +532,7 @@
ppapi::host::ReplyMessageContext reply_context,
base::PlatformFileError error_code,
base::PassPlatformFile file) {
- int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
+ int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code);
if (pp_error == PP_OK)
state_manager_.SetOpenSucceed();
@@ -582,11 +540,26 @@
file_ = file.ReleaseValue();
DCHECK(!quota_file_io_.get());
- if (file_ != base::kInvalidPlatformFileValue &&
- (file_system_type_ == PP_FILESYSTEMTYPE_LOCALTEMPORARY ||
- file_system_type_ == PP_FILESYSTEMTYPE_LOCALPERSISTENT)) {
- quota_file_io_.reset(new QuotaFileIO(
- new QuotaFileIODelegate, file_, file_system_url_, file_system_type_));
+ if (file_ != base::kInvalidPlatformFileValue) {
+ if (file_system_type_ == PP_FILESYSTEMTYPE_LOCALTEMPORARY ||
+ file_system_type_ == PP_FILESYSTEMTYPE_LOCALPERSISTENT) {
+ quota_file_io_.reset(new QuotaFileIO(
+ new QuotaFileIODelegate, file_, file_system_url_, file_system_type_));
+ }
+
+ IPC::PlatformFileForTransit file_for_transit =
+ renderer_ppapi_host_->ShareHandleWithRemote(file_, false);
+ if (!(file_for_transit == IPC::InvalidPlatformFileForTransit())) {
+ // Send the file descriptor to the plugin process. This is used in the
+ // plugin for any file operations that can be done there.
+ // IMPORTANT: Clear PP_FILEOPENFLAG_WRITE and PP_FILEOPENFLAG_APPEND so
+ // the plugin can't write and so bypass our quota checks.
+ int32_t no_write_flags =
+ open_flags_ & ~(PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_APPEND);
+ ppapi::proxy::SerializedHandle file_handle;
+ file_handle.set_file_handle(file_for_transit, no_write_flags);
+ reply_context.params.AppendHandle(file_handle);
+ }
}
reply_context.params.set_result(pp_error);
@@ -606,36 +579,6 @@
ExecutePlatformOpenFileCallback(reply_context, error_code, file);
}
-void PepperFileIOHost::ExecutePlatformQueryCallback(
- ppapi::host::ReplyMessageContext reply_context,
- base::PlatformFileError error_code,
- const base::PlatformFileInfo& file_info) {
- PP_FileInfo pp_info;
- ppapi::PlatformFileInfoToPepperFileInfo(file_info, file_system_type_,
- &pp_info);
-
- int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
- reply_context.params.set_result(pp_error);
- host()->SendReply(reply_context,
- PpapiPluginMsg_FileIO_QueryReply(pp_info));
- state_manager_.SetOperationFinished();
-}
-
-void PepperFileIOHost::ExecutePlatformReadCallback(
- ppapi::host::ReplyMessageContext reply_context,
- base::PlatformFileError error_code,
- const char* data, int bytes_read) {
- int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
-
- // Only send the amount of data in the string that was actually read.
- std::string buffer;
- if (pp_error == PP_OK)
- buffer.append(data, bytes_read);
- reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_read));
- host()->SendReply(reply_context, PpapiPluginMsg_FileIO_ReadReply(buffer));
- state_manager_.SetOperationFinished();
-}
-
void PepperFileIOHost::ExecutePlatformWriteCallback(
ppapi::host::ReplyMessageContext reply_context,
base::PlatformFileError error_code,
@@ -643,7 +586,7 @@
// On the plugin side, the callback expects a parameter with different meaning
// depends on whether is negative or not. It is the result here. We translate
// for the callback.
- int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
+ int32_t pp_error = ppapi::PlatformFileErrorToPepperError(error_code);
reply_context.params.set_result(ErrorOrByteNumber(pp_error, bytes_written));
host()->SendReply(reply_context, PpapiPluginMsg_FileIO_GeneralReply());
state_manager_.SetOperationFinished();
diff --git a/content/renderer/pepper/pepper_file_io_host.h b/content/renderer/pepper/pepper_file_io_host.h
index 1d3dbbd..1680406 100644
--- a/content/renderer/pepper/pepper_file_io_host.h
+++ b/content/renderer/pepper/pepper_file_io_host.h
@@ -19,6 +19,7 @@
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
#include "ppapi/shared_impl/file_io_state_manager.h"
+#include "ppapi/shared_impl/file_ref_detailed_info.h"
#include "ppapi/thunk/ppb_file_ref_api.h"
#include "url/gurl.h"
#include "webkit/common/quota/quota_types.h"
@@ -26,6 +27,7 @@
using ppapi::host::ReplyMessageContext;
namespace content {
+class PepperPluginInstanceImpl;
class QuotaFileIO;
class PepperFileIOHost : public ppapi::host::ResourceHost,
@@ -57,13 +59,9 @@
int32_t OnHostMsgOpen(ppapi::host::HostMessageContext* context,
PP_Resource file_ref_resource,
int32_t open_flags);
- int32_t OnHostMsgQuery(ppapi::host::HostMessageContext* context);
int32_t OnHostMsgTouch(ppapi::host::HostMessageContext* context,
PP_Time last_access_time,
PP_Time last_modified_time);
- int32_t OnHostMsgRead(ppapi::host::HostMessageContext* context,
- int64_t offset,
- int32_t bytes_to_read);
int32_t OnHostMsgWrite(ppapi::host::HostMessageContext* context,
int64_t offset,
const std::string& buffer);
@@ -83,6 +81,11 @@
int32_t OnHostMsgWillSetLength(ppapi::host::HostMessageContext* context,
int64_t length);
+ void DidGetFileRefInfo(
+ ppapi::host::ReplyMessageContext reply_context,
+ int flags,
+ const std::vector<ppapi::FileRefDetailedInfo>& infos);
+
// Callback handlers. These mostly convert the PlatformFileError to the
// PP_Error code and send back the reply. Note that the argument
// ReplyMessageContext is copied so that we have a closure containing all
@@ -108,6 +111,8 @@
base::PlatformFileError error_code,
int bytes_written);
+ RendererPpapiHost* renderer_ppapi_host_;
+ PepperPluginInstanceImpl* plugin_instance_;
base::PlatformFile file_;
// The file system type specified in the Open() call. This will be
diff --git a/content/renderer/pepper/pepper_in_process_resource_creation.cc b/content/renderer/pepper/pepper_in_process_resource_creation.cc
index 3732583..cb10ff2 100644
--- a/content/renderer/pepper/pepper_in_process_resource_creation.cc
+++ b/content/renderer/pepper/pepper_in_process_resource_creation.cc
@@ -19,6 +19,7 @@
#include "ppapi/proxy/ext_crx_file_system_private_resource.h"
#include "ppapi/proxy/file_chooser_resource.h"
#include "ppapi/proxy/file_io_resource.h"
+#include "ppapi/proxy/file_ref_resource.h"
#include "ppapi/proxy/file_system_resource.h"
#include "ppapi/proxy/graphics_2d_resource.h"
#include "ppapi/proxy/ppapi_messages.h"
@@ -85,6 +86,15 @@
instance))->GetReference();
}
+PP_Resource PepperInProcessResourceCreation::CreateFileRef(
+ PP_Instance instance,
+ const ppapi::FileRefCreateInfo& create_info) {
+ return ppapi::proxy::FileRefResource::CreateFileRef(
+ host_impl_->in_process_router()->GetPluginConnection(instance),
+ instance,
+ create_info);
+}
+
PP_Resource PepperInProcessResourceCreation::CreateFileSystem(
PP_Instance instance,
PP_FileSystemType type) {
@@ -127,7 +137,7 @@
PP_Instance instance) {
return (new ppapi::proxy::URLRequestInfoResource(
host_impl_->in_process_router()->GetPluginConnection(instance),
- instance, ::ppapi::URLRequestInfoData()))->GetReference();
+ instance, ppapi::URLRequestInfoData()))->GetReference();
}
PP_Resource PepperInProcessResourceCreation::CreateWebSocket(
diff --git a/content/renderer/pepper/pepper_in_process_resource_creation.h b/content/renderer/pepper/pepper_in_process_resource_creation.h
index 985ae09..847aac1 100644
--- a/content/renderer/pepper/pepper_in_process_resource_creation.h
+++ b/content/renderer/pepper/pepper_in_process_resource_creation.h
@@ -49,6 +49,9 @@
PP_FileChooserMode_Dev mode,
const PP_Var& accept_types) OVERRIDE;
virtual PP_Resource CreateFileIO(PP_Instance instance) OVERRIDE;
+ virtual PP_Resource CreateFileRef(
+ PP_Instance instance,
+ const ppapi::FileRefCreateInfo& create_info) OVERRIDE;
virtual PP_Resource CreateFileSystem(PP_Instance instance,
PP_FileSystemType type) OVERRIDE;
virtual PP_Resource CreateGraphics2D(
diff --git a/content/renderer/pepper/pepper_media_device_manager.cc b/content/renderer/pepper/pepper_media_device_manager.cc
index ede9796..3531816 100644
--- a/content/renderer/pepper/pepper_media_device_manager.cc
+++ b/content/renderer/pepper/pepper_media_device_manager.cc
@@ -152,6 +152,9 @@
void PepperMediaDeviceManager::OnStreamGenerationFailed(int request_id) {
}
+void PepperMediaDeviceManager::OnStopGeneratedStream(const std::string& label) {
+}
+
void PepperMediaDeviceManager::OnDevicesEnumerated(
int request_id,
const StreamDeviceInfoArray& device_array) {
diff --git a/content/renderer/pepper/pepper_media_device_manager.h b/content/renderer/pepper/pepper_media_device_manager.h
index dd1d9d5..67d8976 100644
--- a/content/renderer/pepper/pepper_media_device_manager.h
+++ b/content/renderer/pepper/pepper_media_device_manager.h
@@ -60,6 +60,7 @@
const StreamDeviceInfoArray& audio_device_array,
const StreamDeviceInfoArray& video_device_array) OVERRIDE;
virtual void OnStreamGenerationFailed(int request_id) OVERRIDE;
+ virtual void OnStopGeneratedStream(const std::string& label) OVERRIDE;
virtual void OnDevicesEnumerated(
int request_id,
const StreamDeviceInfoArray& device_array) OVERRIDE;
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc
index 310ebe8..1ba473b 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -16,6 +16,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "cc/layers/texture_layer.h"
+#include "content/common/content_constants_internal.h"
#include "content/public/common/page_zoom.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/pepper/common.h"
@@ -35,7 +36,6 @@
#include "content/renderer/pepper/plugin_module.h"
#include "content/renderer/pepper/plugin_object.h"
#include "content/renderer/pepper/ppb_buffer_impl.h"
-#include "content/renderer/pepper/ppb_file_ref_impl.h"
#include "content/renderer/pepper/ppb_graphics_3d_impl.h"
#include "content/renderer/pepper/ppb_image_data_impl.h"
#include "content/renderer/pepper/ppp_pdf.h"
@@ -45,6 +45,7 @@
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
#include "content/renderer/render_widget_fullscreen_pepper.h"
+#include "content/renderer/sad_plugin.h"
#include "media/base/audio_hardware_config.h"
#include "ppapi/c/dev/ppb_find_dev.h"
#include "ppapi/c/dev/ppb_zoom_dev.h"
@@ -110,8 +111,6 @@
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
#include "v8/include/v8.h"
-#include "webkit/plugins/plugin_constants.h"
-#include "webkit/plugins/sad_plugin.h"
#include "webkit/renderer/compositor_bindings/web_layer_impl.h"
#if defined(OS_MACOSX)
@@ -373,14 +372,14 @@
plugin_url);
}
-PepperPluginInstanceImpl::NaClDocumentLoader::NaClDocumentLoader()
+PepperPluginInstanceImpl::ExternalDocumentLoader::ExternalDocumentLoader()
: finished_loading_(false) {
}
-PepperPluginInstanceImpl::NaClDocumentLoader::~NaClDocumentLoader(){
+PepperPluginInstanceImpl::ExternalDocumentLoader::~ExternalDocumentLoader() {
}
-void PepperPluginInstanceImpl::NaClDocumentLoader::ReplayReceivedData(
+void PepperPluginInstanceImpl::ExternalDocumentLoader::ReplayReceivedData(
WebURLLoaderClient* document_loader) {
for (std::list<std::string>::iterator it = data_.begin();
it != data_.end(); ++it) {
@@ -396,7 +395,7 @@
}
}
-void PepperPluginInstanceImpl::NaClDocumentLoader::didReceiveData(
+void PepperPluginInstanceImpl::ExternalDocumentLoader::didReceiveData(
WebURLLoader* loader,
const char* data,
int data_length,
@@ -404,14 +403,14 @@
data_.push_back(std::string(data, data_length));
}
-void PepperPluginInstanceImpl::NaClDocumentLoader::didFinishLoading(
+void PepperPluginInstanceImpl::ExternalDocumentLoader::didFinishLoading(
WebURLLoader* loader,
double finish_time) {
DCHECK(!finished_loading_);
finished_loading_ = true;
}
-void PepperPluginInstanceImpl::NaClDocumentLoader::didFail(
+void PepperPluginInstanceImpl::ExternalDocumentLoader::didFail(
WebURLLoader* loader,
const WebURLError& error) {
DCHECK(!error_.get());
@@ -419,7 +418,7 @@
}
PepperPluginInstanceImpl::GamepadImpl::GamepadImpl()
- : Resource(::ppapi::Resource::Untracked()) {
+ : Resource(ppapi::Resource::Untracked()) {
}
PepperPluginInstanceImpl::GamepadImpl::~GamepadImpl() {
@@ -435,13 +434,13 @@
WebKit::WebGamepads webkit_data;
RenderThreadImpl::current()->SampleGamepads(&webkit_data);
ConvertWebKitGamepadData(
- *reinterpret_cast<const ::ppapi::WebKitGamepads*>(&webkit_data), data);
+ *reinterpret_cast<const ppapi::WebKitGamepads*>(&webkit_data), data);
}
PepperPluginInstanceImpl::PepperPluginInstanceImpl(
RenderViewImpl* render_view,
PluginModule* module,
- ::ppapi::PPP_Instance_Combined* instance_interface,
+ ppapi::PPP_Instance_Combined* instance_interface,
WebPluginContainer* container,
const GURL& plugin_url)
: render_view_(render_view),
@@ -488,7 +487,7 @@
selection_anchor_(0),
pending_user_gesture_(0.0),
document_loader_(NULL),
- nacl_document_load_(false),
+ external_document_load_(false),
npp_(new NPP_t),
isolate_(v8::Isolate::GetCurrent()) {
pp_instance_ = HostGlobals::Get()->AddInstance(this);
@@ -517,11 +516,9 @@
RendererPpapiHostImpl* host_impl = module_->renderer_ppapi_host();
resource_creation_ = host_impl->CreateInProcessResourceCreationAPI(this);
- // TODO(bbudge) remove this when the trusted NaCl plugin has been removed.
- // We must defer certain plugin events for NaCl instances since we switch
- // from the in-process to the out-of-process proxy after instantiating them.
- if (module->name() == "Native Client")
- nacl_document_load_ = true;
+ if (GetContentClient()->renderer() && // NULL in unit tests.
+ GetContentClient()->renderer()->IsExternalPepperPlugin(module->name()))
+ external_document_load_ = true;
}
PepperPluginInstanceImpl::~PepperPluginInstanceImpl() {
@@ -609,7 +606,7 @@
if (!sad_plugin_) // Lazily initialize bitmap.
sad_plugin_ = GetContentClient()->renderer()->GetSadPluginBitmap();
if (sad_plugin_)
- webkit::PaintSadPlugin(canvas, plugin_rect, *sad_plugin_);
+ PaintSadPlugin(canvas, plugin_rect, *sad_plugin_);
return;
}
@@ -671,7 +668,7 @@
UnSetAndDeleteLockTargetAdapter();
}
-static void SetGPUHistogram(const ::ppapi::Preferences& prefs,
+static void SetGPUHistogram(const ppapi::Preferences& prefs,
const std::vector<std::string>& arg_names,
const std::vector<std::string>& arg_values) {
// Calculate a histogram to let us determine how likely people are to try to
@@ -732,12 +729,12 @@
bool PepperPluginInstanceImpl::HandleDocumentLoad(
const WebKit::WebURLResponse& response) {
DCHECK(!document_loader_);
- if (nacl_document_load_) {
- // The NaCl proxy isn't available, so save the response and record document
- // load notifications for later replay.
- nacl_document_response_ = response;
- nacl_document_loader_.reset(new NaClDocumentLoader());
- document_loader_ = nacl_document_loader_.get();
+ if (external_document_load_) {
+ // The external proxy isn't available, so save the response and record
+ // document load notifications for later replay.
+ external_document_response_ = response;
+ external_document_loader_.reset(new ExternalDocumentLoader());
+ document_loader_ = external_document_loader_.get();
return true;
}
@@ -770,6 +767,7 @@
DCHECK(pending_host_id);
DataFromWebURLResponse(
+ host_impl,
pp_instance(),
response,
base::Bind(&PepperPluginInstanceImpl::DidDataFromWebURLResponse,
@@ -809,9 +807,9 @@
!(input_event_mask_ & event_class))
return false;
- ::ppapi::InputEventData event;
+ ppapi::InputEventData event;
event.event_type = type;
- event.event_time_stamp = ::ppapi::TimeTicksToPPTimeTicks(
+ event.event_time_stamp = ppapi::TimeTicksToPPTimeTicks(
base::TimeTicks::Now());
// Convert UTF16 text to UTF8 with offset conversion.
@@ -862,7 +860,7 @@
else
handled = true; // Unfiltered events are assumed to be handled.
scoped_refptr<PPB_InputEvent_Shared> event_resource(
- new PPB_InputEvent_Shared(::ppapi::OBJECT_IS_IMPL, pp_instance(), event));
+ new PPB_InputEvent_Shared(ppapi::OBJECT_IS_IMPL, pp_instance(), event));
handled |= PP_ToBool(plugin_input_event_interface_->HandleInputEvent(
pp_instance(), event_resource->pp_resource()));
return handled;
@@ -963,7 +961,7 @@
if ((filtered_input_event_mask_ & event_class) ||
(input_event_mask_ & event_class)) {
// Actually send the event.
- std::vector< ::ppapi::InputEventData > events;
+ std::vector< ppapi::InputEventData > events;
CreateInputEventData(event, &events);
// Allow the user gesture to be pending after the plugin handles the
@@ -971,7 +969,7 @@
// gesture after processing has finished here.
if (WebUserGestureIndicator::isProcessingUserGesture()) {
pending_user_gesture_ =
- ::ppapi::EventTimeToPPTimeTicks(event.timeStampSeconds);
+ ppapi::EventTimeToPPTimeTicks(event.timeStampSeconds);
pending_user_gesture_token_ =
WebUserGestureIndicator::currentUserGestureToken();
pending_user_gesture_token_.setOutOfProcess();
@@ -984,7 +982,7 @@
else
rv = true; // Unfiltered events are assumed to be handled.
scoped_refptr<PPB_InputEvent_Shared> event_resource(
- new PPB_InputEvent_Shared(::ppapi::OBJECT_IS_IMPL,
+ new PPB_InputEvent_Shared(ppapi::OBJECT_IS_IMPL,
pp_instance(), events[i]));
rv |= PP_ToBool(plugin_input_event_interface_->HandleInputEvent(
@@ -1327,7 +1325,7 @@
bool PepperPluginInstanceImpl::LoadPrintInterface() {
// Only check for the interface if the plugin has dev permission.
- if (!module_->permissions().HasPermission(::ppapi::PERMISSION_DEV))
+ if (!module_->permissions().HasPermission(ppapi::PERMISSION_DEV))
return false;
if (!plugin_print_interface_) {
plugin_print_interface_ = static_cast<const PPP_Printing_Dev*>(
@@ -1338,7 +1336,7 @@
bool PepperPluginInstanceImpl::LoadPrivateInterface() {
// Only check for the interface if the plugin has private permission.
- if (!module_->permissions().HasPermission(::ppapi::PERMISSION_PRIVATE))
+ if (!module_->permissions().HasPermission(ppapi::PERMISSION_PRIVATE))
return false;
if (!plugin_private_interface_) {
plugin_private_interface_ = static_cast<const PPP_Instance_Private*>(
@@ -1447,7 +1445,7 @@
last_sent_view_data_ = view_data_;
ScopedPPResource resource(
ScopedPPResource::PassRef(),
- (new PPB_View_Shared(::ppapi::OBJECT_IS_IMPL,
+ (new PPB_View_Shared(ppapi::OBJECT_IS_IMPL,
pp_instance(), view_data_))->GetReference());
instance_interface_->DidChangeView(pp_instance(), resource,
@@ -1670,7 +1668,7 @@
if (is_mouselock_pending && !IsMouseLocked()) {
if (!IsProcessingUserGesture() &&
!module_->permissions().HasPermission(
- ::ppapi::PERMISSION_BYPASS_USER_GESTURE)) {
+ ppapi::PERMISSION_BYPASS_USER_GESTURE)) {
lock_mouse_callback_->Run(PP_ERROR_NO_USER_GESTURE);
} else {
// Open a user gesture here so the Webkit user gesture checks will succeed
@@ -1703,7 +1701,7 @@
bool PepperPluginInstanceImpl::PrintPDFOutput(PP_Resource print_output,
WebKit::WebCanvas* canvas) {
#if defined(ENABLE_PRINTING)
- ::ppapi::thunk::EnterResourceNoLock<PPB_Buffer_API> enter(print_output, true);
+ ppapi::thunk::EnterResourceNoLock<PPB_Buffer_API> enter(print_output, true);
if (enter.failed())
return false;
@@ -1850,8 +1848,7 @@
}
bool PepperPluginInstanceImpl::IsProcessingUserGesture() {
- PP_TimeTicks now =
- ::ppapi::TimeTicksToPPTimeTicks(base::TimeTicks::Now());
+ PP_TimeTicks now = ppapi::TimeTicksToPPTimeTicks(base::TimeTicks::Now());
// Give a lot of slack so tests won't be flaky.
const PP_TimeTicks kUserGestureDurationInSeconds = 10.0;
return pending_user_gesture_token_.hasGestures() &&
@@ -1973,7 +1970,7 @@
TRACE_EVENT0("ppapi", "PepperPluginInstanceImpl::BindGraphics");
// The Graphics3D instance can't be destroyed until we call
// UpdateLayer().
- scoped_refptr< ::ppapi::Resource> old_graphics = bound_graphics_3d_.get();
+ scoped_refptr<ppapi::Resource> old_graphics = bound_graphics_3d_.get();
if (bound_graphics_3d_.get()) {
bound_graphics_3d_->BindToInstance(false);
bound_graphics_3d_ = NULL;
@@ -2242,25 +2239,25 @@
return PP_TRUE;
}
-::ppapi::Resource* PepperPluginInstanceImpl::GetSingletonResource(
+ppapi::Resource* PepperPluginInstanceImpl::GetSingletonResource(
PP_Instance instance,
- ::ppapi::SingletonResourceID id) {
+ ppapi::SingletonResourceID id) {
// Flash APIs and some others aren't implemented in-process.
switch (id) {
- case ::ppapi::BROKER_SINGLETON_ID:
- case ::ppapi::BROWSER_FONT_SINGLETON_ID:
- case ::ppapi::CRX_FILESYSTEM_SINGLETON_ID:
- case ::ppapi::EXTENSIONS_COMMON_SINGLETON_ID:
- case ::ppapi::FLASH_CLIPBOARD_SINGLETON_ID:
- case ::ppapi::FLASH_FILE_SINGLETON_ID:
- case ::ppapi::FLASH_FULLSCREEN_SINGLETON_ID:
- case ::ppapi::FLASH_SINGLETON_ID:
- case ::ppapi::NETWORK_PROXY_SINGLETON_ID:
- case ::ppapi::PDF_SINGLETON_ID:
- case ::ppapi::TRUETYPE_FONT_SINGLETON_ID:
+ case ppapi::BROKER_SINGLETON_ID:
+ case ppapi::BROWSER_FONT_SINGLETON_ID:
+ case ppapi::CRX_FILESYSTEM_SINGLETON_ID:
+ case ppapi::EXTENSIONS_COMMON_SINGLETON_ID:
+ case ppapi::FLASH_CLIPBOARD_SINGLETON_ID:
+ case ppapi::FLASH_FILE_SINGLETON_ID:
+ case ppapi::FLASH_FULLSCREEN_SINGLETON_ID:
+ case ppapi::FLASH_SINGLETON_ID:
+ case ppapi::NETWORK_PROXY_SINGLETON_ID:
+ case ppapi::PDF_SINGLETON_ID:
+ case ppapi::TRUETYPE_FONT_SINGLETON_ID:
NOTIMPLEMENTED();
return NULL;
- case ::ppapi::GAMEPAD_SINGLETON_ID:
+ case ppapi::GAMEPAD_SINGLETON_ID:
return gamepad_impl_.get();
}
@@ -2450,7 +2447,7 @@
WebElement plugin_element = container()->element();
GURL document_url = plugin_element.document().baseURL();
- return ::ppapi::PPB_URLUtil_Shared::GenerateURLReturn(
+ return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(
document_url.Resolve(relative_string->value()),
components);
}
@@ -2490,15 +2487,15 @@
PP_Instance instance,
PP_URLComponents_Dev* components) {
WebKit::WebDocument document = container()->element().document();
- return ::ppapi::PPB_URLUtil_Shared::GenerateURLReturn(document.url(),
- components);
+ return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(document.url(),
+ components);
}
PP_Var PepperPluginInstanceImpl::GetPluginInstanceURL(
PP_Instance instance,
PP_URLComponents_Dev* components) {
- return ::ppapi::PPB_URLUtil_Shared::GenerateURLReturn(plugin_url_,
- components);
+ return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(plugin_url_,
+ components);
}
PP_ExternalPluginResult PepperPluginInstanceImpl::ResetAsProxied(
@@ -2557,16 +2554,16 @@
view_change_weak_ptr_factory_.InvalidateWeakPtrs();
SendDidChangeView();
- DCHECK(nacl_document_load_);
- nacl_document_load_ = false;
- if (!nacl_document_response_.isNull()) {
+ DCHECK(external_document_load_);
+ external_document_load_ = false;
+ if (!external_document_response_.isNull()) {
document_loader_ = NULL;
// Pass the response to the new proxy.
- HandleDocumentLoad(nacl_document_response_);
- nacl_document_response_ = WebKit::WebURLResponse();
+ HandleDocumentLoad(external_document_response_);
+ external_document_response_ = WebKit::WebURLResponse();
// Replay any document load events we've received to the real loader.
- nacl_document_loader_->ReplayReceivedData(document_loader_);
- nacl_document_loader_.reset(NULL);
+ external_document_loader_->ReplayReceivedData(document_loader_);
+ external_document_loader_.reset(NULL);
}
return PP_EXTERNAL_PLUGIN_OK;
@@ -2598,7 +2595,7 @@
return container_;
}
-::ppapi::VarTracker* PepperPluginInstanceImpl::GetVarTracker() {
+ppapi::VarTracker* PepperPluginInstanceImpl::GetVarTracker() {
return HostGlobals::Get()->GetVarTracker();
}
@@ -2610,13 +2607,6 @@
return module_->path();
}
-PP_Resource PepperPluginInstanceImpl::CreateExternalFileReference(
- const base::FilePath& external_file_path) {
- PPB_FileRef_Impl* ref = PPB_FileRef_Impl::CreateExternal(
- pp_instance(), external_file_path, "");
- return ref->GetReference();
-}
-
PP_Resource PepperPluginInstanceImpl::CreateImage(gfx::ImageSkia* source_image,
float scale) {
ui::ScaleFactor scale_factor = ui::GetScaleFactorFromScale(scale);
@@ -2651,7 +2641,7 @@
PP_ExternalPluginResult PepperPluginInstanceImpl::SwitchToOutOfProcessProxy(
const base::FilePath& file_path,
- ::ppapi::PpapiPermissions permissions,
+ ppapi::PpapiPermissions permissions,
const IPC::ChannelHandle& channel_handle,
base::ProcessId plugin_pid,
int plugin_child_id) {
@@ -2739,7 +2729,7 @@
}
int32_t PepperPluginInstanceImpl::Navigate(
- const ::ppapi::URLRequestInfoData& request,
+ const ppapi::URLRequestInfoData& request,
const char* target,
bool from_user_action) {
if (!container_)
@@ -2750,11 +2740,15 @@
if (!frame)
return PP_ERROR_FAILED;
- ::ppapi::URLRequestInfoData completed_request = request;
+ ppapi::URLRequestInfoData completed_request = request;
WebURLRequest web_request;
- if (!CreateWebURLRequest(&completed_request, frame, &web_request))
+ if (!CreateWebURLRequest(pp_instance_,
+ &completed_request,
+ frame,
+ &web_request)) {
return PP_ERROR_FAILED;
+ }
web_request.setFirstPartyForCookies(document.firstPartyForCookies());
web_request.setHasUserGesture(from_user_action);
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.h b/content/renderer/pepper/pepper_plugin_instance_impl.h
index ad63881..930c55a 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.h
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -114,7 +114,7 @@
: public base::RefCounted<PepperPluginInstanceImpl>,
public base::SupportsWeakPtr<PepperPluginInstanceImpl>,
public NON_EXPORTED_BASE(PepperPluginInstance),
- public ::ppapi::PPB_Instance_Shared {
+ public ppapi::PPB_Instance_Shared {
public:
// Create and return a PepperPluginInstanceImpl object which supports the most
// recent version of PPP_Instance possible by querying the given
@@ -135,7 +135,7 @@
// nonzero.
PP_Instance pp_instance() const { return pp_instance_; }
- ::ppapi::thunk::ResourceCreationAPI& resource_creation() {
+ ppapi::thunk::ResourceCreationAPI& resource_creation() {
return *resource_creation_.get();
}
@@ -170,7 +170,7 @@
// PPB_Instance and PPB_Instance_Private implementation.
bool full_frame() const { return full_frame_; }
- const ::ppapi::ViewData& view_data() const { return view_data_; }
+ const ppapi::ViewData& view_data() const { return view_data_; }
// PPP_Instance and PPP_Instance_Private.
bool Initialize(const std::vector<std::string>& arg_names,
@@ -320,13 +320,13 @@
// Simulates an input event to the plugin by passing it down to WebKit,
// which sends it back up to the plugin as if it came from the user.
- void SimulateInputEvent(const ::ppapi::InputEventData& input_event);
+ void SimulateInputEvent(const ppapi::InputEventData& input_event);
// Simulates an IME event at the level of RenderView which sends it back up to
// the plugin as if it came from the user.
- bool SimulateIMEEvent(const ::ppapi::InputEventData& input_event);
+ bool SimulateIMEEvent(const ppapi::InputEventData& input_event);
void SimulateImeSetCompositionEvent(
- const ::ppapi::InputEventData& input_event);
+ const ppapi::InputEventData& input_event);
// The document loader is valid when the plugin is "full-frame" and in this
// case is non-NULL as long as the corresponding loader resource is alive.
@@ -344,16 +344,14 @@
// PluginInstance implementation
virtual RenderView* GetRenderView() OVERRIDE;
virtual WebKit::WebPluginContainer* GetContainer() OVERRIDE;
- virtual ::ppapi::VarTracker* GetVarTracker() OVERRIDE;
+ virtual ppapi::VarTracker* GetVarTracker() OVERRIDE;
virtual const GURL& GetPluginURL() OVERRIDE;
virtual base::FilePath GetModulePath() OVERRIDE;
- virtual PP_Resource CreateExternalFileReference(
- const base::FilePath& external_file_path) OVERRIDE;
virtual PP_Resource CreateImage(gfx::ImageSkia* source_image,
float scale) OVERRIDE;
virtual PP_ExternalPluginResult SwitchToOutOfProcessProxy(
const base::FilePath& file_path,
- ::ppapi::PpapiPermissions permissions,
+ ppapi::PpapiPermissions permissions,
const IPC::ChannelHandle& channel_handle,
base::ProcessId plugin_pid,
int plugin_child_id) OVERRIDE;
@@ -361,7 +359,7 @@
virtual bool IsFullPagePlugin() OVERRIDE;
virtual void FlashSetFullscreen(bool fullscreen, bool delay_report) OVERRIDE;
virtual bool IsRectTopmost(const gfx::Rect& rect) OVERRIDE;
- virtual int32_t Navigate(const ::ppapi::URLRequestInfoData& request,
+ virtual int32_t Navigate(const ppapi::URLRequestInfoData& request,
const char* target,
bool from_user_action) OVERRIDE;
@@ -369,7 +367,7 @@
virtual PP_Bool BindGraphics(PP_Instance instance,
PP_Resource device) OVERRIDE;
virtual PP_Bool IsFullFrame(PP_Instance instance) OVERRIDE;
- virtual const ::ppapi::ViewData* GetViewData(PP_Instance instance) OVERRIDE;
+ virtual const ppapi::ViewData* GetViewData(PP_Instance instance) OVERRIDE;
virtual PP_Bool FlashIsFullscreen(PP_Instance instance) OVERRIDE;
virtual PP_Var GetWindowObject(PP_Instance instance) OVERRIDE;
virtual PP_Var GetOwnerElementObject(PP_Instance instance) OVERRIDE;
@@ -391,8 +389,8 @@
PP_Bool fullscreen) OVERRIDE;
virtual PP_Bool GetScreenSize(PP_Instance instance, PP_Size* size)
OVERRIDE;
- virtual ::ppapi::Resource* GetSingletonResource(PP_Instance instance,
- ::ppapi::SingletonResourceID id) OVERRIDE;
+ virtual ppapi::Resource* GetSingletonResource(PP_Instance instance,
+ ppapi::SingletonResourceID id) OVERRIDE;
virtual int32_t RequestInputEvents(PP_Instance instance,
uint32_t event_classes) OVERRIDE;
virtual int32_t RequestFilteringInputEvents(PP_Instance instance,
@@ -410,7 +408,7 @@
const PP_Point* hot_spot) OVERRIDE;
virtual int32_t LockMouse(
PP_Instance instance,
- scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
+ scoped_refptr<ppapi::TrackedCallback> callback) OVERRIDE;
virtual void UnlockMouse(PP_Instance instance) OVERRIDE;
virtual void SetTextInputType(PP_Instance instance,
PP_TextInput_Type type) OVERRIDE;
@@ -504,11 +502,11 @@
virtual ~PepperPluginInstanceImpl();
// Class to record document load notifications and play them back once the
- // real document loader becomes available. Used only by NaCl instances.
- class NaClDocumentLoader : public WebKit::WebURLLoaderClient {
+ // real document loader becomes available. Used only by external instances.
+ class ExternalDocumentLoader : public WebKit::WebURLLoaderClient {
public:
- NaClDocumentLoader();
- virtual ~NaClDocumentLoader();
+ ExternalDocumentLoader();
+ virtual ~ExternalDocumentLoader();
void ReplayReceivedData(WebURLLoaderClient* document_loader);
@@ -530,12 +528,12 @@
// Implements PPB_Gamepad_API. This is just to avoid having an excessive
// number of interfaces implemented by PepperPluginInstanceImpl.
- class GamepadImpl : public ::ppapi::thunk::PPB_Gamepad_API,
- public ::ppapi::Resource {
+ class GamepadImpl : public ppapi::thunk::PPB_Gamepad_API,
+ public ppapi::Resource {
public:
GamepadImpl();
// Resource implementation.
- virtual ::ppapi::thunk::PPB_Gamepad_API* AsPPB_Gamepad_API() OVERRIDE;
+ virtual ppapi::thunk::PPB_Gamepad_API* AsPPB_Gamepad_API() OVERRIDE;
virtual void Sample(PP_Instance instance,
PP_GamepadsSampleData* data) OVERRIDE;
private:
@@ -548,7 +546,7 @@
// for member initialization.
PepperPluginInstanceImpl(RenderViewImpl* render_view,
PluginModule* module,
- ::ppapi::PPP_Instance_Combined* instance_interface,
+ ppapi::PPP_Instance_Combined* instance_interface,
WebKit::WebPluginContainer* container,
const GURL& plugin_url);
@@ -644,12 +642,12 @@
RenderViewImpl* render_view_;
scoped_refptr<PluginModule> module_;
- scoped_ptr< ::ppapi::PPP_Instance_Combined> instance_interface_;
+ scoped_ptr<ppapi::PPP_Instance_Combined> instance_interface_;
// If this is the NaCl plugin, we create a new module when we switch to the
// IPC-based PPAPI proxy. Store the original module and instance interface
// so we can shut down properly.
scoped_refptr<PluginModule> original_module_;
- scoped_ptr< ::ppapi::PPP_Instance_Combined> original_instance_interface_;
+ scoped_ptr<ppapi::PPP_Instance_Combined> original_instance_interface_;
PP_Instance pp_instance_;
@@ -667,10 +665,10 @@
bool full_frame_;
// Stores the current state of the plugin view.
- ::ppapi::ViewData view_data_;
+ ppapi::ViewData view_data_;
// The last state sent to the plugin. It is only valid after
// |sent_initial_did_change_view_| is set to true.
- ::ppapi::ViewData last_sent_view_data_;
+ ppapi::ViewData last_sent_view_data_;
// Indicates if we've ever sent a didChangeView to the plugin. This ensures we
// always send an initial notification, even if the position and clip are the
@@ -699,7 +697,7 @@
int find_identifier_;
// Helper object that creates resources.
- scoped_ptr< ::ppapi::thunk::ResourceCreationAPI> resource_creation_;
+ scoped_ptr<ppapi::thunk::ResourceCreationAPI> resource_creation_;
// The plugin-provided interfaces.
// When adding PPP interfaces, make sure to reset them in ResetAsProxied.
@@ -742,7 +740,7 @@
// An array of page ranges.
std::vector<PP_PrintPageNumberRange_Dev> ranges_;
- scoped_refptr< ::ppapi::Resource> gamepad_impl_;
+ scoped_refptr<ppapi::Resource> gamepad_impl_;
// The plugin print interface.
const PPP_Printing_Dev* plugin_print_interface_;
@@ -816,7 +814,7 @@
size_t selection_caret_;
size_t selection_anchor_;
- scoped_refptr< ::ppapi::TrackedCallback> lock_mouse_callback_;
+ scoped_refptr<ppapi::TrackedCallback> lock_mouse_callback_;
// Track pending user gestures so out-of-process plugins can respond to
// a user gesture after it has been processed.
@@ -830,10 +828,10 @@
// Non-owning pointer to the document loader, if any.
WebKit::WebURLLoaderClient* document_loader_;
- // State for deferring document loads. Used only by NaCl instances.
- WebKit::WebURLResponse nacl_document_response_;
- scoped_ptr<NaClDocumentLoader> nacl_document_loader_;
- bool nacl_document_load_;
+ // State for deferring document loads. Used only by external instances.
+ WebKit::WebURLResponse external_document_response_;
+ scoped_ptr<ExternalDocumentLoader> external_document_loader_;
+ bool external_document_load_;
// The ContentDecryptorDelegate forwards PPP_ContentDecryptor_Private
// calls and handles PPB_ContentDecryptor_Private calls.
diff --git a/content/renderer/pepper/pepper_url_loader_host.cc b/content/renderer/pepper/pepper_url_loader_host.cc
index 8343f19..60bb467 100644
--- a/content/renderer/pepper/pepper_url_loader_host.cc
+++ b/content/renderer/pepper/pepper_url_loader_host.cc
@@ -250,8 +250,12 @@
if (!frame)
return PP_ERROR_FAILED;
WebURLRequest web_request;
- if (!CreateWebURLRequest(&filled_in_request_data, frame, &web_request))
+ if (!CreateWebURLRequest(pp_instance(),
+ &filled_in_request_data,
+ frame,
+ &web_request)) {
return PP_ERROR_FAILED;
+ }
web_request.setRequestorProcessID(renderer_ppapi_host_->GetPluginPID());
WebURLLoaderOptions options;
@@ -389,6 +393,7 @@
pending_response_ = true;
DataFromWebURLResponse(
+ renderer_ppapi_host_,
pp_instance(),
response,
base::Bind(&PepperURLLoaderHost::DidDataFromWebURLResponse,
diff --git a/content/renderer/pepper/pepper_url_request_unittest.cc b/content/renderer/pepper/pepper_url_request_unittest.cc
index 20e7f92..05ca764 100644
--- a/content/renderer/pepper/pepper_url_request_unittest.cc
+++ b/content/renderer/pepper/pepper_url_request_unittest.cc
@@ -64,7 +64,7 @@
test_globals_.GetResourceTracker()->DidCreateInstance(pp_instance_);
// This resource doesn't do IPC, so a null connection is fine.
- info_ = new URLRequestInfoResource(::ppapi::proxy::Connection(),
+ info_ = new URLRequestInfoResource(ppapi::proxy::Connection(),
pp_instance_,
URLRequestInfoData());
}
@@ -77,7 +77,7 @@
bool GetDownloadToFile() {
WebURLRequest web_request;
URLRequestInfoData data = info_->GetData();
- if (!CreateWebURLRequest(&data, GetMainFrame(), &web_request))
+ if (!CreateWebURLRequest(pp_instance_, &data, GetMainFrame(), &web_request))
return false;
return web_request.downloadToFile();
}
@@ -85,7 +85,7 @@
WebCString GetURL() {
WebURLRequest web_request;
URLRequestInfoData data = info_->GetData();
- if (!CreateWebURLRequest(&data, GetMainFrame(), &web_request))
+ if (!CreateWebURLRequest(pp_instance_, &data, GetMainFrame(), &web_request))
return WebCString();
return web_request.url().spec();
}
@@ -93,7 +93,7 @@
WebString GetMethod() {
WebURLRequest web_request;
URLRequestInfoData data = info_->GetData();
- if (!CreateWebURLRequest(&data, GetMainFrame(), &web_request))
+ if (!CreateWebURLRequest(pp_instance_, &data, GetMainFrame(), &web_request))
return WebString();
return web_request.httpMethod();
}
@@ -101,7 +101,7 @@
WebString GetHeaderValue(const char* field) {
WebURLRequest web_request;
URLRequestInfoData data = info_->GetData();
- if (!CreateWebURLRequest(&data, GetMainFrame(), &web_request))
+ if (!CreateWebURLRequest(pp_instance_, &data, GetMainFrame(), &web_request))
return WebString();
return web_request.httpHeaderField(WebString::fromUTF8(field));
}
@@ -116,14 +116,14 @@
PP_Instance pp_instance_;
// Needs to be alive for resource tracking to work.
- ::ppapi::TestGlobals test_globals_;
+ ppapi::TestGlobals test_globals_;
scoped_refptr<URLRequestInfoResource> info_;
};
TEST_F(URLRequestInfoTest, GetInterface) {
const PPB_URLRequestInfo* request_info =
- ::ppapi::thunk::GetPPB_URLRequestInfo_1_0_Thunk();
+ ppapi::thunk::GetPPB_URLRequestInfo_1_0_Thunk();
EXPECT_TRUE(request_info);
EXPECT_TRUE(request_info->Create);
EXPECT_TRUE(request_info->IsURLRequestInfo);
diff --git a/content/renderer/pepper/pepper_video_capture_host.cc b/content/renderer/pepper/pepper_video_capture_host.cc
index 191f430..5f90099 100644
--- a/content/renderer/pepper/pepper_video_capture_host.cc
+++ b/content/renderer/pepper/pepper_video_capture_host.cc
@@ -176,7 +176,7 @@
// for sending below.
std::vector<HostResource> buffer_host_resources;
buffers_.reserve(buffer_count_hint_);
- ::ppapi::ResourceTracker* tracker =
+ ppapi::ResourceTracker* tracker =
HostGlobals::Get()->GetResourceTracker();
ppapi::proxy::HostDispatcher* dispatcher =
ppapi::proxy::HostDispatcher::GetForInstance(pp_instance());
@@ -330,7 +330,7 @@
}
void PepperVideoCaptureHost::ReleaseBuffers() {
- ::ppapi::ResourceTracker* tracker = HostGlobals::Get()->GetResourceTracker();
+ ppapi::ResourceTracker* tracker = HostGlobals::Get()->GetResourceTracker();
for (size_t i = 0; i < buffers_.size(); ++i) {
buffers_[i].buffer->Unmap();
tracker->ReleaseResource(buffers_[i].buffer->pp_resource());
diff --git a/content/renderer/pepper/pepper_webplugin_impl.cc b/content/renderer/pepper/pepper_webplugin_impl.cc
index e86c191..acbe838 100644
--- a/content/renderer/pepper/pepper_webplugin_impl.cc
+++ b/content/renderer/pepper/pepper_webplugin_impl.cc
@@ -120,7 +120,7 @@
container_->clearScriptObjects();
if (instance_.get()) {
- ::ppapi::PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(instance_object_);
+ ppapi::PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(instance_object_);
instance_object_ = PP_MakeUndefined();
instance_->Delete();
instance_ = NULL;
diff --git a/content/renderer/pepper/plugin_module.cc b/content/renderer/pepper/plugin_module.cc
index 6ccad4d..7a06929 100644
--- a/content/renderer/pepper/plugin_module.cc
+++ b/content/renderer/pepper/plugin_module.cc
@@ -138,7 +138,6 @@
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_graphics_2d_api.h"
#include "ppapi/thunk/thunk.h"
-#include "webkit/plugins/plugin_switches.h"
using ppapi::InputEventData;
using ppapi::PpapiGlobals;
@@ -306,7 +305,7 @@
// TODO(brettw) put these in a hash map for better performance.
#define UNPROXIED_IFACE(api_name, iface_str, iface_struct) \
if (strcmp(name, iface_str) == 0) \
- return ::ppapi::thunk::Get##iface_struct##_Thunk();
+ return ppapi::thunk::Get##iface_struct##_Thunk();
#define PROXIED_IFACE(api_name, iface_str, iface_struct) \
UNPROXIED_IFACE(api_name, iface_str, iface_struct)
@@ -403,8 +402,8 @@
PluginModule::PluginModule(const std::string& name,
const base::FilePath& path,
- const ::ppapi::PpapiPermissions& perms)
- : callback_tracker_(new ::ppapi::CallbackTracker),
+ const ppapi::PpapiPermissions& perms)
+ : callback_tracker_(new ppapi::CallbackTracker),
is_in_destructor_(false),
is_crashed_(false),
broker_(NULL),
@@ -590,7 +589,7 @@
instances_.erase(instance);
}
-scoped_refptr< ::ppapi::CallbackTracker> PluginModule::GetCallbackTracker() {
+scoped_refptr<ppapi::CallbackTracker> PluginModule::GetCallbackTracker() {
return callback_tracker_;
}
diff --git a/content/renderer/pepper/plugin_module.h b/content/renderer/pepper/plugin_module.h
index 835e387..daadf3c 100644
--- a/content/renderer/pepper/plugin_module.h
+++ b/content/renderer/pepper/plugin_module.h
@@ -72,7 +72,7 @@
// tracks which modules are alive.
PluginModule(const std::string& name,
const base::FilePath& path,
- const ::ppapi::PpapiPermissions& perms);
+ const ppapi::PpapiPermissions& perms);
// Sets the given class as being associated with this module. It will be
// deleted when the module is destroyed. You can only set it once, subsequent
@@ -136,7 +136,7 @@
const std::string& name() const { return name_; }
const base::FilePath& path() const { return path_; }
- const ::ppapi::PpapiPermissions& permissions() const { return permissions_; }
+ const ppapi::PpapiPermissions& permissions() const { return permissions_; }
PepperPluginInstanceImpl* CreateInstance(
RenderViewImpl* render_view,
@@ -161,7 +161,7 @@
void InstanceCreated(PepperPluginInstanceImpl* instance);
void InstanceDeleted(PepperPluginInstanceImpl* instance);
- scoped_refptr< ::ppapi::CallbackTracker> GetCallbackTracker();
+ scoped_refptr<ppapi::CallbackTracker> GetCallbackTracker();
// Called when running out of process and the plugin crashed. This will
// release relevant resources and update all affected instances.
@@ -228,7 +228,7 @@
// Tracker for completion callbacks, used mainly to ensure that all callbacks
// are properly aborted on module shutdown.
- scoped_refptr< ::ppapi::CallbackTracker> callback_tracker_;
+ scoped_refptr<ppapi::CallbackTracker> callback_tracker_;
PP_Module pp_module_;
@@ -263,7 +263,7 @@
const std::string name_;
const base::FilePath path_;
- ::ppapi::PpapiPermissions permissions_;
+ ppapi::PpapiPermissions permissions_;
// Non-owning pointers to all instances associated with this module. When
// there are no more instances, this object should be deleted.
diff --git a/content/renderer/pepper/plugin_object.cc b/content/renderer/pepper/plugin_object.cc
index 62346f5..7746846 100644
--- a/content/renderer/pepper/plugin_object.cc
+++ b/content/renderer/pepper/plugin_object.cc
@@ -214,7 +214,7 @@
// Release the PP_Var that the plugin allocated. On success, they will all
// be converted to NPVariants, and on failure, we want them to just go away.
- ::ppapi::VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker();
+ ppapi::VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker();
for (uint32_t i = 0; i < property_count; ++i)
var_tracker->ReleaseVar(properties[i]);
free(properties);
diff --git a/content/renderer/pepper/ppapi_unittest.cc b/content/renderer/pepper/ppapi_unittest.cc
index 28112aa..f46eb6b 100644
--- a/content/renderer/pepper/ppapi_unittest.cc
+++ b/content/renderer/pepper/ppapi_unittest.cc
@@ -79,8 +79,8 @@
// Initialize the mock module.
module_ = new PluginModule("Mock plugin", base::FilePath(),
- ::ppapi::PpapiPermissions());
- ::ppapi::PpapiGlobals::Get()->ResetMainThreadMessageLoopForTesting();
+ ppapi::PpapiPermissions());
+ ppapi::PpapiGlobals::Get()->ResetMainThreadMessageLoopForTesting();
PepperPluginInfo::EntryPoints entry_points;
entry_points.get_interface = &MockGetInterface;
entry_points.initialize_module = &MockInitializeModule;
diff --git a/content/renderer/pepper/ppb_audio_impl.cc b/content/renderer/pepper/ppb_audio_impl.cc
index 3f1baca..45a9254 100644
--- a/content/renderer/pepper/ppb_audio_impl.cc
+++ b/content/renderer/pepper/ppb_audio_impl.cc
@@ -29,7 +29,7 @@
// PPB_Audio_Impl --------------------------------------------------------------
PPB_Audio_Impl::PPB_Audio_Impl(PP_Instance instance)
- : Resource(::ppapi::OBJECT_IS_IMPL, instance),
+ : Resource(ppapi::OBJECT_IS_IMPL, instance),
audio_(NULL),
sample_frame_count_(0) {
}
diff --git a/content/renderer/pepper/ppb_audio_impl.h b/content/renderer/pepper/ppb_audio_impl.h
index 62a4dd2..d5b9b45 100644
--- a/content/renderer/pepper/ppb_audio_impl.h
+++ b/content/renderer/pepper/ppb_audio_impl.h
@@ -23,8 +23,8 @@
// Some of the backend functionality of this class is implemented by the
// PPB_Audio_Shared so it can be shared with the proxy.
-class PPB_Audio_Impl : public ::ppapi::Resource,
- public ::ppapi::PPB_Audio_Shared,
+class PPB_Audio_Impl : public ppapi::Resource,
+ public ppapi::PPB_Audio_Shared,
public AudioHelper {
public:
// Trusted initialization. You must call Init after this.
@@ -46,7 +46,7 @@
void* user_data);
// Resource overrides.
- virtual ::ppapi::thunk::PPB_Audio_API* AsPPB_Audio_API() OVERRIDE;
+ virtual ppapi::thunk::PPB_Audio_API* AsPPB_Audio_API() OVERRIDE;
// PPB_Audio_API implementation.
virtual PP_Resource GetCurrentConfig() OVERRIDE;
@@ -54,7 +54,7 @@
virtual PP_Bool StopPlayback() OVERRIDE;
virtual int32_t Open(
PP_Resource config_id,
- scoped_refptr< ::ppapi::TrackedCallback> create_callback) OVERRIDE;
+ scoped_refptr<ppapi::TrackedCallback> create_callback) OVERRIDE;
virtual int32_t GetSyncSocket(int* sync_socket) OVERRIDE;
virtual int32_t GetSharedMemory(int* shm_handle, uint32_t* shm_size) OVERRIDE;
@@ -67,7 +67,7 @@
base::SyncSocket::Handle socket) OVERRIDE;
// AudioConfig used for creating this Audio object. We own a ref.
- ::ppapi::ScopedPPResource config_;
+ ppapi::ScopedPPResource config_;
// PluginDelegate audio object that we delegate audio IPC through. We don't
// own this pointer but are responsible for calling Shutdown on it.
diff --git a/content/renderer/pepper/ppb_broker_impl.cc b/content/renderer/pepper/ppb_broker_impl.cc
index 3eab94e..f68d257 100644
--- a/content/renderer/pepper/ppb_broker_impl.cc
+++ b/content/renderer/pepper/ppb_broker_impl.cc
@@ -28,7 +28,7 @@
// PPB_Broker_Impl ------------------------------------------------------
PPB_Broker_Impl::PPB_Broker_Impl(PP_Instance instance)
- : Resource(::ppapi::OBJECT_IS_IMPL, instance),
+ : Resource(ppapi::OBJECT_IS_IMPL, instance),
broker_(NULL),
connect_callback_(),
pipe_handle_(PlatformFileToInt(base::kInvalidPlatformFileValue)),
diff --git a/content/renderer/pepper/ppb_broker_impl.h b/content/renderer/pepper/ppb_broker_impl.h
index 6cd3829..0e77218 100644
--- a/content/renderer/pepper/ppb_broker_impl.h
+++ b/content/renderer/pepper/ppb_broker_impl.h
@@ -25,19 +25,19 @@
namespace content {
class PepperBroker;
-class PPB_Broker_Impl : public ::ppapi::Resource,
- public ::ppapi::thunk::PPB_Broker_API,
+class PPB_Broker_Impl : public ppapi::Resource,
+ public ppapi::thunk::PPB_Broker_API,
public IPC::Listener,
public base::SupportsWeakPtr<PPB_Broker_Impl> {
public:
explicit PPB_Broker_Impl(PP_Instance instance);
// Resource override.
- virtual ::ppapi::thunk::PPB_Broker_API* AsPPB_Broker_API() OVERRIDE;
+ virtual ppapi::thunk::PPB_Broker_API* AsPPB_Broker_API() OVERRIDE;
// PPB_BrokerTrusted implementation.
virtual int32_t Connect(
- scoped_refptr< ::ppapi::TrackedCallback> connect_callback) OVERRIDE;
+ scoped_refptr<ppapi::TrackedCallback> connect_callback) OVERRIDE;
virtual int32_t GetHandle(int32_t* handle) OVERRIDE;
// Returns the URL of the document this plug-in runs in. This is necessary to
@@ -61,7 +61,7 @@
PepperBroker* broker_;
// Callback invoked from BrokerConnected.
- scoped_refptr< ::ppapi::TrackedCallback> connect_callback_;
+ scoped_refptr<ppapi::TrackedCallback> connect_callback_;
// Pipe handle for the plugin instance to use to communicate with the broker.
// Never owned by this object.
diff --git a/content/renderer/pepper/ppb_buffer_impl.cc b/content/renderer/pepper/ppb_buffer_impl.cc
index 7c6ec83..4b806b9 100644
--- a/content/renderer/pepper/ppb_buffer_impl.cc
+++ b/content/renderer/pepper/ppb_buffer_impl.cc
@@ -15,12 +15,12 @@
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_resource.h"
-using ::ppapi::thunk::PPB_Buffer_API;
+using ppapi::thunk::PPB_Buffer_API;
namespace content {
PPB_Buffer_Impl::PPB_Buffer_Impl(PP_Instance instance)
- : Resource(::ppapi::OBJECT_IS_IMPL, instance),
+ : Resource(ppapi::OBJECT_IS_IMPL, instance),
size_(0),
map_count_(0) {
}
diff --git a/content/renderer/pepper/ppb_buffer_impl.h b/content/renderer/pepper/ppb_buffer_impl.h
index ba042d6..7652622 100644
--- a/content/renderer/pepper/ppb_buffer_impl.h
+++ b/content/renderer/pepper/ppb_buffer_impl.h
@@ -14,8 +14,8 @@
namespace content {
-class PPB_Buffer_Impl : public ::ppapi::Resource,
- public ::ppapi::thunk::PPB_Buffer_API {
+class PPB_Buffer_Impl : public ppapi::Resource,
+ public ppapi::thunk::PPB_Buffer_API {
public:
static PP_Resource Create(PP_Instance instance, uint32_t size);
static scoped_refptr<PPB_Buffer_Impl> CreateResource(PP_Instance instance,
@@ -27,7 +27,7 @@
uint32_t size() const { return size_; }
// Resource overrides.
- virtual ::ppapi::thunk::PPB_Buffer_API* AsPPB_Buffer_API() OVERRIDE;
+ virtual ppapi::thunk::PPB_Buffer_API* AsPPB_Buffer_API() OVERRIDE;
// PPB_Buffer_API implementation.
virtual PP_Bool Describe(uint32_t* size_in_bytes) OVERRIDE;
@@ -55,7 +55,7 @@
// mapped state in the destructor.
class BufferAutoMapper {
public:
- explicit BufferAutoMapper(::ppapi::thunk::PPB_Buffer_API* api);
+ explicit BufferAutoMapper(ppapi::thunk::PPB_Buffer_API* api);
~BufferAutoMapper();
// Will be NULL on failure to map.
@@ -63,7 +63,7 @@
uint32_t size() { return size_; }
private:
- ::ppapi::thunk::PPB_Buffer_API* api_;
+ ppapi::thunk::PPB_Buffer_API* api_;
bool needs_unmap_;
diff --git a/content/renderer/pepper/ppb_file_ref_impl.cc b/content/renderer/pepper/ppb_file_ref_impl.cc
deleted file mode 100644
index b50cbde..0000000
--- a/content/renderer/pepper/ppb_file_ref_impl.cc
+++ /dev/null
@@ -1,555 +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 "content/renderer/pepper/ppb_file_ref_impl.h"
-
-#include "base/files/file_util_proxy.h"
-#include "base/platform_file.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/child/fileapi/file_system_dispatcher.h"
-#include "content/common/view_messages.h"
-#include "content/renderer/pepper/common.h"
-#include "content/renderer/pepper/pepper_file_system_host.h"
-#include "content/renderer/pepper/plugin_module.h"
-#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
-#include "content/renderer/render_thread_impl.h"
-#include "net/base/escape.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/c/ppb_file_io.h"
-#include "ppapi/host/ppapi_host.h"
-#include "ppapi/shared_impl/file_type_conversion.h"
-#include "ppapi/shared_impl/time_conversion.h"
-#include "ppapi/shared_impl/var.h"
-#include "ppapi/thunk/enter.h"
-#include "ppapi/thunk/ppb_file_system_api.h"
-#include "url/gurl.h"
-#include "webkit/common/fileapi/directory_entry.h"
-#include "webkit/common/fileapi/file_system_util.h"
-
-using ppapi::HostResource;
-using ppapi::PPB_FileRef_CreateInfo;
-using ppapi::PPTimeToTime;
-using ppapi::StringVar;
-using ppapi::TrackedCallback;
-using ppapi::thunk::EnterResourceNoLock;
-using ppapi::thunk::PPB_FileRef_API;
-using ppapi::thunk::PPB_FileSystem_API;
-
-namespace content {
-
-namespace {
-
-bool IsValidLocalPath(const std::string& path) {
- // The path must start with '/'
- if (path.empty() || path[0] != '/')
- return false;
-
- // The path must contain valid UTF-8 characters.
- if (!IsStringUTF8(path))
- return false;
-
-#if defined(OS_WIN)
- base::FilePath::StringType path_win(path.begin(), path.end());
- base::FilePath file_path(path_win);
-#else
- base::FilePath file_path(path);
-#endif
- if (file_path.ReferencesParent())
- return false;
-
- return true;
-}
-
-void TrimTrailingSlash(std::string* path) {
- // If this path ends with a slash, then normalize it away unless path is the
- // root path.
- if (path->size() > 1 && path->at(path->size() - 1) == '/')
- path->erase(path->size() - 1, 1);
-}
-
-std::string GetNameForExternalFilePath(const base::FilePath& in_path) {
- const base::FilePath::StringType& path = in_path.value();
- size_t pos = path.rfind(base::FilePath::kSeparators[0]);
- CHECK(pos != base::FilePath::StringType::npos);
-#if defined(OS_WIN)
- return WideToUTF8(path.substr(pos + 1));
-#elif defined(OS_POSIX)
- return path.substr(pos + 1);
-#else
-#error "Unsupported platform."
-#endif
-}
-
-std::string GetNameForVirtualFilePath(const std::string& path) {
- if (path.size() == 1 && path[0] == '/')
- return path;
-
- // There should always be a leading slash at least!
- size_t pos = path.rfind('/');
- CHECK(pos != std::string::npos);
- return path.substr(pos + 1);
-}
-
-void IgnoreCloseCallback(base::PlatformFileError error_code) {
-}
-
-void PlatformFileInfoToPPFileInfo(
- const base::PlatformFileInfo& file_info,
- PP_FileSystemType file_system_type,
- PP_FileInfo* info) {
- DCHECK(info);
- ::ppapi::PlatformFileInfoToPepperFileInfo(file_info, file_system_type, info);
-}
-
-void GetFileInfoCallback(
- scoped_refptr<base::TaskRunner> task_runner,
- base::PlatformFile file,
- linked_ptr<PP_FileInfo> info,
- scoped_refptr<TrackedCallback> callback,
- base::PlatformFileError error_code,
- const base::PlatformFileInfo& file_info) {
- base::FileUtilProxy::Close(
- task_runner.get(), file, base::Bind(&IgnoreCloseCallback));
-
- if (!TrackedCallback::IsPending(callback))
- return;
-
- int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
- if (pp_error != PP_OK) {
- callback->Run(pp_error);
- return;
- }
-
- PlatformFileInfoToPPFileInfo(
- file_info, PP_FILESYSTEMTYPE_EXTERNAL, info.get());
-
- callback->Run(PP_OK);
-}
-
-void QueryCallback(scoped_refptr<base::TaskRunner> task_runner,
- linked_ptr<PP_FileInfo> info,
- scoped_refptr<TrackedCallback> callback,
- base::PlatformFileError error_code,
- base::PassPlatformFile passed_file) {
- if (!TrackedCallback::IsPending(callback))
- return;
-
- int32_t pp_error = ::ppapi::PlatformFileErrorToPepperError(error_code);
- if (pp_error != PP_OK) {
- callback->Run(pp_error);
- return;
- }
- base::PlatformFile file = passed_file.ReleaseValue();
-
- if (!base::FileUtilProxy::GetFileInfoFromPlatformFile(
- task_runner.get(),
- file,
- base::Bind(
- &GetFileInfoCallback, task_runner, file, info, callback))) {
- base::FileUtilProxy::Close(
- task_runner.get(), file, base::Bind(&IgnoreCloseCallback));
- callback->Run(PP_ERROR_FAILED);
- }
-}
-
-void DidReadMetadata(
- scoped_refptr< ::ppapi::TrackedCallback> callback,
- linked_ptr<PP_FileInfo> info,
- PP_FileSystemType file_system_type,
- const base::PlatformFileInfo& file_info) {
- if (!TrackedCallback::IsPending(callback))
- return;
-
- PlatformFileInfoToPPFileInfo(file_info, file_system_type, info.get());
- callback->Run(PP_OK);
-}
-
-void DidReadDirectory(
- scoped_refptr< ::ppapi::TrackedCallback> callback,
- PPB_FileRef_Impl* dir_ref,
- linked_ptr<std::vector< ::ppapi::PPB_FileRef_CreateInfo> > dir_files,
- linked_ptr<std::vector<PP_FileType> > dir_file_types,
- const std::vector<fileapi::DirectoryEntry>& entries,
- bool has_more) {
- if (!TrackedCallback::IsPending(callback))
- return;
-
- // The current filesystem backend always returns false.
- DCHECK(!has_more);
-
- DCHECK(dir_ref);
- DCHECK(dir_files.get());
- DCHECK(dir_file_types.get());
-
- std::string dir_path = dir_ref->GetCreateInfo().path;
- if (dir_path.empty() || dir_path[dir_path.size() - 1] != '/')
- dir_path += '/';
-
- for (size_t i = 0; i < entries.size(); ++i) {
- const fileapi::DirectoryEntry& entry = entries[i];
- scoped_refptr<PPB_FileRef_Impl> file_ref(PPB_FileRef_Impl::CreateInternal(
- dir_ref->pp_instance(),
- dir_ref->file_system_resource(),
- dir_path + fileapi::FilePathToString(base::FilePath(entry.name))));
- dir_files->push_back(file_ref->GetCreateInfo());
- dir_file_types->push_back(
- entry.is_directory ? PP_FILETYPE_DIRECTORY : PP_FILETYPE_REGULAR);
- // Add a ref count on behalf of the plugin side.
- file_ref->GetReference();
- }
- CHECK_EQ(dir_files->size(), dir_file_types->size());
-
- callback->Run(PP_OK);
-}
-
-void DidFinishFileOperation(
- scoped_refptr< ::ppapi::TrackedCallback> callback,
- base::PlatformFileError error_code) {
- if (callback->completed())
- return;
- callback->Run(::ppapi::PlatformFileErrorToPepperError(error_code));
-}
-
-} // namespace
-
-PPB_FileRef_Impl::PPB_FileRef_Impl(const PPB_FileRef_CreateInfo& info,
- PP_Resource file_system)
- : PPB_FileRef_Shared(::ppapi::OBJECT_IS_IMPL, info),
- file_system_(file_system),
- external_file_system_path_(),
- routing_id_(MSG_ROUTING_NONE) {
- if (RenderThreadImpl::current()) { // NULL in tests.
- routing_id_ = RenderThreadImpl::current()->GenerateRoutingID();
- ChildThread::current()->AddRoute(routing_id_, this);
- }
-}
-
-PPB_FileRef_Impl::PPB_FileRef_Impl(const PPB_FileRef_CreateInfo& info,
- const base::FilePath& external_file_path)
- : PPB_FileRef_Shared(::ppapi::OBJECT_IS_IMPL, info),
- file_system_(),
- external_file_system_path_(external_file_path),
- routing_id_(MSG_ROUTING_NONE) {
- if (RenderThreadImpl::current()) { // NULL in tests.
- routing_id_ = RenderThreadImpl::current()->GenerateRoutingID();
- ChildThread::current()->AddRoute(routing_id_, this);
- }
-}
-
-PPB_FileRef_Impl::~PPB_FileRef_Impl() {
- if (RenderThreadImpl::current())
- ChildThread::current()->RemoveRoute(routing_id_);
-}
-
-// static
-PPB_FileRef_Impl* PPB_FileRef_Impl::CreateInternal(PP_Instance instance,
- PP_Resource pp_file_system,
- const std::string& path) {
- PepperFileSystemHost* fs_host = GetFileSystemHostInternal(
- instance, pp_file_system);
- if (!fs_host)
- return 0;
-
- PP_FileSystemType type = fs_host->GetType();
- if (type != PP_FILESYSTEMTYPE_LOCALPERSISTENT &&
- type != PP_FILESYSTEMTYPE_LOCALTEMPORARY &&
- type != PP_FILESYSTEMTYPE_EXTERNAL &&
- type != PP_FILESYSTEMTYPE_ISOLATED)
- return 0;
-
- PPB_FileRef_CreateInfo info;
- info.resource = HostResource::MakeInstanceOnly(instance);
- info.file_system_plugin_resource = pp_file_system;
- info.file_system_type = type;
-
- // Validate the path.
- info.path = path;
- if (!IsValidLocalPath(info.path))
- return 0;
- TrimTrailingSlash(&info.path);
-
- info.name = GetNameForVirtualFilePath(info.path);
-
- PPB_FileRef_Impl* file_ref = new PPB_FileRef_Impl(info, pp_file_system);
-
- RendererPpapiHostImpl* renderer_host =
- RendererPpapiHostImpl::GetForPPInstance(instance);
- if (renderer_host && renderer_host->IsRunningInProcess())
- file_ref->AddFileSystemRefCount();
- return file_ref;
-}
-
-// static
-PPB_FileRef_Impl* PPB_FileRef_Impl::CreateExternal(
- PP_Instance instance,
- const base::FilePath& external_file_path,
- const std::string& display_name) {
- PPB_FileRef_CreateInfo info;
- info.resource = HostResource::MakeInstanceOnly(instance);
- info.file_system_plugin_resource = 0;
- info.file_system_type = PP_FILESYSTEMTYPE_EXTERNAL;
- if (display_name.empty())
- info.name = GetNameForExternalFilePath(external_file_path);
- else
- info.name = display_name;
-
- return new PPB_FileRef_Impl(info, external_file_path);
-}
-
-PP_Resource PPB_FileRef_Impl::GetParent() {
- if (GetFileSystemType() == PP_FILESYSTEMTYPE_EXTERNAL)
- return 0;
-
- const std::string& virtual_path = GetCreateInfo().path;
-
- // There should always be a leading slash at least!
- size_t pos = virtual_path.rfind('/');
- CHECK(pos != std::string::npos);
-
- // If the path is "/foo", then we want to include the slash.
- if (pos == 0)
- pos++;
- std::string parent_path = virtual_path.substr(0, pos);
-
- scoped_refptr<PPB_FileRef_Impl> parent_ref(
- CreateInternal(pp_instance(), file_system_, parent_path));
- if (!parent_ref.get())
- return 0;
- return parent_ref->GetReference();
-}
-
-int32_t PPB_FileRef_Impl::MakeDirectory(
- PP_Bool make_ancestors,
- scoped_refptr<TrackedCallback> callback) {
- if (!IsValidNonExternalFileSystem())
- return PP_ERROR_NOACCESS;
-
- FileSystemDispatcher* file_system_dispatcher =
- ChildThread::current()->file_system_dispatcher();
- file_system_dispatcher->CreateDirectory(
- GetFileSystemURL(), false /* exclusive */, PP_ToBool(make_ancestors),
- base::Bind(&DidFinishFileOperation, callback));
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PPB_FileRef_Impl::Touch(PP_Time last_access_time,
- PP_Time last_modified_time,
- scoped_refptr<TrackedCallback> callback) {
- if (!IsValidNonExternalFileSystem())
- return PP_ERROR_NOACCESS;
-
- FileSystemDispatcher* file_system_dispatcher =
- ChildThread::current()->file_system_dispatcher();
- file_system_dispatcher->TouchFile(
- GetFileSystemURL(),
- PPTimeToTime(last_access_time),
- PPTimeToTime(last_modified_time),
- base::Bind(&DidFinishFileOperation, callback));
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PPB_FileRef_Impl::Delete(scoped_refptr<TrackedCallback> callback) {
- if (!IsValidNonExternalFileSystem())
- return PP_ERROR_NOACCESS;
-
- FileSystemDispatcher* file_system_dispatcher =
- ChildThread::current()->file_system_dispatcher();
- file_system_dispatcher->Remove(
- GetFileSystemURL(),
- false /* recursive */,
- base::Bind(&DidFinishFileOperation, callback));
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PPB_FileRef_Impl::Rename(PP_Resource new_pp_file_ref,
- scoped_refptr<TrackedCallback> callback) {
- EnterResourceNoLock<PPB_FileRef_API> enter(new_pp_file_ref, true);
- if (enter.failed())
- return PP_ERROR_BADRESOURCE;
- PPB_FileRef_Impl* new_file_ref =
- static_cast<PPB_FileRef_Impl*>(enter.object());
-
- if (!IsValidNonExternalFileSystem() ||
- file_system_ != new_file_ref->file_system_)
- return PP_ERROR_NOACCESS;
-
- // TODO(viettrungluu): Also cancel when the new file ref is destroyed?
- // http://crbug.com/67624
- FileSystemDispatcher* file_system_dispatcher =
- ChildThread::current()->file_system_dispatcher();
- file_system_dispatcher->Move(
- GetFileSystemURL(), new_file_ref->GetFileSystemURL(),
- base::Bind(&DidFinishFileOperation, callback));
- return PP_OK_COMPLETIONPENDING;
-}
-
-PP_Var PPB_FileRef_Impl::GetAbsolutePath() {
- if (GetFileSystemType() != PP_FILESYSTEMTYPE_EXTERNAL)
- return GetPath();
- if (!external_path_var_.get()) {
- external_path_var_ =
- new StringVar(external_file_system_path_.AsUTF8Unsafe());
- }
- return external_path_var_->GetPPVar();
-}
-
-base::FilePath PPB_FileRef_Impl::GetSystemPath() const {
- if (GetFileSystemType() != PP_FILESYSTEMTYPE_EXTERNAL) {
- NOTREACHED();
- return base::FilePath();
- }
- return external_file_system_path_;
-}
-
-GURL PPB_FileRef_Impl::GetFileSystemURL() const {
- if (GetFileSystemType() != PP_FILESYSTEMTYPE_LOCALPERSISTENT &&
- GetFileSystemType() != PP_FILESYSTEMTYPE_LOCALTEMPORARY &&
- GetFileSystemType() != PP_FILESYSTEMTYPE_EXTERNAL &&
- GetFileSystemType() != PP_FILESYSTEMTYPE_ISOLATED) {
- NOTREACHED();
- return GURL();
- }
-
- const std::string& virtual_path = GetCreateInfo().path;
- CHECK(!virtual_path.empty()); // Should always be at least "/".
-
- // Since |virtual_path_| starts with a '/', it looks like an absolute path.
- // We need to trim off the '/' before calling Resolve, as FileSystem URLs
- // start with a storage type identifier that looks like a path segment.
-
- PepperFileSystemHost* host = GetFileSystemHost();
- if (!host)
- return GURL();
-
- return GURL(host->GetRootUrl()).Resolve(net::EscapePath(
- virtual_path.substr(1)));
-}
-
-bool PPB_FileRef_Impl::OnMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(PPB_FileRef_Impl, msg)
- IPC_MESSAGE_HANDLER(ViewMsg_AsyncOpenPepperFile_ACK, OnAsyncFileOpened)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void PPB_FileRef_Impl::OnAsyncFileOpened(
- base::PlatformFileError error_code,
- IPC::PlatformFileForTransit file_for_transit,
- int message_id) {
- AsyncOpenFileCallback* callback =
- pending_async_open_files_.Lookup(message_id);
- DCHECK(callback);
- pending_async_open_files_.Remove(message_id);
-
- base::PlatformFile file =
- IPC::PlatformFileForTransitToPlatformFile(file_for_transit);
- callback->Run(error_code, base::PassPlatformFile(&file));
- // Make sure we won't leak file handle if the requester has died.
- if (file != base::kInvalidPlatformFileValue) {
- base::FileUtilProxy::Close(
- RenderThreadImpl::current()->GetFileThreadMessageLoopProxy().get(),
- file,
- base::FileUtilProxy::StatusCallback());
- }
- delete callback;
-}
-
-bool PPB_FileRef_Impl::IsValidNonExternalFileSystem() const {
- PepperFileSystemHost* host = GetFileSystemHost();
- return HasValidFileSystem() && host &&
- host->GetType() != PP_FILESYSTEMTYPE_EXTERNAL;
-}
-
-bool PPB_FileRef_Impl::HasValidFileSystem() const {
- PepperFileSystemHost* host = GetFileSystemHost();
- return host && host->IsOpened();
-}
-
-int32_t PPB_FileRef_Impl::Query(PP_FileInfo* info,
- scoped_refptr<TrackedCallback> callback) {
- NOTREACHED();
- return PP_ERROR_FAILED;
-}
-
-int32_t PPB_FileRef_Impl::QueryInHost(
- linked_ptr<PP_FileInfo> info,
- scoped_refptr<TrackedCallback> callback) {
- if (!file_system_) {
- // External file system
- // We have to do something totally different for external file systems.
-
- // TODO(teravest): Use the SequencedWorkerPool instead.
- scoped_refptr<base::TaskRunner> task_runner =
- RenderThreadImpl::current()->GetFileThreadMessageLoopProxy();
-
- int message_id = pending_async_open_files_.Add(new AsyncOpenFileCallback(
- base::Bind(&QueryCallback, task_runner, info, callback)));
- RenderThreadImpl::current()->Send(new ViewHostMsg_AsyncOpenPepperFile(
- routing_id_,
- GetSystemPath(),
- PP_FILEOPENFLAG_READ,
- message_id));
- } else {
- // Non-external file system
- if (!HasValidFileSystem())
- return PP_ERROR_NOACCESS;
-
- PP_FileSystemType file_system_type = GetFileSystemHost()->GetType();
- FileSystemDispatcher* file_system_dispatcher =
- ChildThread::current()->file_system_dispatcher();
- file_system_dispatcher->ReadMetadata(
- GetFileSystemURL(),
- base::Bind(&DidReadMetadata, callback, info, file_system_type),
- base::Bind(&DidFinishFileOperation, callback));
- }
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PPB_FileRef_Impl::ReadDirectoryEntries(
- const PP_ArrayOutput& output,
- scoped_refptr<TrackedCallback> callback) {
- NOTREACHED();
- return PP_ERROR_FAILED;
-}
-
-int32_t PPB_FileRef_Impl::ReadDirectoryEntriesInHost(
- linked_ptr<std::vector< ::ppapi::PPB_FileRef_CreateInfo> > files,
- linked_ptr<std::vector<PP_FileType> > file_types,
- scoped_refptr<TrackedCallback> callback) {
- if (!IsValidNonExternalFileSystem())
- return PP_ERROR_NOACCESS;
-
- // TODO(yzshen): Passing base::Unretained(this) to the callback could
- // be dangerous.
- FileSystemDispatcher* file_system_dispatcher =
- ChildThread::current()->file_system_dispatcher();
- file_system_dispatcher->ReadDirectory(
- GetFileSystemURL(),
- base::Bind(&DidReadDirectory,
- callback, base::Unretained(this), files, file_types),
- base::Bind(&DidFinishFileOperation, callback));
- return PP_OK_COMPLETIONPENDING;
-}
-
-PepperFileSystemHost* PPB_FileRef_Impl::GetFileSystemHost() const {
- return GetFileSystemHostInternal(pp_instance(), file_system_);
-}
-
-PepperFileSystemHost* PPB_FileRef_Impl::GetFileSystemHostInternal(
- PP_Instance instance, PP_Resource resource) {
- const ppapi::host::PpapiHost* ppapi_host =
- RendererPpapiHost::GetForPPInstance(instance)->GetPpapiHost();
- if (!resource || !ppapi_host)
- return NULL;
- ppapi::host::ResourceHost* resource_host =
- ppapi_host->GetResourceHost(resource);
- if (resource_host && resource_host->IsFileSystemHost())
- return static_cast<PepperFileSystemHost*>(resource_host);
- return NULL;
-}
-
-} // namespace content
diff --git a/content/renderer/pepper/ppb_file_ref_impl.h b/content/renderer/pepper/ppb_file_ref_impl.h
deleted file mode 100644
index 2dde933..0000000
--- a/content/renderer/pepper/ppb_file_ref_impl.h
+++ /dev/null
@@ -1,155 +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 CONTENT_RENDERER_PEPPER_PPB_FILE_REF_IMPL_H_
-#define CONTENT_RENDERER_PEPPER_PPB_FILE_REF_IMPL_H_
-
-#include <string>
-#include <vector>
-
-#include "base/callback_forward.h"
-#include "base/files/file_path.h"
-#include "base/id_map.h"
-#include "base/memory/linked_ptr.h"
-#include "base/platform_file.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_platform_file.h"
-#include "ppapi/c/pp_file_info.h"
-#include "ppapi/c/ppb_file_ref.h"
-#include "ppapi/shared_impl/ppb_file_ref_shared.h"
-#include "ppapi/shared_impl/scoped_pp_resource.h"
-#include "ppapi/shared_impl/var.h"
-#include "url/gurl.h"
-
-namespace ppapi {
-namespace host {
-class ResourceHost;
-}
-}
-
-namespace content {
-
-using ::ppapi::StringVar;
-
-class PepperFileSystemHost;
-
-class PPB_FileRef_Impl : public ::ppapi::PPB_FileRef_Shared,
- public IPC::Listener {
- public:
- PPB_FileRef_Impl(const ::ppapi::PPB_FileRef_CreateInfo& info,
- PP_Resource file_system);
- PPB_FileRef_Impl(const ::ppapi::PPB_FileRef_CreateInfo& info,
- const base::FilePath& external_file_path);
-
- // The returned object will have a refcount of 0 (just like "new").
- static PPB_FileRef_Impl* CreateInternal(PP_Instance instance,
- PP_Resource pp_file_system,
- const std::string& path);
-
- // The returned object will have a refcount of 0 (just like "new").
- static PPB_FileRef_Impl* CreateExternal(
- PP_Instance instance,
- const base::FilePath& external_file_path,
- const std::string& display_name);
-
- // PPB_FileRef_API implementation (not provided by PPB_FileRef_Shared).
- virtual PP_Resource GetParent() OVERRIDE;
- virtual int32_t MakeDirectory(
- PP_Bool make_ancestors,
- scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
- virtual int32_t Touch(
- PP_Time last_access_time,
- PP_Time last_modified_time,
- scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
- virtual int32_t Delete(
- scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
- virtual int32_t Rename(
- PP_Resource new_file_ref,
- scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
- virtual int32_t Query(
- PP_FileInfo* info,
- scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
- virtual int32_t ReadDirectoryEntries(
- const PP_ArrayOutput& output,
- scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
- virtual int32_t QueryInHost(
- linked_ptr<PP_FileInfo> info,
- scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
- virtual int32_t ReadDirectoryEntriesInHost(
- linked_ptr<std::vector< ::ppapi::PPB_FileRef_CreateInfo> > files,
- linked_ptr<std::vector<PP_FileType> > file_types,
- scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
- virtual PP_Var GetAbsolutePath() OVERRIDE;
-
- PP_Resource file_system_resource() const { return file_system_; }
-
- // Returns the system path corresponding to this file. Valid only for
- // external filesystems.
- base::FilePath GetSystemPath() const;
-
- // Returns the FileSystem API URL corresponding to this file.
- GURL GetFileSystemURL() const;
-
- // Checks if file ref has file system instance and if the instance is opened.
- bool HasValidFileSystem() const;
-
- void AddFileSystemRefCount() {
- file_system_ref_ = file_system_;
- }
-
- private:
- virtual ~PPB_FileRef_Impl();
-
- // IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
- void OnAsyncFileOpened(
- base::PlatformFileError error_code,
- IPC::PlatformFileForTransit file_for_transit,
- int message_id);
-
- // Many mutation functions are allow only to non-external filesystems, This
- // function returns true if the filesystem is opened and isn't external as an
- // access check for these functions.
- bool IsValidNonExternalFileSystem() const;
-
- PepperFileSystemHost* GetFileSystemHost() const;
- static PepperFileSystemHost* GetFileSystemHostInternal(
- PP_Instance instance, PP_Resource resource);
-
- // 0 for external filesystems. This is a plugin side resource that we don't
- // hold a reference here, so file_system_ could be destroyed earlier than
- // this object. Right now we checked the existance in plugin delegate before
- // use. But it's better to hold a reference once we migrate FileRef to the
- // new design.
- PP_Resource file_system_;
-
- // Holds a reference of FileSystem when running in process. See
- // PPB_FileRef_Proxy for corresponding code for out-of-process mode. Note
- // that this ScopedPPResource is only expected to be used when running in
- // process (since PPB_FileRef_Proxy takes care of out-of-process case).
- // Also note that this workaround will be no longer needed after FileRef
- // refactoring.
- ::ppapi::ScopedPPResource file_system_ref_;
-
- // Used only for external filesystems.
- base::FilePath external_file_system_path_;
-
- // Lazily initialized var created from the external path. This is so we can
- // return the identical string object every time it is requested.
- scoped_refptr<StringVar> external_path_var_;
-
- int routing_id_;
-
- typedef base::Callback<void (base::PlatformFileError, base::PassPlatformFile)>
- AsyncOpenFileCallback;
-
- IDMap<AsyncOpenFileCallback> pending_async_open_files_;
-
- DISALLOW_COPY_AND_ASSIGN(PPB_FileRef_Impl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_PEPPER_PPB_FILE_REF_IMPL_H_
diff --git a/content/renderer/pepper/ppb_flash_message_loop_impl.cc b/content/renderer/pepper/ppb_flash_message_loop_impl.cc
index c13ecb8..ff2abc4 100644
--- a/content/renderer/pepper/ppb_flash_message_loop_impl.cc
+++ b/content/renderer/pepper/ppb_flash_message_loop_impl.cc
@@ -43,7 +43,7 @@
};
PPB_Flash_MessageLoop_Impl::PPB_Flash_MessageLoop_Impl(PP_Instance instance)
- : Resource(::ppapi::OBJECT_IS_IMPL, instance),
+ : Resource(ppapi::OBJECT_IS_IMPL, instance),
state_(new State()) {
}
diff --git a/content/renderer/pepper/ppb_flash_message_loop_impl.h b/content/renderer/pepper/ppb_flash_message_loop_impl.h
index 4bd303d..981a7da 100644
--- a/content/renderer/pepper/ppb_flash_message_loop_impl.h
+++ b/content/renderer/pepper/ppb_flash_message_loop_impl.h
@@ -14,13 +14,13 @@
namespace content {
class PPB_Flash_MessageLoop_Impl
- : public ::ppapi::Resource,
- public ::ppapi::thunk::PPB_Flash_MessageLoop_API {
+ : public ppapi::Resource,
+ public ppapi::thunk::PPB_Flash_MessageLoop_API {
public:
static PP_Resource Create(PP_Instance instance);
// Resource.
- virtual ::ppapi::thunk::PPB_Flash_MessageLoop_API*
+ virtual ppapi::thunk::PPB_Flash_MessageLoop_API*
AsPPB_Flash_MessageLoop_API() OVERRIDE;
// PPB_Flash_MessageLoop_API implementation.
diff --git a/content/renderer/pepper/ppb_gpu_blacklist_private_impl.cc b/content/renderer/pepper/ppb_gpu_blacklist_private_impl.cc
index 7649cae..8db33bd 100644
--- a/content/renderer/pepper/ppb_gpu_blacklist_private_impl.cc
+++ b/content/renderer/pepper/ppb_gpu_blacklist_private_impl.cc
@@ -6,7 +6,7 @@
#include "base/command_line.h"
#include "base/logging.h"
-#include "webkit/plugins/plugin_switches.h"
+#include "content/public/common/content_switches.h"
// todo(nfullagar): Remove this private interface when the SRPC proxy is
// permanently disabled.
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.cc b/content/renderer/pepper/ppb_graphics_3d_impl.cc
index 6587781..b48d68a 100644
--- a/content/renderer/pepper/ppb_graphics_3d_impl.cc
+++ b/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -8,6 +8,7 @@
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/public/common/content_switches.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/pepper_platform_context_3d.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
@@ -23,7 +24,6 @@
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "webkit/common/webpreferences.h"
-#include "webkit/plugins/plugin_switches.h"
using ppapi::thunk::EnterResourceNoLock;
using ppapi::thunk::PPB_Graphics3D_API;
@@ -72,8 +72,7 @@
PP_Bool PPB_Graphics3D_Impl::IsGpuBlacklisted() {
CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line)
- return PP_FromBool(
- command_line->HasSwitch(switches::kDisablePepper3d));
+ return PP_FromBool(command_line->HasSwitch(switches::kDisablePepper3d));
return PP_TRUE;
}
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.h b/content/renderer/pepper/ppb_graphics_3d_impl.h
index e00695a..3e1c797 100644
--- a/content/renderer/pepper/ppb_graphics_3d_impl.h
+++ b/content/renderer/pepper/ppb_graphics_3d_impl.h
@@ -12,7 +12,7 @@
namespace content {
class PlatformContext3D;
-class PPB_Graphics3D_Impl : public ::ppapi::PPB_Graphics3D_Shared {
+class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared {
public:
static PP_Resource Create(PP_Instance instance,
PP_Resource share_context,
diff --git a/content/renderer/pepper/ppb_image_data_impl.cc b/content/renderer/pepper/ppb_image_data_impl.cc
index e79e83c..9ea83d5 100644
--- a/content/renderer/pepper/ppb_image_data_impl.cc
+++ b/content/renderer/pepper/ppb_image_data_impl.cc
@@ -21,13 +21,13 @@
#include "third_party/skia/include/core/SkColorPriv.h"
#include "ui/surface/transport_dib.h"
-using ::ppapi::thunk::PPB_ImageData_API;
+using ppapi::thunk::PPB_ImageData_API;
namespace content {
PPB_ImageData_Impl::PPB_ImageData_Impl(PP_Instance instance,
PPB_ImageData_Shared::ImageDataType type)
- : Resource(::ppapi::OBJECT_IS_IMPL, instance),
+ : Resource(ppapi::OBJECT_IS_IMPL, instance),
format_(PP_IMAGEDATAFORMAT_BGRA_PREMUL),
width_(0),
height_(0) {
diff --git a/content/renderer/pepper/ppb_image_data_impl.h b/content/renderer/pepper/ppb_image_data_impl.h
index ee05b5a..a16bbfa 100644
--- a/content/renderer/pepper/ppb_image_data_impl.h
+++ b/content/renderer/pepper/ppb_image_data_impl.h
@@ -25,9 +25,9 @@
namespace content {
class CONTENT_EXPORT PPB_ImageData_Impl
- : public ::ppapi::Resource,
- public ::ppapi::PPB_ImageData_Shared,
- public NON_EXPORTED_BASE(::ppapi::thunk::PPB_ImageData_API) {
+ : public ppapi::Resource,
+ public ppapi::PPB_ImageData_Shared,
+ public NON_EXPORTED_BASE(ppapi::thunk::PPB_ImageData_API) {
public:
// We delegate most of our implementation to a back-end class that either uses
// a PlatformCanvas (for most trusted stuff) or bare shared memory (for use by
@@ -76,7 +76,7 @@
TransportDIB* GetTransportDIB() const;
// Resource override.
- virtual ::ppapi::thunk::PPB_ImageData_API* AsPPB_ImageData_API() OVERRIDE;
+ virtual ppapi::thunk::PPB_ImageData_API* AsPPB_ImageData_API() OVERRIDE;
// PPB_ImageData_API implementation.
virtual PP_Bool Describe(PP_ImageDataDesc* desc) OVERRIDE;
diff --git a/content/renderer/pepper/ppb_network_monitor_private_impl.cc b/content/renderer/pepper/ppb_network_monitor_private_impl.cc
index d43c8f0..a616a2c 100644
--- a/content/renderer/pepper/ppb_network_monitor_private_impl.cc
+++ b/content/renderer/pepper/ppb_network_monitor_private_impl.cc
@@ -44,7 +44,7 @@
PP_Instance instance,
PPB_NetworkMonitor_Callback callback,
void* user_data)
- : Resource(::ppapi::OBJECT_IS_IMPL, instance),
+ : Resource(ppapi::OBJECT_IS_IMPL, instance),
callback_(callback),
user_data_(user_data),
started_(false) {
@@ -66,7 +66,7 @@
return result->GetReference();
}
-::ppapi::thunk::PPB_NetworkMonitor_Private_API*
+ppapi::thunk::PPB_NetworkMonitor_Private_API*
PPB_NetworkMonitor_Private_Impl::AsPPB_NetworkMonitor_Private_API() {
return this;
}
@@ -78,14 +78,14 @@
void PPB_NetworkMonitor_Private_Impl::OnNetworkListChanged(
const net::NetworkInterfaceList& list) {
- ::ppapi::NetworkList list_copy(list.size());
+ ppapi::NetworkList list_copy(list.size());
for (size_t i = 0; i < list.size(); ++i) {
- ::ppapi::NetworkInfo& network = list_copy.at(i);
+ ppapi::NetworkInfo& network = list_copy.at(i);
network.name = list[i].name;
network.addresses.resize(
- 1, ::ppapi::NetAddressPrivateImpl::kInvalidNetAddress);
- bool result = ::ppapi::NetAddressPrivateImpl::IPEndPointToNetAddress(
+ 1, ppapi::NetAddressPrivateImpl::kInvalidNetAddress);
+ bool result = ppapi::NetAddressPrivateImpl::IPEndPointToNetAddress(
list[i].address, 0, &(network.addresses[0]));
DCHECK(result);
@@ -97,11 +97,11 @@
network.display_name = list[i].name;
network.mtu = 0;
}
- scoped_refptr< ::ppapi::NetworkListStorage> list_storage(
- new ::ppapi::NetworkListStorage(list_copy));
+ scoped_refptr<ppapi::NetworkListStorage> list_storage(
+ new ppapi::NetworkListStorage(list_copy));
PP_Resource list_resource =
- ::ppapi::PPB_NetworkList_Private_Shared::Create(
- ::ppapi::OBJECT_IS_IMPL, pp_instance(), list_storage);
+ ppapi::PPB_NetworkList_Private_Shared::Create(
+ ppapi::OBJECT_IS_IMPL, pp_instance(), list_storage);
callback_(user_data_, list_resource);
}
diff --git a/content/renderer/pepper/ppb_network_monitor_private_impl.h b/content/renderer/pepper/ppb_network_monitor_private_impl.h
index 678ee40..317e145 100644
--- a/content/renderer/pepper/ppb_network_monitor_private_impl.h
+++ b/content/renderer/pepper/ppb_network_monitor_private_impl.h
@@ -15,15 +15,15 @@
namespace content {
class PPB_NetworkMonitor_Private_Impl
- : public ::ppapi::Resource,
- public ::ppapi::thunk::PPB_NetworkMonitor_Private_API,
+ : public ppapi::Resource,
+ public ppapi::thunk::PPB_NetworkMonitor_Private_API,
public content::NetworkListObserver {
public:
static PP_Resource Create(PP_Instance instance,
PPB_NetworkMonitor_Callback callback,
void* user_data);
- virtual ::ppapi::thunk::PPB_NetworkMonitor_Private_API*
+ virtual ppapi::thunk::PPB_NetworkMonitor_Private_API*
AsPPB_NetworkMonitor_Private_API() OVERRIDE;
// NetworkListObserver interface.
diff --git a/content/renderer/pepper/ppb_proxy_impl.cc b/content/renderer/pepper/ppb_proxy_impl.cc
index a9d99f3..cdae3ac 100644
--- a/content/renderer/pepper/ppb_proxy_impl.cc
+++ b/content/renderer/pepper/ppb_proxy_impl.cc
@@ -25,7 +25,7 @@
}
PP_Instance GetInstanceForResource(PP_Resource resource) {
- ::ppapi::Resource* obj =
+ ppapi::Resource* obj =
PpapiGlobals::Get()->GetResourceTracker()->GetResource(resource);
if (!obj)
return 0;
diff --git a/content/renderer/pepper/ppb_scrollbar_impl.cc b/content/renderer/pepper/ppb_scrollbar_impl.cc
index e3da676..fb01c59 100644
--- a/content/renderer/pepper/ppb_scrollbar_impl.cc
+++ b/content/renderer/pepper/ppb_scrollbar_impl.cc
@@ -151,7 +151,7 @@
}
PP_Bool PPB_Scrollbar_Impl::HandleEventInternal(
- const ::ppapi::InputEventData& data) {
+ const ppapi::InputEventData& data) {
scoped_ptr<WebInputEvent> web_input_event(CreateWebInputEvent(data));
if (!web_input_event.get() || !scrollbar_)
return PP_FALSE;
diff --git a/content/renderer/pepper/ppb_scrollbar_impl.h b/content/renderer/pepper/ppb_scrollbar_impl.h
index 559c303..eb7906b 100644
--- a/content/renderer/pepper/ppb_scrollbar_impl.h
+++ b/content/renderer/pepper/ppb_scrollbar_impl.h
@@ -19,7 +19,7 @@
namespace content {
class PPB_Scrollbar_Impl : public PPB_Widget_Impl,
- public ::ppapi::thunk::PPB_Scrollbar_API,
+ public ppapi::thunk::PPB_Scrollbar_API,
public WebKit::WebPluginScrollbarClient {
public:
static PP_Resource Create(PP_Instance instance, bool vertical);
@@ -47,7 +47,7 @@
virtual PP_Bool PaintInternal(const gfx::Rect& rect,
PPB_ImageData_Impl* image) OVERRIDE;
virtual PP_Bool HandleEventInternal(
- const ::ppapi::InputEventData& data) OVERRIDE;
+ const ppapi::InputEventData& data) OVERRIDE;
virtual void SetLocationInternal(const PP_Rect* location) OVERRIDE;
// WebKit::WebPluginScrollbarClient implementation.
diff --git a/content/renderer/pepper/ppb_tcp_socket_private_impl.cc b/content/renderer/pepper/ppb_tcp_socket_private_impl.cc
index 13f36a2..2b47e64 100644
--- a/content/renderer/pepper/ppb_tcp_socket_private_impl.cc
+++ b/content/renderer/pepper/ppb_tcp_socket_private_impl.cc
@@ -17,7 +17,7 @@
PP_Instance instance,
uint32 socket_id,
int routing_id)
- : ::ppapi::TCPSocketPrivateImpl(instance, socket_id),
+ : ppapi::TCPSocketPrivateImpl(instance, socket_id),
routing_id_(routing_id) {
ChildThread::current()->AddRoute(routing_id, this);
}
@@ -79,7 +79,7 @@
void PPB_TCPSocket_Private_Impl::SendSetOption(
PP_TCPSocket_Option name,
- const ::ppapi::SocketOptionData& value) {
+ const ppapi::SocketOptionData& value) {
RenderThreadImpl::current()->Send(
new PpapiHostMsg_PPBTCPSocket_SetOption(socket_id_, name, value));
}
diff --git a/content/renderer/pepper/ppb_tcp_socket_private_impl.h b/content/renderer/pepper/ppb_tcp_socket_private_impl.h
index ae53a6e..2ac6981 100644
--- a/content/renderer/pepper/ppb_tcp_socket_private_impl.h
+++ b/content/renderer/pepper/ppb_tcp_socket_private_impl.h
@@ -13,7 +13,7 @@
namespace content {
-class PPB_TCPSocket_Private_Impl : public ::ppapi::TCPSocketPrivateImpl,
+class PPB_TCPSocket_Private_Impl : public ppapi::TCPSocketPrivateImpl,
public IPC::Listener {
public:
static PP_Resource CreateResource(PP_Instance instance);
@@ -30,7 +30,7 @@
virtual void SendWrite(const std::string& buffer) OVERRIDE;
virtual void SendDisconnect() OVERRIDE;
virtual void SendSetOption(PP_TCPSocket_Option name,
- const ::ppapi::SocketOptionData& value) OVERRIDE;
+ const ppapi::SocketOptionData& value) OVERRIDE;
private:
PPB_TCPSocket_Private_Impl(PP_Instance instance,
diff --git a/content/renderer/pepper/ppb_var_deprecated_impl.cc b/content/renderer/pepper/ppb_var_deprecated_impl.cc
index c5353cf..23472fa 100644
--- a/content/renderer/pepper/ppb_var_deprecated_impl.cc
+++ b/content/renderer/pepper/ppb_var_deprecated_impl.cc
@@ -412,10 +412,10 @@
// static
const PPB_Var_Deprecated* PPB_Var_Deprecated_Impl::GetVarDeprecatedInterface() {
static const PPB_Var_Deprecated var_deprecated_interface = {
- ::ppapi::PPB_Var_Shared::GetVarInterface1_0()->AddRef,
- ::ppapi::PPB_Var_Shared::GetVarInterface1_0()->Release,
- ::ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8,
- ::ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8,
+ ppapi::PPB_Var_Shared::GetVarInterface1_0()->AddRef,
+ ppapi::PPB_Var_Shared::GetVarInterface1_0()->Release,
+ ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8,
+ ppapi::PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8,
&HasPropertyDeprecated,
&HasMethodDeprecated,
&GetProperty,
diff --git a/content/renderer/pepper/ppb_video_decoder_impl.h b/content/renderer/pepper/ppb_video_decoder_impl.h
index f716ecd..d9b195b 100644
--- a/content/renderer/pepper/ppb_video_decoder_impl.h
+++ b/content/renderer/pepper/ppb_video_decoder_impl.h
@@ -29,7 +29,7 @@
class PlatformContext3D;
class PlatformVideoDecoder;
-class PPB_VideoDecoder_Impl : public ::ppapi::PPB_VideoDecoder_Shared,
+class PPB_VideoDecoder_Impl : public ppapi::PPB_VideoDecoder_Shared,
public media::VideoDecodeAccelerator::Client {
public:
// See PPB_VideoDecoder_Dev::Create. Returns 0 on failure to create &
@@ -41,14 +41,14 @@
// PPB_VideoDecoder_API implementation.
virtual int32_t Decode(
const PP_VideoBitstreamBuffer_Dev* bitstream_buffer,
- scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
+ scoped_refptr<ppapi::TrackedCallback> callback) OVERRIDE;
virtual void AssignPictureBuffers(
uint32_t no_of_buffers, const PP_PictureBuffer_Dev* buffers) OVERRIDE;
virtual void ReusePictureBuffer(int32_t picture_buffer_id) OVERRIDE;
virtual int32_t Flush(
- scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
+ scoped_refptr<ppapi::TrackedCallback> callback) OVERRIDE;
virtual int32_t Reset(
- scoped_refptr< ::ppapi::TrackedCallback> callback) OVERRIDE;
+ scoped_refptr<ppapi::TrackedCallback> callback) OVERRIDE;
virtual void Destroy() OVERRIDE;
// media::VideoDecodeAccelerator::Client implementation.
diff --git a/content/renderer/pepper/ppb_widget_impl.cc b/content/renderer/pepper/ppb_widget_impl.cc
index eaeae43..494eec7 100644
--- a/content/renderer/pepper/ppb_widget_impl.cc
+++ b/content/renderer/pepper/ppb_widget_impl.cc
@@ -21,7 +21,7 @@
namespace content {
PPB_Widget_Impl::PPB_Widget_Impl(PP_Instance instance)
- : Resource(::ppapi::OBJECT_IS_IMPL, instance),
+ : Resource(ppapi::OBJECT_IS_IMPL, instance),
scale_(1.0f) {
memset(&location_, 0, sizeof(location_));
}
diff --git a/content/renderer/pepper/ppb_widget_impl.h b/content/renderer/pepper/ppb_widget_impl.h
index 5a5ef0d..66139ca 100644
--- a/content/renderer/pepper/ppb_widget_impl.h
+++ b/content/renderer/pepper/ppb_widget_impl.h
@@ -22,13 +22,13 @@
class PPB_ImageData_Impl;
-class PPB_Widget_Impl : public ::ppapi::Resource,
- public ::ppapi::thunk::PPB_Widget_API {
+class PPB_Widget_Impl : public ppapi::Resource,
+ public ppapi::thunk::PPB_Widget_API {
public:
explicit PPB_Widget_Impl(PP_Instance instance);
// Resource overrides.
- virtual ::ppapi::thunk::PPB_Widget_API* AsPPB_Widget_API() OVERRIDE;
+ virtual ppapi::thunk::PPB_Widget_API* AsPPB_Widget_API() OVERRIDE;
// PPB_WidgetAPI implementation.
virtual PP_Bool Paint(const PP_Rect* rect, PP_Resource ) OVERRIDE;
@@ -45,7 +45,7 @@
virtual PP_Bool PaintInternal(const gfx::Rect& rect,
PPB_ImageData_Impl* image) = 0;
- virtual PP_Bool HandleEventInternal(const ::ppapi::InputEventData& data) = 0;
+ virtual PP_Bool HandleEventInternal(const ppapi::InputEventData& data) = 0;
virtual void SetLocationInternal(const PP_Rect* location) = 0;
PP_Rect location() const { return location_; }
diff --git a/content/renderer/pepper/ppb_x509_certificate_private_impl.cc b/content/renderer/pepper/ppb_x509_certificate_private_impl.cc
index 6c287a3..c580e71 100644
--- a/content/renderer/pepper/ppb_x509_certificate_private_impl.cc
+++ b/content/renderer/pepper/ppb_x509_certificate_private_impl.cc
@@ -11,7 +11,7 @@
PPB_X509Certificate_Private_Impl::PPB_X509Certificate_Private_Impl(
PP_Instance instance) :
- PPB_X509Certificate_Private_Shared(::ppapi::OBJECT_IS_IMPL, instance) {
+ PPB_X509Certificate_Private_Shared(ppapi::OBJECT_IS_IMPL, instance) {
}
// static
@@ -22,7 +22,7 @@
bool PPB_X509Certificate_Private_Impl::ParseDER(
const std::vector<char>& der,
- ::ppapi::PPB_X509Certificate_Fields* result) {
+ ppapi::PPB_X509Certificate_Fields* result) {
bool succeeded = false;
RenderThreadImpl::current()->Send(
new PpapiHostMsg_PPBX509Certificate_ParseDER(der, &succeeded, result));
diff --git a/content/renderer/pepper/ppb_x509_certificate_private_impl.h b/content/renderer/pepper/ppb_x509_certificate_private_impl.h
index 76438c9..0f10ec0 100644
--- a/content/renderer/pepper/ppb_x509_certificate_private_impl.h
+++ b/content/renderer/pepper/ppb_x509_certificate_private_impl.h
@@ -17,12 +17,12 @@
namespace content {
class PPB_X509Certificate_Private_Impl :
- public ::ppapi::PPB_X509Certificate_Private_Shared {
+ public ppapi::PPB_X509Certificate_Private_Shared {
public:
PPB_X509Certificate_Private_Impl(PP_Instance instance);
static PP_Resource CreateResource(PP_Instance instance);
virtual bool ParseDER(const std::vector<char>& der,
- ::ppapi::PPB_X509Certificate_Fields* result) OVERRIDE;
+ ppapi::PPB_X509Certificate_Fields* result) OVERRIDE;
private:
virtual ~PPB_X509Certificate_Private_Impl();
diff --git a/content/renderer/pepper/renderer_ppapi_host_impl.cc b/content/renderer/pepper/renderer_ppapi_host_impl.cc
index cd1d6dd..dd78352 100644
--- a/content/renderer/pepper/renderer_ppapi_host_impl.cc
+++ b/content/renderer/pepper/renderer_ppapi_host_impl.cc
@@ -114,10 +114,10 @@
return instance->module()->renderer_ppapi_host();
}
-scoped_ptr< ::ppapi::thunk::ResourceCreationAPI>
+scoped_ptr<ppapi::thunk::ResourceCreationAPI>
RendererPpapiHostImpl::CreateInProcessResourceCreationAPI(
PepperPluginInstanceImpl* instance) {
- return scoped_ptr< ::ppapi::thunk::ResourceCreationAPI>(
+ return scoped_ptr<ppapi::thunk::ResourceCreationAPI>(
new PepperInProcessResourceCreation(this, instance));
}
diff --git a/content/renderer/pepper/renderer_ppapi_host_impl.h b/content/renderer/pepper/renderer_ppapi_host_impl.h
index 4ef47bd..935f38d 100644
--- a/content/renderer/pepper/renderer_ppapi_host_impl.h
+++ b/content/renderer/pepper/renderer_ppapi_host_impl.h
@@ -68,7 +68,7 @@
// host impl should outlive the returned pointer. Since the resource
// creation object is associated with the instance, this will generally
// happen automatically.
- scoped_ptr< ::ppapi::thunk::ResourceCreationAPI>
+ scoped_ptr<ppapi::thunk::ResourceCreationAPI>
CreateInProcessResourceCreationAPI(PepperPluginInstanceImpl* instance);
PepperPluginInstanceImpl* GetPluginInstanceImpl(PP_Instance instance) const;
diff --git a/content/renderer/pepper/resource_creation_impl.cc b/content/renderer/pepper/resource_creation_impl.cc
index d2ddd30..cddc891 100644
--- a/content/renderer/pepper/resource_creation_impl.cc
+++ b/content/renderer/pepper/resource_creation_impl.cc
@@ -8,7 +8,6 @@
#include "content/renderer/pepper/ppb_audio_impl.h"
#include "content/renderer/pepper/ppb_broker_impl.h"
#include "content/renderer/pepper/ppb_buffer_impl.h"
-#include "content/renderer/pepper/ppb_file_ref_impl.h"
#include "content/renderer/pepper/ppb_flash_message_loop_impl.h"
#include "content/renderer/pepper/ppb_graphics_3d_impl.h"
#include "content/renderer/pepper/ppb_image_data_impl.h"
@@ -50,8 +49,8 @@
PP_Instance instance,
PP_AudioSampleRate sample_rate,
uint32_t sample_frame_count) {
- return ::ppapi::PPB_AudioConfig_Shared::Create(
- ::ppapi::OBJECT_IS_IMPL, instance, sample_rate, sample_frame_count);
+ return ppapi::PPB_AudioConfig_Shared::Create(
+ ppapi::OBJECT_IS_IMPL, instance, sample_rate, sample_frame_count);
}
PP_Resource ResourceCreationImpl::CreateAudioTrusted(
@@ -72,22 +71,6 @@
return PPB_Buffer_Impl::Create(instance, size);
}
-PP_Resource ResourceCreationImpl::CreateFileRef(
- PP_Instance instance,
- PP_Resource file_system,
- const char* path) {
- PPB_FileRef_Impl* res = PPB_FileRef_Impl::CreateInternal(
- instance, file_system, path);
- return res ? res->GetReference() : 0;
-}
-
-PP_Resource ResourceCreationImpl::CreateFileRef(
- const ::ppapi::PPB_FileRef_CreateInfo& serialized) {
- // When we're in-process, the host resource in the create info *is* the
- // resource, so we don't need to do anything.
- return serialized.resource.host_resource();
-}
-
PP_Resource ResourceCreationImpl::CreateFlashDRM(PP_Instance instance) {
return 0; // Not supported in-process.
}
@@ -138,7 +121,7 @@
const PP_Size* size,
PP_Bool init_to_zero) {
return PPB_ImageData_Impl::Create(instance,
- ::ppapi::PPB_ImageData_Shared::PLATFORM,
+ ppapi::PPB_ImageData_Shared::PLATFORM,
format, *size, init_to_zero);
}
@@ -148,7 +131,7 @@
const PP_Size* size,
PP_Bool init_to_zero) {
return PPB_ImageData_Impl::Create(instance,
- ::ppapi::PPB_ImageData_Shared::SIMPLE,
+ ppapi::PPB_ImageData_Shared::SIMPLE,
format, *size, init_to_zero);
}
@@ -163,7 +146,7 @@
uint32_t selection_start,
uint32_t selection_end) {
return PPB_InputEvent_Shared::CreateIMEInputEvent(
- ::ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, text, segment_number,
+ ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, text, segment_number,
segment_offsets, target_segment, selection_start, selection_end);
}
@@ -181,7 +164,7 @@
uint32_t key_code,
struct PP_Var character_text) {
return PPB_InputEvent_Shared::CreateKeyboardInputEvent(
- ::ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, modifiers, key_code,
+ ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, modifiers, key_code,
character_text);
}
@@ -195,7 +178,7 @@
int32_t click_count,
const PP_Point* mouse_movement) {
return PPB_InputEvent_Shared::CreateMouseInputEvent(
- ::ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, modifiers,
+ ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, modifiers,
mouse_button, mouse_position, click_count, mouse_movement);
}
@@ -223,7 +206,7 @@
PP_TimeTicks time_stamp,
uint32_t modifiers) {
return PPB_InputEvent_Shared::CreateTouchInputEvent(
- ::ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, modifiers);
+ ppapi::OBJECT_IS_IMPL, instance, type, time_stamp, modifiers);
}
PP_Resource ResourceCreationImpl::CreateNetworkMonitor(
@@ -247,7 +230,7 @@
const PP_Resource elements[],
uint32_t size) {
PPB_ResourceArray_Shared* object = new PPB_ResourceArray_Shared(
- ::ppapi::OBJECT_IS_IMPL, instance, elements, size);
+ ppapi::OBJECT_IS_IMPL, instance, elements, size);
return object->GetReference();
}
@@ -301,7 +284,7 @@
const PP_FloatPoint* wheel_ticks,
PP_Bool scroll_by_page) {
return PPB_InputEvent_Shared::CreateWheelInputEvent(
- ::ppapi::OBJECT_IS_IMPL, instance, time_stamp, modifiers,
+ ppapi::OBJECT_IS_IMPL, instance, time_stamp, modifiers,
wheel_delta, wheel_ticks, scroll_by_page);
}
diff --git a/content/renderer/pepper/resource_creation_impl.h b/content/renderer/pepper/resource_creation_impl.h
index 7d09822..30ddf63 100644
--- a/content/renderer/pepper/resource_creation_impl.h
+++ b/content/renderer/pepper/resource_creation_impl.h
@@ -17,7 +17,7 @@
// "old-style" resources are handled here. See
// content/renderer/pepper/pepper_in_process_resource_creation.h for functions
// that implement "new-style" resources.
-class ResourceCreationImpl : public ::ppapi::thunk::ResourceCreationAPI {
+class ResourceCreationImpl : public ppapi::thunk::ResourceCreationAPI {
public:
explicit ResourceCreationImpl(PepperPluginInstanceImpl* instance);
virtual ~ResourceCreationImpl();
@@ -35,11 +35,6 @@
virtual PP_Resource CreateBroker(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateBuffer(PP_Instance instance,
uint32_t size) OVERRIDE;
- virtual PP_Resource CreateFileRef(PP_Instance instance,
- PP_Resource file_system,
- const char* path) OVERRIDE;
- virtual PP_Resource CreateFileRef(
- const ::ppapi::PPB_FileRef_CreateInfo& serialized) OVERRIDE;
virtual PP_Resource CreateFlashDRM(PP_Instance instance) OVERRIDE;
virtual PP_Resource CreateFlashFontFile(
PP_Instance instance,
diff --git a/content/renderer/pepper/url_request_info_util.cc b/content/renderer/pepper/url_request_info_util.cc
index 9f13fe0..5b3786b 100644
--- a/content/renderer/pepper/url_request_info_util.cc
+++ b/content/renderer/pepper/url_request_info_util.cc
@@ -8,10 +8,13 @@
#include "base/strings/string_util.h"
#include "content/common/fileapi/file_system_messages.h"
#include "content/renderer/pepper/common.h"
+#include "content/renderer/pepper/host_globals.h"
+#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/plugin_module.h"
-#include "content/renderer/pepper/ppb_file_ref_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "net/http/http_util.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/file_ref_detailed_info.h"
#include "ppapi/shared_impl/url_request_info_data.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/thunk/enter.h"
@@ -25,10 +28,9 @@
#include "url/url_util.h"
#include "webkit/child/weburlrequest_extradata_impl.h"
-using ppapi::URLRequestInfoData;
using ppapi::Resource;
+using ppapi::URLRequestInfoData;
using ppapi::thunk::EnterResourceNoLock;
-using ppapi::thunk::PPB_FileRef_API;
using WebKit::WebData;
using WebKit::WebHTTPBody;
using WebKit::WebString;
@@ -43,32 +45,23 @@
// Appends the file ref given the Resource pointer associated with it to the
// given HTTP body, returning true on success.
bool AppendFileRefToBody(
- Resource* file_ref_resource,
+ const ppapi::FileRefDetailedInfo& file_info,
int64_t start_offset,
int64_t number_of_bytes,
PP_Time expected_last_modified_time,
WebHTTPBody *http_body) {
- // Get the underlying file ref impl.
- if (!file_ref_resource)
- return false;
- PPB_FileRef_API* file_ref_api = file_ref_resource->AsPPB_FileRef_API();
- if (!file_ref_api)
- return false;
- const PPB_FileRef_Impl* file_ref =
- static_cast<PPB_FileRef_Impl*>(file_ref_api);
-
base::FilePath platform_path;
- switch (file_ref->GetFileSystemType()) {
+ switch (file_info.file_system_type) {
case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
// TODO(kinuko): remove this sync IPC when we fully support
// AppendURLRange for FileSystem URL.
RenderThreadImpl::current()->Send(
new FileSystemHostMsg_SyncGetPlatformPath(
- file_ref->GetFileSystemURL(), &platform_path));
+ GURL(file_info.file_system_url_spec), &platform_path));
break;
case PP_FILESYSTEMTYPE_EXTERNAL:
- platform_path = file_ref->GetSystemPath();
+ platform_path = file_info.external_path;
break;
default:
NOTREACHED();
@@ -84,7 +77,7 @@
// Checks that the request data is valid. Returns false on failure. Note that
// method and header validation is done by the URL loader when the request is
// opened, and any access errors are returned asynchronously.
-bool ValidateURLRequestData(const ::ppapi::URLRequestInfoData& data) {
+bool ValidateURLRequestData(const URLRequestInfoData& data) {
if (data.prefetch_buffer_lower_threshold < 0 ||
data.prefetch_buffer_upper_threshold < 0 ||
data.prefetch_buffer_upper_threshold <=
@@ -94,33 +87,16 @@
return true;
}
-// Ensures that the file_ref members of the given request info data are
-// populated from the resource IDs. Returns true on success.
-bool EnsureFileRefObjectsPopulated(::ppapi::URLRequestInfoData* data) {
- // Get the Resource objects for any file refs with only host resource (this
- // is the state of the request as it comes off IPC).
- for (size_t i = 0; i < data->body.size(); ++i) {
- URLRequestInfoData::BodyItem& item = data->body[i];
- if (item.is_file && !item.file_ref.get()) {
- EnterResourceNoLock<PPB_FileRef_API> enter(
- item.file_ref_host_resource.host_resource(), false);
- if (!enter.succeeded())
- return false;
- item.file_ref = enter.resource();
- }
- }
- return true;
-}
-
} // namespace
-bool CreateWebURLRequest(::ppapi::URLRequestInfoData* data,
+bool CreateWebURLRequest(PP_Instance instance,
+ URLRequestInfoData* data,
WebFrame* frame,
WebURLRequest* dest) {
// In the out-of-process case, we've received the URLRequestInfoData
// from the untrusted plugin and done no validation on it. We need to be
// sure it's not being malicious by checking everything for consistency.
- if (!ValidateURLRequestData(*data) || !EnsureFileRefObjectsPopulated(data))
+ if (!ValidateURLRequestData(*data))
return false;
dest->initialize();
@@ -145,19 +121,44 @@
}
}
+ // Get file information for FileRefs inside BodyItems.
+ std::vector<PP_Resource> resources;
+ for (size_t i = 0; i < data->body.size(); ++i) {
+ const URLRequestInfoData::BodyItem& item = data->body[i];
+ if (item.is_file)
+ resources.push_back(item.file_ref_pp_resource);
+ }
+ std::vector<ppapi::FileRefDetailedInfo> infos;
+
+ if (!resources.empty()) {
+ PepperPluginInstanceImpl* instance_impl =
+ HostGlobals::Get()->GetInstance(instance);
+ int child_process_id = instance_impl->module()->GetPluginChildId();
+ // The routing id is automatically populated for us when set to 0.
+ RenderThreadImpl::current()->Send(
+ new PpapiHostMsg_FileRef_SyncGetInfoForRenderer(
+ 0, child_process_id, resources, &infos));
+ if (infos.size() != resources.size())
+ return false;
+ }
+
// Append the upload data.
if (!data->body.empty()) {
WebHTTPBody http_body;
http_body.initialize();
+ int file_index = 0;
for (size_t i = 0; i < data->body.size(); ++i) {
const URLRequestInfoData::BodyItem& item = data->body[i];
if (item.is_file) {
- if (!AppendFileRefToBody(item.file_ref.get(),
+ if (item.file_ref_pp_resource != infos[file_index].resource)
+ return false;
+ if (!AppendFileRefToBody(infos[file_index],
item.start_offset,
item.number_of_bytes,
item.expected_last_modified_time,
&http_body))
return false;
+ file_index++;
} else {
DCHECK(!item.data.empty());
http_body.appendData(WebData(item.data));
@@ -190,8 +191,7 @@
return true;
}
-bool URLRequestRequiresUniversalAccess(
- const ::ppapi::URLRequestInfoData& data) {
+bool URLRequestRequiresUniversalAccess(const URLRequestInfoData& data) {
return
data.has_custom_referrer_url ||
data.has_custom_content_transfer_encoding ||
diff --git a/content/renderer/pepper/url_request_info_util.h b/content/renderer/pepper/url_request_info_util.h
index 4261535..2fb40e6 100644
--- a/content/renderer/pepper/url_request_info_util.h
+++ b/content/renderer/pepper/url_request_info_util.h
@@ -7,6 +7,7 @@
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
+#include "ppapi/c/pp_instance.h"
namespace ppapi {
struct URLRequestInfoData;
@@ -23,13 +24,14 @@
// on success, false if the request is invalid (in which case *dest may be
// partially initialized). Any upload files with only resource IDs (no file ref
// pointers) will be populated by this function on success.
-CONTENT_EXPORT bool CreateWebURLRequest(::ppapi::URLRequestInfoData* data,
+CONTENT_EXPORT bool CreateWebURLRequest(PP_Instance instance,
+ ppapi::URLRequestInfoData* data,
WebKit::WebFrame* frame,
WebKit::WebURLRequest* dest);
// Returns true if universal access is required to use the given request.
CONTENT_EXPORT bool URLRequestRequiresUniversalAccess(
- const ::ppapi::URLRequestInfoData& data);
+ const ppapi::URLRequestInfoData& data);
} // namespace content
diff --git a/content/renderer/pepper/url_response_info_util.cc b/content/renderer/pepper/url_response_info_util.cc
index a9eccef..811ed35 100644
--- a/content/renderer/pepper/url_response_info_util.cc
+++ b/content/renderer/pepper/url_response_info_util.cc
@@ -7,7 +7,10 @@
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/message_loop/message_loop.h"
-#include "content/renderer/pepper/ppb_file_ref_impl.h"
+#include "content/public/renderer/renderer_ppapi_host.h"
+#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
+#include "ipc/ipc_message.h"
+#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/url_response_info_data.h"
#include "third_party/WebKit/public/platform/WebCString.h"
#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
@@ -43,13 +46,23 @@
return status >= 300 && status <= 399;
}
+void DidCreateResourceHost(const ppapi::URLResponseInfoData& in_data,
+ const base::FilePath& external_path,
+ const DataFromWebURLResponseCallback& callback,
+ int pending_resource_id) {
+ ppapi::URLResponseInfoData data = in_data;
+ data.body_as_file_ref = ppapi::MakeExternalFileRefCreateInfo(
+ external_path, std::string(), pending_resource_id);
+ callback.Run(data);
+}
+
} // namespace
-void DataFromWebURLResponse(PP_Instance pp_instance,
+void DataFromWebURLResponse(RendererPpapiHostImpl* host_impl,
+ PP_Instance pp_instance,
const WebURLResponse& response,
const DataFromWebURLResponseCallback& callback) {
ppapi::URLResponseInfoData data;
-
data.url = response.url().spec();
data.status_code = response.httpStatusCode();
data.status_text = response.httpStatusText().utf8();
@@ -64,18 +77,16 @@
WebString file_path = response.downloadFilePath();
if (!file_path.isEmpty()) {
- scoped_refptr<PPB_FileRef_Impl> file_ref(
- PPB_FileRef_Impl::CreateExternal(
- pp_instance,
- base::FilePath::FromUTF16Unsafe(file_path),
- std::string()));
- data.body_as_file_ref = file_ref->GetCreateInfo();
- file_ref->GetReference(); // The returned data has one ref for the plugin.
+ base::FilePath external_path = base::FilePath::FromUTF16Unsafe(file_path);
+ host_impl->CreateBrowserResourceHost(
+ pp_instance,
+ PpapiHostMsg_FileRef_CreateExternal(external_path),
+ base::Bind(&DidCreateResourceHost, data, external_path, callback));
+ } else {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(callback, data));
}
-
- // We post data to a callback instead of returning it here because the new
- // implementation for FileRef is asynchronous when creating the resource.
- base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, data));
}
} // namespace content
diff --git a/content/renderer/pepper/url_response_info_util.h b/content/renderer/pepper/url_response_info_util.h
index 21eba4c..ee0c238 100644
--- a/content/renderer/pepper/url_response_info_util.h
+++ b/content/renderer/pepper/url_response_info_util.h
@@ -14,6 +14,7 @@
}
namespace content {
+class RendererPpapiHostImpl;
typedef base::Callback<void(const ppapi::URLResponseInfoData&)>
DataFromWebURLResponseCallback;
@@ -21,7 +22,8 @@
// The returned object will have one plugin reference to the "body_as_file_ref"
// if it's non-null. It's expected that the result of this function will be
// passed to the plugin.
-void DataFromWebURLResponse(PP_Instance pp_instance,
+void DataFromWebURLResponse(RendererPpapiHostImpl* host_impl,
+ PP_Instance pp_instance,
const WebKit::WebURLResponse& response,
const DataFromWebURLResponseCallback& callback);
diff --git a/content/renderer/pepper/v8_var_converter.cc b/content/renderer/pepper/v8_var_converter.cc
index 25f9b66..8942c45 100644
--- a/content/renderer/pepper/v8_var_converter.cc
+++ b/content/renderer/pepper/v8_var_converter.cc
@@ -85,7 +85,7 @@
ParentVarSet* parent_ids) {
*did_create = false;
- if (::ppapi::VarTracker::IsVarTypeRefcounted(var.type)) {
+ if (ppapi::VarTracker::IsVarTypeRefcounted(var.type)) {
if (parent_ids->count(var.value.as_id) != 0)
return false;
VarHandleMap::iterator it = visited_ids->find(var.value.as_id);
@@ -151,7 +151,7 @@
}
*did_create = true;
- if (::ppapi::VarTracker::IsVarTypeRefcounted(var.type))
+ if (ppapi::VarTracker::IsVarTypeRefcounted(var.type))
(*visited_ids)[var.value.as_id] = *result;
return true;
}
diff --git a/content/renderer/pepper/v8_var_converter_unittest.cc b/content/renderer/pepper/v8_var_converter_unittest.cc
index 3c3365d..c98766f 100644
--- a/content/renderer/pepper/v8_var_converter_unittest.cc
+++ b/content/renderer/pepper/v8_var_converter_unittest.cc
@@ -45,7 +45,7 @@
bool Equals(const PP_Var& var,
v8::Handle<v8::Value> val,
VarHandleMap* visited_ids) {
- if (::ppapi::VarTracker::IsVarTypeRefcounted(var.type)) {
+ if (ppapi::VarTracker::IsVarTypeRefcounted(var.type)) {
VarHandleMap::iterator it = visited_ids->find(var.value.as_id);
if (it != visited_ids->end())
return it->second == val;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index fdc0df6..92bfb3d 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -6,7 +6,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
-#include "content/child/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_dispatcher.h"
#include "content/child/fileapi/file_system_dispatcher.h"
#include "content/child/fileapi/webfilesystem_callback_adapters.h"
#include "content/child/quota_dispatcher.h"
@@ -65,11 +65,8 @@
using WebKit::WebUserGestureIndicator;
using WebKit::WebVector;
using WebKit::WebView;
-
-using appcache::WebApplicationCacheHostImpl;
using base::Time;
using base::TimeDelta;
-
using webkit_glue::WebURLResponseExtraDataImpl;
namespace content {
@@ -78,9 +75,8 @@
NULL;
// static
-RenderFrameImpl* RenderFrameImpl::Create(
- RenderViewImpl* render_view,
- int32 routing_id) {
+RenderFrameImpl* RenderFrameImpl::Create(RenderViewImpl* render_view,
+ int32 routing_id) {
DCHECK(routing_id != MSG_ROUTING_NONE);
RenderFrameImpl* render_frame = NULL;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index fd86944..b1e4a71 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -26,7 +26,8 @@
#include "base/threading/thread_local.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
-#include "content/child/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_frontend_impl.h"
#include "content/child/child_histogram_message_filter.h"
#include "content/child/db_message_filter.h"
#include "content/child/indexed_db/indexed_db_dispatcher.h"
@@ -108,7 +109,6 @@
#include "v8/include/v8.h"
#include "webkit/child/worker_task_runner.h"
#include "webkit/glue/webkit_glue.h"
-#include "webkit/renderer/appcache/appcache_frontend_impl.h"
#include "webkit/renderer/compositor_bindings/web_external_bitmap_impl.h"
#if defined(OS_WIN)
@@ -351,7 +351,7 @@
shutdown_event_ = NULL;
appcache_dispatcher_.reset(
- new AppCacheDispatcher(Get(), new appcache::AppCacheFrontendImpl()));
+ new AppCacheDispatcher(Get(), new AppCacheFrontendImpl()));
dom_storage_dispatcher_.reset(new DomStorageDispatcher());
main_thread_indexed_db_dispatcher_.reset(new IndexedDBDispatcher(
thread_safe_sender()));
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 5299bdd..c533788 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -29,7 +29,8 @@
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
-#include "content/child/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_dispatcher.h"
+#include "content/child/appcache/web_application_cache_host_impl.h"
#include "content/child/child_thread.h"
#include "content/child/fileapi/file_system_dispatcher.h"
#include "content/child/fileapi/webfilesystem_callback_adapters.h"
@@ -205,7 +206,6 @@
#include "ui/shell_dialogs/selected_file_info.h"
#include "v8/include/v8.h"
#include "webkit/child/weburlresponse_extradata_impl.h"
-#include "webkit/renderer/appcache/web_application_cache_host_impl.h"
#include "webkit/renderer/webpreferences_renderer.h"
#if defined(OS_ANDROID)
@@ -218,7 +218,8 @@
#include "content/renderer/android/email_detector.h"
#include "content/renderer/android/phone_number_detector.h"
#include "content/renderer/media/android/renderer_media_player_manager.h"
-#include "content/renderer/media/android/stream_texture_factory_android.h"
+#include "content/renderer/media/android/stream_texture_factory_android_impl.h"
+#include "content/renderer/media/android/stream_texture_factory_android_synchronous_impl.h"
#include "content/renderer/media/android/webmediaplayer_android.h"
#include "content/renderer/media/android/webmediaplayer_proxy_android.h"
#include "skia/ext/platform_canvas.h"
@@ -336,10 +337,8 @@
using WebKit::WebView;
using WebKit::WebWidget;
using WebKit::WebWindowFeatures;
-using appcache::WebApplicationCacheHostImpl;
using base::Time;
using base::TimeDelta;
-
using webkit_glue::WebURLResponseExtraDataImpl;
#if defined(OS_ANDROID)
@@ -3022,6 +3021,15 @@
media_player_proxy_ = new WebMediaPlayerProxyAndroid(
this, media_player_manager_.get());
}
+
+ scoped_ptr<StreamTextureFactory> stream_texture_factory;
+ if (UsingSynchronousRendererCompositor()) {
+ stream_texture_factory.reset(new StreamTextureFactorySynchronousImpl);
+ } else {
+ stream_texture_factory.reset(new StreamTextureFactoryImpl(
+ context_provider->Context3d(), gpu_channel_host, routing_id_));
+ }
+
scoped_ptr<WebMediaPlayerAndroid> web_media_player_android(
new WebMediaPlayerAndroid(
frame,
@@ -3029,8 +3037,7 @@
AsWeakPtr(),
media_player_manager_.get(),
media_player_proxy_,
- new StreamTextureFactory(
- context_provider->Context3d(), gpu_channel_host, routing_id_),
+ stream_texture_factory.release(),
new RenderMediaLog()));
#if defined(ENABLE_WEBRTC) && defined(GOOGLE_TV)
if (media_stream_client_->IsMediaStream(url)) {
diff --git a/content/renderer/renderer_webapplicationcachehost_impl.h b/content/renderer/renderer_webapplicationcachehost_impl.h
index 334c136..0612039 100644
--- a/content/renderer/renderer_webapplicationcachehost_impl.h
+++ b/content/renderer/renderer_webapplicationcachehost_impl.h
@@ -5,20 +5,19 @@
#ifndef CONTENT_RENDERER_RENDERER_WEBAPPLICATIONCACHEHOST_IMPL_H_
#define CONTENT_RENDERER_RENDERER_WEBAPPLICATIONCACHEHOST_IMPL_H_
-#include "webkit/renderer/appcache/web_application_cache_host_impl.h"
+#include "content/child/appcache/web_application_cache_host_impl.h"
namespace content {
class RenderViewImpl;
-class RendererWebApplicationCacheHostImpl
- : public appcache::WebApplicationCacheHostImpl {
+class RendererWebApplicationCacheHostImpl : public WebApplicationCacheHostImpl {
public:
RendererWebApplicationCacheHostImpl(
RenderViewImpl* render_view,
WebKit::WebApplicationCacheHostClient* client,
appcache::AppCacheBackend* backend);
- // appcache::WebApplicationCacheHostImpl methods.
+ // WebApplicationCacheHostImpl:
virtual void OnLogMessage(appcache::LogLevel log_level,
const std::string& message) OVERRIDE;
virtual void OnContentBlocked(const GURL& manifest_url) OVERRIDE;
diff --git a/webkit/plugins/sad_plugin.cc b/content/renderer/sad_plugin.cc
similarity index 93%
rename from webkit/plugins/sad_plugin.cc
rename to content/renderer/sad_plugin.cc
index ea355ee..a30788c 100644
--- a/webkit/plugins/sad_plugin.cc
+++ b/content/renderer/sad_plugin.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 "webkit/plugins/sad_plugin.h"
+#include "content/renderer/sad_plugin.h"
#include <algorithm>
@@ -11,7 +11,7 @@
#include "ui/gfx/blit.h"
#include "ui/gfx/rect.h"
-namespace webkit {
+namespace content {
void PaintSadPlugin(WebKit::WebCanvas* webcanvas,
const gfx::Rect& plugin_rect,
@@ -36,4 +36,4 @@
SkIntToScalar(std::max(0, (height - sad_plugin_bitmap.height()) / 2)));
}
-} // namespace webkit
+} // namespace content
diff --git a/content/renderer/sad_plugin.h b/content/renderer/sad_plugin.h
new file mode 100644
index 0000000..827d705
--- /dev/null
+++ b/content/renderer/sad_plugin.h
@@ -0,0 +1,26 @@
+// 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.
+
+#ifndef CONTENT_RENDERER_SAD_PLUGIN_H_
+#define CONTENT_RENDERER_SAD_PLUGIN_H_
+
+#include "third_party/WebKit/public/platform/WebCanvas.h"
+
+class SkBitmap;
+
+namespace gfx {
+class Rect;
+}
+
+namespace content {
+
+// Paints the sad plugin to the given canvas for the given plugin bounds. This
+// is used by both the NPAPI and the PPAPI out-of-process plugin impls.
+void PaintSadPlugin(WebKit::WebCanvas* canvas,
+ const gfx::Rect& plugin_rect,
+ const SkBitmap& sad_plugin_bitmap);
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_SAD_PLUGIN_H_
diff --git a/content/shell/renderer/shell_content_renderer_client.cc b/content/shell/renderer/shell_content_renderer_client.cc
index 4db6a52..433b368 100644
--- a/content/shell/renderer/shell_content_renderer_client.cc
+++ b/content/shell/renderer/shell_content_renderer_client.cc
@@ -188,7 +188,7 @@
}
bool ShellContentRendererClient::AllowBrowserPlugin(
- WebKit::WebPluginContainer* container) const {
+ WebKit::WebPluginContainer* container) {
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableBrowserPluginForAllViewTypes)) {
// Allow BrowserPlugin if forced by command line flag. This is generally
diff --git a/content/shell/renderer/shell_content_renderer_client.h b/content/shell/renderer/shell_content_renderer_client.h
index 10b2f43..fc35f03 100644
--- a/content/shell/renderer/shell_content_renderer_client.h
+++ b/content/shell/renderer/shell_content_renderer_client.h
@@ -54,7 +54,7 @@
virtual WebKit::WebCrypto* OverrideWebCrypto() OVERRIDE;
virtual WebKit::WebThemeEngine* OverrideThemeEngine() OVERRIDE;
virtual bool AllowBrowserPlugin(
- WebKit::WebPluginContainer* container) const OVERRIDE;
+ WebKit::WebPluginContainer* container) OVERRIDE;
private:
void WebTestProxyCreated(RenderView* render_view,
diff --git a/content/worker/DEPS b/content/worker/DEPS
index 34e8b17..24a1df5 100644
--- a/content/worker/DEPS
+++ b/content/worker/DEPS
@@ -1,7 +1,6 @@
include_rules = [
"+content/child",
"+sandbox/win/src",
- "+webkit/appcache",
"+webkit/glue",
]
diff --git a/content/worker/worker_thread.cc b/content/worker/worker_thread.cc
index 5cf8dbb..4cabcb4 100644
--- a/content/worker/worker_thread.cc
+++ b/content/worker/worker_thread.cc
@@ -7,7 +7,8 @@
#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/threading/thread_local.h"
-#include "content/child/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_frontend_impl.h"
#include "content/child/db_message_filter.h"
#include "content/child/indexed_db/indexed_db_message_filter.h"
#include "content/child/runtime_features.h"
@@ -22,7 +23,6 @@
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "webkit/glue/webkit_glue.h"
-#include "webkit/renderer/appcache/appcache_frontend_impl.h"
using WebKit::WebRuntimeFeatures;
@@ -40,7 +40,7 @@
WebKit::initialize(webkit_platform_support_.get());
appcache_dispatcher_.reset(
- new AppCacheDispatcher(this, new appcache::AppCacheFrontendImpl()));
+ new AppCacheDispatcher(this, new AppCacheFrontendImpl()));
web_database_observer_impl_.reset(
new WebDatabaseObserverImpl(sync_message_filter()));
diff --git a/content/worker/worker_webapplicationcachehost_impl.cc b/content/worker/worker_webapplicationcachehost_impl.cc
index ef0c966..9283906 100644
--- a/content/worker/worker_webapplicationcachehost_impl.cc
+++ b/content/worker/worker_webapplicationcachehost_impl.cc
@@ -4,7 +4,7 @@
#include "content/worker/worker_webapplicationcachehost_impl.h"
-#include "content/child/appcache_dispatcher.h"
+#include "content/child/appcache/appcache_dispatcher.h"
#include "content/worker/worker_thread.h"
namespace content {
diff --git a/content/worker/worker_webapplicationcachehost_impl.h b/content/worker/worker_webapplicationcachehost_impl.h
index 53482e1..2360cb3 100644
--- a/content/worker/worker_webapplicationcachehost_impl.h
+++ b/content/worker/worker_webapplicationcachehost_impl.h
@@ -5,7 +5,7 @@
#ifndef CHROME_WORKER_WORKER_WEBAPPLICATIONCACHEHOST_IMPL_H_
#define CHROME_WORKER_WORKER_WEBAPPLICATIONCACHEHOST_IMPL_H_
-#include "webkit/renderer/appcache/web_application_cache_host_impl.h"
+#include "content/child/appcache/web_application_cache_host_impl.h"
namespace content {
@@ -26,8 +26,7 @@
}
};
-class WorkerWebApplicationCacheHostImpl
- : public appcache::WebApplicationCacheHostImpl {
+class WorkerWebApplicationCacheHostImpl : public WebApplicationCacheHostImpl {
public:
WorkerWebApplicationCacheHostImpl(
const WorkerAppCacheInitInfo& init_info,
diff --git a/chrome/browser/extensions/error_console/extension_error.cc b/extensions/browser/extension_error.cc
similarity index 89%
rename from chrome/browser/extensions/error_console/extension_error.cc
rename to extensions/browser/extension_error.cc
index 9d8944c..8b6196c 100644
--- a/chrome/browser/extensions/error_console/extension_error.cc
+++ b/extensions/browser/extension_error.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 "chrome/browser/extensions/error_console/extension_error.h"
+#include "extensions/browser/extension_error.h"
#include "base/json/json_reader.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
-#include "chrome/common/extensions/extension.h"
#include "extensions/common/constants.h"
+#include "url/gurl.h"
using base::string16;
@@ -28,7 +28,7 @@
// populates |extension_id| with the ID. On failure, returns false and leaves
// extension_id untouched.
bool GetExtensionIDFromGURL(const GURL& url, std::string* extension_id) {
- if (url.SchemeIs(extensions::kExtensionScheme)) {
+ if (url.SchemeIs(kExtensionScheme)) {
*extension_id = url.host();
return true;
}
@@ -38,10 +38,12 @@
} // namespace
ExtensionError::ExtensionError(Type type,
+ const std::string& extension_id,
bool from_incognito,
const string16& source,
const string16& message)
: type_(type),
+ extension_id_(extension_id),
from_incognito_(from_incognito),
source_(source),
message_(message) {
@@ -58,15 +60,13 @@
"\n ID: " + extension_id_;
}
-ManifestParsingError::ManifestParsingError(bool from_incognito,
- const string16& source,
- const string16& message,
- size_t line_number)
+ManifestParsingError::ManifestParsingError(const std::string& extension_id,
+ const string16& message)
: ExtensionError(ExtensionError::MANIFEST_PARSING_ERROR,
- from_incognito,
- source,
- message),
- line_number_(line_number) {
+ extension_id,
+ false, // extensions can't be installed while incognito.
+ base::FilePath(kManifestFilename).AsUTF16Unsafe(),
+ message) {
}
ManifestParsingError::~ManifestParsingError() {
@@ -74,8 +74,7 @@
std::string ManifestParsingError::PrintForTest() const {
return ExtensionError::PrintForTest() +
- "\n Type: ManifestParsingError" +
- "\n Line: " + base::IntToString(line_number_);
+ "\n Type: ManifestParsingError";
}
JavascriptRuntimeError::StackFrame::StackFrame() : line_number(-1),
@@ -101,6 +100,7 @@
logging::LogSeverity level,
const string16& details)
: ExtensionError(ExtensionError::JAVASCRIPT_RUNTIME_ERROR,
+ std::string(), // We don't know the id yet.
from_incognito,
source,
message),
diff --git a/chrome/browser/extensions/error_console/extension_error.h b/extensions/browser/extension_error.h
similarity index 84%
rename from chrome/browser/extensions/error_console/extension_error.h
rename to extensions/browser/extension_error.h
index e462d91..1cd4a7b 100644
--- a/chrome/browser/extensions/error_console/extension_error.h
+++ b/extensions/browser/extension_error.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_EXTENSIONS_ERROR_CONSOLE_EXTENSION_ERROR_H_
-#define CHROME_BROWSER_EXTENSIONS_ERROR_CONSOLE_EXTENSION_ERROR_H_
+#ifndef EXTENSIONS_BROWSER_EXTENSION_ERROR_H_
+#define EXTENSIONS_BROWSER_EXTENSION_ERROR_H_
#include <string>
#include <vector>
@@ -33,12 +33,15 @@
protected:
ExtensionError(Type type,
+ const std::string& extension_id,
bool from_incognito,
const base::string16& source,
const base::string16& message);
// Which type of error this is.
Type type_;
+ // The ID of the extension which caused the error.
+ std::string extension_id_;
// Whether or not the error was caused while incognito.
bool from_incognito_;
// The source for the error; this can be a script, web page, or manifest file.
@@ -47,27 +50,18 @@
base::string16 source_;
// The error message itself.
base::string16 message_;
- // The ID of the extension which caused the error. This may be absent, since
- // we can't always know the id (such as when a manifest fails to parse).
- std::string extension_id_;
DISALLOW_COPY_AND_ASSIGN(ExtensionError);
};
class ManifestParsingError : public ExtensionError {
public:
- ManifestParsingError(bool from_incognito,
- const base::string16& source,
- const base::string16& message,
- size_t line_number);
+ ManifestParsingError(const std::string& extension_id,
+ const base::string16& message);
virtual ~ManifestParsingError();
virtual std::string PrintForTest() const OVERRIDE;
-
- size_t line_number() const { return line_number_; }
private:
- size_t line_number_;
-
DISALLOW_COPY_AND_ASSIGN(ManifestParsingError);
};
@@ -124,4 +118,4 @@
} // namespace extensions
-#endif // CHROME_BROWSER_EXTENSIONS_ERROR_CONSOLE_EXTENSION_ERROR_H_
+#endif // EXTENSIONS_BROWSER_EXTENSION_ERROR_H_
diff --git a/extensions/common/extensions_client.cc b/extensions/common/extensions_client.cc
new file mode 100644
index 0000000..e7f936d
--- /dev/null
+++ b/extensions/common/extensions_client.cc
@@ -0,0 +1,32 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "extensions/common/extensions_client.h"
+
+namespace extensions {
+
+namespace {
+
+ExtensionsClient* g_client = NULL;
+
+void Initialize(ExtensionsClient* client) {
+ client->RegisterManifestHandlers();
+}
+
+} // namespace
+
+ExtensionsClient* ExtensionsClient::Get() {
+ return g_client;
+}
+
+void ExtensionsClient::Set(ExtensionsClient* client) {
+ // This can happen in unit tests, where the utility thread runs in-process.
+ if (g_client)
+ return;
+ g_client = client;
+ Initialize(g_client);
+}
+
+} // namespace extensions
diff --git a/extensions/common/extensions_client.h b/extensions/common/extensions_client.h
new file mode 100644
index 0000000..83550a9
--- /dev/null
+++ b/extensions/common/extensions_client.h
@@ -0,0 +1,38 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_COMMON_EXTENSIONS_CLIENT_H_
+#define EXTENSIONS_COMMON_EXTENSIONS_CLIENT_H_
+
+#include <string>
+
+namespace extensions {
+
+class FeatureProvider;
+class PermissionsProvider;
+
+// Sets up global state for the extensions system. Should be Set() once in each
+// process. This should be implemented by the client of the extensions system.
+class ExtensionsClient {
+ public:
+ // Returns a PermissionsProvider to initialize the permissions system.
+ virtual const PermissionsProvider& GetPermissionsProvider() const = 0;
+
+ // Gets a feature provider for a specific feature type.
+ virtual FeatureProvider* GetFeatureProviderByName(const std::string& name)
+ const = 0;
+
+ // Called at startup. Registers the handlers for parsing manifests.
+ virtual void RegisterManifestHandlers() const = 0;
+
+ // Return the extensions client.
+ static ExtensionsClient* Get();
+
+ // Initialize the extensions system with this extensions client.
+ static void Set(ExtensionsClient* client);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_EXTENSIONS_CLIENT_H_
diff --git a/extensions/common/features/feature_provider.cc b/extensions/common/features/feature_provider.cc
new file mode 100644
index 0000000..8e15d4b
--- /dev/null
+++ b/extensions/common/features/feature_provider.cc
@@ -0,0 +1,16 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/common/features/feature_provider.h"
+
+#include "base/basictypes.h"
+#include "extensions/common/extensions_client.h"
+
+namespace extensions {
+
+FeatureProvider* FeatureProvider::GetByName(const std::string& name) {
+ return ExtensionsClient::Get()->GetFeatureProviderByName(name);
+}
+
+} // namespace extensions
diff --git a/chrome/common/extensions/features/feature_provider.h b/extensions/common/features/feature_provider.h
similarity index 64%
rename from chrome/common/extensions/features/feature_provider.h
rename to extensions/common/features/feature_provider.h
index 56942d5..c20e5d1 100644
--- a/chrome/common/extensions/features/feature_provider.h
+++ b/extensions/common/features/feature_provider.h
@@ -1,11 +1,12 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CHROME_COMMON_EXTENSIONS_FEATURES_FEATURE_PROVIDER_H_
-#define CHROME_COMMON_EXTENSIONS_FEATURES_FEATURE_PROVIDER_H_
+#ifndef EXTENSIONS_COMMON_FEATURES_FEATURE_PROVIDER_H_
+#define EXTENSIONS_COMMON_FEATURES_FEATURE_PROVIDER_H_
#include <string>
+#include <vector>
namespace extensions {
@@ -25,8 +26,11 @@
// Returns all features described by this instance.
virtual const std::vector<std::string>& GetAllFeatureNames() = 0;
+
+ // Gets a feature provider for a specific feature type, like "permission".
+ static FeatureProvider* GetByName(const std::string& name);
};
} // namespace extensions
-#endif // CHROME_COMMON_EXTENSIONS_FEATURES_FEATURE_PROVIDER_H_
+#endif // EXTENSIONS_COMMON_FEATURES_FEATURE_PROVIDER_H_
diff --git a/extensions/common/permissions/permissions_provider.h b/extensions/common/permissions/permissions_provider.h
new file mode 100644
index 0000000..5a27a86
--- /dev/null
+++ b/extensions/common/permissions/permissions_provider.h
@@ -0,0 +1,37 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_COMMON_PERMISSIONS_PERMISSIONS_PROVIDER_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_PERMISSIONS_PROVIDER_H_
+
+#include <vector>
+
+namespace extensions {
+
+class APIPermissionInfo;
+
+// The PermissionsProvider creates the APIPermissions instances. It is only
+// needed at startup time.
+class PermissionsProvider {
+ public:
+ // An alias for a given permission |name|.
+ struct AliasInfo {
+ const char* name;
+ const char* alias;
+
+ AliasInfo(const char* name, const char* alias)
+ : name(name), alias(alias) {
+ }
+ };
+ // Returns all the known permissions. The caller, PermissionsInfo,
+ // takes ownership of the APIPermissionInfos.
+ virtual std::vector<APIPermissionInfo*> GetAllPermissions() const = 0;
+
+ // Returns all the known permission aliases.
+ virtual std::vector<AliasInfo> GetAllAliases() const = 0;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_PERMISSIONS_PERMISSIONS_PROVIDER_H_
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
index 93d940d..423a723 100644
--- a/gpu/config/gpu_driver_bug_list_json.cc
+++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -38,7 +38,7 @@
// 13. "perf_graphics" is a FLOAT structure (defined below).
// 14. "perf_gaming" is a FLOAT structure (defined below).
// 15. "perf_overall" is a FLOAT structure (defined below).
-// 16. "machine_model" contais "name" and an optional "version". "name" is a
+// 16. "machine_model" contains "name" and an optional "version". "name" is a
// STRING structure and "version" is a VERSION structure (defined below).
// 17. "gpu_count" is a INT structure (defined below).
// 18 "cpu_info" is a STRING structure (defined below).
@@ -85,7 +85,7 @@
{
"name": "gpu driver bug list",
// Please update the version number whenever you change this file.
- "version": "2.4",
+ "version": "2.5",
"entries": [
{
"id": 1,
@@ -411,6 +411,20 @@
"features": [
"disable_d3d11"
]
+ },
+ {
+ "id": 27,
+ "cr_bugs": [265115],
+ "description": "Async Readpixels with GL_BGRA format is broken on Haswell chipset on Mac.",
+ "os": {
+ "type": "macosx"
+ },
+ "vendor_id": "0x8086",
+ "device_id": ["0x0402", "0x0406", "0x040a", "0x0412", "0x0416", "0x041a",
+ "0x0a04", "0x0a16", "0x0a22", "0x0a26", "0x0a2a"],
+ "features": [
+ "swizzle_rgba_for_async_readpixels"
+ ]
}
]
}
diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h
index 8b733ea..20198da 100644
--- a/gpu/config/gpu_driver_bug_workaround_type.h
+++ b/gpu/config/gpu_driver_bug_workaround_type.h
@@ -60,6 +60,8 @@
disable_async_readpixels) \
GPU_OP(DISABLE_D3D11, \
disable_d3d11) \
+ GPU_OP(SWIZZLE_RGBA_FOR_ASYNC_READPIXELS, \
+ swizzle_rgba_for_async_readpixels) \
namespace gpu {
diff --git a/ios/public/DEPS b/ios/public/DEPS
index 3f0cd59..c04c1d5 100644
--- a/ios/public/DEPS
+++ b/ios/public/DEPS
@@ -4,7 +4,6 @@
# be kept in sync with src/DEPS.
"-base",
"-build",
- "-googleurl",
"-library_loaders",
"-testing",
"-third_party/icu/source/common/unicode",
diff --git a/media/audio/OWNERS b/media/audio/OWNERS
index b0a7558..17c8ecc 100644
--- a/media/audio/OWNERS
+++ b/media/audio/OWNERS
@@ -3,9 +3,6 @@
# Linux/Pulse
xians@chromium.org
-# OSX
-crogers@google.com
-
# Windows
henrika@chromium.org
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
index 7ffc7d3..db77f00 100644
--- a/media/audio/audio_manager_base.cc
+++ b/media/audio/audio_manager_base.cc
@@ -269,18 +269,15 @@
const base::TimeDelta kCloseDelay =
base::TimeDelta::FromSeconds(kStreamCloseDelaySeconds);
-
+ scoped_refptr<AudioOutputDispatcher> dispatcher;
if (output_params.format() != AudioParameters::AUDIO_FAKE) {
- scoped_refptr<AudioOutputDispatcher> dispatcher =
- new AudioOutputResampler(this, params, output_params, input_device_id,
- kCloseDelay);
- dispatcher_params->dispatcher = dispatcher;
- return new AudioOutputProxy(dispatcher.get());
+ dispatcher = new AudioOutputResampler(this, params, output_params,
+ input_device_id, kCloseDelay);
+ } else {
+ dispatcher = new AudioOutputDispatcherImpl(this, output_params,
+ input_device_id, kCloseDelay);
}
- scoped_refptr<AudioOutputDispatcher> dispatcher =
- new AudioOutputDispatcherImpl(this, output_params, input_device_id,
- kCloseDelay);
dispatcher_params->dispatcher = dispatcher;
output_dispatchers_.push_back(dispatcher_params);
return new AudioOutputProxy(dispatcher.get());
diff --git a/media/audio/audio_power_monitor.cc b/media/audio/audio_power_monitor.cc
index 4dc1517..fa76828 100644
--- a/media/audio/audio_power_monitor.cc
+++ b/media/audio/audio_power_monitor.cc
@@ -84,7 +84,8 @@
(average_power_ < kInsignificantPower) ? 0.0f : average_power_;
if (power != last_reported_power_ ||
clipped_since_last_notification_ != last_reported_clipped_) {
- const float power_dbfs = 10.0f * log10f(power);
+ const float power_dbfs =
+ power > 0.0f ? 10.0f * log10f(power) : zero_power();
// Try to post a task to run the callback with the dBFS result. The
// posting of the task is guaranteed to be non-blocking, and therefore
// could fail. However, in the common case, failures should be rare (and
diff --git a/media/base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java b/media/base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java
index ac752d4..1de7e42 100644
--- a/media/base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java
+++ b/media/base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java
@@ -61,7 +61,14 @@
MediaFormat format = extractor.getTrackFormat(0);
- int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+ // Number of channels specified in the file
+ int inputChannelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+
+ // Number of channels the decoder will provide. (Not
+ // necessarily the same as inputChannelCount. See
+ // crbug.com/266006.)
+ int outputChannelCount = inputChannelCount;
+
int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
String mime = format.getString(MediaFormat.KEY_MIME);
@@ -77,13 +84,13 @@
if (DEBUG) {
Log.d(LOG_TAG, "Tracks: " + extractor.getTrackCount()
+ " Rate: " + sampleRate
- + " Channels: " + channelCount
+ + " Channels: " + inputChannelCount
+ " Mime: " + mime
+ " Duration: " + durationMicroseconds + " microsec");
}
nativeInitializeDestination(nativeMediaCodecBridge,
- channelCount,
+ inputChannelCount,
sampleRate,
durationMicroseconds);
@@ -139,7 +146,8 @@
ByteBuffer buf = codecOutputBuffers[outputBufIndex];
if (info.size > 0) {
- nativeOnChunkDecoded(nativeMediaCodecBridge, buf, info.size);
+ nativeOnChunkDecoded(nativeMediaCodecBridge, buf, info.size,
+ inputChannelCount, outputChannelCount);
}
buf.clear();
@@ -150,6 +158,10 @@
}
} else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
codecOutputBuffers = codec.getOutputBuffers();
+ } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+ MediaFormat newFormat = codec.getOutputFormat();
+ outputChannelCount = newFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+ Log.d(LOG_TAG, "output format changed to " + newFormat);
}
}
@@ -163,11 +175,12 @@
}
private static native void nativeOnChunkDecoded(
- int nativeWebAudioMediaCodecBridge, ByteBuffer buf, int size);
+ int nativeWebAudioMediaCodecBridge, ByteBuffer buf, int size,
+ int inputChannelCount, int outputChannelCount);
private static native void nativeInitializeDestination(
int nativeWebAudioMediaCodecBridge,
- int channelCount,
+ int inputChannelCount,
int sampleRate,
long durationMicroseconds);
}
diff --git a/media/base/android/media_player_bridge.cc b/media/base/android/media_player_bridge.cc
index e0d9868..342ceaa 100644
--- a/media/base/android/media_player_bridge.cc
+++ b/media/base/android/media_player_bridge.cc
@@ -390,6 +390,16 @@
}
void MediaPlayerBridge::SeekInternal(base::TimeDelta time) {
+ if (time > duration_)
+ time = duration_;
+
+ // Seeking to an invalid position may cause media player to stuck in an
+ // error state.
+ if (time < base::TimeDelta()) {
+ DCHECK_EQ(-1.0, time.InMillisecondsF());
+ return;
+ }
+
JNIEnv* env = base::android::AttachCurrentThread();
CHECK(env);
diff --git a/media/base/android/webaudio_media_codec_bridge.cc b/media/base/android/webaudio_media_codec_bridge.cc
index 6024a59..94f059a 100644
--- a/media/base/android/webaudio_media_codec_bridge.cc
+++ b/media/base/android/webaudio_media_codec_bridge.cc
@@ -17,6 +17,7 @@
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
+#include "base/stl_util.h"
#include "jni/WebAudioMediaCodecBridge_jni.h"
#include "media/base/android/webaudio_media_codec_info.h"
@@ -148,15 +149,35 @@
JNIEnv* env,
jobject /*java object*/,
jobject buf,
- jint buf_size) {
+ jint buf_size,
+ jint input_channel_count,
+ jint output_channel_count) {
if (buf_size <= 0 || !buf)
return;
int8_t* buffer =
static_cast<int8_t*>(env->GetDirectBufferAddress(buf));
-
size_t count = static_cast<size_t>(buf_size);
+ std::vector<int16_t> decoded_data;
+
+ if (input_channel_count == 1 && output_channel_count == 2) {
+ // See crbug.com/266006. The file has one channel, but the
+ // decoder decided to return two channels. To be consistent with
+ // the number of channels in the file, only send one channel (the
+ // first).
+ int16_t* data = static_cast<int16_t*>(env->GetDirectBufferAddress(buf));
+ int frame_count = buf_size / sizeof(*data) / 2;
+
+ decoded_data.resize(frame_count);
+ for (int k = 0; k < frame_count; ++k) {
+ decoded_data[k] = *data;
+ data += 2;
+ }
+ buffer = reinterpret_cast<int8_t*>(vector_as_array(&decoded_data));
+ DCHECK(buffer);
+ count = frame_count * sizeof(*data);
+ }
// Write out the data to the pipe in small chunks if necessary.
while (count > 0) {
diff --git a/media/base/android/webaudio_media_codec_bridge.h b/media/base/android/webaudio_media_codec_bridge.h
index abf7f3f..fda6126 100644
--- a/media/base/android/webaudio_media_codec_bridge.h
+++ b/media/base/android/webaudio_media_codec_bridge.h
@@ -41,7 +41,9 @@
void OnChunkDecoded(JNIEnv* env,
jobject /*java object*/,
jobject buf,
- jint buf_size);
+ jint buf_size,
+ jint input_channel_count,
+ jint output_channel_count);
void InitializeDestination(JNIEnv* env,
jobject /*java object*/,
diff --git a/media/base/media_file_checker.cc b/media/base/media_file_checker.cc
new file mode 100644
index 0000000..d4708e5
--- /dev/null
+++ b/media/base/media_file_checker.cc
@@ -0,0 +1,110 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/media_file_checker.h"
+
+#include <map>
+
+#include "base/bind.h"
+#include "base/time/time.h"
+#include "media/ffmpeg/ffmpeg_common.h"
+#include "media/filters/blocking_url_protocol.h"
+#include "media/filters/ffmpeg_glue.h"
+#include "media/filters/file_data_source.h"
+
+namespace media {
+
+static const int64 kMaxCheckTimeInSeconds = 5;
+
+static void OnError(bool* called) {
+ *called = false;
+}
+
+MediaFileChecker::MediaFileChecker(const base::PlatformFile& file)
+ : file_(file),
+ file_closer_(&file_) {
+}
+
+MediaFileChecker::~MediaFileChecker() {
+}
+
+bool MediaFileChecker::Start(base::TimeDelta check_time) {
+ media::FileDataSource source;
+ bool read_ok = true;
+ media::BlockingUrlProtocol protocol(&source, base::Bind(&OnError, &read_ok));
+ media::FFmpegGlue glue(&protocol);
+ source.InitializeFromPlatformFile(file_);
+ AVFormatContext* format_context = glue.format_context();
+
+ if (!glue.OpenContext())
+ return false;
+
+ if (avformat_find_stream_info(format_context, NULL) < 0)
+ return false;
+
+ // Remember the codec context for any decodable audio or video streams.
+ std::map<int, AVCodecContext*> stream_contexts;
+ for (size_t i = 0; i < format_context->nb_streams; ++i) {
+ AVCodecContext* c = format_context->streams[i]->codec;
+ if (c->codec_type == AVMEDIA_TYPE_AUDIO ||
+ c->codec_type == AVMEDIA_TYPE_VIDEO) {
+ AVCodec* codec = avcodec_find_decoder(c->codec_id);
+ if (codec && avcodec_open2(c, codec, NULL) >= 0)
+ stream_contexts[i] = c;
+ }
+ }
+
+ if (stream_contexts.size() == 0)
+ return false;
+
+ AVPacket packet;
+ scoped_ptr_malloc<AVFrame, media::ScopedPtrAVFree> frame(
+ avcodec_alloc_frame());
+ int result = 0;
+
+ base::Time deadline = base::Time::Now() +
+ std::min(check_time,
+ base::TimeDelta::FromSeconds(kMaxCheckTimeInSeconds));
+ do {
+ result = av_read_frame(glue.format_context(), &packet);
+ if (result < 0)
+ break;
+ result = av_dup_packet(&packet);
+ if (result < 0)
+ break;
+
+ std::map<int, AVCodecContext*>::const_iterator it =
+ stream_contexts.find(packet.stream_index);
+ if (it == stream_contexts.end()) {
+ av_free_packet(&packet);
+ continue;
+ }
+ AVCodecContext* av_context = it->second;
+
+ int frame_decoded = 0;
+ if (av_context->codec_type == AVMEDIA_TYPE_AUDIO) {
+ // A shallow copy of packet so we can slide packet.data as frames are
+ // decoded; otherwise av_free_packet() will corrupt memory.
+ AVPacket temp_packet = packet;
+ do {
+ avcodec_get_frame_defaults(frame.get());
+ result = avcodec_decode_audio4(av_context, frame.get(), &frame_decoded,
+ &temp_packet);
+ if (result < 0)
+ break;
+ temp_packet.size -= result;
+ temp_packet.data += result;
+ } while (temp_packet.size > 0);
+ } else if (av_context->codec_type == AVMEDIA_TYPE_VIDEO) {
+ avcodec_get_frame_defaults(frame.get());
+ result = avcodec_decode_video2(av_context, frame.get(), &frame_decoded,
+ &packet);
+ }
+ av_free_packet(&packet);
+ } while (base::Time::Now() < deadline && read_ok && result >= 0);
+
+ return read_ok && (result == AVERROR_EOF || result >= 0);
+}
+
+} // namespace media
diff --git a/media/base/media_file_checker.h b/media/base/media_file_checker.h
new file mode 100644
index 0000000..6e8fc9f
--- /dev/null
+++ b/media/base/media_file_checker.h
@@ -0,0 +1,41 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_MEDIA_FILE_CHECKER_H_
+#define MEDIA_BASE_MEDIA_FILE_CHECKER_H_
+
+#include "base/basictypes.h"
+#include "base/files/scoped_platform_file_closer.h"
+#include "base/platform_file.h"
+#include "media/base/media_export.h"
+
+namespace base {
+class TimeDelta;
+}
+
+namespace media {
+
+// This class tries to determine if a file is a valid media file. The entire
+// file is not decoded so a positive result from this class does not make the
+// file safe to use in the browser process.
+class MEDIA_EXPORT MediaFileChecker {
+ public:
+ explicit MediaFileChecker(const base::PlatformFile& file);
+ ~MediaFileChecker();
+
+ // After opening |file|, up to |check_time| amount of wall-clock time is spent
+ // decoding the file. The amount of audio/video data decoded will depend on
+ // the bitrate of the file and the speed of the CPU.
+ bool Start(base::TimeDelta check_time);
+
+ private:
+ base::PlatformFile file_;
+ base::ScopedPlatformFileCloser file_closer_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaFileChecker);
+};
+
+} // namespace media
+
+#endif // MEDIA_BASE_MEDIA_FILE_CHECKER_H_
diff --git a/media/base/media_file_checker_unittest.cc b/media/base/media_file_checker_unittest.cc
new file mode 100644
index 0000000..f43c846
--- /dev/null
+++ b/media/base/media_file_checker_unittest.cc
@@ -0,0 +1,48 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "media/base/media_file_checker.h"
+#include "media/base/test_data_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+static void RunMediaFileChecker(const std::string& filename, bool expectation) {
+ base::PlatformFileError error;
+ base::PlatformFile file = base::CreatePlatformFile(
+ GetTestDataFilePath(filename),
+ base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
+ NULL,
+ &error);
+ ASSERT_EQ(base::PLATFORM_FILE_OK, error);
+
+ MediaFileChecker checker(file);
+ const base::TimeDelta check_time = base::TimeDelta::FromMilliseconds(100);
+ bool result = checker.Start(check_time);
+ EXPECT_EQ(expectation, result);
+
+ base::ClosePlatformFile(file);
+}
+
+TEST(MediaFileCheckerTest, InvalidFile) {
+ RunMediaFileChecker("ten_byte_file", false);
+}
+
+TEST(MediaFileCheckerTest, Video) {
+ RunMediaFileChecker("bear.ogv", true);
+}
+
+TEST(MediaFileCheckerTest, Audio) {
+ RunMediaFileChecker("sfx.ogg", true);
+}
+
+#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS)
+TEST(MediaFileCheckerTest, MP3) {
+ RunMediaFileChecker("sfx.mp3", true);
+}
+#endif
+
+} // namespace media
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 153c22a..3c1dc16 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -57,6 +57,12 @@
// for details.
const char kEnableExclusiveAudio[] = "enable-exclusive-audio";
+// Used to troubleshoot problems with different video capture implementations
+// on Windows. By default we use the Media Foundation API on Windows 7 and up,
+// but specifying this switch will force use of DirectShow always.
+// See bug: http://crbug.com/268412
+const char kForceDirectShowVideoCapture[] = "force-directshow";
+
// Use Windows WaveOut/In audio API even if Core Audio is supported.
const char kForceWaveAudio[] = "force-wave-audio";
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 0462ada..885839d 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -39,6 +39,7 @@
#if defined(OS_WIN)
MEDIA_EXPORT extern const char kEnableExclusiveAudio[];
+MEDIA_EXPORT extern const char kForceDirectShowVideoCapture[];
MEDIA_EXPORT extern const char kForceWaveAudio[];
MEDIA_EXPORT extern const char kWaveOutBuffers[];
#endif
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc
index 10ad051..08e7e1a 100644
--- a/media/base/video_frame.cc
+++ b/media/base/video_frame.cc
@@ -34,6 +34,7 @@
case VideoFrame::YV12:
case VideoFrame::YV12A:
case VideoFrame::YV16:
+ case VideoFrame::I420:
frame->AllocateYUV();
break;
default:
@@ -117,20 +118,52 @@
}
// static
+scoped_refptr<VideoFrame> VideoFrame::WrapExternalSharedMemory(
+ Format format,
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect,
+ const gfx::Size& natural_size,
+ uint8* data,
+ base::SharedMemoryHandle handle,
+ base::TimeDelta timestamp,
+ const base::Closure& no_longer_needed_cb) {
+ switch (format) {
+ case I420: {
+ scoped_refptr<VideoFrame> frame(new VideoFrame(
+ format, coded_size, visible_rect, natural_size, timestamp));
+ frame->shared_memory_handle_ = handle;
+ frame->strides_[kYPlane] = coded_size.width();
+ frame->strides_[kUPlane] = coded_size.width() / 2;
+ frame->strides_[kVPlane] = coded_size.width() / 2;
+ frame->data_[kYPlane] = data;
+ frame->data_[kUPlane] = data + coded_size.GetArea();
+ frame->data_[kVPlane] = data + (coded_size.GetArea() * 5 / 4);
+ frame->no_longer_needed_cb_ = no_longer_needed_cb;
+ return frame;
+ }
+ default:
+ NOTIMPLEMENTED();
+ return NULL;
+ }
+}
+
+// static
scoped_refptr<VideoFrame> VideoFrame::WrapExternalYuvData(
Format format,
const gfx::Size& coded_size,
const gfx::Rect& visible_rect,
const gfx::Size& natural_size,
- int32 y_stride, int32 u_stride, int32 v_stride,
- uint8* y_data, uint8* u_data, uint8* v_data,
+ int32 y_stride,
+ int32 u_stride,
+ int32 v_stride,
+ uint8* y_data,
+ uint8* u_data,
+ uint8* v_data,
base::TimeDelta timestamp,
- base::SharedMemoryHandle shm_handle,
const base::Closure& no_longer_needed_cb) {
DCHECK(format == YV12 || format == YV16 || format == I420) << format;
scoped_refptr<VideoFrame> frame(new VideoFrame(
format, coded_size, visible_rect, natural_size, timestamp));
- frame->shared_memory_handle_ = shm_handle;
frame->strides_[kYPlane] = y_stride;
frame->strides_[kUPlane] = u_stride;
frame->strides_[kVPlane] = v_stride;
@@ -198,11 +231,11 @@
return 1;
case VideoFrame::YV12:
case VideoFrame::YV16:
+ case VideoFrame::I420:
return 3;
case VideoFrame::YV12A:
return 4;
case VideoFrame::EMPTY:
- case VideoFrame::I420:
case VideoFrame::INVALID:
break;
}
@@ -239,7 +272,7 @@
void VideoFrame::AllocateYUV() {
DCHECK(format_ == VideoFrame::YV12 || format_ == VideoFrame::YV16 ||
- format_ == VideoFrame::YV12A);
+ format_ == VideoFrame::YV12A || format_ == VideoFrame::I420);
// Align Y rows at least at 16 byte boundaries. The stride for both
// YV12 and YV16 is 1/2 of the stride of Y. For YV12, every row of bytes for
// U and V applies to two rows of Y (one byte of UV for 4 bytes of Y), so in
@@ -259,9 +292,11 @@
// and then the size needs to be a multiple of two macroblocks (vertically).
// See libavcodec/utils.c:avcodec_align_dimensions2().
size_t y_height = RoundUp(coded_size_.height(), kFrameSizeAlignment * 2);
- size_t uv_height = (format_ == VideoFrame::YV12 ||
- format_ == VideoFrame::YV12A) ?
- y_height / 2 : y_height;
+ size_t uv_height =
+ (format_ == VideoFrame::YV12 || format_ == VideoFrame::YV12A ||
+ format_ == VideoFrame::I420)
+ ? y_height / 2
+ : y_height;
size_t y_bytes = y_height * y_stride;
size_t uv_bytes = uv_height * uv_stride;
size_t a_bytes = format_ == VideoFrame::YV12A ? y_bytes : 0;
@@ -327,10 +362,14 @@
return width * 4;
// Planar, 8bpp.
+ case YV12A:
+ if (plane == kAPlane)
+ return width;
+ // Fallthrough.
case YV12:
case YV16:
- case YV12A:
- if (plane == kYPlane || plane == kAPlane)
+ case I420:
+ if (plane == kYPlane)
return width;
return RoundUp(width, 2) / 2;
@@ -351,9 +390,13 @@
case YV16:
return height;
- case YV12:
case YV12A:
- if (plane == kYPlane || plane == kAPlane)
+ if (plane == kAPlane)
+ return height;
+ // Fallthrough.
+ case YV12:
+ case I420:
+ if (plane == kYPlane)
return height;
return RoundUp(height, 2) / 2;
diff --git a/media/base/video_frame.h b/media/base/video_frame.h
index 8207d9b..82a08a9 100644
--- a/media/base/video_frame.h
+++ b/media/base/video_frame.h
@@ -137,9 +137,26 @@
// least as large as 4*visible_rect().width()*visible_rect().height().
void ReadPixelsFromNativeTexture(const SkBitmap& pixels);
+ // Wraps image data in a buffer backed by a base::SharedMemoryHandle with a
+ // VideoFrame. The image data resides in |data| and is assumed to be packed
+ // tightly in a buffer of logical dimensions |coded_size| with the appropriate
+ // bit depth and plane count as given by |format|. When the frame is
+ // destroyed |no_longer_needed_cb.Run()| will be called.
+ static scoped_refptr<VideoFrame> WrapExternalSharedMemory(
+ Format format,
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect,
+ const gfx::Size& natural_size,
+ uint8* data,
+ base::SharedMemoryHandle handle,
+ base::TimeDelta timestamp,
+ const base::Closure& no_longer_needed_cb);
+
// Wraps external YUV data of the given parameters with a VideoFrame.
// The returned VideoFrame does not own the data passed in. When the frame
// is destroyed |no_longer_needed_cb.Run()| will be called.
+ // TODO(sheu): merge this into WrapExternalSharedMemory().
+ // http://crbug.com/270217
static scoped_refptr<VideoFrame> WrapExternalYuvData(
Format format,
const gfx::Size& coded_size,
@@ -152,7 +169,6 @@
uint8* u_data,
uint8* v_data,
base::TimeDelta timestamp,
- base::SharedMemoryHandle shm_handle, // may be NULLHandle()
const base::Closure& no_longer_needed_cb);
// Creates a frame with format equals to VideoFrame::EMPTY, width, height,
diff --git a/media/base/video_util.cc b/media/base/video_util.cc
index 9da651f..fda758e 100644
--- a/media/base/video_util.cc
+++ b/media/base/video_util.cc
@@ -143,7 +143,8 @@
DCHECK(!(view_area.y() & 1));
DCHECK(!(view_area.width() & 1));
DCHECK(!(view_area.height() & 1));
- DCHECK_EQ(frame->format(), VideoFrame::YV12);
+ DCHECK(frame->format() == VideoFrame::YV12 ||
+ frame->format() == VideoFrame::I420);
LetterboxPlane(frame, VideoFrame::kYPlane, view_area, 0x00);
gfx::Rect half_view_area(view_area.x() / 2,
view_area.y() / 2,
diff --git a/media/crypto/DEPS b/media/cdm/DEPS
similarity index 100%
rename from media/crypto/DEPS
rename to media/cdm/DEPS
diff --git a/media/crypto/aes_decryptor.cc b/media/cdm/aes_decryptor.cc
similarity index 98%
rename from media/crypto/aes_decryptor.cc
rename to media/cdm/aes_decryptor.cc
index fd7c628..da11442 100644
--- a/media/crypto/aes_decryptor.cc
+++ b/media/cdm/aes_decryptor.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "media/crypto/aes_decryptor.h"
+#include "media/cdm/aes_decryptor.h"
#include <vector>
diff --git a/media/crypto/aes_decryptor.h b/media/cdm/aes_decryptor.h
similarity index 98%
rename from media/crypto/aes_decryptor.h
rename to media/cdm/aes_decryptor.h
index aec55d7..fda5a0f 100644
--- a/media/crypto/aes_decryptor.h
+++ b/media/cdm/aes_decryptor.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/media/crypto/aes_decryptor_unittest.cc b/media/cdm/aes_decryptor_unittest.cc
similarity index 99%
rename from media/crypto/aes_decryptor_unittest.cc
rename to media/cdm/aes_decryptor_unittest.cc
index 8feaec4..1edb8e8 100644
--- a/media/crypto/aes_decryptor_unittest.cc
+++ b/media/cdm/aes_decryptor_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -10,7 +10,7 @@
#include "media/base/decoder_buffer.h"
#include "media/base/decrypt_config.h"
#include "media/base/mock_filters.h"
-#include "media/crypto/aes_decryptor.h"
+#include "media/cdm/aes_decryptor.h"
#include "media/webm/webm_constants.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/media/cdm/ppapi/DEPS b/media/cdm/ppapi/DEPS
new file mode 100644
index 0000000..473873d
--- /dev/null
+++ b/media/cdm/ppapi/DEPS
@@ -0,0 +1,7 @@
+# Since media/ does not depend on anything in media/cdm/ppapi/, these extra
+# dependencies are okay.
+include_rules = [
+ "+ppapi/c",
+ "+ppapi/cpp",
+ "+ppapi/utility",
+]
diff --git a/webkit/renderer/media/crypto/ppapi/cdm_video_decoder.cc b/media/cdm/ppapi/cdm_video_decoder.cc
similarity index 75%
rename from webkit/renderer/media/crypto/ppapi/cdm_video_decoder.cc
rename to media/cdm/ppapi/cdm_video_decoder.cc
index 5f2d71d..95523d4 100644
--- a/webkit/renderer/media/crypto/ppapi/cdm_video_decoder.cc
+++ b/media/cdm/ppapi/cdm_video_decoder.cc
@@ -4,22 +4,21 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h"
+#include "media/cdm/ppapi/cdm_video_decoder.h"
#if defined(CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER)
-#include "webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.h"
+#include "media/cdm/ppapi/fake_cdm_video_decoder.h"
#endif
#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
-#include "webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h"
+#include "media/cdm/ppapi/ffmpeg_cdm_video_decoder.h"
#endif
#if defined(CLEAR_KEY_CDM_USE_LIBVPX_DECODER)
-#include "webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.h"
+#include "media/cdm/ppapi/libvpx_cdm_video_decoder.h"
#endif
-namespace webkit_media {
+namespace media {
scoped_ptr<CdmVideoDecoder> CreateVideoDecoder(
cdm::Host* host, const cdm::VideoDecoderConfig& config) {
@@ -54,4 +53,4 @@
return video_decoder.Pass();
}
-} // namespace webkit_media
+} // namespace media
diff --git a/webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h b/media/cdm/ppapi/cdm_video_decoder.h
similarity index 81%
rename from webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h
rename to media/cdm/ppapi/cdm_video_decoder.h
index 86caff9..25d48f4 100644
--- a/webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h
+++ b/media/cdm/ppapi/cdm_video_decoder.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_CDM_VIDEO_DECODER_H_
-#define WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_CDM_VIDEO_DECODER_H_
+#ifndef MEDIA_CDM_PPAPI_CDM_VIDEO_DECODER_H_
+#define MEDIA_CDM_PPAPI_CDM_VIDEO_DECODER_H_
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
+#include "media/cdm/ppapi/api/content_decryption_module.h"
-namespace webkit_media {
+namespace media {
class CdmVideoDecoder {
public:
@@ -38,6 +38,6 @@
scoped_ptr<CdmVideoDecoder> CreateVideoDecoder(
cdm::Host* host, const cdm::VideoDecoderConfig& config);
-} // namespace webkit_media
+} // namespace media
-#endif // WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_CDM_VIDEO_DECODER_H_
+#endif // MEDIA_CDM_PPAPI_CDM_VIDEO_DECODER_H_
diff --git a/webkit/renderer/media/crypto/ppapi/cdm_wrapper.cc b/media/cdm/ppapi/cdm_wrapper.cc
similarity index 98%
rename from webkit/renderer/media/crypto/ppapi/cdm_wrapper.cc
rename to media/cdm/ppapi/cdm_wrapper.cc
index f175831..6348f19 100644
--- a/webkit/renderer/media/crypto/ppapi/cdm_wrapper.cc
+++ b/media/cdm/ppapi/cdm_wrapper.cc
@@ -10,6 +10,8 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "media/cdm/ppapi/api/content_decryption_module.h"
+#include "media/cdm/ppapi/linked_ptr.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_stdint.h"
#include "ppapi/c/private/pp_content_decryptor.h"
@@ -25,8 +27,6 @@
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/var_array_buffer.h"
#include "ppapi/utility/completion_callback_factory.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
-#include "webkit/renderer/media/crypto/ppapi/linked_ptr.h"
#if defined(CHECK_DOCUMENT_URL)
#include "ppapi/cpp/dev/url_util_dev.h"
@@ -204,7 +204,7 @@
} // namespace
-namespace webkit_media {
+namespace media {
// cdm::Buffer implementation that provides access to memory owned by a
// pp::Buffer_Dev.
@@ -1186,13 +1186,13 @@
}
};
-} // namespace webkit_media
+} // namespace media
namespace pp {
// Factory function for your specialization of the Module object.
Module* CreateModule() {
- return new webkit_media::CdmWrapperModule();
+ return new media::CdmWrapperModule();
}
} // namespace pp
diff --git a/webkit/renderer/media/crypto/ppapi/clear_key_cdm.cc b/media/cdm/ppapi/clear_key_cdm.cc
similarity index 97%
rename from webkit/renderer/media/crypto/ppapi/clear_key_cdm.cc
rename to media/cdm/ppapi/clear_key_cdm.cc
index 7f35fd8..cd6a61f 100644
--- a/webkit/renderer/media/crypto/ppapi/clear_key_cdm.cc
+++ b/media/cdm/ppapi/clear_key_cdm.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 "webkit/renderer/media/crypto/ppapi/clear_key_cdm.h"
+#include "media/cdm/ppapi/clear_key_cdm.h"
#include <algorithm>
#include <sstream>
@@ -15,7 +15,7 @@
#include "base/time/time.h"
#include "media/base/decoder_buffer.h"
#include "media/base/decrypt_config.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h"
+#include "media/cdm/ppapi/cdm_video_decoder.h"
#if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
#include "base/basictypes.h"
@@ -27,8 +27,8 @@
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "media/base/media.h"
-#include "webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.h"
-#include "webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h"
+#include "media/cdm/ppapi/ffmpeg_cdm_audio_decoder.h"
+#include "media/cdm/ppapi/ffmpeg_cdm_video_decoder.h"
// Include FFmpeg avformat.h for av_register_all().
extern "C" {
@@ -140,14 +140,14 @@
return NULL;
return static_cast<cdm::ContentDecryptionModule*>(
- new webkit_media::ClearKeyCdm(host));
+ new media::ClearKeyCdm(host));
}
const char* GetCdmVersion() {
return kClearKeyCdmVersion;
}
-namespace webkit_media {
+namespace media {
ClearKeyCdm::Client::Client() : status_(kKeyError) {}
@@ -315,7 +315,7 @@
const cdm::AudioDecoderConfig& audio_decoder_config) {
#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
if (!audio_decoder_)
- audio_decoder_.reset(new webkit_media::FFmpegCdmAudioDecoder(host_));
+ audio_decoder_.reset(new media::FFmpegCdmAudioDecoder(host_));
if (!audio_decoder_->Initialize(audio_decoder_config))
return cdm::kSessionError;
@@ -555,4 +555,4 @@
}
#endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
-} // namespace webkit_media
+} // namespace media
diff --git a/webkit/renderer/media/crypto/ppapi/clear_key_cdm.h b/media/cdm/ppapi/clear_key_cdm.h
similarity index 91%
rename from webkit/renderer/media/crypto/ppapi/clear_key_cdm.h
rename to media/cdm/ppapi/clear_key_cdm.h
index d82f90d..67637eb 100644
--- a/webkit/renderer/media/crypto/ppapi/clear_key_cdm.h
+++ b/media/cdm/ppapi/clear_key_cdm.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 WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_CLEAR_KEY_CDM_H_
-#define WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_CLEAR_KEY_CDM_H_
+#ifndef MEDIA_CDM_PPAPI_CLEAR_KEY_CDM_H_
+#define MEDIA_CDM_PPAPI_CLEAR_KEY_CDM_H_
#include <string>
#include <vector>
@@ -13,8 +13,8 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
-#include "media/crypto/aes_decryptor.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
+#include "media/cdm/aes_decryptor.h"
+#include "media/cdm/ppapi/api/content_decryption_module.h"
// Enable this to use the fake decoder for testing.
// TODO(tomfinegan): Move fake audio decoder into a separate class.
@@ -23,12 +23,8 @@
#endif
namespace media {
-class DecoderBuffer;
-}
-
-namespace webkit_media {
-
class CdmVideoDecoder;
+class DecoderBuffer;
class FFmpegCdmAudioDecoder;
// Clear key implementation of the cdm::ContentDecryptionModule interface.
@@ -87,7 +83,7 @@
void KeyAdded(const std::string& session_id);
void KeyError(const std::string& session_id,
- media::MediaKeys::KeyError error_code,
+ MediaKeys::KeyError error_code,
int system_code);
void KeyMessage(const std::string& session_id,
const std::vector<uint8>& message,
@@ -113,7 +109,7 @@
// |decrypted_buffer| should be ignored by the caller.
cdm::Status DecryptToMediaDecoderBuffer(
const cdm::InputBuffer& encrypted_buffer,
- scoped_refptr<media::DecoderBuffer>* decrypted_buffer);
+ scoped_refptr<DecoderBuffer>* decrypted_buffer);
#if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
int64 CurrentTimeStampInMicroseconds() const;
@@ -130,7 +126,7 @@
#endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
Client client_;
- media::AesDecryptor decryptor_;
+ AesDecryptor decryptor_;
// Protects the |client_| from being accessed by the |decryptor_|
// simultaneously.
@@ -165,6 +161,6 @@
DISALLOW_COPY_AND_ASSIGN(ClearKeyCdm);
};
-} // namespace webkit_media
+} // namespace media
-#endif // WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_CLEAR_KEY_CDM_H_
+#endif // MEDIA_CDM_PPAPI_CLEAR_KEY_CDM_H_
diff --git a/webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.cc b/media/cdm/ppapi/fake_cdm_video_decoder.cc
similarity index 92%
rename from webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.cc
rename to media/cdm/ppapi/fake_cdm_video_decoder.cc
index 1870621..b23e5a7 100644
--- a/webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.cc
+++ b/media/cdm/ppapi/fake_cdm_video_decoder.cc
@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.h"
+#include "media/cdm/ppapi/fake_cdm_video_decoder.h"
#include "base/logging.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
-namespace webkit_media {
+namespace media {
FakeCdmVideoDecoder::FakeCdmVideoDecoder(cdm::Host* host)
: is_initialized_(false),
@@ -89,4 +88,4 @@
return cdm::kSuccess;
}
-} // namespace webkit_media
+} // namespace media
diff --git a/webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.h b/media/cdm/ppapi/fake_cdm_video_decoder.h
similarity index 67%
rename from webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.h
rename to media/cdm/ppapi/fake_cdm_video_decoder.h
index 7c110e2..05b16ad 100644
--- a/webkit/renderer/media/crypto/ppapi/fake_cdm_video_decoder.h
+++ b/media/cdm/ppapi/fake_cdm_video_decoder.h
@@ -2,19 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FAKE_CDM_VIDEO_DECODER_H_
-#define WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FAKE_CDM_VIDEO_DECODER_H_
+#ifndef MEDIA_CDM_PPAPI_FAKE_CDM_VIDEO_DECODER_H_
+#define MEDIA_CDM_PPAPI_FAKE_CDM_VIDEO_DECODER_H_
#include "base/basictypes.h"
#include "base/compiler_specific.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h"
+#include "media/cdm/ppapi/api/content_decryption_module.h"
+#include "media/cdm/ppapi/cdm_video_decoder.h"
-namespace webkit_media {
+namespace media {
class FakeCdmVideoDecoder : public CdmVideoDecoder {
public:
- explicit FakeCdmVideoDecoder(cdm::Allocator* allocator);
+ explicit FakeCdmVideoDecoder(cdm::Host* host);
virtual ~FakeCdmVideoDecoder();
// CdmVideoDecoder implementation.
@@ -36,6 +36,6 @@
DISALLOW_COPY_AND_ASSIGN(FakeCdmVideoDecoder);
};
-} // namespace webkit_media
+} // namespace media
-#endif // WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FAKE_CDM_VIDEO_DECODER_H_
+#endif // MEDIA_CDM_PPAPI_FAKE_CDM_VIDEO_DECODER_H_
diff --git a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.cc b/media/cdm/ppapi/ffmpeg_cdm_audio_decoder.cc
similarity index 92%
rename from webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.cc
rename to media/cdm/ppapi/ffmpeg_cdm_audio_decoder.cc
index 1391de8..ed619b2 100644
--- a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.cc
+++ b/media/cdm/ppapi/ffmpeg_cdm_audio_decoder.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 "webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.h"
+#include "media/cdm/ppapi/ffmpeg_cdm_audio_decoder.h"
#include <algorithm>
@@ -12,7 +12,6 @@
#include "media/base/buffers.h"
#include "media/base/data_buffer.h"
#include "media/base/limits.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
// Include FFmpeg header files.
extern "C" {
@@ -22,7 +21,7 @@
MSVC_POP_WARNING();
} // extern "C"
-namespace webkit_media {
+namespace media {
// Maximum number of channels with defined layout in src/media.
static const int kMaxChannels = 8;
@@ -90,7 +89,7 @@
channels_(0),
av_sample_format_(0),
bytes_per_frame_(0),
- last_input_timestamp_(media::kNoTimestamp()),
+ last_input_timestamp_(kNoTimestamp()),
output_bytes_to_drop_(0) {
}
@@ -143,7 +142,7 @@
int channels = codec_context_->channels;
if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLT)
channels = 1;
- converter_bus_ = media::AudioBus::CreateWrapper(channels);
+ converter_bus_ = AudioBus::CreateWrapper(channels);
}
// Success!
@@ -152,7 +151,7 @@
samples_per_second_ = config.samples_per_second;
bytes_per_frame_ = codec_context_->channels * bits_per_channel_ / 8;
output_timestamp_helper_.reset(
- new media::AudioTimestampHelper(config.samples_per_second));
+ new AudioTimestampHelper(config.samples_per_second));
serialized_audio_frames_.reserve(bytes_per_frame_ * samples_per_second_);
is_initialized_ = true;
@@ -183,9 +182,9 @@
config.channel_count > 0 &&
config.channel_count <= kMaxChannels &&
config.bits_per_channel > 0 &&
- config.bits_per_channel <= media::limits::kMaxBitsPerSample &&
+ config.bits_per_channel <= limits::kMaxBitsPerSample &&
config.samples_per_second > 0 &&
- config.samples_per_second <= media::limits::kMaxSampleRate;
+ config.samples_per_second <= limits::kMaxSampleRate;
}
cdm::Status FFmpegCdmAudioDecoder::DecodeBuffer(
@@ -200,7 +199,7 @@
bool is_vorbis = codec_context_->codec_id == AV_CODEC_ID_VORBIS;
if (!is_end_of_stream) {
- if (last_input_timestamp_ == media::kNoTimestamp()) {
+ if (last_input_timestamp_ == kNoTimestamp()) {
if (is_vorbis && timestamp < base::TimeDelta()) {
// Dropping frames for negative timestamps as outlined in section A.2
// in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html
@@ -210,7 +209,7 @@
} else {
last_input_timestamp_ = timestamp;
}
- } else if (timestamp != media::kNoTimestamp()) {
+ } else if (timestamp != kNoTimestamp()) {
if (timestamp < last_input_timestamp_) {
base::TimeDelta diff = timestamp - last_input_timestamp_;
DVLOG(1) << "Input timestamps are not monotonically increasing! "
@@ -260,9 +259,9 @@
packet.size -= result;
packet.data += result;
- if (output_timestamp_helper_->base_timestamp() == media::kNoTimestamp() &&
+ if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() &&
!is_end_of_stream) {
- DCHECK(timestamp != media::kNoTimestamp());
+ DCHECK(timestamp != kNoTimestamp());
if (output_bytes_to_drop_ > 0) {
// Currently Vorbis is the only codec that causes us to drop samples.
// If we have to drop samples it always means the timeline starts at 0.
@@ -311,7 +310,7 @@
output_bytes_to_drop_ -= dropped_size;
}
- scoped_refptr<media::DataBuffer> output;
+ scoped_refptr<DataBuffer> output;
if (decoded_audio_size > 0) {
DCHECK_EQ(decoded_audio_size % bytes_per_frame_, 0)
<< "Decoder didn't output full frames";
@@ -336,7 +335,7 @@
av_frame_->extended_data[i]));
}
- output = new media::DataBuffer(decoded_audio_size);
+ output = new DataBuffer(decoded_audio_size);
output->set_data_size(decoded_audio_size);
DCHECK_EQ(frames_to_interleave, converter_bus_->frames() - skip_frames);
@@ -344,7 +343,7 @@
skip_frames, frames_to_interleave, bits_per_channel_ / 8,
output->writable_data());
} else {
- output = media::DataBuffer::CopyFrom(
+ output = DataBuffer::CopyFrom(
av_frame_->extended_data[0] + start_sample * bytes_per_frame_,
decoded_audio_size);
}
@@ -384,8 +383,8 @@
}
void FFmpegCdmAudioDecoder::ResetTimestampState() {
- output_timestamp_helper_->SetBaseTimestamp(media::kNoTimestamp());
- last_input_timestamp_ = media::kNoTimestamp();
+ output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp());
+ last_input_timestamp_ = kNoTimestamp();
output_bytes_to_drop_ = 0;
}
@@ -410,4 +409,4 @@
memcpy(&serialized_audio_frames_[0] + previous_size, &value, sizeof(value));
}
-} // namespace webkit_media
+} // namespace media
diff --git a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.h b/media/cdm/ppapi/ffmpeg_cdm_audio_decoder.h
similarity index 76%
rename from webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.h
rename to media/cdm/ppapi/ffmpeg_cdm_audio_decoder.h
index 2e93974..1b4fb8f 100644
--- a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.h
+++ b/media/cdm/ppapi/ffmpeg_cdm_audio_decoder.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 WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FFMPEG_CDM_AUDIO_DECODER_H_
-#define WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FFMPEG_CDM_AUDIO_DECODER_H_
+#ifndef MEDIA_CDM_PPAPI_FFMPEG_CDM_AUDIO_DECODER_H_
+#define MEDIA_CDM_PPAPI_FFMPEG_CDM_AUDIO_DECODER_H_
#include <vector>
@@ -11,7 +11,7 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
+#include "media/cdm/ppapi/api/content_decryption_module.h"
struct AVCodecContext;
struct AVFrame;
@@ -21,12 +21,12 @@
class AudioTimestampHelper;
}
-namespace webkit_media {
+namespace media {
-// TODO(xhwang): This class is partially cloned from media::FFmpegAudioDecoder.
-// When media::FFmpegAudioDecoder is updated, it's a pain to keep this class
-// in sync with media::FFmpegAudioDecoder. We need a long term sustainable
-// solution for this. See http://crbug.com/169203
+// TODO(xhwang): This class is partially cloned from FFmpegAudioDecoder. When
+// FFmpegAudioDecoder is updated, it's a pain to keep this class in sync with
+// FFmpegAudioDecoder. We need a long term sustainable solution for this. See
+// http://crbug.com/169203
class FFmpegCdmAudioDecoder {
public:
explicit FFmpegCdmAudioDecoder(cdm::Host* host);
@@ -75,13 +75,13 @@
int av_sample_format_;
// Used for computing output timestamps.
- scoped_ptr<media::AudioTimestampHelper> output_timestamp_helper_;
+ scoped_ptr<AudioTimestampHelper> output_timestamp_helper_;
int bytes_per_frame_;
base::TimeDelta last_input_timestamp_;
// We may need to convert the audio data coming out of FFmpeg from planar
// float to integer.
- scoped_ptr<media::AudioBus> converter_bus_;
+ scoped_ptr<AudioBus> converter_bus_;
// Number of output sample bytes to drop before generating output buffers.
// This is required for handling negative timestamps when decoding Vorbis
@@ -94,6 +94,6 @@
DISALLOW_COPY_AND_ASSIGN(FFmpegCdmAudioDecoder);
};
-} // namespace webkit_media
+} // namespace media
-#endif // WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FFMPEG_CDM_AUDIO_DECODER_H_
+#endif // MEDIA_CDM_PPAPI_FFMPEG_CDM_AUDIO_DECODER_H_
diff --git a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.cc b/media/cdm/ppapi/ffmpeg_cdm_video_decoder.cc
similarity index 96%
rename from webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.cc
rename to media/cdm/ppapi/ffmpeg_cdm_video_decoder.cc
index faaa8f7..9a2439d 100644
--- a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.cc
+++ b/media/cdm/ppapi/ffmpeg_cdm_video_decoder.cc
@@ -2,13 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h"
+#include "media/cdm/ppapi/ffmpeg_cdm_video_decoder.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "media/base/buffers.h"
#include "media/base/limits.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
// Include FFmpeg header files.
extern "C" {
@@ -18,7 +17,7 @@
MSVC_POP_WARNING();
} // extern "C"
-namespace webkit_media {
+namespace media {
static const int kDecodeThreads = 1;
@@ -199,9 +198,9 @@
return ((format == cdm::kYv12 || format == cdm::kI420) &&
(data_size.width % 2) == 0 && (data_size.height % 2) == 0 &&
data_size.width > 0 && data_size.height > 0 &&
- data_size.width <= media::limits::kMaxDimension &&
- data_size.height <= media::limits::kMaxDimension &&
- data_size.width * data_size.height <= media::limits::kMaxCanvas);
+ data_size.width <= limits::kMaxDimension &&
+ data_size.height <= limits::kMaxDimension &&
+ data_size.width * data_size.height <= limits::kMaxCanvas);
}
cdm::Status FFmpegCdmVideoDecoder::DecodeFrame(
@@ -342,4 +341,4 @@
}
}
-} // namespace webkit_media
+} // namespace media
diff --git a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h b/media/cdm/ppapi/ffmpeg_cdm_video_decoder.h
similarity index 79%
rename from webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h
rename to media/cdm/ppapi/ffmpeg_cdm_video_decoder.h
index 5c4bb2b..17e2b57 100644
--- a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h
+++ b/media/cdm/ppapi/ffmpeg_cdm_video_decoder.h
@@ -2,18 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FFMPEG_CDM_VIDEO_DECODER_H_
-#define WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FFMPEG_CDM_VIDEO_DECODER_H_
+#ifndef MEDIA_CDM_PPAPI_FFMPEG_CDM_VIDEO_DECODER_H_
+#define MEDIA_CDM_PPAPI_FFMPEG_CDM_VIDEO_DECODER_H_
#include "base/basictypes.h"
#include "base/compiler_specific.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h"
+#include "media/cdm/ppapi/api/content_decryption_module.h"
+#include "media/cdm/ppapi/cdm_video_decoder.h"
struct AVCodecContext;
struct AVFrame;
-namespace webkit_media {
+namespace media {
class FFmpegCdmVideoDecoder : public CdmVideoDecoder {
public:
@@ -53,6 +53,6 @@
DISALLOW_COPY_AND_ASSIGN(FFmpegCdmVideoDecoder);
};
-} // namespace webkit_media
+} // namespace media
-#endif // WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_FFMPEG_CDM_VIDEO_DECODER_H_
+#endif // MEDIA_CDM_PPAPI_FFMPEG_CDM_VIDEO_DECODER_H_
diff --git a/webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.cc b/media/cdm/ppapi/libvpx_cdm_video_decoder.cc
similarity index 92%
rename from webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.cc
rename to media/cdm/ppapi/libvpx_cdm_video_decoder.cc
index beb365c..a81c485 100644
--- a/webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.cc
+++ b/media/cdm/ppapi/libvpx_cdm_video_decoder.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 "webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.h"
+#include "media/cdm/ppapi/libvpx_cdm_video_decoder.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
@@ -14,17 +14,16 @@
// backwards compatibility for legacy applications using the library.
#define VPX_CODEC_DISABLE_COMPAT 1
extern "C" {
+// Note: vpx_decoder.h must be first or compile will fail.
+#include "third_party/libvpx/source/libvpx/vpx/vpx_decoder.h" // NOLINT
#include "third_party/libvpx/source/libvpx/vpx/vp8dx.h"
-#include "third_party/libvpx/source/libvpx/vpx/vpx_decoder.h"
}
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
-
// Enable USE_COPYPLANE_WITH_LIBVPX to use |CopyPlane()| instead of memcpy to
// copy video frame data.
// #define USE_COPYPLANE_WITH_LIBVPX 1
-namespace webkit_media {
+namespace media {
static const int kDecodeThreads = 2;
@@ -94,9 +93,9 @@
return ((format == cdm::kYv12 || format == cdm::kI420) &&
(data_size.width % 2) == 0 && (data_size.height % 2) == 0 &&
data_size.width > 0 && data_size.height > 0 &&
- data_size.width <= media::limits::kMaxDimension &&
- data_size.height <= media::limits::kMaxDimension &&
- data_size.width * data_size.height <= media::limits::kMaxCanvas);
+ data_size.width <= limits::kMaxDimension &&
+ data_size.height <= limits::kMaxDimension &&
+ data_size.width * data_size.height <= limits::kMaxCanvas);
}
cdm::Status LibvpxCdmVideoDecoder::DecodeFrame(
@@ -193,4 +192,4 @@
return true;
}
-} // namespace webkit_media
+} // namespace media
diff --git a/webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.h b/media/cdm/ppapi/libvpx_cdm_video_decoder.h
similarity index 78%
rename from webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.h
rename to media/cdm/ppapi/libvpx_cdm_video_decoder.h
index 59674b6..3edaa07 100644
--- a/webkit/renderer/media/crypto/ppapi/libvpx_cdm_video_decoder.h
+++ b/media/cdm/ppapi/libvpx_cdm_video_decoder.h
@@ -2,18 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_LIBVPX_CDM_VIDEO_DECODER_H_
-#define WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_LIBVPX_CDM_VIDEO_DECODER_H_
+#ifndef MEDIA_CDM_PPAPI_LIBVPX_CDM_VIDEO_DECODER_H_
+#define MEDIA_CDM_PPAPI_LIBVPX_CDM_VIDEO_DECODER_H_
#include "base/basictypes.h"
#include "base/compiler_specific.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm_video_decoder.h"
+#include "media/cdm/ppapi/api/content_decryption_module.h"
+#include "media/cdm/ppapi/cdm_video_decoder.h"
struct vpx_codec_ctx;
struct vpx_image;
-namespace webkit_media {
+namespace media {
class LibvpxCdmVideoDecoder : public CdmVideoDecoder {
public:
@@ -50,6 +50,6 @@
DISALLOW_COPY_AND_ASSIGN(LibvpxCdmVideoDecoder);
};
-} // namespace webkit_media
+} // namespace media
-#endif // WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_LIBVPX_CDM_VIDEO_DECODER_H_
+#endif // MEDIA_CDM_PPAPI_LIBVPX_CDM_VIDEO_DECODER_H_
diff --git a/webkit/renderer/media/crypto/ppapi/linked_ptr.h b/media/cdm/ppapi/linked_ptr.h
similarity index 96%
rename from webkit/renderer/media/crypto/ppapi/linked_ptr.h
rename to media/cdm/ppapi/linked_ptr.h
index 5dd61fe..f3eccbb 100644
--- a/webkit/renderer/media/crypto/ppapi/linked_ptr.h
+++ b/media/cdm/ppapi/linked_ptr.h
@@ -37,8 +37,8 @@
// - is thread safe for copying and deletion
// - supports weak_ptrs
-#ifndef WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_LINKED_PTR_H_
-#define WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_LINKED_PTR_H_
+#ifndef MEDIA_CDM_PPAPI_LINKED_PTR_H_
+#define MEDIA_CDM_PPAPI_LINKED_PTR_H_
#include "ppapi/cpp/logging.h"
@@ -182,4 +182,4 @@
return linked_ptr<T>(ptr);
}
-#endif // WEBKIT_RENDERER_MEDIA_CRYPTO_PPAPI_LINKED_PTR_H_
+#endif // MEDIA_CDM_PPAPI_LINKED_PTR_H_
diff --git a/media/filters/file_data_source.cc b/media/filters/file_data_source.cc
index 2f34718..341347e 100644
--- a/media/filters/file_data_source.cc
+++ b/media/filters/file_data_source.cc
@@ -25,6 +25,17 @@
return true;
}
+bool FileDataSource::InitializeFromPlatformFile(
+ const base::PlatformFile& file) {
+ DCHECK(!file_.IsValid());
+
+ if (!file_.Initialize(file))
+ return false;
+
+ UpdateHostBytes();
+ return true;
+}
+
void FileDataSource::set_host(DataSourceHost* host) {
DataSource::set_host(host);
UpdateHostBytes();
diff --git a/media/filters/file_data_source.h b/media/filters/file_data_source.h
index e55ecdf..c0164dac 100644
--- a/media/filters/file_data_source.h
+++ b/media/filters/file_data_source.h
@@ -9,6 +9,7 @@
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
+#include "base/platform_file.h"
#include "media/base/data_source.h"
namespace media {
@@ -21,6 +22,7 @@
virtual ~FileDataSource();
bool Initialize(const base::FilePath& file_path);
+ bool InitializeFromPlatformFile(const base::PlatformFile& file);
// Implementation of DataSource.
virtual void set_host(DataSourceHost* host) OVERRIDE;
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc
index a106ab5..30c6dfa 100644
--- a/media/filters/gpu_video_decoder.cc
+++ b/media/filters/gpu_video_decoder.cc
@@ -137,7 +137,7 @@
BindToCurrentLoop(orig_status_cb));
bool previously_initialized = config_.IsValidConfig();
-#if !defined(OS_CHROMEOS) || !defined(ARCH_CPU_X86_FAMILY)
+#if !defined(OS_CHROMEOS)
if (previously_initialized) {
// TODO(xhwang): Make GpuVideoDecoder reinitializable.
// See http://crbug.com/233608
diff --git a/media/filters/pipeline_integration_test.cc b/media/filters/pipeline_integration_test.cc
index f260708..26f65b9 100644
--- a/media/filters/pipeline_integration_test.cc
+++ b/media/filters/pipeline_integration_test.cc
@@ -11,7 +11,7 @@
#include "media/base/decoder_buffer.h"
#include "media/base/media_keys.h"
#include "media/base/test_data_util.h"
-#include "media/crypto/aes_decryptor.h"
+#include "media/cdm/aes_decryptor.h"
#include "media/filters/chunk_demuxer.h"
using testing::AnyNumber;
diff --git a/media/media.gyp b/media/media.gyp
index b2bde3d..c685090 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -261,6 +261,8 @@
'base/filter_collection.h',
'base/media.cc',
'base/media.h',
+ 'base/media_file_checker.cc',
+ 'base/media_file_checker.h',
'base/media_keys.cc',
'base/media_keys.h',
'base/media_log.cc',
@@ -312,8 +314,8 @@
'base/video_util.h',
'base/yuv_convert.cc',
'base/yuv_convert.h',
- 'crypto/aes_decryptor.cc',
- 'crypto/aes_decryptor.h',
+ 'cdm/aes_decryptor.cc',
+ 'cdm/aes_decryptor.h',
'ffmpeg/ffmpeg_common.cc',
'ffmpeg/ffmpeg_common.h',
'filters/audio_decoder_selector.cc',
@@ -466,6 +468,8 @@
'sources!': [
'base/container_names.cc',
'base/container_names.h',
+ 'base/media_file_checker.cc',
+ 'base/media_file_checker.h',
'base/media_posix.cc',
'ffmpeg/ffmpeg_common.cc',
'ffmpeg/ffmpeg_common.h',
@@ -926,6 +930,7 @@
'base/decoder_buffer_unittest.cc',
'base/djb2_unittest.cc',
'base/gmock_callback_support_unittest.cc',
+ 'base/media_file_checker_unittest.cc',
'base/multi_channel_resampler_unittest.cc',
'base/pipeline_unittest.cc',
'base/ranges_unittest.cc',
@@ -940,7 +945,7 @@
'base/video_frame_unittest.cc',
'base/video_util_unittest.cc',
'base/yuv_convert_unittest.cc',
- 'crypto/aes_decryptor_unittest.cc',
+ 'cdm/aes_decryptor_unittest.cc',
'ffmpeg/ffmpeg_common_unittest.cc',
'filters/audio_decoder_selector_unittest.cc',
'filters/audio_file_reader_unittest.cc',
@@ -998,6 +1003,10 @@
'dependencies': [
'../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
],
+ }, { # media_use_ffmpeg== 0
+ 'sources!': [
+ 'base/media_file_checker_unittest.cc',
+ ],
}],
['os_posix==1 and OS!="mac" and OS!="ios"', {
'conditions': [
@@ -1285,6 +1294,9 @@
], # targets
}],
['OS!="ios"', {
+ 'includes': [
+ 'media_cdm.gypi',
+ ],
'targets': [
{
# Minimal target for NaCl and other renderer side media clients which
diff --git a/media/media.target.darwin-arm.mk b/media/media.target.darwin-arm.mk
index 9a453af..4c15e9f 100644
--- a/media/media.target.darwin-arm.mk
+++ b/media/media.target.darwin-arm.mk
@@ -114,7 +114,7 @@
media/base/video_renderer.cc \
media/base/video_util.cc \
media/base/yuv_convert.cc \
- media/crypto/aes_decryptor.cc \
+ media/cdm/aes_decryptor.cc \
media/filters/audio_decoder_selector.cc \
media/filters/audio_renderer_algorithm.cc \
media/filters/audio_renderer_impl.cc \
@@ -220,6 +220,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -331,6 +332,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/media/media.target.darwin-mips.mk b/media/media.target.darwin-mips.mk
index 0df3761..e18928c 100644
--- a/media/media.target.darwin-mips.mk
+++ b/media/media.target.darwin-mips.mk
@@ -114,7 +114,7 @@
media/base/video_renderer.cc \
media/base/video_util.cc \
media/base/yuv_convert.cc \
- media/crypto/aes_decryptor.cc \
+ media/cdm/aes_decryptor.cc \
media/filters/audio_decoder_selector.cc \
media/filters/audio_renderer_algorithm.cc \
media/filters/audio_renderer_impl.cc \
@@ -219,6 +219,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -329,6 +330,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/media/media.target.darwin-x86.mk b/media/media.target.darwin-x86.mk
index 665877b..d4ee0ac 100644
--- a/media/media.target.darwin-x86.mk
+++ b/media/media.target.darwin-x86.mk
@@ -114,7 +114,7 @@
media/base/video_renderer.cc \
media/base/video_util.cc \
media/base/yuv_convert.cc \
- media/crypto/aes_decryptor.cc \
+ media/cdm/aes_decryptor.cc \
media/filters/audio_decoder_selector.cc \
media/filters/audio_renderer_algorithm.cc \
media/filters/audio_renderer_impl.cc \
@@ -223,6 +223,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -336,6 +337,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/media/media.target.linux-arm.mk b/media/media.target.linux-arm.mk
index 9a453af..4c15e9f 100644
--- a/media/media.target.linux-arm.mk
+++ b/media/media.target.linux-arm.mk
@@ -114,7 +114,7 @@
media/base/video_renderer.cc \
media/base/video_util.cc \
media/base/yuv_convert.cc \
- media/crypto/aes_decryptor.cc \
+ media/cdm/aes_decryptor.cc \
media/filters/audio_decoder_selector.cc \
media/filters/audio_renderer_algorithm.cc \
media/filters/audio_renderer_impl.cc \
@@ -220,6 +220,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -331,6 +332,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/media/media.target.linux-mips.mk b/media/media.target.linux-mips.mk
index 0df3761..e18928c 100644
--- a/media/media.target.linux-mips.mk
+++ b/media/media.target.linux-mips.mk
@@ -114,7 +114,7 @@
media/base/video_renderer.cc \
media/base/video_util.cc \
media/base/yuv_convert.cc \
- media/crypto/aes_decryptor.cc \
+ media/cdm/aes_decryptor.cc \
media/filters/audio_decoder_selector.cc \
media/filters/audio_renderer_algorithm.cc \
media/filters/audio_renderer_impl.cc \
@@ -219,6 +219,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -329,6 +330,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/media/media.target.linux-x86.mk b/media/media.target.linux-x86.mk
index 665877b..d4ee0ac 100644
--- a/media/media.target.linux-x86.mk
+++ b/media/media.target.linux-x86.mk
@@ -114,7 +114,7 @@
media/base/video_renderer.cc \
media/base/video_util.cc \
media/base/yuv_convert.cc \
- media/crypto/aes_decryptor.cc \
+ media/cdm/aes_decryptor.cc \
media/filters/audio_decoder_selector.cc \
media/filters/audio_renderer_algorithm.cc \
media/filters/audio_renderer_impl.cc \
@@ -223,6 +223,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -336,6 +337,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/renderer/media/webkit_media.gypi b/media/media_cdm.gypi
similarity index 81%
rename from webkit/renderer/media/webkit_media.gypi
rename to media/media_cdm.gypi
index 198ebfe..a4a94f7 100644
--- a/webkit/renderer/media/webkit_media.gypi
+++ b/media/media_cdm.gypi
@@ -29,8 +29,8 @@
['use_fake_video_decoder == 1' , {
'defines': ['CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER'],
'sources': [
- 'crypto/ppapi/fake_cdm_video_decoder.cc',
- 'crypto/ppapi/fake_cdm_video_decoder.h',
+ 'cdm/ppapi/fake_cdm_video_decoder.cc',
+ 'cdm/ppapi/fake_cdm_video_decoder.h',
],
}],
['use_ffmpeg == 1' , {
@@ -39,14 +39,14 @@
'<(DEPTH)/third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
],
'sources': [
- 'crypto/ppapi/ffmpeg_cdm_audio_decoder.cc',
- 'crypto/ppapi/ffmpeg_cdm_audio_decoder.h',
+ 'cdm/ppapi/ffmpeg_cdm_audio_decoder.cc',
+ 'cdm/ppapi/ffmpeg_cdm_audio_decoder.h',
],
}],
['use_ffmpeg == 1 and use_fake_video_decoder == 0' , {
'sources': [
- 'crypto/ppapi/ffmpeg_cdm_video_decoder.cc',
- 'crypto/ppapi/ffmpeg_cdm_video_decoder.h',
+ 'cdm/ppapi/ffmpeg_cdm_video_decoder.cc',
+ 'cdm/ppapi/ffmpeg_cdm_video_decoder.h',
],
}],
['use_libvpx == 1 and use_fake_video_decoder == 0' , {
@@ -55,8 +55,8 @@
'<(DEPTH)/third_party/libvpx/libvpx.gyp:libvpx',
],
'sources': [
- 'crypto/ppapi/libvpx_cdm_video_decoder.cc',
- 'crypto/ppapi/libvpx_cdm_video_decoder.h',
+ 'cdm/ppapi/libvpx_cdm_video_decoder.cc',
+ 'cdm/ppapi/libvpx_cdm_video_decoder.h',
],
}],
['os_posix == 1 and OS != "mac" and enable_pepper_cdms==1', {
@@ -73,16 +73,16 @@
],
'defines': ['CDM_IMPLEMENTATION'],
'dependencies': [
- '<(DEPTH)/base/base.gyp:base',
- '<(DEPTH)/media/media.gyp:media',
+ 'media',
# Include the following for media::AudioBus.
- '<(DEPTH)/media/media.gyp:shared_memory_support',
+ 'shared_memory_support',
+ '<(DEPTH)/base/base.gyp:base',
],
'sources': [
- 'crypto/ppapi/cdm_video_decoder.cc',
- 'crypto/ppapi/cdm_video_decoder.h',
- 'crypto/ppapi/clear_key_cdm.cc',
- 'crypto/ppapi/clear_key_cdm.h',
+ 'cdm/ppapi/cdm_video_decoder.cc',
+ 'cdm/ppapi/cdm_video_decoder.h',
+ 'cdm/ppapi/clear_key_cdm.cc',
+ 'cdm/ppapi/clear_key_cdm.h',
],
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
'msvs_disabled_warnings': [ 4267, ],
@@ -97,9 +97,9 @@
'clearkeycdm',
],
'sources': [
- 'crypto/ppapi/cdm_wrapper.cc',
- 'crypto/ppapi/cdm/content_decryption_module.h',
- 'crypto/ppapi/linked_ptr.h',
+ 'cdm/ppapi/api/content_decryption_module.h',
+ 'cdm/ppapi/cdm_wrapper.cc',
+ 'cdm/ppapi/linked_ptr.h',
],
'conditions': [
['os_posix == 1 and OS != "mac" and enable_pepper_cdms==1', {
diff --git a/media/video/capture/win/video_capture_device_win.cc b/media/video/capture/win/video_capture_device_win.cc
index 81f057a..1a7c3b7 100644
--- a/media/video/capture/win/video_capture_device_win.cc
+++ b/media/video/capture/win/video_capture_device_win.cc
@@ -7,9 +7,11 @@
#include <algorithm>
#include <list>
+#include "base/command_line.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/win/scoped_variant.h"
+#include "media/base/media_switches.h"
#include "media/video/capture/win/video_capture_device_mf_win.h"
using base::win::ScopedComPtr;
@@ -150,7 +152,9 @@
void VideoCaptureDevice::GetDeviceNames(Names* device_names) {
Names::iterator it;
- if (VideoCaptureDeviceMFWin::PlatformSupported()) {
+ const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+ if (VideoCaptureDeviceMFWin::PlatformSupported() &&
+ !cmd_line->HasSwitch(switches::kForceDirectShowVideoCapture)) {
VideoCaptureDeviceMFWin::GetDeviceNames(device_names);
}
// Retrieve the devices with DirectShow (DS) interface. They might (partially)
diff --git a/native_client_sdk/src/build_tools/build_sdk.py b/native_client_sdk/src/build_tools/build_sdk.py
index 190e5c3..37626fa 100755
--- a/native_client_sdk/src/build_tools/build_sdk.py
+++ b/native_client_sdk/src/build_tools/build_sdk.py
@@ -54,7 +54,7 @@
CYGTAR = os.path.join(NACL_DIR, 'build', 'cygtar.py')
NACLPORTS_URL = 'https://naclports.googlecode.com/svn/trunk/src'
-NACLPORTS_REV = 774
+NACLPORTS_REV = 850
GYPBUILD_DIR = 'gypbuild'
@@ -186,6 +186,18 @@
open(os.path.join(pepperdir, 'README'), 'w').write(readme_text)
+def PrunePNaClToolchain(root):
+ dirs_to_prune = [
+ 'newlib/lib-bc-x86-64',
+ 'newlib/usr-bc-x86-64'
+ # TODO(sbc): remove this once its really not needed.
+ # Currently we seem to rely on it at least for <bits/stat.h>
+ #'newlib/sysroot',
+ ]
+ for dirname in dirs_to_prune:
+ buildbot_common.RemoveDir(os.path.join(root, dirname))
+
+
def BuildStepUntarToolchains(pepperdir, arch, toolchains):
buildbot_common.BuildStep('Untar Toolchains')
platform = getos.GetPlatform()
@@ -236,6 +248,7 @@
# Then rename/move it to the pepper toolchain directory
pnacldir = os.path.join(pepperdir, 'toolchain', tcname + '_pnacl')
buildbot_common.Move(tmpdir, pnacldir)
+ PrunePNaClToolchain(pnacldir)
buildbot_common.RemoveDir(tmpdir)
diff --git a/native_client_sdk/src/build_tools/sdk_files.list b/native_client_sdk/src/build_tools/sdk_files.list
index f4e890a..a210f4a 100644
--- a/native_client_sdk/src/build_tools/sdk_files.list
+++ b/native_client_sdk/src/build_tools/sdk_files.list
@@ -314,7 +314,6 @@
include/nacl_io/error.h
include/nacl_io/event_emitter.h
include/nacl_io/event_listener.h
-include/nacl_io/error.h
include/nacl_io/host_resolver.h
include/nacl_io/inode_pool.h
include/nacl_io/ioctl.h
@@ -331,10 +330,12 @@
include/nacl_io/mount_http.h
include/nacl_io/mount_mem.h
include/nacl_io/mount_node.h
+include/nacl_io/mount_node_char.h
include/nacl_io/mount_node_dir.h
include/nacl_io/mount_node_html5fs.h
include/nacl_io/mount_node_http.h
include/nacl_io/mount_node_mem.h
+include/nacl_io/mount_node_tty.h
include/nacl_io/mount_passthrough.h
include/nacl_io/nacl_io.h
include/nacl_io/osdirent.h
@@ -357,8 +358,10 @@
include/newlib/arpa/inet.h
include/newlib/netdb.h
include/newlib/netinet/in.h
+include/newlib/netinet/tcp.h
include/newlib/netinet6/in6.h
include/newlib/poll.h
+include/newlib/sys/mount.h
include/newlib/sys/select.h
include/newlib/sys/socket.h
include/newlib/sys/termios.h
@@ -366,8 +369,10 @@
include/pnacl/arpa/inet.h
include/pnacl/netdb.h
include/pnacl/netinet/in.h
+include/pnacl/netinet/tcp.h
include/pnacl/netinet6/in6.h
include/pnacl/poll.h
+include/pnacl/sys/mount.h
include/pnacl/sys/select.h
include/pnacl/sys/socket.h
include/pnacl/sys/termios.h
@@ -612,7 +617,6 @@
[win]include/win/pthread.h
[win]include/win/sched.h
[win]include/win/semaphore.h
-
[linux]lib/${PLATFORM}_host/Debug/libgmock.a
[linux]lib/${PLATFORM}_host/Debug/libgtest.a
[linux]lib/${PLATFORM}_host/Debug/libjsoncpp.a
@@ -858,33 +862,58 @@
src/nacl_io/mount_node_html5fs.cc
src/nacl_io/mount_node_http.cc
src/nacl_io/mount_node_mem.cc
+src/nacl_io/mount_node_tty.cc
src/nacl_io/mount_passthrough.cc
src/nacl_io/nacl_io.cc
src/nacl_io/path.cc
src/nacl_io/pepper_interface.cc
src/nacl_io/real_pepper_interface.cc
+src/nacl_io/syscalls/accept.c
src/nacl_io/syscalls/access.c
+src/nacl_io/syscalls/bind.c
src/nacl_io/syscalls/chdir.c
src/nacl_io/syscalls/chmod.c
src/nacl_io/syscalls/chown.c
+src/nacl_io/syscalls/connect.c
src/nacl_io/syscalls/fchown.c
src/nacl_io/syscalls/fsync.c
src/nacl_io/syscalls/ftruncate.c
src/nacl_io/syscalls/getcwd.c
src/nacl_io/syscalls/getdents.c
+src/nacl_io/syscalls/gethostbyname.c
+src/nacl_io/syscalls/getpeername.c
+src/nacl_io/syscalls/getsockname.c
+src/nacl_io/syscalls/getsockopt.c
src/nacl_io/syscalls/getwd.c
+src/nacl_io/syscalls/herror.c
+src/nacl_io/syscalls/hstrerror.cc
+src/nacl_io/syscalls/htonl.c
+src/nacl_io/syscalls/htons.c
src/nacl_io/syscalls/inet_ntoa.cc
src/nacl_io/syscalls/inet_ntop.cc
src/nacl_io/syscalls/ioctl.c
src/nacl_io/syscalls/isatty.c
src/nacl_io/syscalls/lchown.c
src/nacl_io/syscalls/link.c
+src/nacl_io/syscalls/listen.c
src/nacl_io/syscalls/mkdir.c
src/nacl_io/syscalls/mount.c
+src/nacl_io/syscalls/ntohl.c
+src/nacl_io/syscalls/ntohs.c
src/nacl_io/syscalls/poll.c
+src/nacl_io/syscalls/recv.c
+src/nacl_io/syscalls/recvfrom.c
+src/nacl_io/syscalls/recvmsg.c
src/nacl_io/syscalls/remove.c
src/nacl_io/syscalls/rmdir.c
src/nacl_io/syscalls/select.c
+src/nacl_io/syscalls/send.c
+src/nacl_io/syscalls/sendmsg.c
+src/nacl_io/syscalls/sendto.c
+src/nacl_io/syscalls/setsockopt.c
+src/nacl_io/syscalls/shutdown.c
+src/nacl_io/syscalls/socket.c
+src/nacl_io/syscalls/socketpair.c
src/nacl_io/syscalls/tcflush.c
src/nacl_io/syscalls/tcgetattr.c
src/nacl_io/syscalls/tcsetattr.c
diff --git a/native_client_sdk/src/examples/common.js b/native_client_sdk/src/examples/common.js
index efa140c..51adb54 100644
--- a/native_client_sdk/src/examples/common.js
+++ b/native_client_sdk/src/examples/common.js
@@ -6,6 +6,10 @@
// string.
var isTest = false;
+// Set to true when loading a "Release" NaCl module, false when loading a
+// "Debug" NaCl module.
+var isRelease = false;
+
// Javascript module pattern:
// see http://en.wikipedia.org/wiki/Unobtrusive_JavaScript#Namespaces
// In essence, we define an anonymous function which is immediately called and
@@ -22,11 +26,10 @@
* Return the mime type for NaCl plugin.
*
* @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc.
- * @param {bool} isRelease True if this is a release build.
* @return {string} The mime-type for the kind of NaCl plugin matching
* the given toolchain.
*/
- function mimeTypeForTool(tool, isRelease) {
+ function mimeTypeForTool(tool) {
// For NaCl modules use application/x-nacl.
var mimetype = 'application/x-nacl';
if (isHostToolchain(tool)) {
@@ -36,7 +39,7 @@
mimetype = 'application/x-ppapi-release';
else
mimetype = 'application/x-ppapi-debug';
- } else if (tool == 'pnacl') {
+ } else if (tool == 'pnacl' && isRelease) {
mimetype = 'application/x-pnacl';
}
return mimetype;
@@ -293,8 +296,7 @@
// status message indicating that the module is still loading. Otherwise,
// do not change the status message.
updateStatus('Page loaded.');
- var isRelease = path.toLowerCase().indexOf('release') != -1;
- if (!browserSupportsNaCl(tool, isRelease)) {
+ if (!browserSupportsNaCl(tool)) {
updateStatus(
'Browser does not support NaCl (' + tool + '), or NaCl is disabled');
} else if (common.naclModule == null) {
@@ -399,6 +401,7 @@
var path = pathFormat.replace('{tc}', tc).replace('{config}', config);
isTest = searchVars.test === 'true';
+ isRelease = path.toLowerCase().indexOf('release') != -1;
loadFunction(body.dataset.name, tc, path, body.dataset.width,
body.dataset.height, attrs);
diff --git a/native_client_sdk/src/examples/demo/earth/earth.cc b/native_client_sdk/src/examples/demo/earth/earth.cc
index d0c6de7..2a1c958 100644
--- a/native_client_sdk/src/examples/demo/earth/earth.cc
+++ b/native_client_sdk/src/examples/demo/earth/earth.cc
@@ -383,9 +383,14 @@
if (!base_tex_ || !night_tex_)
return;
const int kColorBlack = MakeRGBA(0, 0, 0, 0xFF);
+ float width = ps_context_->width;
+ float height = ps_context_->height;
+ float min_dim = width < height ? width : height;
+ float offset_x = width < height ? 0 : (width - min_dim) * 0.5f;
+ float offset_y = width < height ? (height - min_dim) * 0.5f : 0;
float y0 = eye_y_;
float z0 = eye_z_;
- float y1 = (static_cast<float>(y) / ps_context_->height) * 2.0f - 1.0f;
+ float y1 = (static_cast<float>(y - offset_y) / min_dim) * 2.0f - 1.0f;
float z1 = 0.0f;
float dy = (y1 - y0);
float dz = (z1 - z0);
@@ -394,11 +399,11 @@
2.0f * dz * (z0 - planet_z_);
float planet_xyz_eye_xyz = planet_xyz_ + eye_xyz_;
float y_y0_z_z0 = planet_y_ * y0 + planet_z_ * z0;
- float oowidth = 1.0f / ps_context_->width;
+ float oowidth = 1.0f / min_dim;
uint32_t* pixels = this->wGetAddr(x0, y);
for (int x = x0; x <= x1; ++x) {
// scan normalized screen -1..1
- float x1 = (static_cast<float>(x) * oowidth) * 2.0f - 1.0f;
+ float x1 = (static_cast<float>(x - offset_x) * oowidth) * 2.0f - 1.0f;
// eye
float x0 = eye_x_;
// delta from screen to eye
diff --git a/native_client_sdk/src/examples/demo/flock/flock.cc b/native_client_sdk/src/examples/demo/flock/flock.cc
index de23691..94707a0 100644
--- a/native_client_sdk/src/examples/demo/flock/flock.cc
+++ b/native_client_sdk/src/examples/demo/flock/flock.cc
@@ -5,14 +5,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/mount.h>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
-#include "nacl_io/nacl_io.h"
-
#include "ppapi/c/pp_rect.h"
#include "ppapi/c/pp_size.h"
diff --git a/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c b/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c
index 9a1babd..c38fefc 100644
--- a/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c
+++ b/native_client_sdk/src/examples/demo/nacl_io/nacl_io_demo.c
@@ -9,6 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/mount.h>
#include <pthread.h>
#include "ppapi/c/pp_errors.h"
diff --git a/native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc b/native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc
index 9291464..8b5df97 100644
--- a/native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc
+++ b/native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc
@@ -7,6 +7,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/mount.h>
#include <ppapi/cpp/completion_callback.h>
#include <ppapi/cpp/instance.h>
diff --git a/native_client_sdk/src/libraries/nacl_io/host_resolver.cc b/native_client_sdk/src/libraries/nacl_io/host_resolver.cc
index f059f9a..beae726 100644
--- a/native_client_sdk/src/libraries/nacl_io/host_resolver.cc
+++ b/native_client_sdk/src/libraries/nacl_io/host_resolver.cc
@@ -4,13 +4,9 @@
#include "nacl_io/host_resolver.h"
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sstream>
-#include <string>
-
#include "nacl_io/kernel_proxy.h"
#include "nacl_io/ossocket.h"
#include "nacl_io/pepper_interface.h"
@@ -176,51 +172,6 @@
hostent_.h_addr_list = NULL;
}
-void HostResolver::herror(const char* s) {
- if (s) {
- fprintf(stderr, "%s: ", s);
- }
-
- fprintf(stderr, "%s\n", hstrerror(h_errno));
-}
-
-const char* HostResolver::hstrerror(int err) {
- // These error message texts are taken straight from the man page
- const char* host_not_found_msg =
- "The specified host is unknown.";
- const char* no_address_msg =
- "The requested name is valid but does not have an IP address.";
- const char* no_recovery_msg =
- "A nonrecoverable name server error occurred.";
- const char* try_again_msg =
- "A temporary error occurred on an authoritative name server. "
- "Try again later.";
- const char* internal_msg =
- "Internal error in gethostbyname.";
- const char* unknown_msg_base =
- "Unknown error in gethostbyname: ";
-
- switch (err) {
- case HOST_NOT_FOUND:
- return host_not_found_msg;
- case NO_ADDRESS:
- return no_address_msg;
- case NO_RECOVERY:
- return no_recovery_msg;
- case TRY_AGAIN:
- return try_again_msg;
- case NETDB_INTERNAL:
- return internal_msg;
- default:
- std::stringstream msg;
- msg << unknown_msg_base << err << ".";
-
- static std::string unknown_msg;
- unknown_msg.assign(msg.str());
- return unknown_msg.c_str();
- }
-}
-
} // namespace nacl_io
#endif // PROVIDES_SOCKET_API
diff --git a/native_client_sdk/src/libraries/nacl_io/host_resolver.h b/native_client_sdk/src/libraries/nacl_io/host_resolver.h
index 0a942bd..59f3f7f 100644
--- a/native_client_sdk/src/libraries/nacl_io/host_resolver.h
+++ b/native_client_sdk/src/libraries/nacl_io/host_resolver.h
@@ -20,8 +20,6 @@
void Init(PepperInterface* ppapi);
struct hostent* gethostbyname(const char* name);
- static void herror(const char* s);
- static const char* hstrerror(int err);
private:
void hostent_initialize();
diff --git a/native_client_sdk/src/libraries/nacl_io/include/sys/mount.h b/native_client_sdk/src/libraries/nacl_io/include/sys/mount.h
new file mode 100644
index 0000000..dde0ab3
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/include/sys/mount.h
@@ -0,0 +1,19 @@
+/* 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 LIBRARIES_NACL_IO_INCLUDE_SYS_MOUNT_H
+#define LIBRARIES_NACL_IO_INCLUDE_SYS_MOUNT_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+int mount(const char* source, const char* target, const char* filesystemtype,
+ unsigned long mountflags, const void *data);
+
+int umount(const char *target);
+
+__END_DECLS
+
+#endif /* LIBRARIES_NACL_IO_INCLUDE_SYS_MOUNT_H */
diff --git a/native_client_sdk/src/libraries/nacl_io/include/sys/termios.h b/native_client_sdk/src/libraries/nacl_io/include/sys/termios.h
index 8eabbd9..a817565 100644
--- a/native_client_sdk/src/libraries/nacl_io/include/sys/termios.h
+++ b/native_client_sdk/src/libraries/nacl_io/include/sys/termios.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 SYS_TERMIOS_H_
-#define SYS_TERMIOS_H_
+#ifndef LIBRARIES_NACL_IO_INCLUDE_SYS_TERMIOS_H_
+#define LIBRARIES_NACL_IO_INCLUDE_SYS_TERMIOS_H_
#define IGNBRK 0000001
#define BRKINT 0000002
@@ -126,4 +126,4 @@
__END_DECLS
-#endif /* SYS_TERMIOS_H_ */
+#endif /* LIBRARIES_NACL_IO_INCLUDE_SYS_TERMIOS_H_ */
diff --git a/native_client_sdk/src/libraries/nacl_io/include/sys/utsname.h b/native_client_sdk/src/libraries/nacl_io/include/sys/utsname.h
index 2e3cd3d..2292915 100644
--- a/native_client_sdk/src/libraries/nacl_io/include/sys/utsname.h
+++ b/native_client_sdk/src/libraries/nacl_io/include/sys/utsname.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 LIBRARIES_NACL_SYS_UTSNAME_H_
-#define LIBRARIES_NACL_SYS_UTSNAME_H_
+#ifndef LIBRARIES_NACL_IO_INCLUDE_SYS_UTSNAME_H_
+#define LIBRARIES_NACL_IO_INCLUDE_SYS_UTSNAME_H_
#define _UTSNAME_LENGTH 65
@@ -15,6 +15,12 @@
char machine[_UTSNAME_LENGTH];
};
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
int uname(struct utsname *buf);
-#endif
+__END_DECLS
+
+#endif /* LIBRARIES_NACL_IO_INCLUDE_SYS_UTSNAME_H_ */
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
index 912fd18..d1bad01 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
@@ -287,14 +287,6 @@
return s_kp->getsockopt(fd, lvl, optname, optval, len);
}
-void ki_herror(const char *s) {
- return s_kp->herror(s);
-}
-
-const char *ki_hstrerror(int err) {
- return s_kp->hstrerror(err);
-}
-
int ki_listen(int fd, int backlog) {
return s_kp->listen(fd, backlog);
}
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
index b570c8f..6ef44b3 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
@@ -85,8 +85,6 @@
int ki_getpeername(int fd, struct sockaddr* addr, socklen_t* len);
int ki_getsockname(int fd, struct sockaddr* addr, socklen_t* len);
int ki_getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len);
-void ki_herror(const char *s);
-const char *ki_hstrerror(int err);
int ki_listen(int fd, int backlog);
ssize_t ki_recv(int fd, void* buf, size_t len, int flags);
ssize_t ki_recvfrom(int fd, void* buf, size_t len, int flags,
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 a64a800..292f91e 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
@@ -975,14 +975,6 @@
return -1;
}
-void KernelProxy::herror(const char* s) {
- return host_resolver_.herror(s);
-}
-
-const char* KernelProxy::hstrerror(int err) {
- return host_resolver_.hstrerror(err);
-}
-
int KernelProxy::listen(int fd, int backlog) {
ScopedKernelHandle handle;
if (AcquireSocketHandle(fd, &handle) == -1)
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
index 47b6f77..fc0191f 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
@@ -142,8 +142,6 @@
int optname,
void* optval,
socklen_t* len);
- virtual void herror(const char* s);
- virtual const char* hstrerror(int err);
virtual int listen(int fd, int backlog);
virtual ssize_t recv(int fd,
void* buf,
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap.h b/native_client_sdk/src/libraries/nacl_io/kernel_wrap.h
index 6b79d4f..33a4c2d 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap.h
@@ -106,8 +106,6 @@
int getpeername(int fd, struct sockaddr* addr, socklen_t* len);
int getsockname(int fd, struct sockaddr* addr, socklen_t* len);
int getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len);
-void herror(const char *s);
-const char *hstrerror(int err);
int listen(int fd, int backlog);
ssize_t recv(int fd, void* buf, size_t len, int flags);
ssize_t recvfrom(int fd, void* buf, size_t len, int flags,
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_glibc.cc b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_glibc.cc
index 7c52f4d..c2a9e1f 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_glibc.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_glibc.cc
@@ -11,6 +11,7 @@
#include "nacl_io/kernel_wrap.h"
#include <alloca.h>
+#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <irt.h>
@@ -103,9 +104,14 @@
// Macro to get the WRAP function
#define WRAP(name) __nacl_irt_##name##_wrap
-// Declare REAL function pointer and assign it the REAL function.
+// Declare REAL function pointer.
#define DECLARE_REAL_PTR(name) \
- typeof(__nacl_irt_##name) REAL(name) = __nacl_irt_##name;
+ typeof(__nacl_irt_##name) REAL(name);
+
+// Assign the REAL function pointer.
+#define ASSIGN_REAL_PTR(name) \
+ assert(__nacl_irt_##name != NULL); \
+ REAL(name) = __nacl_irt_##name;
// Switch IRT's pointer to the REAL pointer
#define USE_REAL(name) \
@@ -279,90 +285,6 @@
return (signed_nwrote < 0) ? errno : 0;
}
-// Socket functions
-int accept(int fd, struct sockaddr* addr, socklen_t* len) {
- return ki_accept(fd, addr, len);
-}
-
-int bind(int fd, const struct sockaddr* addr, socklen_t len) {
- return ki_bind(fd, addr, len);
-}
-
-int connect(int fd, const struct sockaddr* addr, socklen_t len) {
- return ki_connect(fd, addr, len);
-}
-
-struct hostent* gethostbyname(const char* name) {
- return ki_gethostbyname(name);
-}
-
-int getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
- return ki_getpeername(fd, addr, len);
-}
-
-int getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
- return ki_getsockname(fd, addr, len);
-}
-
-int getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len) {
- return ki_getsockopt(fd, lvl, optname, optval, len);
-}
-
-void herror(const char *s) {
- return ki_herror(s);
-}
-
-const char *hstrerror(int err) {
- return ki_hstrerror(err);
-}
-
-int listen(int fd, int backlog) {
- return ki_listen(fd, backlog);
-}
-
-ssize_t recv(int fd, void* buf, size_t len, int flags) {
- return ki_recv(fd, buf, len, flags);
-}
-
-ssize_t recvfrom(int fd, void* buf, size_t len, int flags,
- struct sockaddr* addr, socklen_t* addrlen) {
- return ki_recvfrom(fd, buf, len, flags, addr, addrlen);
-}
-
-ssize_t recvmsg(int fd, struct msghdr* msg, int flags) {
- return ki_recvmsg(fd, msg, flags);
-}
-
-ssize_t send(int fd, const void* buf, size_t len, int flags) {
- return ki_send(fd, buf, len, flags);
-}
-
-ssize_t sendto(int fd, const void* buf, size_t len, int flags,
- const struct sockaddr* addr, socklen_t addrlen) {
- return ki_sendto(fd, buf, len, flags, addr, addrlen);
-}
-
-ssize_t sendmsg(int fd, const struct msghdr* msg, int flags) {
- return ki_sendmsg(fd, msg, flags);
-}
-
-int setsockopt(int fd, int lvl, int optname, const void* optval,
- socklen_t len) {
- return ki_setsockopt(fd, lvl, optname, optval, len);
-}
-
-int shutdown(int fd, int how) {
- return ki_shutdown(fd, how);
-}
-
-int socket(int domain, int type, int protocol) {
- return ki_socket(domain, type, protocol);
-}
-
-int socketpair(int domain, int type, int protocol, int* sv) {
- return ki_socketpair(domain, type, protocol, sv);
-}
-
// "real" functions, i.e. the unwrapped original functions.
int _real_close(int fd) {
@@ -454,8 +376,13 @@
}
static bool s_wrapped = false;
+static bool s_assigned = false;
void kernel_wrap_init() {
if (!s_wrapped) {
+ if (!s_assigned) {
+ EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR)
+ s_assigned = true;
+ }
EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP)
s_wrapped = true;
}
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc
index e218301..34ab407 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc
@@ -9,6 +9,7 @@
#if defined(__native_client__) && !defined(__GLIBC__)
#include "nacl_io/kernel_wrap.h"
+#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <irt.h>
@@ -25,9 +26,14 @@
// Macro to get the WRAP function
#define WRAP(name) __nacl_irt_##name##_wrap
-// Declare REAL function pointer and assign it the REAL function.
+// Declare REAL function pointer.
#define DECLARE_REAL_PTR(group, name) \
- typeof(__libnacl_irt_##group.name) REAL(name) = __libnacl_irt_##group.name;
+ typeof(__libnacl_irt_##group.name) REAL(name);
+
+// Assign the REAL function pointer.
+#define ASSIGN_REAL_PTR(group, name) \
+ assert(__libnacl_irt_##group.name != NULL); \
+ REAL(name) = __libnacl_irt_##group.name;
// Switch IRT's pointer to the REAL pointer
#define USE_REAL(group, name) \
@@ -37,10 +43,10 @@
#define USE_WRAP(group, name) \
__libnacl_irt_##group.name = (typeof(REAL(name))) WRAP(name); \
-
+extern void __libnacl_irt_filename_init(void);
extern struct nacl_irt_fdio __libnacl_irt_fdio;
-extern struct nacl_irt_filename __libnacl_irt_filename;
+extern struct nacl_irt_dev_filename __libnacl_irt_dev_filename;
extern struct nacl_irt_memory __libnacl_irt_memory;
// Create function pointers to the REAL implementation
@@ -53,8 +59,8 @@
OP(fdio, read); \
OP(fdio, seek); \
OP(fdio, write); \
- OP(filename, open); \
- OP(filename, stat); \
+ OP(dev_filename, open); \
+ OP(dev_filename, stat); \
OP(memory, mmap); \
OP(memory, munmap);
@@ -131,90 +137,6 @@
return (signed_nwrote < 0) ? errno : 0;
}
-// Socket functions
-int accept(int fd, struct sockaddr* addr, socklen_t* len) {
- return ki_accept(fd, addr, len);
-}
-
-int bind(int fd, const struct sockaddr* addr, socklen_t len) {
- return ki_bind(fd, addr, len);
-}
-
-int connect(int fd, const struct sockaddr* addr, socklen_t len) {
- return ki_connect(fd, addr, len);
-}
-
-struct hostent* gethostbyname(const char* name) {
- return ki_gethostbyname(name);
-}
-
-int getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
- return ki_getpeername(fd, addr, len);
-}
-
-int getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
- return ki_getsockname(fd, addr, len);
-}
-
-int getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len) {
- return ki_getsockopt(fd, lvl, optname, optval, len);
-}
-
-void herror(const char* s) {
- return ki_herror(s);
-}
-
-const char* hstrerror(int err) {
- return ki_hstrerror(err);
-}
-
-int listen(int fd, int backlog) {
- return ki_listen(fd, backlog);
-}
-
-ssize_t recv(int fd, void* buf, size_t len, int flags) {
- return ki_recv(fd, buf, len, flags);
-}
-
-ssize_t recvfrom(int fd, void* buf, size_t len, int flags,
- struct sockaddr* addr, socklen_t* addrlen) {
- return ki_recvfrom(fd, buf, len, flags, addr, addrlen);
-}
-
-ssize_t recvmsg(int fd, struct msghdr* msg, int flags) {
- return ki_recvmsg(fd, msg, flags);
-}
-
-ssize_t send(int fd, const void* buf, size_t len, int flags) {
- return ki_send(fd, buf, len, flags);
-}
-
-ssize_t sendto(int fd, const void* buf, size_t len, int flags,
- const struct sockaddr* addr, socklen_t addrlen) {
- return ki_sendto(fd, buf, len, flags, addr, addrlen);
-}
-
-ssize_t sendmsg(int fd, const struct msghdr* msg, int flags) {
- return ki_sendmsg(fd, msg, flags);
-}
-
-int setsockopt(int fd, int lvl, int optname, const void* optval,
- socklen_t len) {
- return ki_setsockopt(fd, lvl, optname, optval, len);
-}
-
-int shutdown(int fd, int how) {
- return ki_shutdown(fd, how);
-}
-
-int socket(int domain, int type, int protocol) {
- return ki_socket(domain, type, protocol);
-}
-
-int socketpair(int domain, int type, int protocol, int* sv) {
- return ki_socketpair(domain, type, protocol, sv);
-}
-
// "real" functions, i.e. the unwrapped original functions.
int _real_close(int fd) {
@@ -273,16 +195,22 @@
}
static bool s_wrapped = false;
+static bool s_assigned = false;
void kernel_wrap_init() {
if (!s_wrapped) {
- EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP);
+ if (!s_assigned) {
+ __libnacl_irt_filename_init();
+ EXPAND_SYMBOL_LIST_OPERATION(ASSIGN_REAL_PTR)
+ s_assigned = true;
+ }
+ EXPAND_SYMBOL_LIST_OPERATION(USE_WRAP)
s_wrapped = true;
}
}
void kernel_wrap_uninit() {
if (s_wrapped) {
- EXPAND_SYMBOL_LIST_OPERATION(USE_REAL);
+ EXPAND_SYMBOL_LIST_OPERATION(USE_REAL)
s_wrapped = false;
}
}
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h
index b13d7f8..9a9bce6 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h
@@ -5,6 +5,7 @@
#ifndef LIBRARIES_NACL_IO_KERNEL_WRAP_REAL_H_
#define LIBRARIES_NACL_IO_KERNEL_WRAP_REAL_H_
+#include "nacl_io/osstat.h"
#include "nacl_io/ostypes.h"
#include "sdk_util/macros.h"
diff --git a/native_client_sdk/src/libraries/nacl_io/library.dsc b/native_client_sdk/src/libraries/nacl_io/library.dsc
index 011a9c6..4d75b2c 100644
--- a/native_client_sdk/src/libraries/nacl_io/library.dsc
+++ b/native_client_sdk/src/libraries/nacl_io/library.dsc
@@ -32,36 +32,61 @@
"mount_node_html5fs.cc",
"mount_node_http.cc",
"mount_node_mem.cc",
+ "mount_node_tty.cc",
"mount_passthrough.cc",
"nacl_io.cc",
"path.cc",
"pepper_interface.cc",
"real_pepper_interface.cc",
+ "syscalls/accept.c",
"syscalls/access.c",
+ "syscalls/bind.c",
"syscalls/chdir.c",
"syscalls/chmod.c",
"syscalls/chown.c",
+ "syscalls/connect.c",
"syscalls/fchown.c",
"syscalls/fsync.c",
"syscalls/ftruncate.c",
- "syscalls/getdents.c",
- "syscalls/getwd.c",
"syscalls/getcwd.c",
+ "syscalls/getdents.c",
+ "syscalls/gethostbyname.c",
+ "syscalls/getpeername.c",
+ "syscalls/getsockname.c",
+ "syscalls/getsockopt.c",
+ "syscalls/getwd.c",
+ "syscalls/herror.c",
+ "syscalls/hstrerror.cc",
+ "syscalls/htonl.c",
+ "syscalls/htons.c",
"syscalls/inet_ntoa.cc",
"syscalls/inet_ntop.cc",
"syscalls/ioctl.c",
"syscalls/isatty.c",
- "syscalls/link.c",
"syscalls/lchown.c",
+ "syscalls/link.c",
+ "syscalls/listen.c",
"syscalls/mkdir.c",
"syscalls/mount.c",
+ "syscalls/ntohl.c",
+ "syscalls/ntohs.c",
"syscalls/poll.c",
- "syscalls/remove.c",
"syscalls/rmdir.c",
- "syscalls/select.c",
+ "syscalls/recv.c",
+ "syscalls/recvfrom.c",
+ "syscalls/recvmsg.c",
+ "syscalls/remove.c",
"syscalls/tcflush.c",
"syscalls/tcgetattr.c",
"syscalls/tcsetattr.c",
+ "syscalls/select.c",
+ "syscalls/send.c",
+ "syscalls/sendmsg.c",
+ "syscalls/sendto.c",
+ "syscalls/setsockopt.c",
+ "syscalls/shutdown.c",
+ "syscalls/socket.c",
+ "syscalls/socketpair.c",
"syscalls/unlink.c",
"syscalls/umount.c",
"syscalls/uname.c",
@@ -90,11 +115,13 @@
"mount_html5fs.h",
"mount_http.h",
"mount_mem.h",
- "mount_node_dir.h",
"mount_node.h",
+ "mount_node_char.h",
+ "mount_node_dir.h",
"mount_node_html5fs.h",
"mount_node_http.h",
"mount_node_mem.h",
+ "mount_node_tty.h",
"mount_passthrough.h",
"nacl_io.h",
"osdirent.h",
@@ -119,8 +146,10 @@
"arpa/inet.h",
"netdb.h",
"netinet/in.h",
+ "netinet/tcp.h",
"netinet6/in6.h",
"poll.h",
+ "sys/mount.h",
"sys/select.h",
"sys/socket.h",
"sys/termios.h",
@@ -133,8 +162,10 @@
"arpa/inet.h",
"netdb.h",
"netinet/in.h",
+ "netinet/tcp.h",
"netinet6/in6.h",
"poll.h",
+ "sys/mount.h",
"sys/select.h",
"sys/socket.h",
"sys/termios.h",
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_dev.cc b/native_client_sdk/src/libraries/nacl_io/mount_dev.cc
index f409b19..3c7ffe0 100644
--- a/native_client_sdk/src/libraries/nacl_io/mount_dev.cc
+++ b/native_client_sdk/src/libraries/nacl_io/mount_dev.cc
@@ -11,13 +11,11 @@
#include <pthread.h>
#include <string.h>
-#include <deque>
-
-#include "nacl_io/ioctl.h"
#include "nacl_io/kernel_wrap_real.h"
#include "nacl_io/mount_dev.h"
#include "nacl_io/mount_node.h"
#include "nacl_io/mount_node_dir.h"
+#include "nacl_io/mount_node_tty.h"
#include "nacl_io/osunistd.h"
#include "nacl_io/pepper_interface.h"
#include "sdk_util/auto_lock.h"
@@ -47,9 +45,9 @@
int fd_;
};
-class NullNode : public MountNode {
+class NullNode : public MountNodeCharDevice {
public:
- explicit NullNode(Mount* mount);
+ explicit NullNode(Mount* mount) : MountNodeCharDevice(mount) {}
virtual Error Read(size_t offs, void* buf, size_t count, int* out_bytes);
virtual Error Write(size_t offs,
@@ -58,7 +56,7 @@
int* out_bytes);
};
-class ConsoleNode : public NullNode {
+class ConsoleNode : public MountNodeCharDevice {
public:
ConsoleNode(Mount* mount, PP_LogLevel level);
@@ -71,30 +69,6 @@
PP_LogLevel level_;
};
-class TtyNode : public NullNode {
- public:
- explicit TtyNode(Mount* mount);
- ~TtyNode();
-
- virtual Error Ioctl(int request,
- char* arg);
-
- virtual Error Read(size_t offs,
- void* buf,
- size_t count,
- int* out_bytes);
-
- virtual Error Write(size_t offs,
- const void* buf,
- size_t count,
- int* out_bytes);
-
- private:
- std::deque<char> input_buffer_;
- pthread_cond_t is_readable_;
- std::string prefix_;
-};
-
class ZeroNode : public MountNode {
public:
explicit ZeroNode(Mount* mount);
@@ -156,8 +130,6 @@
Error RealNode::GetStat(struct stat* stat) { return _real_fstat(fd_, stat); }
-NullNode::NullNode(Mount* mount) : MountNode(mount) { stat_.st_mode = S_IFCHR; }
-
Error NullNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
*out_bytes = 0;
return 0;
@@ -172,8 +144,7 @@
}
ConsoleNode::ConsoleNode(Mount* mount, PP_LogLevel level)
- : NullNode(mount), level_(level) {
- stat_.st_mode = S_IFCHR;
+ : MountNodeCharDevice(mount), level_(level) {
}
Error ConsoleNode::Write(size_t offs,
@@ -197,88 +168,6 @@
return 0;
}
-TtyNode::TtyNode(Mount* mount) : NullNode(mount) {
- pthread_cond_init(&is_readable_, NULL);
-}
-
-TtyNode::~TtyNode() {
- pthread_cond_destroy(&is_readable_);
-}
-
-Error TtyNode::Write(size_t offs,
- const void* buf,
- size_t count,
- int* out_bytes) {
- *out_bytes = 0;
-
- MessagingInterface* msg_intr = mount_->ppapi()->GetMessagingInterface();
- VarInterface* var_intr = mount_->ppapi()->GetVarInterface();
-
- if (!(var_intr && msg_intr))
- return ENOSYS;
-
- // We append the prefix_ to the data in buf, then package it up
- // and post it as a message.
- const char* data = static_cast<const char*>(buf);
- std::string message;
- {
- AUTO_LOCK(node_lock_);
- message = prefix_;
- }
- message.append(data, count);
- uint32_t len = static_cast<uint32_t>(message.size());
- struct PP_Var val = var_intr->VarFromUtf8(message.data(), len);
- msg_intr->PostMessage(mount_->ppapi()->GetInstance(), val);
- *out_bytes = count;
- return 0;
-}
-
-Error TtyNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
- AUTO_LOCK(node_lock_);
- while (input_buffer_.size() <= 0) {
- pthread_cond_wait(&is_readable_, node_lock_.mutex());
- }
-
- // Copies data from the input buffer into buf.
- size_t bytes_to_copy = std::min(count, input_buffer_.size());
- std::copy(input_buffer_.begin(), input_buffer_.begin() + bytes_to_copy,
- static_cast<char*>(buf));
- *out_bytes = bytes_to_copy;
- input_buffer_.erase(input_buffer_.begin(),
- input_buffer_.begin() + bytes_to_copy);
- return 0;
-}
-
-Error TtyNode::Ioctl(int request, char* arg) {
- if (request == TIOCNACLPREFIX) {
- // This ioctl is used to change the prefix for this tty node.
- // The prefix is used to distinguish messages intended for this
- // tty node from all the other messages cluttering up the
- // javascript postMessage() channel.
- AUTO_LOCK(node_lock_);
- prefix_ = arg;
- return 0;
- } else if (request == TIOCNACLINPUT) {
- // This ioctl is used to deliver data from the user to this tty node's
- // input buffer. We check if the prefix in the input data matches the
- // prefix for this node, and only deliver the data if so.
- struct tioc_nacl_input_string* message =
- reinterpret_cast<struct tioc_nacl_input_string*>(arg);
- AUTO_LOCK(node_lock_);
- if (message->length >= prefix_.size() &&
- strncmp(message->buffer, prefix_.data(), prefix_.size()) == 0) {
- input_buffer_.insert(input_buffer_.end(),
- message->buffer + prefix_.size(),
- message->buffer + message->length);
- pthread_cond_broadcast(&is_readable_);
- return 0;
- }
- return ENOTTY;
- } else {
- return EINVAL;
- }
-}
-
ZeroNode::ZeroNode(Mount* mount) : MountNode(mount) { stat_.st_mode = S_IFCHR; }
Error ZeroNode::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
@@ -407,7 +296,7 @@
INITIALIZE_DEV_NODE_1("/console1", ConsoleNode, PP_LOGLEVEL_LOG);
INITIALIZE_DEV_NODE_1("/console2", ConsoleNode, PP_LOGLEVEL_WARNING);
INITIALIZE_DEV_NODE_1("/console3", ConsoleNode, PP_LOGLEVEL_ERROR);
- INITIALIZE_DEV_NODE("/tty", TtyNode);
+ INITIALIZE_DEV_NODE("/tty", MountNodeTty);
INITIALIZE_DEV_NODE_1("/stdin", RealNode, 0);
INITIALIZE_DEV_NODE_1("/stdout", RealNode, 1);
INITIALIZE_DEV_NODE_1("/stderr", RealNode, 2);
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_char.h b/native_client_sdk/src/libraries/nacl_io/mount_node_char.h
new file mode 100644
index 0000000..48ad86f
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_char.h
@@ -0,0 +1,21 @@
+// 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 LIBRARIES_NACL_IO_MOUNT_NODE_CHAR_H
+#define LIBRARIES_NACL_IO_MOUNT_NODE_CHAR_H
+
+#include "nacl_io/mount_node.h"
+
+namespace nacl_io {
+
+class MountNodeCharDevice : public MountNode {
+ public:
+ explicit MountNodeCharDevice(Mount* mount) : MountNode(mount) {
+ stat_.st_mode = S_IFCHR;
+ }
+};
+
+}
+
+#endif // LIBRARIES_NACL_IO_MOUNT_NODE_CHAR_H
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc
new file mode 100644
index 0000000..7b9fb79
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc
@@ -0,0 +1,271 @@
+// 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 "nacl_io/mount_node_tty.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <algorithm>
+
+#include "nacl_io/ioctl.h"
+#include "nacl_io/mount.h"
+#include "nacl_io/pepper_interface.h"
+#include "sdk_util/auto_lock.h"
+
+#define CHECK_LFLAG(TERMIOS, FLAG) (TERMIOS .c_lflag & FLAG)
+
+#define IS_ECHO CHECK_LFLAG(termios_, ECHO)
+#define IS_ECHOE CHECK_LFLAG(termios_, ECHOE)
+#define IS_ECHONL CHECK_LFLAG(termios_, ECHONL)
+#define IS_ECHOCTL CHECK_LFLAG(termios_, ECHOCTL)
+#define IS_ICANON CHECK_LFLAG(termios_, ICANON)
+
+namespace nacl_io {
+
+MountNodeTty::MountNodeTty(Mount* mount) : MountNodeCharDevice(mount),
+ is_readable_(false) {
+ pthread_cond_init(&is_readable_cond_, NULL);
+ InitTermios();
+}
+
+void MountNodeTty::InitTermios() {
+ // Some sane values that produce good result.
+ termios_.c_iflag = ICRNL | IXON | IXOFF | IUTF8;
+ termios_.c_oflag = OPOST | ONLCR;
+ termios_.c_cflag = CREAD | 077;
+ termios_.c_lflag =
+ ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
+ termios_.c_ispeed = B38400;
+ termios_.c_ospeed = B38400;
+ termios_.c_cc[VINTR] = 3;
+ termios_.c_cc[VQUIT] = 28;
+ termios_.c_cc[VERASE] = 127;
+ termios_.c_cc[VKILL] = 21;
+ termios_.c_cc[VEOF] = 4;
+ termios_.c_cc[VTIME] = 0;
+ termios_.c_cc[VMIN] = 1;
+ termios_.c_cc[VSWTC] = 0;
+ termios_.c_cc[VSTART] = 17;
+ termios_.c_cc[VSTOP] = 19;
+ termios_.c_cc[VSUSP] = 26;
+ termios_.c_cc[VEOL] = 0;
+ termios_.c_cc[VREPRINT] = 18;
+ termios_.c_cc[VDISCARD] = 15;
+ termios_.c_cc[VWERASE] = 23;
+ termios_.c_cc[VLNEXT] = 22;
+ termios_.c_cc[VEOL2] = 0;
+}
+
+MountNodeTty::~MountNodeTty() {
+ pthread_cond_destroy(&is_readable_cond_);
+}
+
+Error MountNodeTty::Write(size_t offs,
+ const void* buf,
+ size_t count,
+ int* out_bytes) {
+ return Write(offs, buf, count, out_bytes, false);
+}
+
+Error MountNodeTty::Write(size_t offs,
+ const void* buf,
+ size_t count,
+ int* out_bytes,
+ bool locked) {
+ *out_bytes = 0;
+
+ if (!mount_->ppapi())
+ return ENOSYS;
+
+ MessagingInterface* msg_intr = mount_->ppapi()->GetMessagingInterface();
+ VarInterface* var_intr = mount_->ppapi()->GetVarInterface();
+
+ if (!(var_intr && msg_intr))
+ return ENOSYS;
+
+ // We append the prefix_ to the data in buf, then package it up
+ // and post it as a message.
+ const char* data = static_cast<const char*>(buf);
+ std::string message;
+ if (locked) {
+ message = prefix_;
+ } else {
+ AUTO_LOCK(node_lock_);
+ message = prefix_;
+ }
+
+ message.append(data, count);
+ uint32_t len = static_cast<uint32_t>(message.size());
+ struct PP_Var val = var_intr->VarFromUtf8(message.data(), len);
+ msg_intr->PostMessage(mount_->ppapi()->GetInstance(), val);
+ var_intr->Release(val);
+ *out_bytes = count;
+ return 0;
+}
+
+Error MountNodeTty::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
+ AUTO_LOCK(node_lock_);
+ while (!is_readable_) {
+ pthread_cond_wait(&is_readable_cond_, node_lock_.mutex());
+ }
+
+ size_t bytes_to_copy = std::min(count, input_buffer_.size());
+
+ if (IS_ICANON) {
+ // Only read up to (and including) the first newline
+ std::deque<char>::iterator nl = std::find(input_buffer_.begin(),
+ input_buffer_.end(),
+ '\n');
+
+ if (nl != input_buffer_.end()) {
+ // We found a newline in the buffer, adjust bytes_to_copy accordingly
+ size_t line_len = static_cast<size_t>(nl - input_buffer_.begin()) + 1;
+ bytes_to_copy = std::min(bytes_to_copy, line_len);
+ }
+ }
+
+
+ // Copies data from the input buffer into buf.
+ std::copy(input_buffer_.begin(), input_buffer_.begin() + bytes_to_copy,
+ static_cast<char*>(buf));
+ *out_bytes = bytes_to_copy;
+ input_buffer_.erase(input_buffer_.begin(),
+ input_buffer_.begin() + bytes_to_copy);
+
+ // mark input as no longer readable if we consumed
+ // the entire buffer or, in the case of buffered input,
+ // we consumed the final \n char.
+ if (IS_ICANON)
+ is_readable_ =
+ std::find(input_buffer_.begin(),
+ input_buffer_.end(), '\n') != input_buffer_.end();
+ else
+ is_readable_ = input_buffer_.size() > 0;
+
+ return 0;
+}
+
+Error MountNodeTty::Echo(const char* string, int count) {
+ int wrote;
+ Error error = Write(0, string, count, &wrote, true);
+ if (error != 0 || wrote != count) {
+ // TOOD(sbc): Do something more useful in response to a
+ // failure to echo.
+ return error;
+ }
+
+ return 0;
+}
+
+Error MountNodeTty::ProcessInput(struct tioc_nacl_input_string* message) {
+ AUTO_LOCK(node_lock_);
+ if (message->length < prefix_.size() ||
+ strncmp(message->buffer, prefix_.data(), prefix_.size()) != 0) {
+ return ENOTTY;
+ }
+
+ const char* buffer = message->buffer + prefix_.size();
+ int num_bytes = message->length - prefix_.size();
+
+ for (int i = 0; i < num_bytes; i++) {
+ char c = buffer[i];
+ // Transform characters according to input flags.
+ if (c == '\r') {
+ if (termios_.c_iflag & IGNCR)
+ continue;
+ if (termios_.c_iflag & ICRNL)
+ c = '\n';
+ } else if (c == '\n') {
+ if (termios_.c_iflag & INLCR)
+ c = '\r';
+ }
+
+ bool skip = false;
+
+ // ICANON mode means we wait for a newline before making the
+ // file readable.
+ if (IS_ICANON) {
+ if (IS_ECHOE && c == termios_.c_cc[VERASE]) {
+ // Remove previous character in the line if any.
+ if (!input_buffer_.empty()) {
+ char char_to_delete = input_buffer_.back();
+ if (char_to_delete != '\n') {
+ input_buffer_.pop_back();
+ if (IS_ECHO)
+ Echo("\b \b", 3);
+
+ // When ECHOCTL is set the echo buffer contains an extra
+ // char for each control char.
+ if (IS_ECHOCTL && iscntrl(char_to_delete))
+ Echo("\b \b", 3);
+ }
+ }
+ continue;
+ } else if (IS_ECHO || (IS_ECHONL && c == '\n')) {
+ if (c == termios_.c_cc[VEOF]) {
+ // VEOF sequence is not echoed, nor is it sent as
+ // input.
+ skip = true;
+ } else if (c != '\n' && iscntrl(c) && IS_ECHOCTL) {
+ // In ECHOCTL mode a control char C is echoed as '^'
+ // followed by the ascii char which at C + 0x40.
+ char visible_char = c + 0x40;
+ Echo("^", 1);
+ Echo(&visible_char, 1);
+ } else {
+ Echo(&c, 1);
+ }
+ }
+ }
+
+ if (!skip)
+ input_buffer_.push_back(c);
+
+ if (c == '\n' || c == termios_.c_cc[VEOF] || !IS_ICANON)
+ is_readable_ = true;
+ }
+
+ if (is_readable_)
+ pthread_cond_broadcast(&is_readable_cond_);
+ return 0;
+}
+
+Error MountNodeTty::Ioctl(int request, char* arg) {
+ if (request == TIOCNACLPREFIX) {
+ // This ioctl is used to change the prefix for this tty node.
+ // The prefix is used to distinguish messages intended for this
+ // tty node from all the other messages cluttering up the
+ // javascript postMessage() channel.
+ AUTO_LOCK(node_lock_);
+ prefix_ = arg;
+ return 0;
+ } else if (request == TIOCNACLINPUT) {
+ // This ioctl is used to deliver data from the user to this tty node's
+ // input buffer. We check if the prefix in the input data matches the
+ // prefix for this node, and only deliver the data if so.
+ struct tioc_nacl_input_string* message =
+ reinterpret_cast<struct tioc_nacl_input_string*>(arg);
+ return ProcessInput(message);
+ } else {
+ return EINVAL;
+ }
+}
+
+Error MountNodeTty::Tcgetattr(struct termios* termios_p) {
+ AUTO_LOCK(node_lock_);
+ *termios_p = termios_;
+ return 0;
+}
+
+Error MountNodeTty::Tcsetattr(int optional_actions,
+ const struct termios *termios_p) {
+ AUTO_LOCK(node_lock_);
+ termios_ = *termios_p;
+ return 0;
+}
+
+}
diff --git a/native_client_sdk/src/libraries/nacl_io/mount_node_tty.h b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.h
new file mode 100644
index 0000000..0707420
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/mount_node_tty.h
@@ -0,0 +1,60 @@
+// 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 LIBRARIES_NACL_IO_MOUNT_NODE_TTY_H_
+#define LIBRARIES_NACL_IO_MOUNT_NODE_TTY_H_
+
+#include <pthread.h>
+
+#include <deque>
+
+#include "nacl_io/ioctl.h"
+#include "nacl_io/mount_node_char.h"
+#include "nacl_io/ostermios.h"
+
+
+namespace nacl_io {
+
+class MountNodeTty : public MountNodeCharDevice {
+ public:
+ explicit MountNodeTty(Mount* mount);
+ ~MountNodeTty();
+
+ virtual Error Ioctl(int request,
+ char* arg);
+
+ virtual Error Read(size_t offs,
+ void* buf,
+ size_t count,
+ int* out_bytes);
+
+ virtual Error Write(size_t offs,
+ const void* buf,
+ size_t count,
+ int* out_bytes);
+
+ virtual Error Tcgetattr(struct termios* termios_p);
+ virtual Error Tcsetattr(int optional_actions,
+ const struct termios *termios_p);
+
+ private:
+ virtual Error Write(size_t offs,
+ const void* buf,
+ size_t count,
+ int* out_bytes,
+ bool locked);
+ Error ProcessInput(struct tioc_nacl_input_string* message);
+ Error Echo(const char* string, int count);
+ void InitTermios();
+
+ std::deque<char> input_buffer_;
+ bool is_readable_;
+ pthread_cond_t is_readable_cond_;
+ std::string prefix_;
+ struct termios termios_;
+};
+
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/nacl_io.h b/native_client_sdk/src/libraries/nacl_io/nacl_io.h
index e72b5a5..058ba68 100644
--- a/native_client_sdk/src/libraries/nacl_io/nacl_io.h
+++ b/native_client_sdk/src/libraries/nacl_io/nacl_io.h
@@ -8,20 +8,20 @@
#include <ppapi/c/pp_instance.h>
#include <ppapi/c/ppb.h>
-#include "nacl_io/kernel_wrap.h"
#include "sdk_util/macros.h"
EXTERN_C_BEGIN
-
-/** Initialize nacl_io.
+/**
+ * Initialize nacl_io.
*
* NOTE: If you initialize nacl_io with this constructor, you cannot
* use any mounts that require PPAPI; e.g. persistent storage, etc.
*/
void nacl_io_init();
-/** Initialize nacl_io with PPAPI support.
+/**
+ * Initialize nacl_io with PPAPI support.
*
* Usage:
* PP_Instance instance;
@@ -42,7 +42,11 @@
PPB_GetInterface get_interface);
-/** Mount a new filesystem type.
+/**
+ * Mount a new filesystem type.
+ *
+ * This function is declared in <sys/mount.h>, but we document it here
+ * because nacl_io is controlled primarily through mount(2)/umount(2).
*
* Some parameters are dependent on the filesystem type being mounted.
*
@@ -108,9 +112,10 @@
* @param[in] mountflags Unused.
* @param[in] data Depends on the filesystem type. See above.
* @return 0 on success, -1 on failure (with errno set).
+ *
+ * int mount(const char* source, const char* target, const char* filesystemtype,
+ * unsigned long mountflags, const void *data) NOTHROW;
*/
-int mount(const char* source, const char* target, const char* filesystemtype,
- unsigned long mountflags, const void *data) NOTHROW;
EXTERN_C_END
diff --git a/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h b/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h
index cb75d73..1f2e1bf 100644
--- a/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h
+++ b/native_client_sdk/src/libraries/nacl_io/pepper/all_interfaces.h
@@ -64,6 +64,7 @@
END_INTERFACE(MessagingInterface, PPB_Messaging)
BEGIN_INTERFACE(VarInterface, PPB_Var, PPB_VAR_INTERFACE_1_1)
+ METHOD1(VarInterface, void, Release, struct PP_Var)
METHOD2(VarInterface, struct PP_Var, VarFromUtf8, const char *, uint32_t)
METHOD2(VarInterface, const char*, VarToUtf8, PP_Var, uint32_t*)
END_INTERFACE(VarInterface, PPB_Var)
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/accept.c b/native_client_sdk/src/libraries/nacl_io/syscalls/accept.c
new file mode 100644
index 0000000..ff4f7df
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/accept.c
@@ -0,0 +1,14 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int accept(int fd, struct sockaddr* addr, socklen_t* len) {
+ return ki_accept(fd, addr, len);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/bind.c b/native_client_sdk/src/libraries/nacl_io/syscalls/bind.c
new file mode 100644
index 0000000..2dbfb3b
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/bind.c
@@ -0,0 +1,14 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int bind(int fd, const struct sockaddr* addr, socklen_t len) {
+ return ki_bind(fd, addr, len);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/connect.c b/native_client_sdk/src/libraries/nacl_io/syscalls/connect.c
new file mode 100644
index 0000000..8d2a10f
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/connect.c
@@ -0,0 +1,14 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int connect(int fd, const struct sockaddr* addr, socklen_t len) {
+ return ki_connect(fd, addr, len);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/gethostbyname.c b/native_client_sdk/src/libraries/nacl_io/syscalls/gethostbyname.c
new file mode 100644
index 0000000..d370075
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/gethostbyname.c
@@ -0,0 +1,16 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/ossocket.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+struct hostent* gethostbyname(const char* name) {
+ return ki_gethostbyname(name);
+}
+
+#endif /* PROVIDES_SOCKET_API */
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/getpeername.c b/native_client_sdk/src/libraries/nacl_io/syscalls/getpeername.c
new file mode 100644
index 0000000..20d241c
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/getpeername.c
@@ -0,0 +1,14 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
+ return ki_getpeername(fd, addr, len);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/getsockname.c b/native_client_sdk/src/libraries/nacl_io/syscalls/getsockname.c
new file mode 100644
index 0000000..79639de
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/getsockname.c
@@ -0,0 +1,14 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
+ return ki_getsockname(fd, addr, len);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/getsockopt.c b/native_client_sdk/src/libraries/nacl_io/syscalls/getsockopt.c
new file mode 100644
index 0000000..aa55f22
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/getsockopt.c
@@ -0,0 +1,15 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len) {
+ return ki_getsockopt(fd, lvl, optname, optval, len);
+}
+
+#endif
+
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/herror.c b/native_client_sdk/src/libraries/nacl_io/syscalls/herror.c
new file mode 100644
index 0000000..01bcd91
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/herror.c
@@ -0,0 +1,19 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/ossocket.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+#include <stdio.h>
+
+void herror(const char* s) {
+ if (s) {
+ fprintf(stderr, "%s: ", s);
+ }
+
+ fprintf(stderr, "%s\n", hstrerror(h_errno));
+}
+
+#endif /* PROVIDES_SOCKET_API */
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/hstrerror.cc b/native_client_sdk/src/libraries/nacl_io/syscalls/hstrerror.cc
new file mode 100644
index 0000000..f1354d9
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/hstrerror.cc
@@ -0,0 +1,54 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "nacl_io/ossocket.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+#include <sstream>
+#include <string>
+#include "sdk_util/macros.h"
+
+EXTERN_C_BEGIN
+
+const char* hstrerror(int err) {
+ // These error message texts are taken straight from the man page
+ const char* host_not_found_msg =
+ "The specified host is unknown.";
+ const char* no_address_msg =
+ "The requested name is valid but does not have an IP address.";
+ const char* no_recovery_msg =
+ "A nonrecoverable name server error occurred.";
+ const char* try_again_msg =
+ "A temporary error occurred on an authoritative name server. "
+ "Try again later.";
+ const char* internal_msg =
+ "Internal error in gethostbyname.";
+ const char* unknown_msg_base =
+ "Unknown error in gethostbyname: ";
+
+ switch (err) {
+ case HOST_NOT_FOUND:
+ return host_not_found_msg;
+ case NO_ADDRESS:
+ return no_address_msg;
+ case NO_RECOVERY:
+ return no_recovery_msg;
+ case TRY_AGAIN:
+ return try_again_msg;
+ case NETDB_INTERNAL:
+ return internal_msg;
+ default:
+ std::stringstream msg;
+ msg << unknown_msg_base << err << ".";
+
+ static std::string unknown_msg;
+ unknown_msg.assign(msg.str());
+ return unknown_msg.c_str();
+ }
+}
+
+EXTERN_C_END
+
+#endif // PROVIDES_SOCKET_API
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/htonl.c b/native_client_sdk/src/libraries/nacl_io/syscalls/htonl.c
new file mode 100644
index 0000000..c29386f
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/htonl.c
@@ -0,0 +1,23 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/ossocket.h"
+
+#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__)
+
+#include <string.h>
+
+inline uint32_t htonl(uint32_t hostlong) {
+ uint8_t result_bytes[4];
+ result_bytes[0] = (uint8_t) ((hostlong >> 24) & 0xFF);
+ result_bytes[1] = (uint8_t) ((hostlong >> 16) & 0xFF);
+ result_bytes[2] = (uint8_t) ((hostlong >> 8) & 0xFF);
+ result_bytes[3] = (uint8_t) (hostlong & 0xFF);
+
+ uint32_t result;
+ memcpy(&result, result_bytes, 4);
+ return result;
+}
+
+#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) */
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/htons.c b/native_client_sdk/src/libraries/nacl_io/syscalls/htons.c
new file mode 100644
index 0000000..0bdab70
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/htons.c
@@ -0,0 +1,21 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/ossocket.h"
+
+#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__)
+
+#include <string.h>
+
+inline uint16_t htons(uint16_t hostshort) {
+ uint8_t result_bytes[2];
+ result_bytes[0] = (uint8_t) ((hostshort >> 8) & 0xFF);
+ result_bytes[1] = (uint8_t) (hostshort & 0xFF);
+
+ uint16_t result;
+ memcpy(&result, result_bytes, 2);
+ return result;
+}
+
+#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) */
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.cc b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.cc
index 93825e7..c6cf610 100644
--- a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.cc
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntoa.cc
@@ -1,6 +1,6 @@
-/* Copyright 2013 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#include "nacl_io/ossocket.h"
#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__)
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc
index 807bdfe..ceabae5 100644
--- a/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/inet_ntop.cc
@@ -1,6 +1,6 @@
-/* Copyright 2013 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#include "nacl_io/ossocket.h"
#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__)
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/listen.c b/native_client_sdk/src/libraries/nacl_io/syscalls/listen.c
new file mode 100644
index 0000000..18c7c4f
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/listen.c
@@ -0,0 +1,14 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int listen(int fd, int backlog) {
+ return ki_listen(fd, backlog);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/ntohl.c b/native_client_sdk/src/libraries/nacl_io/syscalls/ntohl.c
new file mode 100644
index 0000000..8338a6a
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/ntohl.c
@@ -0,0 +1,21 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/ossocket.h"
+
+#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__)
+
+#include <string.h>
+
+inline uint32_t ntohl(uint32_t networklong) {
+ uint8_t input[4];
+ memcpy(input, &networklong, 4);
+
+ return ((((uint32_t) input[0]) << 24) |
+ (((uint32_t) input[1]) << 16) |
+ (((uint32_t) input[2]) << 8) |
+ ((uint32_t) input[3]));
+}
+
+#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) */
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/ntohs.c b/native_client_sdk/src/libraries/nacl_io/syscalls/ntohs.c
new file mode 100644
index 0000000..19b6afe
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/ntohs.c
@@ -0,0 +1,19 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/ossocket.h"
+
+#if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__)
+
+#include <string.h>
+
+inline uint16_t ntohs(uint16_t networkshort) {
+ uint8_t input[2];
+ memcpy(input, &networkshort, 2);
+
+ return ((((uint32_t) input[0]) << 8) |
+ ((uint32_t) input[1]));
+}
+
+#endif /* defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) */
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/recv.c b/native_client_sdk/src/libraries/nacl_io/syscalls/recv.c
new file mode 100644
index 0000000..566798c
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/recv.c
@@ -0,0 +1,14 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+ssize_t recv(int fd, void* buf, size_t len, int flags) {
+ return ki_recv(fd, buf, len, flags);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/recvfrom.c b/native_client_sdk/src/libraries/nacl_io/syscalls/recvfrom.c
new file mode 100644
index 0000000..4032ced
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/recvfrom.c
@@ -0,0 +1,15 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+ssize_t recvfrom(int fd, void* buf, size_t len, int flags,
+ struct sockaddr* addr, socklen_t* addrlen) {
+ return ki_recvfrom(fd, buf, len, flags, addr, addrlen);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/recvmsg.c b/native_client_sdk/src/libraries/nacl_io/syscalls/recvmsg.c
new file mode 100644
index 0000000..99cdd3a
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/recvmsg.c
@@ -0,0 +1,10 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+ssize_t recvmsg(int fd, struct msghdr* msg, int flags) {
+ return ki_recvmsg(fd, msg, flags);
+}
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/send.c b/native_client_sdk/src/libraries/nacl_io/syscalls/send.c
new file mode 100644
index 0000000..eb1d53c
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/send.c
@@ -0,0 +1,14 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+ssize_t send(int fd, const void* buf, size_t len, int flags) {
+ return ki_send(fd, buf, len, flags);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/sendmsg.c b/native_client_sdk/src/libraries/nacl_io/syscalls/sendmsg.c
new file mode 100644
index 0000000..64d020c
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/sendmsg.c
@@ -0,0 +1,14 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+ssize_t sendmsg(int fd, const struct msghdr* msg, int flags) {
+ return ki_sendmsg(fd, msg, flags);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/sendto.c b/native_client_sdk/src/libraries/nacl_io/syscalls/sendto.c
new file mode 100644
index 0000000..f0ab62f
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/sendto.c
@@ -0,0 +1,15 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+ssize_t sendto(int fd, const void* buf, size_t len, int flags,
+ const struct sockaddr* addr, socklen_t addrlen) {
+ return ki_sendto(fd, buf, len, flags, addr, addrlen);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/setsockopt.c b/native_client_sdk/src/libraries/nacl_io/syscalls/setsockopt.c
new file mode 100644
index 0000000..bde469e
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/setsockopt.c
@@ -0,0 +1,15 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int setsockopt(int fd, int lvl, int optname, const void* optval,
+ socklen_t len) {
+ return ki_setsockopt(fd, lvl, optname, optval, len);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/shutdown.c b/native_client_sdk/src/libraries/nacl_io/syscalls/shutdown.c
new file mode 100644
index 0000000..985d95f
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/shutdown.c
@@ -0,0 +1,14 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int shutdown(int fd, int how) {
+ return ki_shutdown(fd, how);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/socket.c b/native_client_sdk/src/libraries/nacl_io/syscalls/socket.c
new file mode 100644
index 0000000..d4b4b9b
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/socket.c
@@ -0,0 +1,14 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int socket(int domain, int type, int protocol) {
+ return ki_socket(domain, type, protocol);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/socketpair.c b/native_client_sdk/src/libraries/nacl_io/syscalls/socketpair.c
new file mode 100644
index 0000000..422b4d1
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/socketpair.c
@@ -0,0 +1,14 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_wrap.h"
+
+#ifdef PROVIDES_SOCKET_API
+
+int socketpair(int domain, int type, int protocol, int* sv) {
+ return ki_socketpair(domain, type, protocol, sv);
+}
+
+#endif
diff --git a/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_mock.h b/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_mock.h
index c082856..159e3cb 100644
--- a/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_mock.h
+++ b/native_client_sdk/src/libraries/nacl_io_test/kernel_proxy_mock.h
@@ -67,8 +67,6 @@
MOCK_METHOD3(getpeername, int(int, struct sockaddr*, socklen_t*));
MOCK_METHOD3(getsockname, int(int, struct sockaddr*, socklen_t*));
MOCK_METHOD5(getsockopt, int(int, int, int, void*, socklen_t*));
- MOCK_METHOD1(herror, void(const char*));
- MOCK_METHOD1(hstrerror, const char*(int));
MOCK_METHOD2(listen, int(int, int));
MOCK_METHOD4(recv, ssize_t(int, void*, size_t, int));
MOCK_METHOD6(recvfrom, ssize_t(int, void*, size_t, int,
diff --git a/native_client_sdk/src/libraries/nacl_io_test/kernel_wrap_test.cc b/native_client_sdk/src/libraries/nacl_io_test/kernel_wrap_test.cc
index 6b48c88..34db64a 100644
--- a/native_client_sdk/src/libraries/nacl_io_test/kernel_wrap_test.cc
+++ b/native_client_sdk/src/libraries/nacl_io_test/kernel_wrap_test.cc
@@ -347,16 +347,6 @@
getsockopt(DUMMY_FD, 456, 789, NULL, NULL);
}
-TEST_F(KernelWrapTest, herror) {
- EXPECT_CALL(mock, herror(NULL)).Times(1);
- herror(NULL);
-}
-
-TEST_F(KernelWrapTest, hstrerror) {
- EXPECT_CALL(mock, hstrerror(123)).Times(1);
- hstrerror(123);
-}
-
TEST_F(KernelWrapTest, listen) {
EXPECT_CALL(mock, listen(DUMMY_FD, 456)).Times(1);
listen(DUMMY_FD, 456);
diff --git a/native_client_sdk/src/libraries/nacl_io_test/mount_test.cc b/native_client_sdk/src/libraries/nacl_io_test/mount_test.cc
index cc1c437..4829ccf 100644
--- a/native_client_sdk/src/libraries/nacl_io_test/mount_test.cc
+++ b/native_client_sdk/src/libraries/nacl_io_test/mount_test.cc
@@ -322,7 +322,7 @@
// Now let's try sending some data over.
// First we create the message.
- std::string content("hello, how are you?");
+ std::string content("hello, how are you?\n");
std::string message = prefix.append(content);
struct tioc_nacl_input_string packaged_message;
packaged_message.length = message.size();
diff --git a/native_client_sdk/src/libraries/nacl_io_test/socket_test.cc b/native_client_sdk/src/libraries/nacl_io_test/socket_test.cc
index ec45185..e98aa7a 100644
--- a/native_client_sdk/src/libraries/nacl_io_test/socket_test.cc
+++ b/native_client_sdk/src/libraries/nacl_io_test/socket_test.cc
@@ -128,11 +128,6 @@
EXPECT_EQ(errno, ENOTSOCK);
}
-TEST_F(SocketTest, Hstrerror) {
- EXPECT_STREQ(ki_hstrerror(2718),
- "Unknown error in gethostbyname: 2718.");
-}
-
TEST_F(SocketTest, Listen) {
EXPECT_LT(ki_listen(-1, 123), 0);
EXPECT_EQ(errno, EBADF);
@@ -268,6 +263,31 @@
// implementations of these functions).
#if !defined(__GLIBC__)
+TEST(SocketUtilityFunctions, Hstrerror) {
+ EXPECT_STREQ(hstrerror(2718),
+ "Unknown error in gethostbyname: 2718.");
+}
+
+TEST(SocketUtilityFunctions, Htonl) {
+ uint32_t host_long = 0x44332211;
+ uint32_t network_long = htonl(host_long);
+ uint8_t network_bytes[4];
+ memcpy(network_bytes, &network_long, 4);
+ EXPECT_EQ(network_bytes[0], 0x44);
+ EXPECT_EQ(network_bytes[1], 0x33);
+ EXPECT_EQ(network_bytes[2], 0x22);
+ EXPECT_EQ(network_bytes[3], 0x11);
+}
+
+TEST(SocketUtilityFunctions, Htons) {
+ uint16_t host_short = 0x2211;
+ uint16_t network_short = htons(host_short);
+ uint8_t network_bytes[2];
+ memcpy(network_bytes, &network_short, 2);
+ EXPECT_EQ(network_bytes[0], 0x22);
+ EXPECT_EQ(network_bytes[1], 0x11);
+}
+
static struct in_addr generate_ipv4_addr(int tuple1, int tuple2,
int tuple3, int tuple4) {
unsigned char addr[4];
@@ -275,8 +295,9 @@
addr[1] = static_cast<unsigned char>(tuple2);
addr[2] = static_cast<unsigned char>(tuple3);
addr[3] = static_cast<unsigned char>(tuple4);
- struct in_addr* real_addr = reinterpret_cast<struct in_addr*>(addr);
- return *real_addr;
+ struct in_addr real_addr;
+ memcpy(&real_addr, addr, 4);
+ return real_addr;
}
static struct in6_addr generate_ipv6_addr(int* tuples) {
@@ -285,8 +306,9 @@
addr[2*i] = (tuples[i] >> 8) & 0xFF;
addr[2*i+1] = tuples[i] & 0xFF;
}
- struct in6_addr* real_addr = reinterpret_cast<struct in6_addr*>(addr);
- return *real_addr;
+ struct in6_addr real_addr;
+ memcpy(&real_addr, addr, 16);
+ return real_addr;
}
TEST(SocketUtilityFunctions, Inet_ntoa) {
@@ -372,5 +394,21 @@
EXPECT_EQ(errno, ENOSPC);
}
+TEST(SocketUtilityFunctions, Ntohs) {
+ uint8_t network_bytes[2] = { 0x22, 0x11 };
+ uint16_t network_short;
+ memcpy(&network_short, network_bytes, 2);
+ uint16_t host_short = ntohs(network_short);
+ EXPECT_EQ(host_short, 0x2211);
+}
+
+TEST(SocketUtilityFunctions, Ntohl) {
+ uint8_t network_bytes[4] = { 0x44, 0x33, 0x22, 0x11 };
+ uint32_t network_long;
+ memcpy(&network_long, network_bytes, 4);
+ uint32_t host_long = ntohl(network_long);
+ EXPECT_EQ(host_long, 0x44332211);
+}
+
#endif // !defined(__GLIBC__)
#endif // PROVIDES_SOCKETPAIR_API
diff --git a/native_client_sdk/src/libraries/third_party/newlib-extras/README.chromium b/native_client_sdk/src/libraries/third_party/newlib-extras/README.chromium
index 4d577fd..3b46d4c 100644
--- a/native_client_sdk/src/libraries/third_party/newlib-extras/README.chromium
+++ b/native_client_sdk/src/libraries/third_party/newlib-extras/README.chromium
@@ -21,3 +21,6 @@
* Removed the revoked third clause from the licenses in the header files.
* Correctly wrapped netdb.h to allow it to be included in both C and C++ files.
* Removed faulty _BSD_SIZE_T_ typedef in arpa/inet.h
+* Removed macros in arpa/inet.h which added underbars to various functions of
+ the form inet_*, to avoid problems with forward declarations in user code.
+* Added prototypes for htonl, htons, ntohl, and ntohs to netinet/in.h
diff --git a/native_client_sdk/src/libraries/third_party/newlib-extras/arpa/inet.h b/native_client_sdk/src/libraries/third_party/newlib-extras/arpa/inet.h
index 8578137..1d496a9 100644
--- a/native_client_sdk/src/libraries/third_party/newlib-extras/arpa/inet.h
+++ b/native_client_sdk/src/libraries/third_party/newlib-extras/arpa/inet.h
@@ -107,21 +107,6 @@
#define _STRUCT_IN_ADDR_DECLARED
#endif
-#define inet_addr __inet_addr
-#define inet_aton __inet_aton
-#define inet_lnaof __inet_lnaof
-#define inet_makeaddr __inet_makeaddr
-#define inet_neta __inet_neta
-#define inet_netof __inet_netof
-#define inet_network __inet_network
-#define inet_net_ntop __inet_net_ntop
-#define inet_net_pton __inet_net_pton
-#define inet_ntoa __inet_ntoa
-#define inet_pton __inet_pton
-#define inet_ntop __inet_ntop
-#define inet_nsap_addr __inet_nsap_addr
-#define inet_nsap_ntoa __inet_nsap_ntoa
-
__BEGIN_DECLS
in_addr_t inet_addr(const char *);
char *inet_ntoa(struct in_addr);
diff --git a/native_client_sdk/src/libraries/third_party/newlib-extras/netinet/in.h b/native_client_sdk/src/libraries/third_party/newlib-extras/netinet/in.h
index c66ad51..a0cd05c 100644
--- a/native_client_sdk/src/libraries/third_party/newlib-extras/netinet/in.h
+++ b/native_client_sdk/src/libraries/third_party/newlib-extras/netinet/in.h
@@ -562,4 +562,11 @@
#include <netinet6/in6.h>
#undef __KAME_NETINET_IN_H_INCLUDED_
+__BEGIN_DECLS
+uint32_t htonl(uint32_t hostlong);
+uint16_t htons(uint16_t hostshort);
+uint32_t ntohl(uint32_t networklong);
+uint16_t ntohs(uint16_t networkshort);
+__END_DECLS
+
#endif /* !_NETINET_IN_H_*/
diff --git a/native_client_sdk/src/libraries/third_party/newlib-extras/netinet/tcp.h b/native_client_sdk/src/libraries/third_party/newlib-extras/netinet/tcp.h
new file mode 100644
index 0000000..04d2284
--- /dev/null
+++ b/native_client_sdk/src/libraries/third_party/newlib-extras/netinet/tcp.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)tcp.h 8.1 (Berkeley) 6/10/93
+ * $FreeBSD: src/sys/netinet/tcp.h,v 1.16 2001/01/09 18:26:17 rwatson Exp $
+ */
+
+#ifndef _NETINET_TCP_H_
+#define _NETINET_TCP_H_
+
+#include <sys/types.h>
+
+#if defined(__native_client__)
+/*
+ * The following section is NaCl specific and is needed to more
+ * closely match the types defined in the BSD sys/types.h.
+ * This is needed to let the RTEMS/BSD TCP/IP stack compile.
+ */
+
+/* deprecated */
+#if ___int8_t_defined
+typedef __uint8_t u_int8_t;
+#endif
+#if ___int16_t_defined
+typedef __uint16_t u_int16_t;
+#endif
+#if ___int32_t_defined
+typedef __uint32_t u_int32_t;
+#endif
+
+#if ___int64_t_defined
+typedef __uint64_t u_int64_t;
+
+/* deprecated */
+typedef __uint64_t u_quad_t;
+typedef __int64_t quad_t;
+typedef quad_t * qaddr_t;
+#endif
+#endif
+
+typedef u_int32_t tcp_seq;
+typedef u_int32_t tcp_cc; /* connection count per rfc1644 */
+
+#define tcp6_seq tcp_seq /* for KAME src sync over BSD*'s */
+#define tcp6hdr tcphdr /* for KAME src sync over BSD*'s */
+
+/*
+ * TCP header.
+ * Per RFC 793, September, 1981.
+ */
+struct tcphdr {
+ u_short th_sport; /* source port */
+ u_short th_dport; /* destination port */
+ tcp_seq th_seq; /* sequence number */
+ tcp_seq th_ack; /* acknowledgement number */
+#if BYTE_ORDER == LITTLE_ENDIAN
+ u_int th_x2:4, /* (unused) */
+ th_off:4; /* data offset */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_int th_off:4, /* data offset */
+ th_x2:4; /* (unused) */
+#endif
+ u_char th_flags;
+#define TH_FIN 0x01
+#define TH_SYN 0x02
+#define TH_RST 0x04
+#define TH_PUSH 0x08
+#define TH_ACK 0x10
+#define TH_URG 0x20
+#define TH_ECE 0x40
+#define TH_CWR 0x80
+#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
+
+ u_short th_win; /* window */
+ u_short th_sum; /* checksum */
+ u_short th_urp; /* urgent pointer */
+};
+
+#define TCPOPT_EOL 0
+#define TCPOPT_NOP 1
+#define TCPOPT_MAXSEG 2
+#define TCPOLEN_MAXSEG 4
+#define TCPOPT_WINDOW 3
+#define TCPOLEN_WINDOW 3
+#define TCPOPT_SACK_PERMITTED 4 /* Experimental */
+#define TCPOLEN_SACK_PERMITTED 2
+#define TCPOPT_SACK 5 /* Experimental */
+#define TCPOPT_TIMESTAMP 8
+#define TCPOLEN_TIMESTAMP 10
+#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */
+#define TCPOPT_TSTAMP_HDR \
+ (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)
+
+#define TCPOPT_CC 11 /* CC options: RFC-1644 */
+#define TCPOPT_CCNEW 12
+#define TCPOPT_CCECHO 13
+#define TCPOLEN_CC 6
+#define TCPOLEN_CC_APPA (TCPOLEN_CC+2)
+#define TCPOPT_CC_HDR(ccopt) \
+ (TCPOPT_NOP<<24|TCPOPT_NOP<<16|(ccopt)<<8|TCPOLEN_CC)
+
+/*
+ * Default maximum segment size for TCP.
+ * With an IP MSS of 576, this is 536,
+ * but 512 is probably more convenient.
+ * This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)).
+ */
+#define TCP_MSS 512
+
+/*
+ * Default maximum segment size for TCP6.
+ * With an IP6 MSS of 1280, this is 1220,
+ * but 1024 is probably more convenient. (xxx kazu in doubt)
+ * This should be defined as MIN(1024, IP6_MSS - sizeof (struct tcpip6hdr))
+ */
+#define TCP6_MSS 1024
+
+#define TCP_MAXWIN 65535 /* largest value for (unscaled) window */
+#define TTCP_CLIENT_SND_WND 4096 /* dflt send window for T/TCP client */
+
+#define TCP_MAX_WINSHIFT 14 /* maximum window shift */
+
+#define TCP_MAXBURST 4 /* maximum segments in a burst */
+
+#define TCP_MAXHLEN (0xf<<2) /* max length of header in bytes */
+#define TCP_MAXOLEN (TCP_MAXHLEN - sizeof(struct tcphdr))
+ /* max space left for options */
+
+/*
+ * User-settable options (used with setsockopt).
+ */
+#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
+#define TCP_MAXSEG 0x02 /* set maximum segment size */
+#define TCP_NOPUSH 0x04 /* don't push last block of write */
+#define TCP_NOOPT 0x08 /* don't use TCP options */
+
+#endif
diff --git a/native_client_sdk/src/tools/common.mk b/native_client_sdk/src/tools/common.mk
index 11feea8..3082072 100644
--- a/native_client_sdk/src/tools/common.mk
+++ b/native_client_sdk/src/tools/common.mk
@@ -476,9 +476,9 @@
run_package: check_for_chrome all
$(CHROME_PATH) --load-and-launch-app=$(CURDIR) $(CHROME_ARGS)
-
-GDB_ARGS += -D $(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/$(SYSARCH)-nacl-gdb
-GDB_ARGS += -D $(abspath $(OUTDIR))/$(TARGET)_$(SYSARCH).nexe
+GDB_ARGS += -D $(TC_PATH)/$(OSNAME)_x86_newlib/bin/$(SYSARCH)-nacl-gdb
+GDB_ARGS += -D --eval-command="nacl-manifest $(abspath $(OUTDIR))/$(TARGET).nmf"
+GDB_ARGS += -D $(GDB_DEBUG_TARGET)
.PHONY: debug
debug: check_for_chrome all $(PAGE)
diff --git a/native_client_sdk/src/tools/nacl_gcc.mk b/native_client_sdk/src/tools/nacl_gcc.mk
index d046714..c176d9b 100644
--- a/native_client_sdk/src/tools/nacl_gcc.mk
+++ b/native_client_sdk/src/tools/nacl_gcc.mk
@@ -429,3 +429,22 @@
$(OUTDIR)/$(1).html: $(EXECUTABLES)
$(call LOG,CREATE_HTML,$$@,$(CREATE_HTML) $(HTML_FLAGS) -o $$@ $$^)
endef
+
+
+#
+# Determine which executable to pass into the debugger. For newlib
+# this is the NEXE which will actually be used. For glibc, runnable-ld.so
+# is the "app", and the "app" is actual an .so we load.
+#
+ifeq (x86_32,$(SYSARCH))
+LIB_NAME = lib32
+else
+LIB_NAME = lib64
+endif
+
+
+ifeq (newlib,$(TOOLCHAIN))
+GDB_DEBUG_TARGET = $(abspath $(OUTDIR))/$(TARGET)_$(SYSARCH).nexe
+else
+GDB_DEBUG_TARGET = $(abspath $(OUTDIR))/$(LIB_NAME)/runnable-ld.so
+endif
diff --git a/native_client_sdk/src/tools/nacl_llvm.mk b/native_client_sdk/src/tools/nacl_llvm.mk
index 3299e4c..a8a310b 100644
--- a/native_client_sdk/src/tools/nacl_llvm.mk
+++ b/native_client_sdk/src/tools/nacl_llvm.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# 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.
@@ -17,6 +17,7 @@
PNACL_LIB ?= $(PNACL_BIN)/pnacl-ar
PNACL_STRIP ?= $(PNACL_BIN)/pnacl-strip
PNACL_FINALIZE ?= $(PNACL_BIN)/pnacl-finalize
+PNACL_TRANSLATE ?= $(PNACL_BIN)/pnacl-translate
#
# Compile Macro
@@ -93,11 +94,24 @@
# $5 = List of lib dirs
# $6 = Other Linker Args
#
+# For debugging, we translate the pre-finalized .bc file.
+#
define LINKER_RULE
-all: $(1).pexe
-$(1).pexe: $(2) $(foreach dep,$(4),$(STAMPDIR)/$(dep).stamp)
- $(call LOG,LINK,$(1).bc,$(PNACL_LINK) -o $(1).bc $(2) $(foreach path,$(5),-L$(path)/pnacl/$(CONFIG)) $(foreach lib,$(3),-l$(lib)) $(6))
- $(call LOG,FINALIZE,$(1).pexe,$(PNACL_FINALIZE) -o $(1).pexe $(1).bc)
+all: $(1).pexe
+$(1)_x86_32.nexe : $(1).bc
+ $(call LOG,TRANSLATE,$$@,$(PNACL_TRANSLATE) --allow-llvm-bitcode-input -arch x86-32 $$^ -o $$@)
+
+$(1)_x86_64.nexe : $(1).bc
+ $(call LOG,TRANSLATE,$$@,$(PNACL_TRANSLATE) --allow-llvm-bitcode-input -arch x86-64 $$^ -o $$@)
+
+$(1)_arm.nexe : $(1).bc
+ $(call LOG,TRANSLATE,$$@,$(PNACL_TRANSLATE) --allow-llvm-bitcode-input -arch arm $$^ -o $$@)
+
+$(1).pexe: $(1).bc
+ $(call LOG,FINALIZE,$$@,$(PNACL_FINALIZE) -o $$@ $$^)
+
+$(1).bc: $(2) $(foreach dep,$(4),$(STAMPDIR)/$(dep).stamp)
+ $(call LOG,LINK,$$@,$(PNACL_LINK) -o $$@ $(2) $(foreach path,$(5),-L$(path)/pnacl/$(CONFIG)) $(foreach lib,$(3),-l$(lib)) $(6))
endef
@@ -111,7 +125,15 @@
# $5 = POSIX Linker Switches
# $6 = VC Linker Switches
#
+# NOTE: For Debug builds we translate the .bc file to a .nexe instead of
+# using the finalizing to a .pexe. This enables debugging.
+#
define LINK_RULE
+ifeq ($(CONFIG),Debug)
+EXECUTABLES=$(OUTDIR)/$(1)_x86_32.nexe $(OUTDIR)/$(1)_x86_64.nexe $(OUTDIR)/$(1)_arm.nexe
+else
+EXECUTABLES=$(OUTDIR)/$(1).pexe
+endif
$(call LINKER_RULE,$(OUTDIR)/$(1),$(foreach src,$(2),$(call SRC_TO_OBJ,$(src),_pnacl)),$(filter-out pthread,$(3)),$(4),$(LIB_PATHS),$(5))
endef
@@ -149,7 +171,7 @@
define NMF_RULE
all: $(OUTDIR)/$(1).nmf
-$(OUTDIR)/$(1).nmf: $(OUTDIR)/$(1).pexe
+$(OUTDIR)/$(1).nmf: $(EXECUTABLES)
$(call LOG,CREATE_NMF,$$@,$(NMF) -o $$@ $$^ -s $(OUTDIR) $(2))
endef
@@ -160,6 +182,13 @@
define HTML_RULE
all: $(OUTDIR)/$(1).html
-$(OUTDIR)/$(1).html: $(OUTDIR)/$(1).pexe
+$(OUTDIR)/$(1).html: $(EXECUTABLES)
$(call LOG,CREATE_HTML,$$@,$(CREATE_HTML) -o $$@ $$^)
endef
+
+
+#
+# Determine which executable to pass into the debugger. For pnacl, this is
+# the .bc -> .nexe translated app.
+#
+GDB_DEBUG_TARGET = $(abspath $(OUTDIR))/$(TARGET)_$(SYSARCH).nexe
diff --git a/net/base/mime_sniffer.cc b/net/base/mime_sniffer.cc
index c582cff..cc83c7c 100644
--- a/net/base/mime_sniffer.cc
+++ b/net/base/mime_sniffer.cc
@@ -807,6 +807,9 @@
url.SchemeIs("http") ||
url.SchemeIs("https") ||
url.SchemeIs("ftp") ||
+#if defined(OS_ANDROID)
+ url.SchemeIs("content") ||
+#endif
url.SchemeIsFile() ||
url.SchemeIsFileSystem();
if (!sniffable_scheme) {
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc
index b9bbbe0..ec1ef68 100644
--- a/net/cert/cert_verify_proc.cc
+++ b/net/cert/cert_verify_proc.cc
@@ -64,12 +64,12 @@
}
void RecordPublicKeyHistogram(const char* chain_position,
- bool after_baseline_date,
+ bool baseline_keysize_applies,
size_t size_bits,
X509Certificate::PublicKeyType cert_type) {
std::string histogram_name =
- base::StringPrintf("CertificateType.%s.%s.%s",
- after_baseline_date ? "BR" : "NonBR",
+ base::StringPrintf("CertificateType2.%s.%s.%s",
+ baseline_keysize_applies ? "BR" : "NonBR",
chain_position,
CertTypeToString(cert_type));
// Do not use UMA_HISTOGRAM_... macros here, as it caches the Histogram
@@ -118,18 +118,26 @@
bool ExaminePublicKeys(const scoped_refptr<X509Certificate>& cert,
bool should_histogram) {
// The effective date of the CA/Browser Forum's Baseline Requirements -
- // 2014-01-01 00:00:00 UTC.
+ // 2012-07-01 00:00:00 UTC.
const base::Time kBaselineEffectiveDate =
+ base::Time::FromInternalValue(GG_INT64_C(12985574400000000));
+ // The effective date of the key size requirements from Appendix A, v1.1.5
+ // 2014-01-01 00:00:00 UTC.
+ const base::Time kBaselineKeysizeEffectiveDate =
base::Time::FromInternalValue(GG_INT64_C(13033008000000000));
size_t size_bits = 0;
X509Certificate::PublicKeyType type = X509Certificate::kPublicKeyTypeUnknown;
bool weak_key = false;
- bool after_baseline_date = cert->valid_expiry() >= kBaselineEffectiveDate;
+ bool baseline_keysize_applies =
+ cert->valid_start() >= kBaselineEffectiveDate &&
+ cert->valid_expiry() >= kBaselineKeysizeEffectiveDate;
X509Certificate::GetPublicKeyInfo(cert->os_cert_handle(), &size_bits, &type);
- if (should_histogram)
- RecordPublicKeyHistogram(kLeafCert, after_baseline_date, size_bits, type);
+ if (should_histogram) {
+ RecordPublicKeyHistogram(kLeafCert, baseline_keysize_applies, size_bits,
+ type);
+ }
if (IsWeakKey(type, size_bits))
weak_key = true;
@@ -140,7 +148,7 @@
if (should_histogram) {
RecordPublicKeyHistogram(
(i < intermediates.size() - 1) ? kIntermediateCert : kRootCert,
- after_baseline_date,
+ baseline_keysize_applies,
size_bits,
type);
}
diff --git a/net/cert/jwk_serializer_nss.cc b/net/cert/jwk_serializer_nss.cc
index 0259c5c..d844580 100644
--- a/net/cert/jwk_serializer_nss.cc
+++ b/net/cert/jwk_serializer_nss.cc
@@ -22,12 +22,12 @@
bool ConvertEcPrime256v1PublicKeyInfoToJwk(
CERTSubjectPublicKeyInfo* spki,
base::DictionaryValue* public_key_jwk) {
- static const int kPrime256v1EncodingType = 4;
+ static const int kUncompressedEncodingType = 4;
static const int kPrime256v1PublicKeyLength = 64;
// The public key value is encoded as 0x04 + 64 bytes of public key.
// NSS gives the length as the bit length.
if (spki->subjectPublicKey.len != (kPrime256v1PublicKeyLength + 1) * 8 ||
- spki->subjectPublicKey.data[0] != kPrime256v1EncodingType)
+ spki->subjectPublicKey.data[0] != kUncompressedEncodingType)
return false;
public_key_jwk->SetString("alg", "EC");
diff --git a/net/cert/jwk_serializer_openssl.cc b/net/cert/jwk_serializer_openssl.cc
index ef15b4b..b11e969 100644
--- a/net/cert/jwk_serializer_openssl.cc
+++ b/net/cert/jwk_serializer_openssl.cc
@@ -2,9 +2,10 @@
// 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 "net/cert/jwk_serializer.h"
+#include "base/logging.h"
+
namespace net {
namespace JwkSerializer {
diff --git a/net/cert/jwk_serializer_unittest.cc b/net/cert/jwk_serializer_unittest.cc
index 37b8002..8059e73 100644
--- a/net/cert/jwk_serializer_unittest.cc
+++ b/net/cert/jwk_serializer_unittest.cc
@@ -26,7 +26,7 @@
0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
0x42, 0x00, 0x04
};
-static const unsigned int kEcPointSize = 32U;
+static const unsigned int kEcCoordinateSize = 32U;
// This is a valid P-256 public key.
static const unsigned char kSpkiEc[] = {
@@ -82,19 +82,19 @@
EXPECT_TRUE(public_key_jwk.GetString("x", &string_value));
std::string decoded_coordinate;
EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate));
- EXPECT_EQ(kEcPointSize, decoded_coordinate.size());
+ EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
EXPECT_EQ(0,
memcmp(decoded_coordinate.data(),
kSpkiEc + sizeof(kP256SpkiPrefix),
- kEcPointSize));
+ kEcCoordinateSize));
EXPECT_TRUE(public_key_jwk.GetString("y", &string_value));
EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate));
- EXPECT_EQ(kEcPointSize, decoded_coordinate.size());
+ EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
EXPECT_EQ(0,
memcmp(decoded_coordinate.data(),
- kSpkiEc + sizeof(kP256SpkiPrefix) + kEcPointSize,
- kEcPointSize));
+ kSpkiEc + sizeof(kP256SpkiPrefix) + kEcCoordinateSize,
+ kEcCoordinateSize));
// Test the result of a corner case: leading 0s in the x, y coordinates are
// not trimmed, but the point is fixed-length encoded.
@@ -109,19 +109,19 @@
EXPECT_TRUE(public_key_jwk.GetString("x", &string_value));
EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate));
- EXPECT_EQ(kEcPointSize, decoded_coordinate.size());
+ EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
EXPECT_EQ(0,
memcmp(decoded_coordinate.data(),
kSpkiEcWithZeroXY + sizeof(kP256SpkiPrefix),
- kEcPointSize));
+ kEcCoordinateSize));
EXPECT_TRUE(public_key_jwk.GetString("y", &string_value));
EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate));
- EXPECT_EQ(kEcPointSize, decoded_coordinate.size());
+ EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
EXPECT_EQ(0,
- memcmp(decoded_coordinate.data(),
- kSpkiEcWithZeroXY + sizeof(kP256SpkiPrefix) + kEcPointSize,
- kEcPointSize));
+ memcmp(decoded_coordinate.data(),
+ kSpkiEcWithZeroXY + sizeof(kP256SpkiPrefix) + kEcCoordinateSize,
+ kEcCoordinateSize));
}
#else
diff --git a/net/disk_cache/simple/simple_index.cc b/net/disk_cache/simple/simple_index.cc
index caec19f..78ce87e 100644
--- a/net/disk_cache/simple/simple_index.cc
+++ b/net/disk_cache/simple/simple_index.cc
@@ -359,18 +359,24 @@
index_file_entries->erase(*it);
}
- // Recalculate the cache size while merging the two sets.
- for (EntrySet::const_iterator it = index_file_entries->begin();
- it != index_file_entries->end(); ++it) {
- // If there is already an entry in the current entries_set_, we need to
- // merge the new data there with the data loaded in the initialization.
- EntrySet::iterator current_entry = entries_set_.find(it->first);
- // When Merging, existing data in the |current_entry| will prevail.
- if (current_entry == entries_set_.end()) {
- InsertInEntrySet(it->first, it->second, &entries_set_);
- cache_size_ += it->second.GetEntrySize();
- }
+ for (EntrySet::const_iterator it = entries_set_.begin();
+ it != entries_set_.end(); ++it) {
+ const uint64 entry_hash = it->first;
+ std::pair<EntrySet::iterator, bool> insert_result =
+ index_file_entries->insert(EntrySet::value_type(entry_hash,
+ EntryMetadata()));
+ EntrySet::iterator& possibly_inserted_entry = insert_result.first;
+ possibly_inserted_entry->second = it->second;
}
+
+ uint64 merged_cache_size = 0;
+ for (EntrySet::iterator it = index_file_entries->begin();
+ it != index_file_entries->end(); ++it) {
+ merged_cache_size += it->second.GetEntrySize();
+ }
+
+ entries_set_.swap(*index_file_entries);
+ cache_size_ = merged_cache_size;
initialized_ = true;
removed_entries_.clear();
diff --git a/net/disk_cache/simple/simple_index_file.cc b/net/disk_cache/simple/simple_index_file.cc
index 596b816..7bcea7c 100644
--- a/net/disk_cache/simple/simple_index_file.cc
+++ b/net/disk_cache/simple/simple_index_file.cc
@@ -8,6 +8,7 @@
#include "base/file_util.h"
#include "base/files/file_enumerator.h"
+#include "base/files/memory_mapped_file.h"
#include "base/hash.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
@@ -254,14 +255,16 @@
SimpleIndexLoadResult* out_result) {
out_result->Reset();
- std::string contents;
- if (!file_util::ReadFileToString(index_filename, &contents)) {
- LOG(WARNING) << "Could not read Simple Index file.";
+ base::MemoryMappedFile index_file_map;
+ if (!index_file_map.Initialize(index_filename)) {
+ LOG(WARNING) << "Could not map Simple Index file.";
base::DeleteFile(index_filename, false);
return;
}
- SimpleIndexFile::Deserialize(contents.data(), contents.size(), out_result);
+ SimpleIndexFile::Deserialize(
+ reinterpret_cast<const char*>(index_file_map.data()),
+ index_file_map.length(), out_result);
if (!out_result->did_load)
base::DeleteFile(index_filename, false);
@@ -322,6 +325,10 @@
return;
}
+#if !defined(OS_WIN)
+ // TODO(gavinp): Consider using std::unordered_map.
+ entries->resize(index_metadata.GetNumberOfEntries() + kExtraSizeForMerge);
+#endif
while (entries->size() < index_metadata.GetNumberOfEntries()) {
uint64 hash_key;
EntryMetadata entry_metadata;
diff --git a/net/disk_cache/simple/simple_index_file.h b/net/disk_cache/simple/simple_index_file.h
index 8a96a72..b536df9 100644
--- a/net/disk_cache/simple/simple_index_file.h
+++ b/net/disk_cache/simple/simple_index_file.h
@@ -97,6 +97,10 @@
private:
friend class WrappedSimpleIndexFile;
+ // When loading the entries from disk, add this many extra hash buckets to
+ // prevent reallocation on the IO thread when merging in new live entries.
+ static const int kExtraSizeForMerge = 512;
+
// Synchronous (IO performing) implementation of LoadIndexEntries.
static void SyncLoadIndexEntries(base::Time cache_last_modified,
const base::FilePath& cache_directory,
diff --git a/net/disk_cache/simple/simple_index_unittest.cc b/net/disk_cache/simple/simple_index_unittest.cc
index cfc83b3..0c845b2 100644
--- a/net/disk_cache/simple/simple_index_unittest.cc
+++ b/net/disk_cache/simple/simple_index_unittest.cc
@@ -197,12 +197,15 @@
{
scoped_ptr<SimpleIndexLoadResult> result(new SimpleIndexLoadResult());
result->did_load = true;
- const uint64 hash_key = simple_util::GetEntryHashKey("eleven");
+ const uint64 new_hash_key = simple_util::GetEntryHashKey("eleven");
result->entries.insert(
- std::make_pair(hash_key, EntryMetadata(base::Time::Now(), 11)));
+ std::make_pair(new_hash_key, EntryMetadata(base::Time::Now(), 11)));
+ const uint64 redundant_hash_key = simple_util::GetEntryHashKey("seven");
+ result->entries.insert(std::make_pair(redundant_hash_key,
+ EntryMetadata(base::Time::Now(), 7)));
index()->MergeInitializingSet(result.Pass());
}
- EXPECT_EQ(25U, index()->cache_size_);
+ EXPECT_EQ(2U + 5U + 7U + 11U, index()->cache_size_);
}
// State of index changes as expected with an insert and a remove.
diff --git a/net/disk_cache/simple/simple_util.cc b/net/disk_cache/simple/simple_util.cc
index 40d3894..72a4612 100644
--- a/net/disk_cache/simple/simple_util.cc
+++ b/net/disk_cache/simple/simple_util.cc
@@ -21,25 +21,6 @@
// Size of the uint64 hash_key number in Hex format in a string.
const size_t kEntryHashKeyAsHexStringSize = 2 * sizeof(uint64);
-// TODO(clamy, gavinp): this should go in base
-bool GetNanoSecsFromStat(const struct stat& st,
- time_t* out_sec,
- long* out_nsec) {
-#if defined(OS_ANDROID)
- *out_sec = st.st_mtime;
- *out_nsec = st.st_mtime_nsec;
-#elif defined(OS_LINUX)
- *out_sec = st.st_mtim.tv_sec;
- *out_nsec = st.st_mtim.tv_nsec;
-#elif defined(OS_MACOSX) || defined(OS_IOS) || defined(OS_BSD)
- *out_sec = st.st_mtimespec.tv_sec;
- *out_nsec = st.st_mtimespec.tv_nsec;
-#else
- return false;
-#endif
- return true;
-}
-
} // namespace
namespace disk_cache {
@@ -107,20 +88,6 @@
// TODO(clamy, gavinp): this should go in base
bool GetMTime(const base::FilePath& path, base::Time* out_mtime) {
DCHECK(out_mtime);
-#if defined(OS_POSIX)
- base::ThreadRestrictions::AssertIOAllowed();
- struct stat file_stat;
- if (stat(path.value().c_str(), &file_stat) != 0)
- return false;
- time_t sec;
- long nsec;
- if (GetNanoSecsFromStat(file_stat, &sec, &nsec)) {
- int64 usec = (nsec / base::Time::kNanosecondsPerMicrosecond);
- *out_mtime = base::Time::FromTimeT(sec)
- + base::TimeDelta::FromMicroseconds(usec);
- return true;
- }
-#endif
base::PlatformFileInfo file_info;
if (!file_util::GetFileInfo(path, &file_info))
return false;
diff --git a/net/disk_cache/simple/simple_util.h b/net/disk_cache/simple/simple_util.h
index 505501e..2e92b4a 100644
--- a/net/disk_cache/simple/simple_util.h
+++ b/net/disk_cache/simple/simple_util.h
@@ -62,8 +62,8 @@
const std::string& key,
int data_offset);
-// Fills |out_time| with the time the file last modified time. Unlike the
-// functions in platform_file.h, the time resolution is milliseconds.
+// Fills |out_time| with the time the file last modified time.
+// TODO(gavinp): Remove this function.
NET_EXPORT_PRIVATE bool GetMTime(const base::FilePath& path,
base::Time* out_mtime);
} // namespace simple_backend
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index c26564c..70292be 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -1219,6 +1219,7 @@
GetHostAndPort(request_->url));
}
+ bool should_fallback = false;
uint16 version_max = server_ssl_config_.version_max;
switch (error) {
@@ -1250,18 +1251,33 @@
(server_ssl_config_.unrestricted_ssl3_fallback_enabled ||
!TransportSecurityState::IsGooglePinnedProperty(
request_->url.host(), true /* include SNI */))) {
- net_log_.AddEvent(
- NetLog::TYPE_SSL_VERSION_FALLBACK,
- base::Bind(&NetLogSSLVersionFallbackCallback,
- &request_->url, error, server_ssl_config_.version_max,
- version_max));
- server_ssl_config_.version_max = version_max;
- server_ssl_config_.version_fallback = true;
- ResetConnectionAndRequestForResend();
- error = OK;
+ should_fallback = true;
}
}
break;
+ case ERR_SSL_BAD_RECORD_MAC_ALERT:
+ if (version_max >= SSL_PROTOCOL_VERSION_TLS1_1 &&
+ version_max > server_ssl_config_.version_min) {
+ // Some broken SSL devices negotiate TLS 1.0 when sent a TLS 1.1 or
+ // 1.2 ClientHello, but then return a bad_record_mac alert. See
+ // crbug.com/260358. In order to make the fallback as minimal as
+ // possible, this fallback is only triggered for >= TLS 1.1.
+ version_max--;
+ should_fallback = true;
+ }
+ break;
+ }
+
+ if (should_fallback) {
+ net_log_.AddEvent(
+ NetLog::TYPE_SSL_VERSION_FALLBACK,
+ base::Bind(&NetLogSSLVersionFallbackCallback,
+ &request_->url, error, server_ssl_config_.version_max,
+ version_max));
+ server_ssl_config_.version_max = version_max;
+ server_ssl_config_.version_fallback = true;
+ ResetConnectionAndRequestForResend();
+ error = OK;
}
return error;
diff --git a/net/net.gyp b/net/net.gyp
index 0165031..cedc05b 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -782,6 +782,8 @@
'quic/crypto/strike_register.h',
'quic/crypto/source_address_token.cc',
'quic/crypto/source_address_token.h',
+ 'quic/quic_alarm.cc',
+ 'quic/quic_alarm.h',
'quic/quic_bandwidth.cc',
'quic/quic_bandwidth.h',
'quic/quic_blocked_writer_interface.h',
@@ -1734,6 +1736,7 @@
'quic/test_tools/simple_quic_framer.h',
'quic/test_tools/test_task_runner.cc',
'quic/test_tools/test_task_runner.h',
+ 'quic/quic_alarm_test.cc',
'quic/quic_bandwidth_test.cc',
'quic/quic_client_session_test.cc',
'quic/quic_clock_test.cc',
@@ -1867,6 +1870,9 @@
'flip_balsa_and_epoll_library',
],
'sources': [
+ 'tools/flip_server/balsa_frame_test.cc',
+ 'tools/flip_server/balsa_headers_test.cc',
+ 'tools/flip_server/mem_cache_test.cc',
'tools/flip_server/simple_buffer.cc',
'tools/flip_server/simple_buffer.h',
'tools/quic/end_to_end_test.cc',
diff --git a/net/net.target.darwin-arm.mk b/net/net.target.darwin-arm.mk
index 88d78fc..36ad05d 100644
--- a/net/net.target.darwin-arm.mk
+++ b/net/net.target.darwin-arm.mk
@@ -308,6 +308,7 @@
net/quic/crypto/scoped_evp_cipher_ctx.cc \
net/quic/crypto/strike_register.cc \
net/quic/crypto/source_address_token.cc \
+ net/quic/quic_alarm.cc \
net/quic/quic_bandwidth.cc \
net/quic/quic_client_session.cc \
net/quic/quic_config.cc \
diff --git a/net/net.target.darwin-mips.mk b/net/net.target.darwin-mips.mk
index 6fedabc..203e38d 100644
--- a/net/net.target.darwin-mips.mk
+++ b/net/net.target.darwin-mips.mk
@@ -308,6 +308,7 @@
net/quic/crypto/scoped_evp_cipher_ctx.cc \
net/quic/crypto/strike_register.cc \
net/quic/crypto/source_address_token.cc \
+ net/quic/quic_alarm.cc \
net/quic/quic_bandwidth.cc \
net/quic/quic_client_session.cc \
net/quic/quic_config.cc \
diff --git a/net/net.target.darwin-x86.mk b/net/net.target.darwin-x86.mk
index 4479a95..e8410cd 100644
--- a/net/net.target.darwin-x86.mk
+++ b/net/net.target.darwin-x86.mk
@@ -308,6 +308,7 @@
net/quic/crypto/scoped_evp_cipher_ctx.cc \
net/quic/crypto/strike_register.cc \
net/quic/crypto/source_address_token.cc \
+ net/quic/quic_alarm.cc \
net/quic/quic_bandwidth.cc \
net/quic/quic_client_session.cc \
net/quic/quic_config.cc \
diff --git a/net/net.target.linux-arm.mk b/net/net.target.linux-arm.mk
index 88d78fc..36ad05d 100644
--- a/net/net.target.linux-arm.mk
+++ b/net/net.target.linux-arm.mk
@@ -308,6 +308,7 @@
net/quic/crypto/scoped_evp_cipher_ctx.cc \
net/quic/crypto/strike_register.cc \
net/quic/crypto/source_address_token.cc \
+ net/quic/quic_alarm.cc \
net/quic/quic_bandwidth.cc \
net/quic/quic_client_session.cc \
net/quic/quic_config.cc \
diff --git a/net/net.target.linux-mips.mk b/net/net.target.linux-mips.mk
index 6fedabc..203e38d 100644
--- a/net/net.target.linux-mips.mk
+++ b/net/net.target.linux-mips.mk
@@ -308,6 +308,7 @@
net/quic/crypto/scoped_evp_cipher_ctx.cc \
net/quic/crypto/strike_register.cc \
net/quic/crypto/source_address_token.cc \
+ net/quic/quic_alarm.cc \
net/quic/quic_bandwidth.cc \
net/quic/quic_client_session.cc \
net/quic/quic_config.cc \
diff --git a/net/net.target.linux-x86.mk b/net/net.target.linux-x86.mk
index 4479a95..e8410cd 100644
--- a/net/net.target.linux-x86.mk
+++ b/net/net.target.linux-x86.mk
@@ -308,6 +308,7 @@
net/quic/crypto/scoped_evp_cipher_ctx.cc \
net/quic/crypto/strike_register.cc \
net/quic/crypto/source_address_token.cc \
+ net/quic/quic_alarm.cc \
net/quic/quic_bandwidth.cc \
net/quic/quic_client_session.cc \
net/quic/quic_config.cc \
diff --git a/net/quic/congestion_control/quic_congestion_manager.cc b/net/quic/congestion_control/quic_congestion_manager.cc
index 838195f..ba6bab8 100644
--- a/net/quic/congestion_control/quic_congestion_manager.cc
+++ b/net/quic/congestion_control/quic_congestion_manager.cc
@@ -20,7 +20,7 @@
// define the minimum RTO to 200ms, we will use the same until we have data to
// support a higher or lower value.
static const int kMinRetransmissionTimeMs = 200;
-static const int kMaxRetransmissionTimeMs = 10000;
+static const int kMaxRetransmissionTimeMs = 60000;
static const size_t kMaxRetransmissions = 10;
static const size_t kTailDropWindowSize = 5;
static const size_t kTailDropMaxRetransmissions = 4;
@@ -176,6 +176,7 @@
retransmission_delay.ToMilliseconds() * static_cast<size_t>(
(1 << min<size_t>(number_retransmissions, kMaxRetransmissions))));
+ // TODO(rch): This code should move to |send_algorithm_|.
if (retransmission_delay.ToMilliseconds() < kMinRetransmissionTimeMs) {
return QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs);
}
diff --git a/net/quic/congestion_control/send_algorithm_interface.cc b/net/quic/congestion_control/send_algorithm_interface.cc
index 9b794b0..ce24a00 100644
--- a/net/quic/congestion_control/send_algorithm_interface.cc
+++ b/net/quic/congestion_control/send_algorithm_interface.cc
@@ -4,12 +4,17 @@
#include "net/quic/congestion_control/send_algorithm_interface.h"
+#include "net/quic/congestion_control/cubic.h"
#include "net/quic/congestion_control/fix_rate_sender.h"
#include "net/quic/congestion_control/tcp_cubic_sender.h"
namespace net {
const bool kUseReno = false;
+// TODO(ianswett): Increase the max congestion window once the RTO logic is
+// improved, particularly in cases when RTT is larger than the RTO. b/10075719
+// Maximum number of outstanding packets for tcp.
+const QuicTcpCongestionWindow kMaxTcpCongestionWindow = 50;
// Factory for send side congestion control algorithm.
SendAlgorithmInterface* SendAlgorithmInterface::Create(
@@ -17,7 +22,7 @@
CongestionFeedbackType type) {
switch (type) {
case kTCP:
- return new TcpCubicSender(clock, kUseReno);
+ return new TcpCubicSender(clock, kUseReno, kMaxTcpCongestionWindow);
case kInterArrival:
break; // TODO(pwestin) Implement.
case kFixRate:
diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc
index 56cc624..1e98c12 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender.cc
@@ -12,7 +12,6 @@
const QuicByteCount kMaxSegmentSize = kMaxPacketSize;
const QuicByteCount kDefaultReceiveWindow = 64000;
const int64 kInitialCongestionWindow = 10;
-const int64 kMaxCongestionWindow = 10000;
const int kMaxBurstLength = 3;
const int kInitialRttMs = 60; // At a typical RTT 60 ms.
const float kAlpha = 0.125f;
@@ -21,7 +20,10 @@
const float kOneMinusBeta = (1 - kBeta);
}; // namespace
-TcpCubicSender::TcpCubicSender(const QuicClock* clock, bool reno)
+TcpCubicSender::TcpCubicSender(
+ const QuicClock* clock,
+ bool reno,
+ QuicTcpCongestionWindow max_tcp_congestion_window)
: hybrid_slow_start_(clock),
cubic_(clock),
reno_(reno),
@@ -32,7 +34,8 @@
update_end_sequence_number_(true),
end_sequence_number_(0),
congestion_window_(kInitialCongestionWindow),
- slowstart_threshold_(kMaxCongestionWindow),
+ slowstart_threshold_(max_tcp_congestion_window),
+ max_tcp_congestion_window_(max_tcp_congestion_window),
delay_min_(QuicTime::Delta::Zero()),
smoothed_rtt_(QuicTime::Delta::Zero()),
mean_deviation_(QuicTime::Delta::Zero()) {
@@ -191,13 +194,13 @@
hybrid_slow_start_.Reset(end_sequence_number_);
}
// congestion_window_cnt is the number of acks since last change of snd_cwnd
- if (congestion_window_ < kMaxCongestionWindow) {
+ if (congestion_window_ < max_tcp_congestion_window_) {
// TCP slow start, exponentail growth, increase by one for each ACK.
congestion_window_++;
}
DLOG(INFO) << "Slow start; congestion window:" << congestion_window_;
} else {
- if (congestion_window_ < kMaxCongestionWindow) {
+ if (congestion_window_ < max_tcp_congestion_window_) {
if (reno_) {
// Classic Reno congestion avoidance provided for testing.
if (congestion_window_count_ >= congestion_window_) {
diff --git a/net/quic/congestion_control/tcp_cubic_sender.h b/net/quic/congestion_control/tcp_cubic_sender.h
index de8f9c3..c22813a 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.h
+++ b/net/quic/congestion_control/tcp_cubic_sender.h
@@ -26,8 +26,10 @@
class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
public:
- // Reno option provided for testing.
- TcpCubicSender(const QuicClock* clock, bool reno);
+ // Reno option and max_tcp_congestion_window are provided for testing.
+ TcpCubicSender(const QuicClock* clock,
+ bool reno,
+ QuicTcpCongestionWindow max_tcp_congestion_window);
virtual ~TcpCubicSender();
// Start implementation of SendAlgorithmInterface.
@@ -94,6 +96,9 @@
// Slow start congestion window in packets.
QuicTcpCongestionWindow slowstart_threshold_;
+ // Maximum number of outstanding packets for tcp.
+ QuicTcpCongestionWindow max_tcp_congestion_window_;
+
// Min RTT during this session.
QuicTime::Delta delay_min_;
diff --git a/net/quic/congestion_control/tcp_cubic_sender_test.cc b/net/quic/congestion_control/tcp_cubic_sender_test.cc
index ecc8f21..e9f8893 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_test.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_test.cc
@@ -17,8 +17,9 @@
class TcpCubicSenderPeer : public TcpCubicSender {
public:
+ // TODO(ianswett): Remove 10000 once b/10075719 is fixed.
TcpCubicSenderPeer(const QuicClock* clock, bool reno)
- : TcpCubicSender(clock, reno) {
+ : TcpCubicSender(clock, reno, 10000) {
}
using TcpCubicSender::AvailableCongestionWindow;
using TcpCubicSender::CongestionWindow;
@@ -35,6 +36,7 @@
sequence_number_(1),
acked_sequence_number_(0) {
}
+
void SendAvailableCongestionWindow() {
QuicByteCount bytes_to_send = sender_->AvailableCongestionWindow();
while (bytes_to_send > 0) {
@@ -138,8 +140,8 @@
SendAvailableCongestionWindow();
AckNPackets(2);
}
- QuicByteCount expected_congestion_window = kDefaultWindowTCP +
- (kMaxPacketSize * 2 * kNumberOfAck);
+ QuicByteCount expected_congestion_window =
+ kDefaultWindowTCP + (kMaxPacketSize * 2 * kNumberOfAck);
EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
// We should now have fallen out of slow start.
SendAvailableCongestionWindow();
diff --git a/net/quic/crypto/crypto_protocol.h b/net/quic/crypto/crypto_protocol.h
index 082976a..586569a 100644
--- a/net/quic/crypto/crypto_protocol.h
+++ b/net/quic/crypto/crypto_protocol.h
@@ -48,8 +48,12 @@
const QuicTag kINAR = TAG('I', 'N', 'A', 'R'); // Inter arrival
// Proof types (i.e. certificate types)
-const QuicTag kX509 = TAG('X', '5', '0', '9'); // X.509 certificate
-const QuicTag kX59R = TAG('X', '5', '9', 'R'); // X.509 - RSA only
+// NOTE: although it would be silly to do so, specifying both kX509 and kX59R
+// is allowed and is equivalent to specifying only kX509.
+const QuicTag kX509 = TAG('X', '5', '0', '9'); // X.509 certificate, all key
+ // types
+const QuicTag kX59R = TAG('X', '5', '9', 'R'); // X.509 certificate, RSA keys
+ // only
const QuicTag kCHID = TAG('C', 'H', 'I', 'D'); // Channel ID.
// Client hello tags
diff --git a/net/quic/crypto/crypto_server_config.cc b/net/quic/crypto/crypto_server_config.cc
index 62a4381..f270dde 100644
--- a/net/quic/crypto/crypto_server_config.cc
+++ b/net/quic/crypto/crypto_server_config.cc
@@ -304,6 +304,7 @@
QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
const CryptoHandshakeMessage& client_hello,
+ QuicVersion version,
QuicGuid guid,
const IPEndPoint& client_ip,
const QuicClock* clock,
@@ -358,7 +359,8 @@
!info.client_nonce_well_formed ||
!info.unique ||
!requested_config.get()) {
- BuildRejection(primary_config, client_hello, info, rand, out);
+ BuildRejection(version, primary_config.get(), client_hello, info, rand,
+ out);
return QUIC_NO_ERROR;
}
@@ -662,6 +664,7 @@
}
void QuicCryptoServerConfig::BuildRejection(
+ QuicVersion version,
const scoped_refptr<Config>& config,
const CryptoHandshakeMessage& client_hello,
const ClientHelloInfo& info,
@@ -705,8 +708,9 @@
const vector<string>* certs;
string signature;
- if (!proof_source_->GetProof(info.sni.as_string(), config->serialized,
- x509_ecdsa_supported, &certs, &signature)) {
+ if (!proof_source_->GetProof(version, info.sni.as_string(),
+ config->serialized, x509_ecdsa_supported,
+ &certs, &signature)) {
return;
}
diff --git a/net/quic/crypto/crypto_server_config.h b/net/quic/crypto/crypto_server_config.h
index 1a99136..364c200 100644
--- a/net/quic/crypto/crypto_server_config.h
+++ b/net/quic/crypto/crypto_server_config.h
@@ -116,6 +116,8 @@
// an error code is returned.
//
// client_hello: the incoming client hello message.
+ // version: the QUIC version for the connection. TODO(wtc): Remove once
+ // QUIC_VERSION_7 and before are removed.
// guid: the GUID for the connection, which is used in key derivation.
// client_ip: the IP address of the client, which is used to generate and
// validate source-address tokens.
@@ -127,6 +129,7 @@
// out: the resulting handshake message (either REJ or SHLO)
// error_details: used to store a string describing any error.
QuicErrorCode ProcessClientHello(const CryptoHandshakeMessage& client_hello,
+ QuicVersion version,
QuicGuid guid,
const IPEndPoint& client_ip,
const QuicClock* clock,
@@ -259,6 +262,7 @@
// BuildRejection sets |out| to be a REJ message in reply to |client_hello|.
void BuildRejection(
+ QuicVersion version,
const scoped_refptr<Config>& config,
const CryptoHandshakeMessage& client_hello,
const ClientHelloInfo& info,
diff --git a/net/quic/crypto/crypto_server_test.cc b/net/quic/crypto/crypto_server_test.cc
index b2cdf82..6744d12 100644
--- a/net/quic/crypto/crypto_server_test.cc
+++ b/net/quic/crypto/crypto_server_test.cc
@@ -72,8 +72,8 @@
void ShouldSucceed(const CryptoHandshakeMessage& message) {
string error_details;
QuicErrorCode error = config_.ProcessClientHello(
- message, 1 /* GUID */, addr_, &clock_,
- rand_, ¶ms_, &out_, &error_details);
+ message, QuicVersionMax(), 1 /* GUID */, addr_,
+ &clock_, rand_, ¶ms_, &out_, &error_details);
ASSERT_EQ(error, QUIC_NO_ERROR)
<< "Message failed with error " << error_details << ": "
@@ -84,8 +84,8 @@
const CryptoHandshakeMessage& message) {
string error_details;
QuicErrorCode error = config_.ProcessClientHello(
- message, 1 /* GUID */, addr_, &clock_,
- rand_, ¶ms_, &out_, &error_details);
+ message, QuicVersionMax(), 1 /* GUID */, addr_,
+ &clock_, rand_, ¶ms_, &out_, &error_details);
ASSERT_NE(error, QUIC_NO_ERROR)
<< "Message didn't fail: " << message.DebugString();
diff --git a/net/quic/crypto/proof_source.h b/net/quic/crypto/proof_source.h
index 277549f..42d8d50 100644
--- a/net/quic/crypto/proof_source.h
+++ b/net/quic/crypto/proof_source.h
@@ -9,6 +9,7 @@
#include <vector>
#include "net/base/net_export.h"
+#include "net/quic/quic_protocol.h"
namespace net {
@@ -27,6 +28,12 @@
//
// The signature uses SHA-256 as the hash function when the key is ECDSA.
//
+ // If |ecdsa_ok| is true, the signature may use an ECDSA key. Otherwise, the
+ // signature must use an RSA key.
+ //
+ // |version| is the QUIC version for the connection. TODO(wtc): Remove once
+ // QUIC_VERSION_7 and before are removed.
+ //
// |out_certs| is a pointer to a pointer, not a pointer to an array.
//
// The number of certificate chains is expected to be small and fixed thus
@@ -42,7 +49,8 @@
// used.
//
// This function may be called concurrently.
- virtual bool GetProof(const std::string& hostname,
+ virtual bool GetProof(QuicVersion version,
+ const std::string& hostname,
const std::string& server_config,
bool ecdsa_ok,
const std::vector<std::string>** out_certs,
diff --git a/net/quic/crypto/proof_source_chromium.cc b/net/quic/crypto/proof_source_chromium.cc
index 7522631..4c1fe26 100644
--- a/net/quic/crypto/proof_source_chromium.cc
+++ b/net/quic/crypto/proof_source_chromium.cc
@@ -12,7 +12,8 @@
ProofSourceChromium::ProofSourceChromium() {
}
-bool ProofSourceChromium::GetProof(const string& hostname,
+bool ProofSourceChromium::GetProof(QuicVersion version,
+ const string& hostname,
const string& server_config,
bool ecdsa_ok,
const vector<string>** out_certs,
diff --git a/net/quic/crypto/proof_source_chromium.h b/net/quic/crypto/proof_source_chromium.h
index 70ab92d..2b93e2d 100644
--- a/net/quic/crypto/proof_source_chromium.h
+++ b/net/quic/crypto/proof_source_chromium.h
@@ -23,7 +23,8 @@
virtual ~ProofSourceChromium() {}
// ProofSource interface
- virtual bool GetProof(const std::string& hostname,
+ virtual bool GetProof(QuicVersion version,
+ const std::string& hostname,
const std::string& server_config,
bool ecdsa_ok,
const std::vector<std::string>** out_certs,
diff --git a/net/quic/crypto/proof_test.cc b/net/quic/crypto/proof_test.cc
index f973bde..97b0dcb 100644
--- a/net/quic/crypto/proof_test.cc
+++ b/net/quic/crypto/proof_test.cc
@@ -25,7 +25,21 @@
namespace net {
namespace test {
-TEST(Proof, Verify) {
+class ProofTest : public ::testing::TestWithParam<QuicVersion> {
+ protected:
+ ProofTest() {
+ version_ = GetParam();
+ }
+
+ QuicVersion version_;
+};
+
+// Run all ProofTests with QUIC versions 7 and 8.
+INSTANTIATE_TEST_CASE_P(ProofTests,
+ ProofTest,
+ ::testing::Values(QUIC_VERSION_7, QUIC_VERSION_8));
+
+TEST_P(ProofTest, Verify) {
// TODO(rtenneti): Enable testing of ProofVerifier.
#if 0
scoped_ptr<ProofSource> source(CryptoTestUtils::ProofSourceForTesting());
@@ -39,10 +53,11 @@
string error_details, signature, first_signature;
CertVerifyResult cert_verify_result;
- ASSERT_TRUE(source->GetProof(hostname, server_config, false /* no ECDSA */,
- &first_certs, &first_signature));
- ASSERT_TRUE(source->GetProof(hostname, server_config, false /* no ECDSA */,
- &certs, &signature));
+ ASSERT_TRUE(source->GetProof(version_, hostname, server_config,
+ false /* no ECDSA */, &first_certs,
+ &first_signature));
+ ASSERT_TRUE(source->GetProof(version_, hostname, server_config,
+ false /* no ECDSA */, &certs, &signature));
// Check that the proof source is caching correctly:
ASSERT_EQ(first_certs, certs);
@@ -50,22 +65,23 @@
int rv;
TestCompletionCallback callback;
- rv = verifier->VerifyProof(hostname, server_config, *certs, signature,
- &error_details, &cert_verify_result,
+ rv = verifier->VerifyProof(version_, hostname, server_config, *certs,
+ signature, &error_details, &cert_verify_result,
callback.callback());
rv = callback.GetResult(rv);
ASSERT_EQ(OK, rv);
ASSERT_EQ("", error_details);
ASSERT_FALSE(IsCertStatusError(cert_verify_result.cert_status));
- rv = verifier->VerifyProof("foo.com", server_config, *certs, signature,
- &error_details, &cert_verify_result,
+ rv = verifier->VerifyProof(version_, "foo.com", server_config, *certs,
+ signature, &error_details, &cert_verify_result,
callback.callback());
rv = callback.GetResult(rv);
ASSERT_EQ(ERR_FAILED, rv);
ASSERT_NE("", error_details);
- rv = verifier->VerifyProof(hostname, server_config.substr(1, string::npos),
+ rv = verifier->VerifyProof(version_, hostname,
+ server_config.substr(1, string::npos),
*certs, signature, &error_details,
&cert_verify_result, callback.callback());
rv = callback.GetResult(rv);
@@ -73,9 +89,9 @@
ASSERT_NE("", error_details);
const string corrupt_signature = "1" + signature;
- rv = verifier->VerifyProof(hostname, server_config, *certs, corrupt_signature,
- &error_details, &cert_verify_result,
- callback.callback());
+ rv = verifier->VerifyProof(version_, hostname, server_config, *certs,
+ corrupt_signature, &error_details,
+ &cert_verify_result, callback.callback());
rv = callback.GetResult(rv);
ASSERT_EQ(ERR_FAILED, rv);
ASSERT_NE("", error_details);
@@ -84,8 +100,8 @@
for (size_t i = 1; i < certs->size(); i++) {
wrong_certs.push_back((*certs)[i]);
}
- rv = verifier->VerifyProof("foo.com", server_config, wrong_certs, signature,
- &error_details, &cert_verify_result,
+ rv = verifier->VerifyProof(version_, "foo.com", server_config, wrong_certs,
+ signature, &error_details, &cert_verify_result,
callback.callback());
rv = callback.GetResult(rv);
ASSERT_EQ(ERR_FAILED, rv);
@@ -122,7 +138,8 @@
// RunVerification runs |verifier->VerifyProof| and asserts that the result
// matches |expected_ok|.
-static void RunVerification(ProofVerifier* verifier,
+static void RunVerification(QuicVersion version,
+ ProofVerifier* verifier,
const std::string& hostname,
const std::string& server_config,
const vector<std::string>& certs,
@@ -136,7 +153,7 @@
new TestProofVerifierCallback(&comp_callback, &ok, &error_details);
ProofVerifier::Status status = verifier->VerifyProof(
- hostname, server_config, certs, proof, &error_details, &details,
+ version, hostname, server_config, certs, proof, &error_details, &details,
callback);
switch (status) {
@@ -168,59 +185,9 @@
// A known answer test that allows us to test ProofVerifier without a working
// ProofSource.
-TEST(Proof, VerifyRSAKnownAnswerTest) {
+TEST_P(ProofTest, VerifyRSAKnownAnswerTest) {
// These sample signatures were generated by running the Proof.Verify test
// and dumping the bytes of the |signature| output of ProofSource::GetProof().
-#if 0
- // In the future, we will change the |sLen| parameter of RSA-PSS to be the
- // same as |hLen|, and these are the sample signatures with the parameter
- // |sLen| equal to |hLen|.
- static const unsigned char signature_data_0[] = {
- 0x9e, 0xe6, 0x74, 0x3b, 0x8f, 0xb8, 0x66, 0x77, 0x57, 0x09,
- 0x8a, 0x04, 0xe9, 0xf0, 0x7c, 0x91, 0xa9, 0x5c, 0xe9, 0xdf,
- 0x12, 0x4d, 0x23, 0x82, 0x8c, 0x29, 0x72, 0x7f, 0xc2, 0x20,
- 0xa7, 0xb3, 0xe5, 0xbc, 0xcf, 0x3c, 0x0d, 0x8f, 0xae, 0x46,
- 0x6a, 0xb9, 0xee, 0x0c, 0xe1, 0x13, 0x21, 0xc0, 0x7e, 0x45,
- 0x24, 0x24, 0x4b, 0x72, 0x43, 0x5e, 0xc4, 0x0d, 0xdf, 0x6c,
- 0xd8, 0xaa, 0x35, 0x97, 0x05, 0x40, 0x76, 0xd3, 0x2c, 0xee,
- 0x82, 0x16, 0x6a, 0x43, 0xf9, 0xa2, 0xd0, 0x41, 0x3c, 0xed,
- 0x3f, 0x40, 0x10, 0x95, 0xc7, 0xa9, 0x1f, 0x04, 0xdb, 0xd5,
- 0x98, 0x9f, 0xe2, 0xbf, 0x77, 0x3d, 0xc9, 0x9a, 0xaf, 0xf7,
- 0xef, 0x63, 0x0b, 0x7d, 0xc8, 0x37, 0xda, 0x37, 0x23, 0x88,
- 0x78, 0xc8, 0x8b, 0xf5, 0xb9, 0x36, 0x5d, 0x72, 0x1f, 0xfc,
- 0x14, 0xff, 0xa7, 0x81, 0x27, 0x49, 0xae, 0xe1,
- };
- static const unsigned char signature_data_1[] = {
- 0x5e, 0xc2, 0xab, 0x6b, 0x16, 0xe6, 0x55, 0xf3, 0x16, 0x46,
- 0x35, 0xdc, 0xcc, 0xde, 0xd0, 0xbd, 0x6c, 0x66, 0xb2, 0x3d,
- 0xd3, 0x14, 0x78, 0xed, 0x47, 0x55, 0xfb, 0xdb, 0xe1, 0x7d,
- 0xbf, 0x31, 0xf6, 0xf4, 0x10, 0x4c, 0x8d, 0x22, 0x17, 0xaa,
- 0xe1, 0x85, 0xc7, 0x96, 0x4c, 0x42, 0xfb, 0xf4, 0x63, 0x53,
- 0x8a, 0x79, 0x01, 0x63, 0x48, 0xa8, 0x3a, 0xbc, 0xc9, 0xd2,
- 0xf5, 0xec, 0xe9, 0x09, 0x71, 0xaf, 0xce, 0x34, 0x56, 0xe5,
- 0x00, 0xbe, 0xee, 0x3c, 0x1c, 0xc4, 0xa0, 0x07, 0xd5, 0x77,
- 0xb8, 0x83, 0x57, 0x7d, 0x1a, 0xc9, 0xd0, 0xc0, 0x59, 0x9a,
- 0x88, 0x19, 0x3f, 0xb9, 0xf0, 0x45, 0x37, 0xc3, 0x00, 0x8b,
- 0xb3, 0x89, 0xf4, 0x89, 0x07, 0xa9, 0xc3, 0x26, 0xbf, 0x81,
- 0xaf, 0x6b, 0x47, 0xbc, 0x16, 0x55, 0x37, 0x0a, 0xbe, 0x0e,
- 0xc5, 0x75, 0x3f, 0x3d, 0x8e, 0xe8, 0x44, 0xe3,
- };
- static const unsigned char signature_data_2[] = {
- 0x8e, 0x5c, 0x78, 0x63, 0x74, 0x99, 0x2e, 0x96, 0xc0, 0x14,
- 0x8d, 0xb5, 0x13, 0x74, 0xa3, 0xa4, 0xe0, 0x43, 0x3e, 0x85,
- 0xba, 0x8f, 0x3c, 0x5e, 0x14, 0x64, 0x0e, 0x5e, 0xff, 0x89,
- 0x88, 0x8a, 0x65, 0xe2, 0xa2, 0x79, 0xe4, 0xe9, 0x3a, 0x7f,
- 0xf6, 0x9d, 0x3d, 0xe2, 0xb0, 0x8a, 0x35, 0x55, 0xed, 0x21,
- 0xee, 0x20, 0xd8, 0x8a, 0x60, 0x47, 0xca, 0x52, 0x54, 0x91,
- 0x99, 0x69, 0x8d, 0x16, 0x34, 0x69, 0xe1, 0x46, 0x56, 0x67,
- 0x5f, 0x50, 0xf0, 0x94, 0xe7, 0x8b, 0xf2, 0x6a, 0x73, 0x0f,
- 0x30, 0x30, 0xde, 0x59, 0xdc, 0xc7, 0xfe, 0xb6, 0x83, 0xe1,
- 0x86, 0x1d, 0x88, 0xd3, 0x2f, 0x2f, 0x74, 0x68, 0xbd, 0x6c,
- 0xd1, 0x46, 0x76, 0x06, 0xa9, 0xd4, 0x03, 0x3f, 0xda, 0x7d,
- 0xa7, 0xff, 0x48, 0xe4, 0xb4, 0x42, 0x06, 0xac, 0x19, 0x12,
- 0xe6, 0x05, 0xae, 0xbe, 0x29, 0x94, 0x8f, 0x99,
- };
-#else
// sLen = special value -2 used by OpenSSL.
static const unsigned char signature_data_0[] = {
0x4c, 0x68, 0x3c, 0xc2, 0x1f, 0x31, 0x73, 0xa5, 0x29, 0xd3,
@@ -267,7 +234,51 @@
0xd2, 0x50, 0x81, 0x78, 0x41, 0x13, 0x2c, 0x65, 0x9c, 0x9e,
0xf4, 0xd2, 0xd5, 0x58, 0x5b, 0x8b, 0x87, 0xcf,
};
-#endif
+ static const unsigned char signature_data_4[] = {
+ 0x9e, 0xe6, 0x74, 0x3b, 0x8f, 0xb8, 0x66, 0x77, 0x57, 0x09,
+ 0x8a, 0x04, 0xe9, 0xf0, 0x7c, 0x91, 0xa9, 0x5c, 0xe9, 0xdf,
+ 0x12, 0x4d, 0x23, 0x82, 0x8c, 0x29, 0x72, 0x7f, 0xc2, 0x20,
+ 0xa7, 0xb3, 0xe5, 0xbc, 0xcf, 0x3c, 0x0d, 0x8f, 0xae, 0x46,
+ 0x6a, 0xb9, 0xee, 0x0c, 0xe1, 0x13, 0x21, 0xc0, 0x7e, 0x45,
+ 0x24, 0x24, 0x4b, 0x72, 0x43, 0x5e, 0xc4, 0x0d, 0xdf, 0x6c,
+ 0xd8, 0xaa, 0x35, 0x97, 0x05, 0x40, 0x76, 0xd3, 0x2c, 0xee,
+ 0x82, 0x16, 0x6a, 0x43, 0xf9, 0xa2, 0xd0, 0x41, 0x3c, 0xed,
+ 0x3f, 0x40, 0x10, 0x95, 0xc7, 0xa9, 0x1f, 0x04, 0xdb, 0xd5,
+ 0x98, 0x9f, 0xe2, 0xbf, 0x77, 0x3d, 0xc9, 0x9a, 0xaf, 0xf7,
+ 0xef, 0x63, 0x0b, 0x7d, 0xc8, 0x37, 0xda, 0x37, 0x23, 0x88,
+ 0x78, 0xc8, 0x8b, 0xf5, 0xb9, 0x36, 0x5d, 0x72, 0x1f, 0xfc,
+ 0x14, 0xff, 0xa7, 0x81, 0x27, 0x49, 0xae, 0xe1,
+ };
+ static const unsigned char signature_data_5[] = {
+ 0x5e, 0xc2, 0xab, 0x6b, 0x16, 0xe6, 0x55, 0xf3, 0x16, 0x46,
+ 0x35, 0xdc, 0xcc, 0xde, 0xd0, 0xbd, 0x6c, 0x66, 0xb2, 0x3d,
+ 0xd3, 0x14, 0x78, 0xed, 0x47, 0x55, 0xfb, 0xdb, 0xe1, 0x7d,
+ 0xbf, 0x31, 0xf6, 0xf4, 0x10, 0x4c, 0x8d, 0x22, 0x17, 0xaa,
+ 0xe1, 0x85, 0xc7, 0x96, 0x4c, 0x42, 0xfb, 0xf4, 0x63, 0x53,
+ 0x8a, 0x79, 0x01, 0x63, 0x48, 0xa8, 0x3a, 0xbc, 0xc9, 0xd2,
+ 0xf5, 0xec, 0xe9, 0x09, 0x71, 0xaf, 0xce, 0x34, 0x56, 0xe5,
+ 0x00, 0xbe, 0xee, 0x3c, 0x1c, 0xc4, 0xa0, 0x07, 0xd5, 0x77,
+ 0xb8, 0x83, 0x57, 0x7d, 0x1a, 0xc9, 0xd0, 0xc0, 0x59, 0x9a,
+ 0x88, 0x19, 0x3f, 0xb9, 0xf0, 0x45, 0x37, 0xc3, 0x00, 0x8b,
+ 0xb3, 0x89, 0xf4, 0x89, 0x07, 0xa9, 0xc3, 0x26, 0xbf, 0x81,
+ 0xaf, 0x6b, 0x47, 0xbc, 0x16, 0x55, 0x37, 0x0a, 0xbe, 0x0e,
+ 0xc5, 0x75, 0x3f, 0x3d, 0x8e, 0xe8, 0x44, 0xe3,
+ };
+ static const unsigned char signature_data_6[] = {
+ 0x8e, 0x5c, 0x78, 0x63, 0x74, 0x99, 0x2e, 0x96, 0xc0, 0x14,
+ 0x8d, 0xb5, 0x13, 0x74, 0xa3, 0xa4, 0xe0, 0x43, 0x3e, 0x85,
+ 0xba, 0x8f, 0x3c, 0x5e, 0x14, 0x64, 0x0e, 0x5e, 0xff, 0x89,
+ 0x88, 0x8a, 0x65, 0xe2, 0xa2, 0x79, 0xe4, 0xe9, 0x3a, 0x7f,
+ 0xf6, 0x9d, 0x3d, 0xe2, 0xb0, 0x8a, 0x35, 0x55, 0xed, 0x21,
+ 0xee, 0x20, 0xd8, 0x8a, 0x60, 0x47, 0xca, 0x52, 0x54, 0x91,
+ 0x99, 0x69, 0x8d, 0x16, 0x34, 0x69, 0xe1, 0x46, 0x56, 0x67,
+ 0x5f, 0x50, 0xf0, 0x94, 0xe7, 0x8b, 0xf2, 0x6a, 0x73, 0x0f,
+ 0x30, 0x30, 0xde, 0x59, 0xdc, 0xc7, 0xfe, 0xb6, 0x83, 0xe1,
+ 0x86, 0x1d, 0x88, 0xd3, 0x2f, 0x2f, 0x74, 0x68, 0xbd, 0x6c,
+ 0xd1, 0x46, 0x76, 0x06, 0xa9, 0xd4, 0x03, 0x3f, 0xda, 0x7d,
+ 0xa7, 0xff, 0x48, 0xe4, 0xb4, 0x42, 0x06, 0xac, 0x19, 0x12,
+ 0xe6, 0x05, 0xae, 0xbe, 0x29, 0x94, 0x8f, 0x99,
+ };
scoped_ptr<ProofVerifier> verifier(
CryptoTestUtils::ProofVerifierForTesting());
@@ -284,41 +295,52 @@
// Signatures are nondeterministic, so we test multiple signatures on the
// same server_config.
vector<string> signatures(3);
- signatures[0].assign(reinterpret_cast<const char*>(signature_data_0),
- sizeof(signature_data_0));
- signatures[1].assign(reinterpret_cast<const char*>(signature_data_1),
- sizeof(signature_data_1));
- signatures[2].assign(reinterpret_cast<const char*>(signature_data_2),
- sizeof(signature_data_2));
+ if (version_ < QUIC_VERSION_8) {
+ signatures[0].assign(reinterpret_cast<const char*>(signature_data_0),
+ sizeof(signature_data_0));
+ signatures[1].assign(reinterpret_cast<const char*>(signature_data_1),
+ sizeof(signature_data_1));
+ signatures[2].assign(reinterpret_cast<const char*>(signature_data_2),
+ sizeof(signature_data_2));
+ } else {
+ signatures[0].assign(reinterpret_cast<const char*>(signature_data_4),
+ sizeof(signature_data_4));
+ signatures[1].assign(reinterpret_cast<const char*>(signature_data_5),
+ sizeof(signature_data_5));
+ signatures[2].assign(reinterpret_cast<const char*>(signature_data_6),
+ sizeof(signature_data_6));
+ }
for (size_t i = 0; i < signatures.size(); i++) {
const string& signature = signatures[i];
RunVerification(
- verifier.get(), hostname, server_config, certs, signature, true);
+ version_, verifier.get(), hostname, server_config, certs, signature,
+ true);
RunVerification(
- verifier.get(), "foo.com", server_config, certs, signature, false);
+ version_, verifier.get(), "foo.com", server_config, certs, signature,
+ false);
RunVerification(
- verifier.get(), hostname, server_config.substr(1, string::npos),
- certs, signature, false);
+ version_, verifier.get(), hostname,
+ server_config.substr(1, string::npos), certs, signature, false);
const string corrupt_signature = "1" + signature;
RunVerification(
- verifier.get(), hostname, server_config, certs, corrupt_signature,
- false);
+ version_, verifier.get(), hostname, server_config, certs,
+ corrupt_signature, false);
vector<string> wrong_certs;
for (size_t i = 1; i < certs.size(); i++) {
wrong_certs.push_back(certs[i]);
}
- RunVerification(verifier.get(), hostname, server_config, wrong_certs,
- signature, false);
+ RunVerification(version_, verifier.get(), hostname, server_config,
+ wrong_certs, signature, false);
}
}
// A known answer test that allows us to test ProofVerifier without a working
// ProofSource.
-TEST(Proof, VerifyECDSAKnownAnswerTest) {
+TEST_P(ProofTest, VerifyECDSAKnownAnswerTest) {
// Disable this test on platforms that do not support ECDSA certificates.
#if defined(OS_WIN)
if (base::win::GetVersion() < base::win::VERSION_VISTA)
@@ -384,33 +406,36 @@
const string& signature = signatures[i];
RunVerification(
- verifier.get(), hostname, server_config, certs, signature, true);
+ version_, verifier.get(), hostname, server_config, certs, signature,
+ true);
RunVerification(
- verifier.get(), "foo.com", server_config, certs, signature, false);
+ version_, verifier.get(), "foo.com", server_config, certs, signature,
+ false);
RunVerification(
- verifier.get(), hostname, server_config.substr(1, string::npos),
- certs, signature, false);
+ version_, verifier.get(), hostname,
+ server_config.substr(1, string::npos), certs, signature, false);
// An ECDSA signature is DER-encoded. Corrupt the last byte so that the
// signature can still be DER-decoded correctly.
string corrupt_signature = signature;
corrupt_signature[corrupt_signature.size() - 1] += 1;
RunVerification(
- verifier.get(), hostname, server_config, certs, corrupt_signature,
- false);
+ version_, verifier.get(), hostname, server_config, certs,
+ corrupt_signature, false);
// Prepending a "1" makes the DER invalid.
const string bad_der_signature1 = "1" + signature;
RunVerification(
- verifier.get(), hostname, server_config, certs, bad_der_signature1,
- false);
+ version_, verifier.get(), hostname, server_config, certs,
+ bad_der_signature1, false);
vector<string> wrong_certs;
for (size_t i = 1; i < certs.size(); i++) {
wrong_certs.push_back(certs[i]);
}
RunVerification(
- verifier.get(), hostname, server_config, wrong_certs, signature, false);
+ version_, verifier.get(), hostname, server_config, wrong_certs,
+ signature, false);
}
}
diff --git a/net/quic/crypto/proof_verifier.h b/net/quic/crypto/proof_verifier.h
index f469c55..ecab113 100644
--- a/net/quic/crypto/proof_verifier.h
+++ b/net/quic/crypto/proof_verifier.h
@@ -10,6 +10,7 @@
#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
+#include "net/quic/quic_protocol.h"
namespace net {
@@ -70,7 +71,11 @@
//
// The signature uses SHA-256 as the hash function and PSS padding in the
// case of RSA.
- virtual Status VerifyProof(const std::string& hostname,
+ //
+ // |version| is the QUIC version for the connection. TODO(wtc): Remove once
+ // QUIC_VERSION_7 and before are removed.
+ virtual Status VerifyProof(QuicVersion version,
+ const std::string& hostname,
const std::string& server_config,
const std::vector<std::string>& certs,
const std::string& signature,
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc
index c8b197b..8865305 100644
--- a/net/quic/crypto/proof_verifier_chromium.cc
+++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -42,6 +42,7 @@
}
ProofVerifierChromium::Status ProofVerifierChromium::VerifyProof(
+ QuicVersion version,
const string& hostname,
const string& server_config,
const vector<string>& certs,
@@ -89,7 +90,7 @@
// We call VerifySignature first to avoid copying of server_config and
// signature.
- if (!VerifySignature(server_config, signature, certs[0])) {
+ if (!VerifySignature(version, server_config, signature, certs[0])) {
*error_details = "Failed to verify signature of server config";
DLOG(WARNING) << *error_details;
verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
@@ -176,7 +177,8 @@
return result;
}
-bool ProofVerifierChromium::VerifySignature(const string& signed_data,
+bool ProofVerifierChromium::VerifySignature(QuicVersion version,
+ const string& signed_data,
const string& signature,
const string& cert) {
StringPiece spki;
@@ -196,8 +198,8 @@
crypto::SignatureVerifier::SHA256;
crypto::SignatureVerifier::HashAlgorithm mask_hash_alg = hash_alg;
unsigned int hash_len = 32; // 32 is the length of a SHA-256 hash.
- // TODO(wtc): change this to hash_len when we can change the wire format.
- unsigned int salt_len = signature.size() - hash_len - 2;
+ unsigned int salt_len =
+ version >= QUIC_VERSION_8 ? hash_len : signature.size() - hash_len - 2;
bool ok = verifier.VerifyInitRSAPSS(
hash_alg, mask_hash_alg, salt_len,
diff --git a/net/quic/crypto/proof_verifier_chromium.h b/net/quic/crypto/proof_verifier_chromium.h
index 4969cc8..8786e52 100644
--- a/net/quic/crypto/proof_verifier_chromium.h
+++ b/net/quic/crypto/proof_verifier_chromium.h
@@ -39,7 +39,8 @@
virtual ~ProofVerifierChromium();
// ProofVerifier interface
- virtual Status VerifyProof(const std::string& hostname,
+ virtual Status VerifyProof(QuicVersion version,
+ const std::string& hostname,
const std::string& server_config,
const std::vector<std::string>& certs,
const std::string& signature,
@@ -59,7 +60,8 @@
int DoVerifyCert(int result);
int DoVerifyCertComplete(int result);
- bool VerifySignature(const std::string& signed_data,
+ bool VerifySignature(QuicVersion version,
+ const std::string& signed_data,
const std::string& signature,
const std::string& cert);
diff --git a/net/quic/quic_alarm.cc b/net/quic/quic_alarm.cc
new file mode 100644
index 0000000..e1d4a16
--- /dev/null
+++ b/net/quic/quic_alarm.cc
@@ -0,0 +1,48 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_alarm.h"
+
+#include "base/logging.h"
+
+namespace net {
+
+QuicAlarm::QuicAlarm(Delegate* delegate)
+ : delegate_(delegate),
+ deadline_(QuicTime::Zero()) {
+}
+
+QuicAlarm::~QuicAlarm() {}
+
+void QuicAlarm::Set(QuicTime deadline) {
+ DCHECK(!IsSet());
+ DCHECK(deadline.IsInitialized());
+ deadline_ = deadline;
+ SetImpl();
+}
+
+void QuicAlarm::Cancel() {
+ deadline_ = QuicTime::Zero();
+ CancelImpl();
+}
+
+bool QuicAlarm::IsSet() const {
+ return deadline_.IsInitialized();
+}
+
+void QuicAlarm::Fire() {
+ if (!deadline_.IsInitialized()) {
+ return;
+ }
+
+ deadline_ = QuicTime::Zero();
+ QuicTime deadline = delegate_->OnAlarm();
+ // delegate_->OnAlarm() might call Set(), in which case deadline_ will
+ // already contain the new value, so don't overwrite it.
+ if (!deadline_.IsInitialized() && deadline.IsInitialized()) {
+ Set(deadline);
+ }
+}
+
+} // namespace net
diff --git a/net/quic/quic_alarm.h b/net/quic/quic_alarm.h
new file mode 100644
index 0000000..bee5157
--- /dev/null
+++ b/net/quic/quic_alarm.h
@@ -0,0 +1,77 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_QUIC_ALARM_H_
+#define NET_QUIC_QUIC_ALARM_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "net/base/net_export.h"
+#include "net/quic/quic_time.h"
+
+namespace net {
+
+// Abstract class which represents an alarm which will go off at a
+// scheduled time, and execute the |OnAlarm| method of the delegate.
+// An alarm may be cancelled, in which case it may or may not be
+// removed from the underlying scheduling system, but in either case
+// the task will not be executed.
+class NET_EXPORT_PRIVATE QuicAlarm {
+ public:
+ class NET_EXPORT_PRIVATE Delegate {
+ public:
+ virtual ~Delegate() {}
+
+ // Invoked when the alarm fires. If the return value is not
+ // infinite, then the alarm will be rescheduled at the
+ // specified time.
+ virtual QuicTime OnAlarm() = 0;
+ };
+
+ explicit QuicAlarm(Delegate* delegate);
+ virtual ~QuicAlarm();
+
+ // Sets the alarm to fire at |deadline|. Must not be called while
+ // the alarm is set. To reschedule an alarm, call Cancel() first,
+ // then Set().
+ void Set(QuicTime deadline);
+
+ // Cancels the alarm. May be called repeatedly. Does not
+ // guarantee that the underlying scheduling system will remove
+ // the alarm's associated task, but guarantees that the
+ // delegates OnAlarm method will not be called.
+ void Cancel();
+
+ bool IsSet() const;
+
+ QuicTime deadline() const { return deadline_; }
+
+ protected:
+ // Subclasses implement this method to perform the platform-specific
+ // scheduling of the alarm. Is called from Set() or Fire(), after the
+ // deadline has been updated.
+ virtual void SetImpl() = 0;
+
+ // Subclasses implement this method to perform the platform-specific
+ // cancelation of the alarm.
+ virtual void CancelImpl() = 0;
+
+ // Called by subclasses when the alarm fires. Invokes the
+ // delegates |OnAlarm| if a delegate is set, and if the deadline
+ // has been exceeded. Implementations which do not remove the
+ // alarm from the underlying scheduler on Cancel() may need to handle
+ // the situation where the task executes before the deadline has been
+ // reached, in which case they need to reschedule the task and must not
+ // call invoke this method.
+ void Fire();
+
+ private:
+ scoped_ptr<Delegate> delegate_;
+ QuicTime deadline_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicAlarm);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_QUIC_ALARM_H_
diff --git a/net/quic/quic_alarm_test.cc b/net/quic/quic_alarm_test.cc
new file mode 100644
index 0000000..cd7d8a5
--- /dev/null
+++ b/net/quic/quic_alarm_test.cc
@@ -0,0 +1,126 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_alarm.h"
+
+#include "base/logging.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::Return;
+using testing::Invoke;
+
+namespace net {
+namespace test {
+namespace {
+
+class MockDelegate : public QuicAlarm::Delegate {
+ public:
+ MOCK_METHOD0(OnAlarm, QuicTime());
+};
+
+class TestAlarm : public QuicAlarm {
+ public:
+ TestAlarm(QuicAlarm::Delegate* delegate)
+ : QuicAlarm(delegate) {
+ }
+
+ bool scheduled() const { return scheduled_; }
+
+ void FireAlarm() {
+ scheduled_ = false;
+ Fire();
+ }
+
+ protected:
+ virtual void SetImpl() OVERRIDE {
+ DCHECK(deadline().IsInitialized());
+ scheduled_ = true;
+ }
+
+ virtual void CancelImpl() OVERRIDE {
+ DCHECK(!deadline().IsInitialized());
+ scheduled_ = false;
+ }
+
+ private:
+ bool scheduled_;
+};
+
+class QuicAlarmTest : public ::testing::Test {
+ public:
+ QuicAlarmTest()
+ : delegate_(new MockDelegate()),
+ alarm_(delegate_),
+ deadline_(QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7))),
+ deadline2_(QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(14))),
+ new_deadline_(QuicTime::Zero()) {
+ }
+
+ void ResetAlarm() {
+ alarm_.Set(new_deadline_);
+ }
+
+ MockDelegate* delegate_; // not owned
+ TestAlarm alarm_;
+ QuicTime deadline_;
+ QuicTime deadline2_;
+ QuicTime new_deadline_;
+};
+
+TEST_F(QuicAlarmTest, IsSet) {
+ EXPECT_FALSE(alarm_.IsSet());
+}
+
+TEST_F(QuicAlarmTest, Set) {
+ QuicTime deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7));
+ alarm_.Set(deadline);
+ EXPECT_TRUE(alarm_.IsSet());
+ EXPECT_TRUE(alarm_.scheduled());
+ EXPECT_EQ(deadline, alarm_.deadline());
+}
+
+TEST_F(QuicAlarmTest, Cancel) {
+ QuicTime deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7));
+ alarm_.Set(deadline);
+ alarm_.Cancel();
+ EXPECT_FALSE(alarm_.IsSet());
+ EXPECT_FALSE(alarm_.scheduled());
+ EXPECT_EQ(QuicTime::Zero(), alarm_.deadline());
+}
+
+TEST_F(QuicAlarmTest, Fire) {
+ QuicTime deadline = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(7));
+ alarm_.Set(deadline);
+ EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(Return(QuicTime::Zero()));
+ alarm_.FireAlarm();
+ EXPECT_FALSE(alarm_.IsSet());
+ EXPECT_FALSE(alarm_.scheduled());
+ EXPECT_EQ(QuicTime::Zero(), alarm_.deadline());
+}
+
+TEST_F(QuicAlarmTest, FireAndResetViaReturn) {
+ alarm_.Set(deadline_);
+ EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(Return(deadline2_));
+ alarm_.FireAlarm();
+ EXPECT_TRUE(alarm_.IsSet());
+ EXPECT_TRUE(alarm_.scheduled());
+ EXPECT_EQ(deadline2_, alarm_.deadline());
+}
+
+TEST_F(QuicAlarmTest, FireAndResetViaSet) {
+ alarm_.Set(deadline_);
+ new_deadline_ = deadline2_;
+ EXPECT_CALL(*delegate_, OnAlarm()).WillOnce(DoAll(
+ Invoke(this, &QuicAlarmTest::ResetAlarm),
+ Return(QuicTime::Zero())));
+ alarm_.FireAlarm();
+ EXPECT_TRUE(alarm_.IsSet());
+ EXPECT_TRUE(alarm_.scheduled());
+ EXPECT_EQ(deadline2_, alarm_.deadline());
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/net/quic/quic_client_session.cc b/net/quic/quic_client_session.cc
index 69e9775..d7fb0d2 100644
--- a/net/quic/quic_client_session.cc
+++ b/net/quic/quic_client_session.cc
@@ -263,6 +263,8 @@
void QuicClientSession::ConnectionClose(QuicErrorCode error, bool from_peer) {
UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.ConnectionCloseErrorCode",
error);
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.QuicVersion",
+ connection()->version());
if (!callback_.is_null()) {
base::ResetAndReturn(&callback_).Run(ERR_QUIC_PROTOCOL_ERROR);
}
@@ -319,6 +321,7 @@
base::Value* QuicClientSession::GetInfoAsValue(const HostPortPair& pair) const {
base::DictionaryValue* dict = new base::DictionaryValue();
dict->SetString("host_port_pair", pair.ToString());
+ dict->SetString("version", QuicVersionToString(connection()->version()));
dict->SetInteger("open_streams", GetNumOpenStreams());
dict->SetInteger("total_streams", num_total_streams_);
dict->SetString("peer_address", peer_address().ToString());
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index 30f822c..fefeba9 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -62,6 +62,74 @@
return delta <= kMaxPacketGap;
}
+
+// An alarm that is scheduled to send an ack if a timeout occurs.
+class AckAlarm : public QuicAlarm::Delegate {
+ public:
+ explicit AckAlarm(QuicConnection* connection)
+ : connection_(connection) {
+ }
+
+ virtual QuicTime OnAlarm() OVERRIDE {
+ connection_->SendAck();
+ return QuicTime::Zero();
+ }
+
+ private:
+ QuicConnection* connection_;
+};
+
+// This alarm will be scheduled any time a data-bearing packet is sent out.
+// When the alarm goes off, the connection checks to see if the oldest packets
+// have been acked, and retransmit them if they have not.
+class RetransmissionAlarm : public QuicAlarm::Delegate {
+ public:
+ explicit RetransmissionAlarm(QuicConnection* connection)
+ : connection_(connection) {
+ }
+
+ virtual QuicTime OnAlarm() OVERRIDE {
+ return connection_->OnRetransmissionTimeout();
+ }
+
+ private:
+ QuicConnection* connection_;
+};
+
+// An alarm that is scheduled when the sent scheduler requires a
+// a delay before sending packets and fires when the packet may be sent.
+class SendAlarm : public QuicAlarm::Delegate {
+ public:
+ explicit SendAlarm(QuicConnection* connection)
+ : connection_(connection) {
+ }
+
+ virtual QuicTime OnAlarm() OVERRIDE {
+ connection_->OnCanWrite();
+ // Never reschedule the alarm, since OnCanWrite does that.
+ return QuicTime::Zero();
+ }
+
+ private:
+ QuicConnection* connection_;
+};
+
+class TimeoutAlarm : public QuicAlarm::Delegate {
+ public:
+ explicit TimeoutAlarm(QuicConnection* connection)
+ : connection_(connection) {
+ }
+
+ virtual QuicTime OnAlarm() OVERRIDE {
+ connection_->CheckForTimeout();
+ // Never reschedule the alarm, since CheckForTimeout does that.
+ return QuicTime::Zero();
+ }
+
+ private:
+ QuicConnection* connection_;
+};
+
} // namespace
#define ENDPOINT (is_server_ ? "Server: " : " Client: ")
@@ -83,6 +151,10 @@
largest_seen_packet_with_ack_(0),
handling_retransmission_timeout_(false),
write_blocked_(false),
+ ack_alarm_(helper->CreateAlarm(new AckAlarm(this))),
+ retransmission_alarm_(helper->CreateAlarm(new RetransmissionAlarm(this))),
+ send_alarm_(helper->CreateAlarm(new SendAlarm(this))),
+ timeout_alarm_(helper->CreateAlarm(new TimeoutAlarm(this))),
debug_visitor_(NULL),
packet_creator_(guid_, &framer_, random_generator_, is_server),
packet_generator_(this, NULL, &packet_creator_),
@@ -101,7 +173,7 @@
send_ack_in_response_to_packet_(false),
address_migrating_(false) {
helper_->SetConnection(this);
- helper_->SetTimeoutAlarm(idle_network_timeout_);
+ timeout_alarm_->Set(clock_->ApproximateNow().Add(idle_network_timeout_));
framer_.set_visitor(this);
framer_.set_received_entropy_calculator(&received_packet_manager_);
@@ -151,6 +223,11 @@
}
void QuicConnection::OnPacket() {
+ DCHECK(last_stream_frames_.empty() &&
+ last_goaway_frames_.empty() &&
+ last_rst_frames_.empty() &&
+ last_ack_frames_.empty() &&
+ last_congestion_frames_.empty());
}
void QuicConnection::OnPublicResetPacket(
@@ -179,12 +256,12 @@
case START_NEGOTIATION:
if (!framer_.IsSupportedVersion(received_version)) {
SendVersionNegotiationPacket();
- version_negotiation_state_ = SENT_NEGOTIATION_PACKET;
+ version_negotiation_state_ = NEGOTIATION_IN_PROGRESS;
return false;
}
break;
- case SENT_NEGOTIATION_PACKET:
+ case NEGOTIATION_IN_PROGRESS:
if (!framer_.IsSupportedVersion(received_version)) {
// Drop packets which can't be parsed due to version mismatch.
return false;
@@ -224,7 +301,7 @@
debug_visitor_->OnVersionNegotiationPacket(packet);
}
- if (version_negotiation_state_ == NEGOTIATED_VERSION) {
+ if (version_negotiation_state_ != START_NEGOTIATION) {
// Possibly a duplicate version negotiation packet.
return;
}
@@ -245,7 +322,7 @@
return;
}
- version_negotiation_state_ = NEGOTIATED_VERSION;
+ version_negotiation_state_ = NEGOTIATION_IN_PROGRESS;
RetransmitUnackedPackets(ALL_PACKETS);
}
@@ -314,6 +391,7 @@
--stats_.packets_dropped;
DVLOG(1) << ENDPOINT << "Received packet header: " << header;
last_header_ = header;
+ DCHECK(connected_);
return true;
}
@@ -346,12 +424,17 @@
DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring";
return true;
}
- largest_seen_packet_with_ack_ = last_header_.packet_sequence_number;
if (!ValidateAckFrame(incoming_ack)) {
SendConnectionClose(QUIC_INVALID_ACK_DATA);
return false;
}
+ last_ack_frames_.push_back(incoming_ack);
+ return connected_;
+}
+
+void QuicConnection::ProcessAckFrame(const QuicAckFrame& incoming_ack) {
+ largest_seen_packet_with_ack_ = last_header_.packet_sequence_number;
received_truncated_ack_ =
incoming_ack.received_info.missing_packets.size() >=
@@ -373,19 +456,6 @@
}
congestion_manager_.OnIncomingAckFrame(incoming_ack,
time_of_last_received_packet_);
-
- // Now the we have received an ack, we might be able to send packets which are
- // queued locally, or drain streams which are blocked.
- QuicTime::Delta delay = congestion_manager_.TimeUntilSend(
- time_of_last_received_packet_, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE);
- if (delay.IsZero()) {
- helper_->UnregisterSendAlarmIfRegistered();
- WriteIfNotBlocked();
- } else if (!delay.IsInfinite()) {
- helper_->SetSendAlarm(time_of_last_received_packet_.Add(delay));
- }
- return connected_;
}
bool QuicConnection::OnCongestionFeedbackFrame(
@@ -394,8 +464,7 @@
if (debug_visitor_) {
debug_visitor_->OnCongestionFeedbackFrame(feedback);
}
- congestion_manager_.OnIncomingQuicCongestionFeedbackFrame(
- feedback, time_of_last_received_packet_);
+ last_congestion_frames_.push_back(feedback);
return connected_;
}
@@ -557,7 +626,7 @@
}
DLOG(INFO) << ENDPOINT << "Stream reset with error "
<< QuicUtils::StreamErrorToString(frame.error_code);
- visitor_->OnRstStream(frame);
+ last_rst_frames_.push_back(frame);
return connected_;
}
@@ -571,6 +640,7 @@
<< QuicUtils::ErrorToString(frame.error_code)
<< " " << frame.error_details;
CloseConnection(frame.error_code, true);
+ DCHECK(!connected_);
return false;
}
@@ -579,30 +649,35 @@
DLOG(INFO) << ENDPOINT << "Go away received with error "
<< QuicUtils::ErrorToString(frame.error_code)
<< " and reason:" << frame.reason_phrase;
- visitor_->OnGoAway(frame);
+ last_goaway_frames_.push_back(frame);
return connected_;
}
void QuicConnection::OnPacketComplete() {
// Don't do anything if this packet closed the connection.
if (!connected_) {
- last_stream_frames_.clear();
+ ClearLastFrames();
return;
}
+ DLOG(INFO) << ENDPOINT << (last_packet_revived_ ? "Revived" : "Got")
+ << " packet " << last_header_.packet_sequence_number
+ << " with " << last_ack_frames_.size() << " acks, "
+ << last_congestion_frames_.size() << " congestions, "
+ << last_goaway_frames_.size() << " goaways, "
+ << last_rst_frames_.size() << " rsts, "
+ << last_stream_frames_.size()
+ << " stream frames for " << last_header_.public_header.guid;
if (!last_packet_revived_) {
- DLOG(INFO) << ENDPOINT << "Got packet "
- << last_header_.packet_sequence_number
- << " with " << last_stream_frames_.size()
- << " stream frames for " << last_header_.public_header.guid;
congestion_manager_.RecordIncomingPacket(
last_size_, last_header_.packet_sequence_number,
time_of_last_received_packet_, last_packet_revived_);
- } else {
- DLOG(INFO) << ENDPOINT << "Got revived packet with "
- << last_stream_frames_.size() << " frames.";
}
+ // Must called before ack processing, because processing acks removes entries
+ // from unacket_packets_, increasing the least_unacked.
+ const bool last_packet_should_instigate_ack = ShouldLastPacketInstigateAck();
+
if ((last_stream_frames_.empty() ||
visitor_->OnPacket(self_address_, peer_address_,
last_header_, last_stream_frames_))) {
@@ -610,8 +685,32 @@
last_header_, time_of_last_received_packet_);
}
- MaybeSendAckInResponseToPacket();
+ // Process stream resets, then acks, then congestion feedback.
+ for (size_t i = 0; i < last_goaway_frames_.size(); ++i) {
+ visitor_->OnGoAway(last_goaway_frames_[i]);
+ }
+ for (size_t i = 0; i < last_rst_frames_.size(); ++i) {
+ visitor_->OnRstStream(last_rst_frames_[i]);
+ }
+ for (size_t i = 0; i < last_ack_frames_.size(); ++i) {
+ ProcessAckFrame(last_ack_frames_[i]);
+ }
+ for (size_t i = 0; i < last_congestion_frames_.size(); ++i) {
+ congestion_manager_.OnIncomingQuicCongestionFeedbackFrame(
+ last_congestion_frames_[i], time_of_last_received_packet_);
+ }
+
+ MaybeSendInResponseToPacket(last_packet_should_instigate_ack);
+
+ ClearLastFrames();
+}
+
+void QuicConnection::ClearLastFrames() {
last_stream_frames_.clear();
+ last_goaway_frames_.clear();
+ last_rst_frames_.clear();
+ last_ack_frames_.clear();
+ last_congestion_frames_.clear();
}
QuicAckFrame* QuicConnection::CreateAckFrame() {
@@ -627,13 +726,60 @@
return new QuicCongestionFeedbackFrame(outgoing_congestion_feedback_);
}
-void QuicConnection::MaybeSendAckInResponseToPacket() {
+bool QuicConnection::ShouldLastPacketInstigateAck() {
+ if (!last_stream_frames_.empty() ||
+ !last_goaway_frames_.empty() ||
+ !last_rst_frames_.empty()) {
+ return true;
+ }
+
+ // If the peer is still waiting for a packet that we are no
+ // longer planning to send, we should send an ack to raise
+ // the high water mark.
+ if (!last_ack_frames_.empty() &&
+ !last_ack_frames_.back().received_info.missing_packets.empty() &&
+ !unacked_packets_.empty()) {
+ if (unacked_packets_.begin()->first >
+ *last_ack_frames_.back().received_info.missing_packets.begin()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void QuicConnection::MaybeSendInResponseToPacket(
+ bool last_packet_should_instigate_ack) {
+ // TODO(ianswett): Better merge these two blocks to queue up an ack if
+ // necessary, then either only send the ack or bundle it with other data.
+ if (!last_ack_frames_.empty()) {
+ // Now the we have received an ack, we might be able to send packets which
+ // are queued locally, or drain streams which are blocked.
+ QuicTime::Delta delay = congestion_manager_.TimeUntilSend(
+ time_of_last_received_packet_, NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE);
+ if (delay.IsZero()) {
+ send_alarm_->Cancel();
+ WriteIfNotBlocked();
+ } else if (!delay.IsInfinite()) {
+ send_alarm_->Cancel();
+ send_alarm_->Set(time_of_last_received_packet_.Add(delay));
+ }
+ }
+
+ if (!last_packet_should_instigate_ack) {
+ return;
+ }
+
if (send_ack_in_response_to_packet_) {
SendAck();
} else if (!last_stream_frames_.empty()) {
// TODO(alyssar) this case should really be "if the packet contained any
// non-ack frame", rather than "if the packet contained a stream frame"
- helper_->SetAckAlarm(congestion_manager_.DefaultRetransmissionTime());
+ if (!ack_alarm_->IsSet()) {
+ ack_alarm_->Set(clock_->ApproximateNow().Add(
+ congestion_manager_.DefaultRetransmissionTime()));
+ }
}
send_ack_in_response_to_packet_ = !send_ack_in_response_to_packet_;
}
@@ -750,7 +896,8 @@
// We're not write blocked, but some stream didn't write out all of its
// bytes. Register for 'immediate' resumption so we'll keep writing after
// other quic connections have had a chance to use the socket.
- helper_->SetSendAlarm(clock_->ApproximateNow());
+ send_alarm_->Cancel();
+ send_alarm_->Set(clock_->ApproximateNow());
}
}
@@ -900,7 +1047,7 @@
IsHandshake handshake) {
// TODO(ianswett): If the packet is a retransmit, the current send alarm may
// be too long.
- if (write_blocked_ || helper_->IsSendAlarmSet()) {
+ if (write_blocked_ || send_alarm_->IsSet()) {
return false;
}
@@ -913,7 +1060,8 @@
// If the scheduler requires a delay, then we can not send this packet now.
if (!delay.IsZero()) {
- helper_->SetSendAlarm(now.Add(delay));
+ send_alarm_->Cancel();
+ send_alarm_->Set(now.Add(delay));
return false;
}
return true;
@@ -953,8 +1101,9 @@
// Do not set the retransmisson alarm if we're already handling the
// retransmission alarm because the retransmission alarm will be reset when
// OnRetransmissionTimeout completes.
- if (!handling_retransmission_timeout_) {
- helper_->SetRetransmissionAlarm(retransmission_delay);
+ if (!handling_retransmission_timeout_ && !retransmission_alarm_->IsSet()) {
+ retransmission_alarm_->Set(
+ clock_->ApproximateNow().Add(retransmission_delay));
}
// TODO(satyamshekhar): restore packet reordering with Ian's TODO in
// SendStreamData().
@@ -1169,7 +1318,7 @@
}
void QuicConnection::SendAck() {
- helper_->ClearAckAlarm();
+ ack_alarm_->Cancel();
// TODO(rch): delay this until the CreateFeedbackFrame
// method is invoked. This requires changes SetShouldSendAck
@@ -1286,7 +1435,7 @@
return;
}
- while (!undecryptable_packets_.empty()) {
+ while (connected_ && !undecryptable_packets_.empty()) {
DVLOG(1) << ENDPOINT << "Attempting to process undecryptable packet";
QuicEncryptedPacket* packet = undecryptable_packets_.front();
if (!framer_.ProcessPacket(*packet) &&
@@ -1309,7 +1458,7 @@
void QuicConnection::MaybeProcessRevivedPacket() {
QuicFecGroup* group = GetFecGroup();
- if (group == NULL || !group->CanRevive()) {
+ if (!connected_ || group == NULL || !group->CanRevive()) {
return;
}
QuicPacketHeader revived_header;
@@ -1384,7 +1533,7 @@
serialized_packet.sequence_number,
serialized_packet.packet,
serialized_packet.retransmittable_frames != NULL ?
- HAS_RETRANSMITTABLE_DATA : NO_RETRANSMITTABLE_DATA,
+ HAS_RETRANSMITTABLE_DATA : NO_RETRANSMITTABLE_DATA,
FORCE)) {
delete serialized_packet.packet;
}
@@ -1399,6 +1548,7 @@
}
void QuicConnection::CloseConnection(QuicErrorCode error, bool from_peer) {
+ DCHECK(connected_);
connected_ = false;
visitor_->ConnectionClose(error, from_peer);
}
@@ -1499,7 +1649,8 @@
}
}
- helper_->SetTimeoutAlarm(timeout);
+ timeout_alarm_->Cancel();
+ timeout_alarm_->Set(clock_->ApproximateNow().Add(timeout));
return false;
}
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index 4ac4fa4..41172f7 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -27,6 +27,7 @@
#include "net/base/ip_endpoint.h"
#include "net/base/linked_hash_map.h"
#include "net/quic/congestion_control/quic_congestion_manager.h"
+#include "net/quic/quic_alarm.h"
#include "net/quic/quic_blocked_writer_interface.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_packet_creator.h"
@@ -167,38 +168,10 @@
// as EAGAIN or ERR_IO_PENDING.
virtual bool IsWriteBlocked(int error) = 0;
- // Sets up an alarm to retransmit a packet if we haven't received an ack
- // in the expected time frame. Implementations must invoke
- // OnRetransmissionAlarm when the alarm fires. Implementations must also
- // handle the case where |this| is deleted before the alarm fires. If the
- // alarm is already set, this call is a no-op.
- virtual void SetRetransmissionAlarm(QuicTime::Delta delay) = 0;
-
- // Sets an alarm to send packets at |alarm_time|. Implementations must
- // invoke OnCanWrite when the alarm fires. Implementations must also
- // handle the case where |this| is deleted before the alarm fires.
- virtual void SetSendAlarm(QuicTime alarm_time) = 0;
-
- // Sets an alarm which fires when the connection may have timed out.
- // Implementations must call CheckForTimeout() and then reregister the alarm
- // if the connection has not yet timed out.
- virtual void SetTimeoutAlarm(QuicTime::Delta delay) = 0;
-
- // Returns true if a send alarm is currently set.
- virtual bool IsSendAlarmSet() = 0;
-
- // If a send alarm is currently set, this method unregisters it. If
- // no send alarm is set, it does nothing.
- virtual void UnregisterSendAlarmIfRegistered() = 0;
-
- // Sets an alarm which fires when an Ack may need to be sent.
- // Implementations must call SendAck() when the alarm fires.
- // If the alarm is already registered for a shorter timeout, this call is a
- // no-op.
- virtual void SetAckAlarm(QuicTime::Delta delay) = 0;
-
- // Clears the ack alarm if it was set. If it was not set, this is a no-op.
- virtual void ClearAckAlarm() = 0;
+ // Creates a new platform-specific alarm which will be configured to
+ // notify |delegate| when the alarm fires. Caller takes ownership
+ // of the new alarm, which will not yet be "set" to fire.
+ virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) = 0;
};
class NET_EXPORT_PRIVATE QuicConnection
@@ -530,6 +503,9 @@
void SetupAbandonFecTimer(QuicPacketSequenceNumber sequence_number);
+ // Clears any accumulated frames from the last received packet.
+ void ClearLastFrames();
+
// Called from OnCanWrite and WriteIfNotBlocked to write queued packets.
// Returns false if the socket has become blocked.
bool DoWrite();
@@ -555,6 +531,8 @@
// revive and process the packet.
void MaybeProcessRevivedPacket();
+ void ProcessAckFrame(const QuicAckFrame& incoming_ack);
+
void HandleAckForSentPackets(const QuicAckFrame& incoming_ack,
SequenceNumberSet* acked_packets);
void HandleAckForSentFecPackets(const QuicAckFrame& incoming_ack,
@@ -563,7 +541,12 @@
// Update the |sent_info| for an outgoing ack.
void UpdateSentPacketInfo(SentPacketInfo* sent_info);
- void MaybeSendAckInResponseToPacket();
+ // Checks if the last packet should instigate an ack.
+ bool ShouldLastPacketInstigateAck();
+
+ // Sends any packets which are a response to the last packet, including both
+ // acks and pending writes if an ack opened the congestion window.
+ void MaybeSendInResponseToPacket(bool last_packet_should_instigate_ack);
void MaybeAbandonFecPacket(QuicPacketSequenceNumber sequence_number);
@@ -589,6 +572,10 @@
size_t last_size_; // Size of the last received packet.
QuicPacketHeader last_header_;
std::vector<QuicStreamFrame> last_stream_frames_;
+ std::vector<QuicAckFrame> last_ack_frames_;
+ std::vector<QuicCongestionFeedbackFrame> last_congestion_frames_;
+ std::vector<QuicRstStreamFrame> last_rst_frames_;
+ std::vector<QuicGoAwayFrame> last_goaway_frames_;
QuicCongestionFeedbackFrame outgoing_congestion_feedback_;
@@ -640,6 +627,16 @@
QuicReceivedPacketManager received_packet_manager_;
QuicSentEntropyManager sent_entropy_manager_;
+ // An alarm that fires when an ACK should be sent to the peer.
+ scoped_ptr<QuicAlarm> ack_alarm_;
+ // An alarm that fires when a packet needs to be retransmitted.
+ scoped_ptr<QuicAlarm> retransmission_alarm_;
+ // An alarm that is scheduled when the sent scheduler requires a
+ // a delay before sending packets and fires when the packet may be sent.
+ scoped_ptr<QuicAlarm> send_alarm_;
+ // An alarm that fires when the connection may have timed out.
+ scoped_ptr<QuicAlarm> timeout_alarm_;
+
QuicConnectionVisitorInterface* visitor_;
QuicConnectionDebugVisitorInterface* debug_visitor_;
QuicPacketCreator packet_creator_;
diff --git a/net/quic/quic_connection_helper.cc b/net/quic/quic_connection_helper.cc
index c58bbad..c3e796f 100644
--- a/net/quic/quic_connection_helper.cc
+++ b/net/quic/quic_connection_helper.cc
@@ -14,6 +14,72 @@
namespace net {
+namespace {
+
+class QuicChromeAlarm : public QuicAlarm {
+ public:
+ QuicChromeAlarm(const QuicClock* clock,
+ base::TaskRunner* task_runner,
+ QuicAlarm::Delegate* delegate)
+ : QuicAlarm(delegate),
+ clock_(clock),
+ task_runner_(task_runner),
+ task_posted_(false),
+ weak_factory_(this) {}
+
+ protected:
+ virtual void SetImpl() OVERRIDE {
+ DCHECK(deadline().IsInitialized());
+ if (task_posted_) {
+ // Since tasks can not be un-posted, OnAlarm will be invoked which
+ // will notice that deadline has not yet been reached, and will set
+ // the alarm for the new deadline.
+ return;
+ }
+
+ int64 delay_us = deadline().Subtract(clock_->Now()).ToMicroseconds();
+ if (delay_us < 0) {
+ delay_us = 0;
+ }
+ task_runner_->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&QuicChromeAlarm::OnAlarm, weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMicroseconds(delay_us));
+ task_posted_ = true;
+ }
+
+ virtual void CancelImpl() OVERRIDE {
+ DCHECK(!deadline().IsInitialized());
+ // Since tasks can not be un-posted, OnAlarm will be invoked which
+ // will notice that deadline is not Initialized and will do nothing.
+ }
+
+ private:
+ void OnAlarm() {
+ DCHECK(task_posted_);
+ task_posted_ = false;
+ // The alarm may have been cancelled.
+ if (!deadline().IsInitialized()) {
+ return;
+ }
+
+ // The alarm may have been re-set to a later time.
+ if (clock_->Now() < deadline()) {
+ SetImpl();
+ return;
+ }
+
+ Fire();
+ }
+
+ const QuicClock* clock_;
+ base::TaskRunner* task_runner_;
+ bool task_posted_;
+ base::WeakPtrFactory<QuicChromeAlarm> weak_factory_;
+};
+
+} // namespace
+
QuicConnectionHelper::QuicConnectionHelper(base::TaskRunner* task_runner,
const QuicClock* clock,
QuicRandom* random_generator,
@@ -22,13 +88,7 @@
task_runner_(task_runner),
socket_(socket),
clock_(clock),
- random_generator_(random_generator),
- send_alarm_registered_(false),
- timeout_alarm_registered_(false),
- retransmission_alarm_registered_(false),
- retransmission_alarm_running_(false),
- ack_alarm_registered_(false),
- ack_alarm_time_(QuicTime::Zero()) {
+ random_generator_(random_generator) {
}
QuicConnectionHelper::~QuicConnectionHelper() {
@@ -81,107 +141,8 @@
return error == ERR_IO_PENDING;
}
-void QuicConnectionHelper::SetRetransmissionAlarm(QuicTime::Delta delay) {
- if (!retransmission_alarm_registered_) {
- task_runner_->PostDelayedTask(
- FROM_HERE,
- base::Bind(&QuicConnectionHelper::OnRetransmissionAlarm,
- weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromMicroseconds(delay.ToMicroseconds()));
- }
-}
-
-void QuicConnectionHelper::SetAckAlarm(QuicTime::Delta delay) {
- ack_alarm_time_ = clock_->Now().Add(delay);
- if (!ack_alarm_registered_) {
- task_runner_->PostDelayedTask(
- FROM_HERE,
- base::Bind(&QuicConnectionHelper::OnAckAlarm,
- weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromMicroseconds(delay.ToMicroseconds()));
- }
- ack_alarm_registered_ = true;
-}
-
-void QuicConnectionHelper::ClearAckAlarm() {
- ack_alarm_time_ = QuicTime::Zero();
-}
-
-void QuicConnectionHelper::SetSendAlarm(QuicTime alarm_time) {
- send_alarm_registered_ = true;
- int64 delay_us = alarm_time.Subtract(clock_->Now()).ToMicroseconds();
- if (delay_us < 0) {
- delay_us = 0;
- }
- task_runner_->PostDelayedTask(
- FROM_HERE,
- base::Bind(&QuicConnectionHelper::OnSendAlarm,
- weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromMicroseconds(delay_us));
-}
-
-void QuicConnectionHelper::SetTimeoutAlarm(QuicTime::Delta delay) {
- // CheckForTimeout will call SetTimeoutAlarm for the remaining time if alarm
- // goes off before the delay.
- if (timeout_alarm_registered_)
- return;
- timeout_alarm_registered_ = true;
- task_runner_->PostDelayedTask(
- FROM_HERE,
- base::Bind(&QuicConnectionHelper::OnTimeoutAlarm,
- weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromMicroseconds(delay.ToMicroseconds()));
-}
-
-bool QuicConnectionHelper::IsSendAlarmSet() {
- return send_alarm_registered_;
-}
-
-void QuicConnectionHelper::UnregisterSendAlarmIfRegistered() {
- send_alarm_registered_ = false;
-}
-
-void QuicConnectionHelper::OnRetransmissionAlarm() {
- QuicTime when = connection_->OnRetransmissionTimeout();
- if (!when.IsInitialized()) {
- return;
- }
- QuicTime now = clock_->Now();
- QuicTime::Delta delta(when.Subtract(now));
- if (delta < QuicTime::Delta::FromSeconds(0)) {
- delta = QuicTime::Delta::FromSeconds(0);
- }
- SetRetransmissionAlarm(delta);
-}
-
-void QuicConnectionHelper::OnSendAlarm() {
- if (send_alarm_registered_) {
- send_alarm_registered_ = false;
- connection_->OnCanWrite();
- }
-}
-
-void QuicConnectionHelper::OnTimeoutAlarm() {
- timeout_alarm_registered_ = false;
- connection_->CheckForTimeout();
-}
-
-void QuicConnectionHelper::OnAckAlarm() {
- ack_alarm_registered_ = false;
- // Alarm may have been cleared.
- if (!ack_alarm_time_.IsInitialized()) {
- return;
- }
-
- // Alarm may have been reset to a later time.
- QuicTime now = clock_->Now();
- if (now < ack_alarm_time_) {
- SetAckAlarm(ack_alarm_time_.Subtract(now));
- return;
- }
-
- ack_alarm_time_ = QuicTime::Zero();
- connection_->SendAck();
+QuicAlarm* QuicConnectionHelper::CreateAlarm(QuicAlarm::Delegate* delegate) {
+ return new QuicChromeAlarm(clock_, task_runner_, delegate);
}
void QuicConnectionHelper::OnWriteComplete(int result) {
diff --git a/net/quic/quic_connection_helper.h b/net/quic/quic_connection_helper.h
index 12f80bb..6667b95 100644
--- a/net/quic/quic_connection_helper.h
+++ b/net/quic/quic_connection_helper.h
@@ -49,30 +49,13 @@
int* error) OVERRIDE;
virtual bool IsWriteBlockedDataBuffered() OVERRIDE;
virtual bool IsWriteBlocked(int error) OVERRIDE;
- virtual void SetRetransmissionAlarm(QuicTime::Delta delay) OVERRIDE;
- virtual void SetSendAlarm(QuicTime alarm_time) OVERRIDE;
- virtual void SetTimeoutAlarm(QuicTime::Delta delay) OVERRIDE;
- virtual bool IsSendAlarmSet() OVERRIDE;
- virtual void UnregisterSendAlarmIfRegistered() OVERRIDE;
- virtual void SetAckAlarm(QuicTime::Delta delay) OVERRIDE;
- virtual void ClearAckAlarm() OVERRIDE;
+ virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) OVERRIDE;
private:
friend class test::QuicConnectionHelperPeer;
- // An alarm is scheduled for each data-bearing packet as it is sent out.
- // When the alarm goes off, the connection checks to see if the packet has
- // been acked, and retransmits if it has not.
- void OnRetransmissionAlarm();
- // An alarm that is scheduled when the sent scheduler requires a
- // a delay before sending packets and fires when the packet may be sent.
- void OnSendAlarm();
- // An alarm which fires when the connection may have timed out.
- void OnTimeoutAlarm();
// A completion callback invoked when a write completes.
void OnWriteComplete(int result);
- // An alarm which fires if we've hit a timeout on sending an ack.
- void OnAckAlarm();
base::WeakPtrFactory<QuicConnectionHelper> weak_factory_;
base::TaskRunner* task_runner_;
@@ -80,14 +63,6 @@
QuicConnection* connection_;
const QuicClock* clock_;
QuicRandom* random_generator_;
- bool send_alarm_registered_;
- bool timeout_alarm_registered_;
- bool retransmission_alarm_registered_;
- bool retransmission_alarm_running_;
- bool ack_alarm_registered_;
- QuicTime ack_alarm_time_;
- // Times that packets should be retransmitted.
- std::map<QuicPacketSequenceNumber, QuicTime> retransmission_times_;
DISALLOW_COPY_AND_ASSIGN(QuicConnectionHelper);
};
diff --git a/net/quic/quic_connection_helper_test.cc b/net/quic/quic_connection_helper_test.cc
index 6e84c0f..4822ea6 100644
--- a/net/quic/quic_connection_helper_test.cc
+++ b/net/quic/quic_connection_helper_test.cc
@@ -25,6 +25,21 @@
const char kData[] = "foo";
const bool kFromPeer = true;
+class TestDelegate : public QuicAlarm::Delegate {
+ public:
+ TestDelegate() : fired_(false) {}
+
+ virtual QuicTime OnAlarm() OVERRIDE {
+ fired_ = true;
+ return QuicTime::Zero();
+ }
+
+ bool fired() const { return fired_; }
+
+ private:
+ bool fired_;
+};
+
class TestConnection : public QuicConnection {
public:
TestConnection(QuicGuid guid,
@@ -218,85 +233,69 @@
EXPECT_EQ(&random_generator_, helper_->GetRandomGenerator());
}
-TEST_F(QuicConnectionHelperTest, IsSendAlarmSet) {
- EXPECT_FALSE(helper_->IsSendAlarmSet());
-}
-
-TEST_F(QuicConnectionHelperTest, SetSendAlarm) {
- helper_->SetSendAlarm(
- clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
- EXPECT_TRUE(helper_->IsSendAlarmSet());
-}
-
-TEST_F(QuicConnectionHelperTest, UnregisterSendAlarmIfRegistered) {
- helper_->SetSendAlarm(
- clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
- helper_->UnregisterSendAlarmIfRegistered() ;
- EXPECT_FALSE(helper_->IsSendAlarmSet());
-}
-
-TEST_F(QuicConnectionHelperTest, SetAckAlarm) {
- AddWrite(SYNCHRONOUS, ConstructAckPacket(1));
- Initialize();
+TEST_F(QuicConnectionHelperTest, CreateAlarm) {
+ TestDelegate* delegate = new TestDelegate();
+ scoped_ptr<QuicAlarm> alarm(helper_->CreateAlarm(delegate));
// The timeout alarm task is always posted.
ASSERT_EQ(1u, runner_->GetPostedTasks().size());
- QuicTime::Delta delta(QuicTime::Delta::FromMilliseconds(10));
- helper_->SetAckAlarm(delta);
+ QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
+ alarm->Set(clock_.Now().Add(delta));
- // Verify that the ack alarm task has been posted.
+ // Verify that the alarm task has been posted.
ASSERT_EQ(2u, runner_->GetPostedTasks().size());
EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
runner_->GetPostedTasks()[1].delay);
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION));
runner_->RunNextTask();
- EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.ApproximateNow());
+ EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
+ EXPECT_TRUE(delegate->fired());
}
-TEST_F(QuicConnectionHelperTest, ClearAckAlarm) {
- Initialize();
+TEST_F(QuicConnectionHelperTest, CreateAlarmAndCancel) {
+ TestDelegate* delegate = new TestDelegate();
+ scoped_ptr<QuicAlarm> alarm(helper_->CreateAlarm(delegate));
- // Verify that the timeout alarm task has been posted.
- ASSERT_EQ(1u, runner_->GetPostedTasks().size());
+ QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
+ alarm->Set(clock_.Now().Add(delta));
+ alarm->Cancel();
- QuicTime::Delta delta(QuicTime::Delta::FromMilliseconds(10));
- helper_->SetAckAlarm(delta);
+ // The alarm task should still be posted.
+ ASSERT_EQ(2u, runner_->GetPostedTasks().size());
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
+ runner_->GetPostedTasks()[1].delay);
- helper_->ClearAckAlarm();
-
- // When the AckAlarm actually fires, no ack will be sent.
runner_->RunNextTask();
- EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.ApproximateNow());
+ EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
+ EXPECT_FALSE(delegate->fired());
}
-TEST_F(QuicConnectionHelperTest, ResetAckAlarm) {
- AddWrite(SYNCHRONOUS, ConstructAckPacket(1));
- Initialize();
+TEST_F(QuicConnectionHelperTest, CreateAlarmAndReset) {
+ TestDelegate* delegate = new TestDelegate();
+ scoped_ptr<QuicAlarm> alarm(helper_->CreateAlarm(delegate));
- // Verify that the timeout alarm task has been posted.
- ASSERT_EQ(1u, runner_->GetPostedTasks().size());
+ QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
+ alarm->Set(clock_.Now().Add(delta));
+ alarm->Cancel();
+ QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3);
+ alarm->Set(clock_.Now().Add(new_delta));
- QuicTime::Delta delta1(QuicTime::Delta::FromMilliseconds(10));
- QuicTime::Delta delta2(QuicTime::Delta::FromMilliseconds(20));
- helper_->SetAckAlarm(delta1);
- helper_->ClearAckAlarm();
- helper_->SetAckAlarm(delta2);
- // We should only have 1 ack alarm task posted.
+ // The alarm task should still be posted.
+ ASSERT_EQ(2u, runner_->GetPostedTasks().size());
+ EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
+ runner_->GetPostedTasks()[1].delay);
+
+ runner_->RunNextTask();
+ EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
+ EXPECT_FALSE(delegate->fired());
+
+ // The alarm task should be posted again.
ASSERT_EQ(2u, runner_->GetPostedTasks().size());
- // The task will execute at delta1, but will not send and ack,
- // but it will reschedule itself for delta2
runner_->RunNextTask();
- EXPECT_EQ(QuicTime::Zero().Add(delta1), clock_.ApproximateNow());
-
- // Verify that the ack alarm task has been re-posted.
- ASSERT_EQ(2u, runner_->GetPostedTasks().size());
-
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION));
- runner_->RunNextTask();
- EXPECT_EQ(QuicTime::Zero().Add(delta2), clock_.ApproximateNow());
+ EXPECT_EQ(QuicTime::Zero().Add(new_delta), clock_.Now());
+ EXPECT_TRUE(delegate->fired());
}
TEST_F(QuicConnectionHelperTest, TestRetransmission) {
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index 80854aa..8732713 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -221,17 +221,24 @@
class TestConnectionHelper : public QuicConnectionHelperInterface {
public:
+ class TestAlarm : public QuicAlarm {
+ public:
+ explicit TestAlarm(QuicAlarm::Delegate* delegate)
+ : QuicAlarm(delegate) {
+ }
+
+ virtual void SetImpl() OVERRIDE {}
+ virtual void CancelImpl() OVERRIDE {}
+ };
+
TestConnectionHelper(MockClock* clock, MockRandom* random_generator)
: clock_(clock),
random_generator_(random_generator),
- retransmission_alarm_(QuicTime::Zero()),
- send_alarm_(QuicTime::Zero().Subtract(
- QuicTime::Delta::FromMilliseconds(1))),
- timeout_alarm_(QuicTime::Zero()),
blocked_(false),
is_server_(true),
use_tagging_decrypter_(false),
packets_write_attempts_(0) {
+ clock_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
}
// QuicConnectionHelperInterface
@@ -293,36 +300,10 @@
return error == ERR_IO_PENDING;
}
- virtual void SetRetransmissionAlarm(QuicTime::Delta delay) OVERRIDE {
- retransmission_alarm_ = clock_->ApproximateNow().Add(delay);
+ virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) OVERRIDE {
+ return new TestAlarm(delegate);
}
- virtual void SetSendAlarm(QuicTime alarm_time) OVERRIDE {
- send_alarm_ = alarm_time;
- }
-
- virtual void SetTimeoutAlarm(QuicTime::Delta delay) OVERRIDE {
- timeout_alarm_ = clock_->ApproximateNow().Add(delay);
- }
-
- virtual bool IsSendAlarmSet() OVERRIDE {
- return send_alarm_ >= clock_->ApproximateNow();
- }
-
- virtual void UnregisterSendAlarmIfRegistered() OVERRIDE {
- send_alarm_ =
- QuicTime::Zero().Subtract(QuicTime::Delta::FromMilliseconds(1));
- }
-
- virtual void SetAckAlarm(QuicTime::Delta delay) OVERRIDE {}
- virtual void ClearAckAlarm() OVERRIDE {}
-
- QuicTime retransmission_alarm() const {
- return retransmission_alarm_;
- }
-
- QuicTime timeout_alarm() const { return timeout_alarm_; }
-
QuicPacketHeader* header() { return &header_; }
size_t frame_count() const { return frame_count_; }
@@ -362,9 +343,6 @@
private:
MockClock* clock_;
MockRandom* random_generator_;
- QuicTime retransmission_alarm_;
- QuicTime send_alarm_;
- QuicTime timeout_alarm_;
QuicPacketHeader header_;
size_t frame_count_;
scoped_ptr<QuicAckFrame> ack_;
@@ -427,6 +405,22 @@
QuicConnectionPeer::SetIsServer(this, is_server);
}
+ QuicAlarm* GetAckAlarm() {
+ return QuicConnectionPeer::GetAckAlarm(this);
+ }
+
+ QuicAlarm* GetRetransmissionAlarm() {
+ return QuicConnectionPeer::GetRetransmissionAlarm(this);
+ }
+
+ QuicAlarm* GetSendAlarm() {
+ return QuicConnectionPeer::GetSendAlarm(this);
+ }
+
+ QuicAlarm* GetTimeoutAlarm() {
+ return QuicConnectionPeer::GetTimeoutAlarm(this);
+ }
+
using QuicConnection::SendOrQueuePacket;
using QuicConnection::SelectMutualVersion;
@@ -544,7 +538,6 @@
void ProcessClosePacket(QuicPacketSequenceNumber number,
QuicFecGroupNumber fec_group) {
- EXPECT_CALL(visitor_, OnCanWrite()).Times(1).WillOnce(Return(true));
scoped_ptr<QuicPacket> packet(ConstructClosePacket(number, fec_group));
scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(
ENCRYPTION_NONE, number, *packet));
@@ -839,7 +832,7 @@
EXPECT_FALSE(QuicConnectionPeer::GetReceivedTruncatedAck(&connection_));
}
-TEST_F(QuicConnectionTest, DISABLED_AckReceiptCausesAckSend) {
+TEST_F(QuicConnectionTest, AckReceiptCausesAckSendBadEntropy) {
ProcessPacket(1);
// Delay sending, then queue up an ack.
EXPECT_CALL(*send_algorithm_,
@@ -858,6 +851,37 @@
ProcessAckPacket(&frame, true);
}
+TEST_F(QuicConnectionTest, AckReceiptCausesAckSend) {
+ EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_)).Times(1);
+ QuicPacketSequenceNumber largest_observed;
+ QuicByteCount packet_size;
+ EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, NOT_RETRANSMISSION))
+ .WillOnce(DoAll(SaveArg<1>(&largest_observed), SaveArg<2>(&packet_size)));
+ EXPECT_CALL(*send_algorithm_, AbandoningPacket(1, _)).Times(1);
+ connection_.SendStreamData(1, "foo", 0, !kFin);
+ QuicAckFrame frame(1, QuicTime::Zero(), largest_observed);
+ frame.received_info.missing_packets.insert(largest_observed);
+ frame.received_info.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
+ &connection_, largest_observed - 1);
+ ProcessAckPacket(&frame, true);
+ ProcessAckPacket(&frame, true);
+ // Third nack should retransmit the largest observed packet.
+ EXPECT_CALL(*send_algorithm_, SentPacket(_, _, packet_size - kQuicVersionSize,
+ IS_RETRANSMISSION));
+ ProcessAckPacket(&frame, true);
+
+ // Now if the peer sends an ack which still reports the retransmitted packet
+ // as missing, then that will count as a packet which instigates an ack.
+ ProcessAckPacket(&frame, true);
+ EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, NOT_RETRANSMISSION));
+ ProcessAckPacket(&frame, true);
+
+ // But an ack with no new missing packest will not send an ack.
+ frame.received_info.missing_packets.clear();
+ ProcessAckPacket(&frame, true);
+ ProcessAckPacket(&frame, true);
+}
+
TEST_F(QuicConnectionTest, LeastUnackedLower) {
SendStreamDataToPeer(1, "foo", 0, !kFin, NULL);
SendStreamDataToPeer(1, "bar", 3, !kFin, NULL);
@@ -960,7 +984,7 @@
SequenceNumberSet expected_acks;
expected_acks.insert(1);
- // Client acks up to packet 3
+ // Peer acks up to packet 3.
EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks)));
QuicAckFrame frame(3, QuicTime::Zero(), 0);
frame.received_info.entropy_hash =
@@ -975,25 +999,28 @@
expected_acks.clear();
expected_acks.insert(4);
- // Client acks up to packet 4, the last packet
+ // Peer acks up to packet 4, the last packet.
EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks)));
QuicAckFrame frame2(6, QuicTime::Zero(), 0);
frame2.received_info.entropy_hash =
QuicConnectionPeer::GetSentEntropyHash(&connection_, 6);
- ProcessAckPacket(&frame2, true); // Even parity triggers ack packet 7
+ ProcessAckPacket(&frame2, true); // Acks don't instigate acks.
- // The least packet awaiting ack should now be 7
- EXPECT_EQ(7u, last_ack()->sent_info.least_unacked);
+ // Verify that we did not send an ack.
+ EXPECT_EQ(6u, last_header()->packet_sequence_number);
+
+ // So the last ack has not changed.
+ EXPECT_EQ(4u, last_ack()->sent_info.least_unacked);
// If we force an ack, we shouldn't change our retransmit state.
- SendAckPacketToPeer(); // Packet 8
- EXPECT_EQ(8u, last_ack()->sent_info.least_unacked);
+ SendAckPacketToPeer(); // Packet 7
+ EXPECT_EQ(7u, last_ack()->sent_info.least_unacked);
// But if we send more data it should.
- SendStreamDataToPeer(1, "eep", 6, !kFin, &last_packet); // Packet 9
- EXPECT_EQ(9u, last_packet);
- SendAckPacketToPeer(); // Packet10
- EXPECT_EQ(9u, last_ack()->sent_info.least_unacked);
+ SendStreamDataToPeer(1, "eep", 6, !kFin, &last_packet); // Packet 8
+ EXPECT_EQ(8u, last_packet);
+ SendAckPacketToPeer(); // Packet 9
+ EXPECT_EQ(8u, last_ack()->sent_info.least_unacked);
}
TEST_F(QuicConnectionTest, FECSending) {
@@ -1086,7 +1113,7 @@
TEST_F(QuicConnectionTest, FramePacking) {
// Block the connection.
- helper_->SetSendAlarm(
+ connection_.GetSendAlarm()->Set(
clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
// Send an ack and two stream frames in 1 packet by queueing them.
@@ -1099,7 +1126,7 @@
Return(true)));
// Unblock the connection.
- helper_->UnregisterSendAlarmIfRegistered();
+ connection_.GetSendAlarm()->Cancel();
EXPECT_CALL(*send_algorithm_,
SentPacket(_, _, _, NOT_RETRANSMISSION))
.Times(1);
@@ -1120,7 +1147,7 @@
// Enable fec.
connection_.options()->max_packets_per_fec_group = 6;
// Block the connection.
- helper_->SetSendAlarm(
+ connection_.GetSendAlarm()->Set(
clock_.ApproximateNow().Add(QuicTime::Delta::FromSeconds(1)));
// Send an ack and two stream frames in 1 packet by queueing them.
@@ -1133,7 +1160,7 @@
Return(true)));
// Unblock the connection.
- helper_->UnregisterSendAlarmIfRegistered();
+ connection_.GetSendAlarm()->Cancel();
EXPECT_CALL(*send_algorithm_,
SentPacket(_, _, _, NOT_RETRANSMISSION)).Times(2);
connection_.OnCanWrite();
@@ -1183,7 +1210,7 @@
expected_acks.insert(1);
EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks)));
- // Client acks one but not two or three. Right now we only retransmit on
+ // Peer acks one but not two or three. Right now we only retransmit on
// explicit nack, so it should not trigger a retransimission.
QuicAckFrame ack_one(1, QuicTime::Zero(), 0);
ack_one.received_info.entropy_hash =
@@ -1196,7 +1223,7 @@
expected_acks.insert(3);
EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks)));
- // Client acks up to 3 with two explicitly missing. Two nacks should cause no
+ // Peer acks up to 3 with two explicitly missing. Two nacks should cause no
// change.
QuicAckFrame nack_two(3, QuicTime::Zero(), 0);
nack_two.received_info.missing_packets.insert(2);
@@ -1227,9 +1254,6 @@
frame.received_info.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
&connection_, largest_observed - 1);
ProcessAckPacket(&frame, true);
- // Second udp packet will force an ack frame.
- EXPECT_CALL(*send_algorithm_,
- SentPacket(_, _, _, NOT_RETRANSMISSION));
ProcessAckPacket(&frame, true);
// Third nack should retransmit the largest observed packet.
EXPECT_CALL(*send_algorithm_, SentPacket(_, _, packet_size - kQuicVersionSize,
@@ -1302,15 +1326,13 @@
// Nack three times.
ProcessAckPacket(&nack, true);
- // The second call will trigger an ack.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _)).Times(1);
ProcessAckPacket(&nack, true);
// The third call should trigger retransmitting 10 packets.
EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _)).Times(10);
ProcessAckPacket(&nack, true);
- // The fourth call should trigger retransmitting the 11th packet and an ack.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _)).Times(2);
+ // The fourth call should trigger retransmitting the 11th packet.
+ EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _)).Times(1);
ProcessAckPacket(&nack, true);
}
@@ -1371,7 +1393,7 @@
// an ack for Packet 2 (ack packet).
SequenceNumberSet expected_acks;
expected_acks.insert(1);
- // Client acks packet 1
+ // Peer acks packet 1.
EXPECT_CALL(visitor_, OnAck(ContainerEq(expected_acks)));
QuicAckFrame frame(1, QuicTime::Zero(), 0);
frame.received_info.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
@@ -1445,7 +1467,8 @@
EXPECT_EQ(1u, outgoing_ack()->sent_info.least_unacked);
EXPECT_EQ(1u, last_header()->packet_sequence_number);
- EXPECT_EQ(default_retransmission_time, helper_->retransmission_alarm());
+ EXPECT_EQ(default_retransmission_time,
+ connection_.GetRetransmissionAlarm()->deadline());
// Simulate the retransimission alarm firing
clock_.AdvanceTime(kDefaultRetransmissionTime);
EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _));
@@ -1474,7 +1497,8 @@
SendStreamDataToPeer(1, "foo", 0, !kFin, NULL);
EXPECT_EQ(0x02020202u, final_bytes_of_last_packet());
- EXPECT_EQ(default_retransmission_time, helper_->retransmission_alarm());
+ EXPECT_EQ(default_retransmission_time,
+ connection_.GetRetransmissionAlarm()->deadline());
// Simulate the retransimission alarm firing
clock_.AdvanceTime(kDefaultRetransmissionTime);
EXPECT_CALL(*send_algorithm_, AbandoningPacket(_, _)).Times(2);
@@ -1509,7 +1533,8 @@
QuicTime default_retransmission_time = clock_.ApproximateNow().Add(
kDefaultRetransmissionTime);
- EXPECT_EQ(default_retransmission_time, helper_->retransmission_alarm());
+ EXPECT_EQ(default_retransmission_time,
+ connection_.GetRetransmissionAlarm()->deadline());
// Simulate the retransimission alarm firing
clock_.AdvanceTime(kDefaultRetransmissionTime);
connection_.OnRetransmissionTimeout();
@@ -1714,7 +1739,7 @@
QuicTime default_timeout = clock_.ApproximateNow().Add(
QuicTime::Delta::FromSeconds(kDefaultInitialTimeoutSecs));
- EXPECT_EQ(default_timeout, helper_->timeout_alarm());
+ EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
// Simulate the timeout alarm firing
clock_.AdvanceTime(
@@ -1735,7 +1760,7 @@
// Send an ack so we don't set the retransimission alarm.
SendAckPacketToPeer();
- EXPECT_EQ(default_timeout, helper_->timeout_alarm());
+ EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
// The original alarm will fire. We should not time out because we had a
// network event at t=5000. The alarm will reregister.
@@ -1745,7 +1770,7 @@
EXPECT_FALSE(connection_.CheckForTimeout());
EXPECT_TRUE(connection_.connected());
EXPECT_EQ(default_timeout.Add(QuicTime::Delta::FromMilliseconds(5)),
- helper_->timeout_alarm());
+ connection_.GetTimeoutAlarm()->deadline());
// This time, we should time out.
EXPECT_CALL(visitor_, ConnectionClose(QUIC_CONNECTION_TIMED_OUT, false));
@@ -1822,7 +1847,7 @@
TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillRepeatedly(
testing::Return(QuicTime::Delta::Zero()));
clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(1));
- helper_->UnregisterSendAlarmIfRegistered();
+ connection_.GetSendAlarm()->Cancel();
EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _));
EXPECT_CALL(visitor_, OnCanWrite());
connection_.OnCanWrite();
@@ -1856,7 +1881,7 @@
EXPECT_CALL(*send_algorithm_,
SentPacket(_, _, _, IS_RETRANSMISSION));
clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(1));
- helper_->UnregisterSendAlarmIfRegistered();
+ connection_.GetSendAlarm()->Cancel();
EXPECT_CALL(visitor_, OnCanWrite());
connection_.OnCanWrite();
EXPECT_EQ(0u, connection_.NumQueuedPackets());
@@ -1899,7 +1924,7 @@
EXPECT_EQ(0u, connection_.NumQueuedPackets());
// Ensure alarm is not set
- EXPECT_FALSE(helper_->IsSendAlarmSet());
+ EXPECT_FALSE(connection_.GetSendAlarm()->IsSet());
}
TEST_F(QuicConnectionTest, SendSchedulerDelayThenAckAndHold) {
@@ -2119,10 +2144,7 @@
<< "";
}
-// TODO(satyamsehkhar): Add more test when we start supporting more versions.
-TEST_F(QuicConnectionTest, SendVersionNegotiationPacket) {
- // TODO(rjshade): Update this to use a real version once we have multiple
- // versions in the codebase.
+TEST_F(QuicConnectionTest, ServerSendsVersionNegotiationPacket) {
framer_.set_version_for_tests(QUIC_VERSION_UNSUPPORTED);
QuicPacketHeader header;
@@ -2159,6 +2181,72 @@
}
}
+TEST_F(QuicConnectionTest, ClientHandlesVersionNegotiation) {
+ // Start out with some unsupported version.
+ QuicConnectionPeer::GetFramer(&connection_)->set_version_for_tests(
+ QUIC_VERSION_UNSUPPORTED);
+
+ QuicPacketHeader header;
+ header.public_header.guid = guid_;
+ header.public_header.reset_flag = false;
+ header.public_header.version_flag = true;
+ header.entropy_flag = false;
+ header.fec_flag = false;
+ header.packet_sequence_number = 12;
+ header.fec_group = 0;
+
+ QuicVersionVector supported_versions;
+ for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
+ supported_versions.push_back(kSupportedQuicVersions[i]);
+ }
+
+ // Send a version negotiation packet.
+ scoped_ptr<QuicEncryptedPacket> encrypted(
+ framer_.BuildVersionNegotiationPacket(
+ header.public_header, supported_versions));
+ connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
+
+ // Now force another packet. The connection should transition into
+ // NEGOTIATED_VERSION state and tell the packet creator to StopSendingVersion.
+ header.public_header.version_flag = false;
+ QuicFrames frames;
+ QuicFrame frame(&frame1_);
+ frames.push_back(frame);
+ scoped_ptr<QuicPacket> packet(
+ framer_.BuildUnsizedDataPacket(header, frames).packet);
+ encrypted.reset(framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
+ EXPECT_CALL(visitor_, OnPacket(_, _, _, _)).Times(1);
+ connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
+
+ ASSERT_FALSE(QuicPacketCreatorPeer::SendVersionInPacket(
+ QuicConnectionPeer::GetPacketCreator(&connection_)));
+}
+
+TEST_F(QuicConnectionTest, BadVersionNegotiation) {
+ QuicPacketHeader header;
+ header.public_header.guid = guid_;
+ header.public_header.reset_flag = false;
+ header.public_header.version_flag = true;
+ header.entropy_flag = false;
+ header.fec_flag = false;
+ header.packet_sequence_number = 12;
+ header.fec_group = 0;
+
+ QuicVersionVector supported_versions;
+ for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
+ supported_versions.push_back(kSupportedQuicVersions[i]);
+ }
+
+ // Send a version negotiation packet with the version the client started with.
+ // It should be rejected.
+ EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_VERSION_NEGOTIATION_PACKET,
+ false));
+ scoped_ptr<QuicEncryptedPacket> encrypted(
+ framer_.BuildVersionNegotiationPacket(
+ header.public_header, supported_versions));
+ connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
+}
+
TEST_F(QuicConnectionTest, CheckSendStats) {
EXPECT_CALL(*send_algorithm_, AbandoningPacket(_, _)).Times(3);
EXPECT_CALL(*send_algorithm_,
@@ -2167,7 +2255,7 @@
size_t first_packet_size = last_sent_packet_size();
EXPECT_CALL(*send_algorithm_,
- SentPacket(_, _, _, NOT_RETRANSMISSION)).Times(2);
+ SentPacket(_, _, _, NOT_RETRANSMISSION));
connection_.SendStreamData(1u, "second", 0, !kFin);
size_t second_packet_size = last_sent_packet_size();
@@ -2194,7 +2282,6 @@
ProcessFramePacket(frame);
ProcessFramePacket(frame);
- size_t ack_packet_size = last_sent_packet_size();
ProcessFramePacket(frame);
EXPECT_CALL(*send_algorithm_, SmoothedRtt()).WillOnce(
@@ -2203,9 +2290,9 @@
Return(QuicBandwidth::Zero()));
const QuicConnectionStats& stats = connection_.GetStats();
- EXPECT_EQ(3 * first_packet_size + 2 * second_packet_size + ack_packet_size -
- kQuicVersionSize, stats.bytes_sent);
- EXPECT_EQ(6u, stats.packets_sent);
+ EXPECT_EQ(3 * first_packet_size + 2 * second_packet_size - kQuicVersionSize,
+ stats.bytes_sent);
+ EXPECT_EQ(5u, stats.packets_sent);
EXPECT_EQ(2 * first_packet_size + second_packet_size - kQuicVersionSize,
stats.bytes_retransmitted);
EXPECT_EQ(3u, stats.packets_retransmitted);
@@ -2280,7 +2367,6 @@
scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(
ENCRYPTION_NONE, 1, *packet));
- EXPECT_CALL(visitor_, OnCanWrite()).Times(1).WillOnce(Return(true));
EXPECT_CALL(visitor_, ConnectionClose(QUIC_PEER_GOING_AWAY, true));
EXPECT_CALL(visitor_, OnPacket(_, _, _, _)).Times(0);
@@ -2318,7 +2404,7 @@
helper_->set_blocked(false); // Already default.
// Send a packet (but write will not block).
- ProcessFecPacket(2, 1, true, !kEntropyFlag);
+ connection_.SendStreamData(1, "foo", 0, !kFin);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_EQ(1u, helper_->packets_write_attempts());
@@ -2329,10 +2415,11 @@
}
TEST_F(QuicConnectionTest, ConnectionCloseWhenWriteBlocked) {
+ EXPECT_EQ(0u, connection_.NumQueuedPackets());
helper_->set_blocked(true);
// Send a packet to so that write will really block.
- ProcessFecPacket(2, 1, true, !kEntropyFlag);
+ connection_.SendStreamData(1, "foo", 0, !kFin);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
EXPECT_EQ(1u, helper_->packets_write_attempts());
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc
index edeef11..ab1d974 100644
--- a/net/quic/quic_crypto_client_stream.cc
+++ b/net/quic/quic_crypto_client_stream.cc
@@ -262,6 +262,7 @@
verify_ok_ = false;
ProofVerifier::Status status = verifier->VerifyProof(
+ session()->connection()->version(),
server_hostname_,
cached->server_config(),
cached->certs(),
diff --git a/net/quic/quic_crypto_server_stream.cc b/net/quic/quic_crypto_server_stream.cc
index 6f49864..f7b67b7 100644
--- a/net/quic/quic_crypto_server_stream.cc
+++ b/net/quic/quic_crypto_server_stream.cc
@@ -129,6 +129,7 @@
string* error_details) {
return crypto_config_.ProcessClientHello(
message,
+ session()->connection()->version(),
session()->connection()->guid(),
session()->connection()->peer_address(),
session()->connection()->clock(),
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index 997dc95..b378416 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -324,7 +324,6 @@
SetRequestString("GET", "/");
AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0,
request_data_));
- AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 1));
Initialize();
request_.method = "GET";
@@ -366,7 +365,6 @@
TEST_F(QuicHttpStreamTest, GetRequestFullResponseInSinglePacket) {
SetRequestString("GET", "/");
AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0, request_data_));
- AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 1));
Initialize();
request_.method = "GET";
@@ -412,7 +410,7 @@
AddWrite(SYNCHRONOUS, ConstructDataPacket(2, true, kFin,
request_data_.length(),
kUploadData));
- AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 2, 1));
+ AddWrite(SYNCHRONOUS, ConstructAckPacket(3, 3, 1));
Initialize();
@@ -473,7 +471,7 @@
AddWrite(SYNCHRONOUS, ConstructDataPacket(3, true, kFin,
request_data_.length() + chunk_size,
kUploadData));
- AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 2, 1));
+ AddWrite(SYNCHRONOUS, ConstructAckPacket(4, 3, 1));
Initialize();
@@ -528,7 +526,6 @@
TEST_F(QuicHttpStreamTest, DestroyedEarly) {
SetRequestString("GET", "/");
AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0, request_data_));
- AddWrite(SYNCHRONOUS, ConstructAckPacket(2, 2, 1));
use_closing_stream_ = true;
Initialize();
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc
index 6d21710..0b83b14 100644
--- a/net/quic/quic_protocol.cc
+++ b/net/quic/quic_protocol.cc
@@ -129,6 +129,8 @@
return MakeQuicTag('Q', '0', '0', '6');
case QUIC_VERSION_7:
return MakeQuicTag('Q', '0', '0', '7');
+ case QUIC_VERSION_8:
+ return MakeQuicTag('Q', '0', '0', '8');
default:
// This shold be an ERROR because we should never attempt to convert an
// invalid QuicVersion to be written to the wire.
@@ -140,11 +142,14 @@
QuicVersion QuicTagToQuicVersion(const QuicTag version_tag) {
const QuicTag quic_tag_v6 = MakeQuicTag('Q', '0', '0', '6');
const QuicTag quic_tag_v7 = MakeQuicTag('Q', '0', '0', '7');
+ const QuicTag quic_tag_v8 = MakeQuicTag('Q', '0', '0', '8');
if (version_tag == quic_tag_v6) {
return QUIC_VERSION_6;
} else if (version_tag == quic_tag_v7) {
return QUIC_VERSION_7;
+ } else if (version_tag == quic_tag_v8) {
+ return QUIC_VERSION_8;
} else {
// Reading from the client so this should not be considered an ERROR.
DLOG(INFO) << "Unsupported QuicTag version: "
@@ -153,14 +158,15 @@
}
}
+#define RETURN_STRING_LITERAL(x) \
+case x: \
+return #x
+
string QuicVersionToString(const QuicVersion version) {
- // TODO(rjshade): Possibly start using RETURN_STRING_LITERAL here when we
- // start supporting a lot of versions.
switch (version) {
- case QUIC_VERSION_6:
- return "QUIC_VERSION_6";
- case QUIC_VERSION_7:
- return "QUIC_VERSION_7";
+ RETURN_STRING_LITERAL(QUIC_VERSION_6);
+ RETURN_STRING_LITERAL(QUIC_VERSION_7);
+ RETURN_STRING_LITERAL(QUIC_VERSION_8);
default:
return "QUIC_VERSION_UNSUPPORTED";
}
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h
index fe4da4c..f332f9f 100644
--- a/net/quic/quic_protocol.h
+++ b/net/quic/quic_protocol.h
@@ -180,14 +180,16 @@
// The available versions of QUIC. Guaranteed that the integer value of the enum
// will match the version number.
// When adding a new version to this enum you should add it to
-// kSupportedVersions (if appropriate), and also add a new case to the helper
-// methods QuicVersionToQuicTag, and QuicTagToQuicVersion.
+// kSupportedQuicVersions (if appropriate), and also add a new case to the
+// helper methods QuicVersionToQuicTag, QuicTagToQuicVersion, and
+// QuicVersionToString.
enum QuicVersion {
// Special case to indicate unknown/unsupported QUIC version.
QUIC_VERSION_UNSUPPORTED = 0,
QUIC_VERSION_6 = 6,
- QUIC_VERSION_7 = 7, // Current version.
+ QUIC_VERSION_7 = 7,
+ QUIC_VERSION_8 = 8, // Current version.
};
// This vector contains QUIC versions which we currently support.
@@ -195,7 +197,7 @@
// element, with subsequent elements in descending order (versions can be
// skipped as necessary).
static const QuicVersion kSupportedQuicVersions[] =
- {QUIC_VERSION_7, QUIC_VERSION_6};
+ {QUIC_VERSION_8, QUIC_VERSION_7, QUIC_VERSION_6};
typedef std::vector<QuicVersion> QuicVersionVector;
@@ -424,7 +426,15 @@
enum QuicVersionNegotiationState {
START_NEGOTIATION = 0,
- SENT_NEGOTIATION_PACKET,
+ // Server-side this implies we've sent a version negotiation packet and are
+ // waiting on the client to select a compatible version. Client-side this
+ // implies we've gotten a version negotiation packet, are retransmitting the
+ // initial packets with a supported version and are waiting for our first
+ // packet from the server.
+ NEGOTIATION_IN_PROGRESS,
+ // This indicates this endpoint has received a packet from the peer with a
+ // version this endpoint supports. Version negotiation is complete, and the
+ // version number will no longer be sent with future packets.
NEGOTIATED_VERSION
};
diff --git a/net/quic/quic_protocol_test.cc b/net/quic/quic_protocol_test.cc
index 877f03d..b073d85 100644
--- a/net/quic/quic_protocol_test.cc
+++ b/net/quic/quic_protocol_test.cc
@@ -56,8 +56,8 @@
#endif
// Explicitly test a specific version.
- EXPECT_EQ(MakeQuicTag('Q', '0', '0', '6'),
- QuicVersionToQuicTag(QUIC_VERSION_6));
+ EXPECT_EQ(MakeQuicTag('Q', '0', '0', '7'),
+ QuicVersionToQuicTag(QUIC_VERSION_7));
// Loop over all supported versions and make sure that we never hit the
// default case (i.e. all supported versions should be successfully converted
@@ -95,8 +95,8 @@
#endif
// Explicitly test specific versions.
- EXPECT_EQ(QUIC_VERSION_6,
- QuicTagToQuicVersion(MakeQuicTag('Q', '0', '0', '6')));
+ EXPECT_EQ(QUIC_VERSION_7,
+ QuicTagToQuicVersion(MakeQuicTag('Q', '0', '0', '7')));
for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
const QuicVersion& version = kSupportedQuicVersions[i];
@@ -127,16 +127,16 @@
}
TEST(QuicProtocolTest, QuicVersionToString) {
- EXPECT_EQ("QUIC_VERSION_6",
- QuicVersionToString(QUIC_VERSION_6));
+ EXPECT_EQ("QUIC_VERSION_7",
+ QuicVersionToString(QUIC_VERSION_7));
EXPECT_EQ("QUIC_VERSION_UNSUPPORTED",
QuicVersionToString(QUIC_VERSION_UNSUPPORTED));
- QuicVersion single_version[] = {QUIC_VERSION_6};
- EXPECT_EQ("QUIC_VERSION_6,", QuicVersionArrayToString(single_version,
+ QuicVersion single_version[] = {QUIC_VERSION_7};
+ EXPECT_EQ("QUIC_VERSION_7,", QuicVersionArrayToString(single_version,
arraysize(single_version)));
- QuicVersion multiple_versions[] = {QUIC_VERSION_7, QUIC_VERSION_6};
- EXPECT_EQ("QUIC_VERSION_7,QUIC_VERSION_6,",
+ QuicVersion multiple_versions[] = {QUIC_VERSION_8, QUIC_VERSION_7};
+ EXPECT_EQ("QUIC_VERSION_8,QUIC_VERSION_7,",
QuicVersionArrayToString(multiple_versions,
arraysize(multiple_versions)));
}
diff --git a/net/quic/quic_received_packet_manager.cc b/net/quic/quic_received_packet_manager.cc
index 3ade8fb..9a136db 100644
--- a/net/quic/quic_received_packet_manager.cc
+++ b/net/quic/quic_received_packet_manager.cc
@@ -116,9 +116,7 @@
void QuicReceivedPacketManager::RecalculateEntropyHash(
QuicPacketSequenceNumber peer_least_unacked,
QuicPacketEntropyHash entropy_hash) {
- DLOG_IF(WARNING, peer_least_unacked > received_info_.largest_observed)
- << "Prematurely updating the entropy manager before registering the "
- << "entropy of the containing packet creates a temporary inconsistency.";
+ DCHECK_LE(peer_least_unacked, received_info_.largest_observed);
if (peer_least_unacked < largest_sequence_number_) {
DLOG(INFO) << "Ignoring received peer_least_unacked:" << peer_least_unacked
<< " less than largest_peer_sequence_number:"
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc
index 9fb44d4..a07f413 100644
--- a/net/quic/quic_session.cc
+++ b/net/quic/quic_session.cc
@@ -77,19 +77,20 @@
: connection_(connection),
visitor_shim_(new VisitorShim(this)),
config_(config),
- max_open_streams_(kDefaultMaxStreamsPerConnection),
+ max_open_streams_(config_.max_streams_per_connection()),
next_stream_id_(is_server ? 2 : 3),
is_server_(is_server),
largest_peer_created_stream_id_(0),
error_(QUIC_NO_ERROR),
goaway_received_(false),
goaway_sent_(false) {
- set_max_open_streams(config_.max_streams_per_connection());
connection_->set_visitor(visitor_shim_.get());
connection_->SetIdleNetworkTimeout(config_.idle_connection_state_lifetime());
- connection_->SetOverallConnectionTimeout(
- config_.max_time_before_crypto_handshake());
+ if (connection_->connected()) {
+ connection_->SetOverallConnectionTimeout(
+ config_.max_time_before_crypto_handshake());
+ }
// TODO(satyamshekhar): Set congestion control and ICSL also.
}
@@ -149,6 +150,7 @@
if (!stream) {
connection()->SendConnectionClose(
QUIC_STREAM_RST_BEFORE_HEADERS_DECOMPRESSED);
+ return false;
}
stream->OnDecompressorAvailable();
}
diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h
index 3f0f99f..9f7aceb 100644
--- a/net/quic/quic_session.h
+++ b/net/quic/quic_session.h
@@ -197,10 +197,6 @@
return max_open_streams_;
}
- void set_max_open_streams(size_t max_open_streams) {
- max_open_streams_ = max_open_streams;
- }
-
private:
friend class test::QuicSessionPeer;
friend class VisitorShim;
diff --git a/net/quic/test_tools/quic_connection_peer.cc b/net/quic/test_tools/quic_connection_peer.cc
index bb6b3fc..610c505 100644
--- a/net/quic/test_tools/quic_connection_peer.cc
+++ b/net/quic/test_tools/quic_connection_peer.cc
@@ -145,11 +145,37 @@
return connection->helper_.get();
}
+// static
+QuicFramer* QuicConnectionPeer::GetFramer(QuicConnection* connection) {
+ return &connection->framer_;
+}
+
QuicFecGroup* QuicConnectionPeer::GetFecGroup(QuicConnection* connection,
int fec_group) {
connection->last_header_.fec_group = fec_group;
return connection->GetFecGroup();
}
+// static
+QuicAlarm* QuicConnectionPeer::GetAckAlarm(QuicConnection* connection) {
+ return connection->ack_alarm_.get();
+}
+
+// static
+QuicAlarm* QuicConnectionPeer::GetRetransmissionAlarm(
+ QuicConnection* connection) {
+ return connection->retransmission_alarm_.get();
+}
+
+// static
+QuicAlarm* QuicConnectionPeer::GetSendAlarm(QuicConnection* connection) {
+ return connection->send_alarm_.get();
+}
+
+// static
+QuicAlarm* QuicConnectionPeer::GetTimeoutAlarm(QuicConnection* connection) {
+ return connection->timeout_alarm_.get();
+}
+
} // namespace test
} // namespace net
diff --git a/net/quic/test_tools/quic_connection_peer.h b/net/quic/test_tools/quic_connection_peer.h
index 7ce3c5b..4438353 100644
--- a/net/quic/test_tools/quic_connection_peer.h
+++ b/net/quic/test_tools/quic_connection_peer.h
@@ -14,6 +14,7 @@
struct QuicAckFrame;
struct QuicPacketHeader;
+class QuicAlarm;
class QuicConnection;
class QuicConnectionHelperInterface;
class QuicConnectionVisitorInterface;
@@ -84,9 +85,16 @@
static QuicConnectionHelperInterface* GetHelper(QuicConnection* connection);
+ static QuicFramer* GetFramer(QuicConnection* connection);
+
// Set last_header_->fec_group = fec_group and return connection->GetFecGroup
static QuicFecGroup* GetFecGroup(QuicConnection* connection, int fec_group);
+ static QuicAlarm* GetAckAlarm(QuicConnection* connection);
+ static QuicAlarm* GetRetransmissionAlarm(QuicConnection* connection);
+ static QuicAlarm* GetSendAlarm(QuicConnection* connection);
+ static QuicAlarm* GetTimeoutAlarm(QuicConnection* connection);
+
private:
DISALLOW_COPY_AND_ASSIGN(QuicConnectionPeer);
};
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index 5d1b3a0..810abdc 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -23,6 +23,20 @@
namespace net {
namespace test {
+namespace {
+
+// No-op alarm implementation used by MockHelper.
+class TestAlarm : public QuicAlarm {
+ public:
+ explicit TestAlarm(QuicAlarm::Delegate* delegate)
+ : QuicAlarm(delegate) {
+ }
+
+ virtual void SetImpl() OVERRIDE {}
+ virtual void CancelImpl() OVERRIDE {}
+};
+
+} // namespace
MockFramerVisitor::MockFramerVisitor() {
// By default, we want to accept packets.
@@ -181,6 +195,10 @@
return &random_generator_;
}
+QuicAlarm* MockHelper::CreateAlarm(QuicAlarm::Delegate* delegate) {
+ return new TestAlarm(delegate);
+}
+
void MockHelper::AdvanceTime(QuicTime::Delta delta) {
clock_.AdvanceTime(delta);
}
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index f6172c9..65fba73 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -206,13 +206,8 @@
int* error));
MOCK_METHOD0(IsWriteBlockedDataBuffered, bool());
MOCK_METHOD1(IsWriteBlocked, bool(int));
- MOCK_METHOD1(SetRetransmissionAlarm, void(QuicTime::Delta delay));
- MOCK_METHOD1(SetAckAlarm, void(QuicTime::Delta delay));
- MOCK_METHOD1(SetSendAlarm, void(QuicTime alarm_time));
- MOCK_METHOD1(SetTimeoutAlarm, void(QuicTime::Delta delay));
- MOCK_METHOD0(IsSendAlarmSet, bool());
- MOCK_METHOD0(UnregisterSendAlarmIfRegistered, void());
- MOCK_METHOD0(ClearAckAlarm, void());
+ virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate);
+
private:
MockClock clock_;
MockRandom random_generator_;
diff --git a/net/server/http_server.cc b/net/server/http_server.cc
index 4217aa0..373025c 100644
--- a/net/server/http_server.cc
+++ b/net/server/http_server.cc
@@ -12,6 +12,7 @@
#include "base/strings/stringprintf.h"
#include "base/sys_byteorder.h"
#include "build/build_config.h"
+#include "net/base/net_errors.h"
#include "net/server/http_connection.h"
#include "net/server/http_server_request_info.h"
#include "net/server/http_server_response_info.h"
@@ -24,7 +25,6 @@
HttpServer::Delegate* delegate)
: delegate_(delegate),
server_(factory.CreateAndListen(this)) {
- DCHECK(server_.get());
}
void HttpServer::AcceptWebSocket(
@@ -89,6 +89,8 @@
}
int HttpServer::GetLocalAddress(IPEndPoint* address) {
+ if (!server_)
+ return ERR_SOCKET_NOT_CONNECTED;
return server_->GetLocalAddress(address);
}
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index d1f2832..72154bb 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -1861,15 +1861,6 @@
net_error = ERR_SSL_PROTOCOL_ERROR;
}
- // Some broken SSL devices negotiate TLS 1.0 when sent a TLS 1.1 or 1.2
- // ClientHello, but then return a bad-record-MAC alert. See
- // crbug.com/260358. In order to make the fallback as minimal as possible,
- // this fallback is only triggered for >= TLS 1.1.
- if (net_error == ERR_SSL_BAD_RECORD_MAC_ALERT &&
- ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_1) {
- net_error = ERR_SSL_PROTOCOL_ERROR;
- }
-
// If not done, stay in this state
if (net_error == ERR_IO_PENDING) {
GotoState(STATE_HANDSHAKE);
diff --git a/net/third_party/nss/patches/alpn.patch b/net/third_party/nss/patches/alpn.patch
index f93c92a..ad21798 100644
--- a/net/third_party/nss/patches/alpn.patch
+++ b/net/third_party/nss/patches/alpn.patch
@@ -16,7 +16,7 @@
diff -pu a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c
--- a/nss/lib/ssl/ssl3ext.c 2013-07-31 14:10:00.342814862 -0700
+++ b/nss/lib/ssl/ssl3ext.c 2013-07-31 14:28:56.549496061 -0700
-@@ -52,8 +52,12 @@ static SECStatus ssl3_HandleRenegotiatio
+@@ -53,8 +53,12 @@ static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss,
PRUint16 ex_type, SECItem *data);
static SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss,
PRUint16 ex_type, SECItem *data);
@@ -29,30 +29,15 @@
static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes);
static PRInt32 ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append,
-@@ -246,14 +250,15 @@ static const ssl3HelloExtensionHandler c
- /* These two tables are used by the client, to handle server hello
- * extensions. */
- static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
-- { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
-+ { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
- /* TODO: add a handler for ssl_ec_point_formats_xtn */
-- { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
-- { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
-- { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
-- { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn },
-- { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
-- { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
-+ { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
-+ { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
-+ { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
-+ { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn },
-+ { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn },
-+ { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
-+ { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
- { -1, NULL }
- };
-
-@@ -270,17 +275,18 @@ static const ssl3HelloExtensionHandler s
+@@ -252,6 +256,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
+ { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
+ { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
+ { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
++ { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn },
+ { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn },
+ { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
+ { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
+@@ -271,18 +276,19 @@ static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = {
*/
static const
ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
@@ -71,16 +56,18 @@
- { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn },
- { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
- { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
+- { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
+ { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn },
+ { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn },
+ { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn },
+ { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn },
+ { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
+ { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
- { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
++ { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
/* any extra entries will appear as { 0, NULL } */
};
-@@ -605,6 +611,11 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSoc
+
+@@ -606,6 +612,11 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
PORT_Assert(!ss->firstHsDone);
@@ -92,7 +79,7 @@
rv = ssl3_ValidateNextProtoNego(data->data, data->len);
if (rv != SECSuccess)
return rv;
-@@ -638,6 +649,44 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSoc
+@@ -639,6 +650,44 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &result);
}
@@ -137,21 +124,15 @@
static PRInt32
ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, PRBool append,
PRUint32 maxBytes)
-@@ -664,6 +713,44 @@ ssl3_ClientSendNextProtoNegoXtn(sslSocke
- } else if (maxBytes < extension_length) {
- return 0;
- }
-+
-+ return extension_length;
-+
-+loser:
-+ return -1;
-+}
-+
+@@ -672,6 +721,70 @@ loser:
+ return -1;
+ }
+
+static PRInt32
+ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
+{
+ PRInt32 extension_length;
++ unsigned char *alpn_protos = NULL;
+
+ /* Renegotiations do not send this extension. */
+ if (!ss->opt.nextProtoNego.data || ss->firstHsDone) {
@@ -163,15 +144,38 @@
+ ss->opt.nextProtoNego.len;
+
+ if (append && maxBytes >= extension_length) {
++ /* NPN requires that the client's fallback protocol is first in the
++ * list. However, ALPN sends protocols in preference order. So we
++ * allocate a buffer and move the first protocol to the end of the
++ * list. */
+ SECStatus rv;
++ const unsigned int len = ss->opt.nextProtoNego.len;
++
++ alpn_protos = PORT_Alloc(len);
++ if (alpn_protos == NULL) {
++ return SECFailure;
++ }
++ if (len > 0) {
++ /* Each protocol string is prefixed with a single byte length. */
++ unsigned int i = ss->opt.nextProtoNego.data[0] + 1;
++ if (i <= len) {
++ memcpy(alpn_protos, &ss->opt.nextProtoNego.data[i], len - i);
++ memcpy(alpn_protos + len - i, ss->opt.nextProtoNego.data, i);
++ } else {
++ /* This seems to be invalid data so we'll send as-is. */
++ memcpy(alpn_protos, ss->opt.nextProtoNego.data, len);
++ }
++ }
++
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
+ if (rv != SECSuccess)
+ goto loser;
-+ rv = ssl3_AppendHandshakeVariable(ss, ss->opt.nextProtoNego.data,
-+ ss->opt.nextProtoNego.len, 2);
++ rv = ssl3_AppendHandshakeVariable(ss, alpn_protos, len, 2);
++ PORT_Free(alpn_protos);
++ alpn_protos = NULL;
+ if (rv != SECSuccess)
+ goto loser;
+ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
@@ -179,13 +183,22 @@
+ } else if (maxBytes < extension_length) {
+ return 0;
+ }
-
- return extension_length;
-
++
++ return extension_length;
++
++loser:
++ if (alpn_protos)
++ PORT_Free(alpn_protos);
++ return -1;
++}
++
+ static SECStatus
+ ssl3_ClientHandleChannelIDXtn(sslSocket *ss, PRUint16 ex_type,
+ SECItem *data)
diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h
--- a/nss/lib/ssl/ssl.h 2013-07-31 14:10:35.113325316 -0700
+++ b/nss/lib/ssl/ssl.h 2013-07-31 14:28:56.589496647 -0700
-@@ -203,6 +203,11 @@ SSL_IMPORT SECStatus SSL_SetNextProtoCal
+@@ -203,6 +203,16 @@ SSL_IMPORT SECStatus SSL_SetNextProtoCal
* protocol in server-preference order. If no matching protocol is found it
* selects the first supported protocol.
*
@@ -194,6 +207,11 @@
+ * uses ALPN to select a protocol, SSL_GetNextProto will return
+ * SSL_NEXT_PROTO_SELECTED as the state.
+ *
++ * Since NPN uses the first protocol as the fallback protocol, when sending an
++ * ALPN extension, the first protocol is moved to the end of the list. This
++ * indicates that the fallback protocol is the least preferred. The other
++ * protocols should be in preference order.
++ *
* The supported protocols are specified in |data| in wire-format (8-bit
* length-prefixed). For example: "\010http/1.1\006spdy/2". */
SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd,
diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h
index 7194257..c083a6b 100644
--- a/net/third_party/nss/ssl/ssl.h
+++ b/net/third_party/nss/ssl/ssl.h
@@ -208,6 +208,11 @@
* uses ALPN to select a protocol, SSL_GetNextProto will return
* SSL_NEXT_PROTO_SELECTED as the state.
*
+ * Since NPN uses the first protocol as the fallback protocol, when sending an
+ * ALPN extension, the first protocol is moved to the end of the list. This
+ * indicates that the fallback protocol is the least preferred. The other
+ * protocols should be in preference order.
+ *
* The supported protocols are specified in |data| in wire-format (8-bit
* length-prefixed). For example: "\010http/1.1\006spdy/2". */
SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd,
diff --git a/net/third_party/nss/ssl/ssl3ext.c b/net/third_party/nss/ssl/ssl3ext.c
index 46e31c3..0415770 100644
--- a/net/third_party/nss/ssl/ssl3ext.c
+++ b/net/third_party/nss/ssl/ssl3ext.c
@@ -724,6 +724,7 @@
ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
{
PRInt32 extension_length;
+ unsigned char *alpn_protos = NULL;
/* Renegotiations do not send this extension. */
if (!ss->opt.nextProtoNego.data || ss->firstHsDone) {
@@ -735,15 +736,38 @@
ss->opt.nextProtoNego.len;
if (append && maxBytes >= extension_length) {
+ /* NPN requires that the client's fallback protocol is first in the
+ * list. However, ALPN sends protocols in preference order. So we
+ * allocate a buffer and move the first protocol to the end of the
+ * list. */
SECStatus rv;
+ const unsigned int len = ss->opt.nextProtoNego.len;
+
+ alpn_protos = PORT_Alloc(len);
+ if (alpn_protos == NULL) {
+ return SECFailure;
+ }
+ if (len > 0) {
+ /* Each protocol string is prefixed with a single byte length. */
+ unsigned int i = ss->opt.nextProtoNego.data[0] + 1;
+ if (i <= len) {
+ memcpy(alpn_protos, &ss->opt.nextProtoNego.data[i], len - i);
+ memcpy(alpn_protos + len - i, ss->opt.nextProtoNego.data, i);
+ } else {
+ /* This seems to be invalid data so we'll send as-is. */
+ memcpy(alpn_protos, ss->opt.nextProtoNego.data, len);
+ }
+ }
+
rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2);
if (rv != SECSuccess)
goto loser;
rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
if (rv != SECSuccess)
goto loser;
- rv = ssl3_AppendHandshakeVariable(ss, ss->opt.nextProtoNego.data,
- ss->opt.nextProtoNego.len, 2);
+ rv = ssl3_AppendHandshakeVariable(ss, alpn_protos, len, 2);
+ PORT_Free(alpn_protos);
+ alpn_protos = NULL;
if (rv != SECSuccess)
goto loser;
ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
@@ -755,6 +779,8 @@
return extension_length;
loser:
+ if (alpn_protos)
+ PORT_Free(alpn_protos);
return -1;
}
diff --git a/net/tools/flip_server/balsa_frame_test.cc b/net/tools/flip_server/balsa_frame_test.cc
new file mode 100644
index 0000000..3bb9a42
--- /dev/null
+++ b/net/tools/flip_server/balsa_frame_test.cc
@@ -0,0 +1,599 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/tools/flip_server/balsa_frame.h"
+
+#include <iterator>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_piece.h"
+#include "net/tools/flip_server/balsa_enums.h"
+#include "net/tools/flip_server/balsa_headers.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+using ::base::StringPiece;
+using ::testing::_;
+using ::testing::InSequence;
+using ::testing::SaveArg;
+
+class Visitor : public BalsaVisitorInterface {
+ public:
+ virtual ~Visitor() {}
+ MOCK_METHOD2(ProcessBodyInput, void(const char*, size_t));
+ MOCK_METHOD2(ProcessBodyData, void(const char*, size_t));
+ MOCK_METHOD2(ProcessHeaderInput, void(const char*, size_t));
+ MOCK_METHOD2(ProcessTrailerInput, void(const char*, size_t));
+ MOCK_METHOD1(ProcessHeaders, void(const BalsaHeaders&));
+ MOCK_METHOD8(ProcessRequestFirstLine, void(const char*,
+ size_t,
+ const char*,
+ size_t,
+ const char*,
+ size_t,
+ const char*,
+ size_t));
+ MOCK_METHOD8(ProcessResponseFirstLine, void(const char*,
+ size_t,
+ const char*,
+ size_t,
+ const char*,
+ size_t,
+ const char*,
+ size_t));
+ MOCK_METHOD2(ProcessChunkExtensions, void(const char*, size_t));
+ MOCK_METHOD1(ProcessChunkLength, void(size_t));
+ MOCK_METHOD0(HeaderDone, void());
+ MOCK_METHOD0(MessageDone, void());
+ MOCK_METHOD1(HandleHeaderError, void(BalsaFrame*));
+ MOCK_METHOD1(HandleHeaderWarning, void(BalsaFrame*));
+ MOCK_METHOD1(HandleChunkingError, void(BalsaFrame*));
+ MOCK_METHOD1(HandleBodyError, void(BalsaFrame*));
+};
+
+class BalsaFrameTest : public ::testing::Test {
+ public:
+ virtual void SetUp() OVERRIDE {
+ frame_.reset(new BalsaFrame);
+ frame_headers_.reset(new BalsaHeaders);
+ visitor_.reset(new Visitor);
+ frame_->set_balsa_visitor(visitor_.get());
+ };
+
+ protected:
+ scoped_ptr<BalsaFrame> frame_;
+ scoped_ptr<BalsaHeaders> frame_headers_;
+ scoped_ptr<Visitor> visitor_;
+};
+
+TEST_F(BalsaFrameTest, EmptyFrame) {
+ ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE,
+ frame_->ParseState());
+ ASSERT_FALSE(frame_->MessageFullyRead());
+ ASSERT_FALSE(frame_->Error());
+ ASSERT_EQ(NULL, frame_->const_balsa_headers());
+ ASSERT_EQ(NULL, frame_->balsa_headers());
+ ASSERT_EQ(NULL, frame_->headers());
+ ASSERT_EQ(NULL, frame_->mutable_headers());
+ ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+ ASSERT_TRUE(frame_->is_request());
+ ASSERT_FALSE(frame_->request_was_head());
+}
+
+TEST_F(BalsaFrameTest, EmptyRequest) {
+ const char input[] = "\r\n";
+ frame_->set_balsa_headers(frame_headers_.get());
+
+ {
+ InSequence s;
+ // No visitor callback should be called.
+ }
+ size_t read = frame_->ProcessInput(input, strlen(input));
+ EXPECT_EQ(2u, read);
+ ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE,
+ frame_->ParseState());
+ ASSERT_FALSE(frame_->Error());
+ ASSERT_EQ(BalsaFrameEnums::NO_ERROR, frame_->ErrorCode());
+ ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+}
+
+TEST_F(BalsaFrameTest, GetRequest) {
+ const char input[] = "GET / HTTP/1.0\r\nkey1: value1\r\n\r\n";
+ const char* line = NULL;
+ size_t line_length = 0;
+ const char* method = NULL;
+ size_t method_length = 0;
+ const char* request_uri = NULL;
+ size_t request_uri_length = 0;
+ const char* version = NULL;
+ size_t version_length = 0;
+ const char* header = NULL;
+ size_t header_length = 0;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*visitor_, ProcessRequestFirstLine(_, _, _, _, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<0>(&line),
+ SaveArg<1>(&line_length),
+ SaveArg<2>(&method),
+ SaveArg<3>(&method_length),
+ SaveArg<4>(&request_uri),
+ SaveArg<5>(&request_uri_length),
+ SaveArg<6>(&version),
+ SaveArg<7>(&version_length)));
+ EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&header), SaveArg<1>(&header_length)));
+ EXPECT_CALL(*visitor_, ProcessHeaders(_));
+ EXPECT_CALL(*visitor_, HeaderDone());
+ EXPECT_CALL(*visitor_, MessageDone());
+ }
+
+ frame_->set_balsa_headers(frame_headers_.get());
+ ASSERT_EQ(frame_headers_.get(), frame_->const_balsa_headers());
+ ASSERT_EQ(frame_headers_.get(), frame_->balsa_headers());
+ ASSERT_EQ(frame_headers_.get(), frame_->headers());
+ ASSERT_EQ(frame_headers_.get(), frame_->mutable_headers());
+
+ size_t read = frame_->ProcessInput(input, strlen(input));
+ ASSERT_EQ(strlen(input), read);
+ ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState());
+ ASSERT_TRUE(frame_->MessageFullyRead());
+ ASSERT_FALSE(frame_->Error());
+ ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+ ASSERT_EQ("GET / HTTP/1.0", StringPiece(line, line_length));
+ ASSERT_EQ("GET", StringPiece(method, method_length));
+ ASSERT_EQ("/", StringPiece(request_uri, request_uri_length));
+ ASSERT_EQ("HTTP/1.0", StringPiece(version, version_length));
+ ASSERT_EQ(input, StringPiece(header, header_length));
+}
+
+TEST_F(BalsaFrameTest, HeadResponse) {
+ const char input[] = "HTTP/1.1 200 OK\r\n"
+ "Content-type: text/plain\r\n"
+ "Content-Length: 14\r\n\r\n";
+ const char* line = NULL;
+ size_t line_length = 0;
+ const char* version = NULL;
+ size_t version_length = 0;
+ const char* status = NULL;
+ size_t status_length = 0;
+ const char* reason = NULL;
+ size_t reason_length = 0;
+ const char* header = NULL;
+ size_t header_length = 0;
+
+ frame_->set_balsa_headers(frame_headers_.get());
+ frame_->set_is_request(false);
+ frame_->set_request_was_head(true);
+
+ {
+ InSequence s;
+ EXPECT_CALL(*visitor_, ProcessResponseFirstLine(_, _, _, _, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<0>(&line),
+ SaveArg<1>(&line_length),
+ SaveArg<2>(&version),
+ SaveArg<3>(&version_length),
+ SaveArg<4>(&status),
+ SaveArg<5>(&status_length),
+ SaveArg<6>(&reason),
+ SaveArg<7>(&reason_length)));
+ EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&header), SaveArg<1>(&header_length)));
+ EXPECT_CALL(*visitor_, ProcessHeaders(_));
+ EXPECT_CALL(*visitor_, HeaderDone());
+ EXPECT_CALL(*visitor_, MessageDone());
+ }
+
+ size_t read = frame_->ProcessInput(input, strlen(input));
+ ASSERT_EQ(strlen(input), read);
+ ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState());
+ ASSERT_TRUE(frame_->MessageFullyRead());
+ ASSERT_FALSE(frame_->Error());
+ ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+
+ ASSERT_EQ("HTTP/1.1 200 OK", StringPiece(line, line_length));
+ ASSERT_EQ("HTTP/1.1", StringPiece(version, version_length));
+ ASSERT_EQ("200", StringPiece(status, status_length));
+ ASSERT_EQ("OK", StringPiece(reason, reason_length));
+ ASSERT_EQ("HTTP/1.1 200 OK\r\n"
+ "Content-type: text/plain\r\n"
+ "Content-Length: 14\r\n\r\n",
+ StringPiece(header, header_length));
+}
+
+TEST_F(BalsaFrameTest, GetResponse) {
+ const char input[] = "HTTP/1.1 200 OK\r\n"
+ "Content-type: text/plain\r\n"
+ "Content-Length: 14\r\n\r\n"
+ "hello, world\r\n";
+ const char* line = NULL;
+ size_t line_length = 0;
+ const char* version = NULL;
+ size_t version_length = 0;
+ const char* status = NULL;
+ size_t status_length = 0;
+ const char* reason = NULL;
+ size_t reason_length = 0;
+ const char* header = NULL;
+ size_t header_length = 0;
+ const char* body = NULL;
+ size_t body_length = 0;
+ const char* body_data = NULL;
+ size_t body_data_length = 0;
+ testing::MockFunction<void(int)> checkpoint;
+
+ frame_->set_balsa_headers(frame_headers_.get());
+ frame_->set_is_request(false);
+
+ {
+ InSequence s;
+ EXPECT_CALL(*visitor_, ProcessResponseFirstLine(_, _, _, _, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<0>(&line),
+ SaveArg<1>(&line_length),
+ SaveArg<2>(&version),
+ SaveArg<3>(&version_length),
+ SaveArg<4>(&status),
+ SaveArg<5>(&status_length),
+ SaveArg<6>(&reason),
+ SaveArg<7>(&reason_length)));
+ EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&header), SaveArg<1>(&header_length)));
+ EXPECT_CALL(*visitor_, ProcessHeaders(_));
+ EXPECT_CALL(*visitor_, HeaderDone());
+ EXPECT_CALL(checkpoint, Call(0));
+ EXPECT_CALL(*visitor_, ProcessBodyInput(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&body), SaveArg<1>(&body_length)));
+ EXPECT_CALL(*visitor_, ProcessBodyData(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&body_data), SaveArg<1>(&body_data_length)));
+ EXPECT_CALL(*visitor_, MessageDone());
+ }
+
+ size_t read = frame_->ProcessInput(input, strlen(input));
+ ASSERT_EQ(65u, read);
+ ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+ checkpoint.Call(0);
+ read += frame_->ProcessInput(&input[read], strlen(input) - read);
+ ASSERT_EQ(strlen(input), read);
+ ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState());
+ ASSERT_TRUE(frame_->MessageFullyRead());
+ ASSERT_FALSE(frame_->Error());
+ ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+
+ ASSERT_EQ("HTTP/1.1 200 OK", StringPiece(line, line_length));
+ ASSERT_EQ("HTTP/1.1", StringPiece(version, version_length));
+ ASSERT_EQ("200", StringPiece(status, status_length));
+ ASSERT_EQ("OK", StringPiece(reason, reason_length));
+ ASSERT_EQ("HTTP/1.1 200 OK\r\n"
+ "Content-type: text/plain\r\n"
+ "Content-Length: 14\r\n\r\n",
+ StringPiece(header, header_length));
+ ASSERT_EQ("hello, world\r\n", StringPiece(body, body_length));
+ ASSERT_EQ("hello, world\r\n", StringPiece(body_data, body_data_length));
+}
+
+TEST_F(BalsaFrameTest, Reset) {
+ const char input[] = "GET / HTTP/1.0\r\nkey1: value1\r\n\r\n";
+
+ {
+ InSequence s;
+ EXPECT_CALL(*visitor_, ProcessRequestFirstLine(_, _, _, _, _, _, _, _));
+ EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _));
+ EXPECT_CALL(*visitor_, ProcessHeaders(_));
+ EXPECT_CALL(*visitor_, HeaderDone());
+ EXPECT_CALL(*visitor_, MessageDone());
+ }
+
+ frame_->set_balsa_headers(frame_headers_.get());
+
+ size_t read = frame_->ProcessInput(input, strlen(input));
+ ASSERT_EQ(strlen(input), read);
+ ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState());
+ ASSERT_TRUE(frame_->MessageFullyRead());
+ ASSERT_FALSE(frame_->Error());
+
+ frame_->Reset();
+ ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE,
+ frame_->ParseState());
+ ASSERT_FALSE(frame_->MessageFullyRead());
+ ASSERT_FALSE(frame_->Error());
+}
+
+TEST_F(BalsaFrameTest, InvalidStatusCode) {
+ const char input[] = "HTTP/1.1 InvalidStatusCode OK\r\n"
+ "Content-type: text/plain\r\n"
+ "Content-Length: 14\r\n\r\n"
+ "hello, world\r\n";
+
+ frame_->set_balsa_headers(frame_headers_.get());
+ frame_->set_is_request(false);
+
+ {
+ InSequence s;
+ EXPECT_CALL(*visitor_, HandleHeaderError(frame_.get()));
+ }
+
+ size_t read = frame_->ProcessInput(input, strlen(input));
+ ASSERT_EQ(30u, read);
+ ASSERT_EQ(BalsaFrameEnums::PARSE_ERROR, frame_->ParseState());
+ ASSERT_EQ(BalsaFrameEnums::FAILED_CONVERTING_STATUS_CODE_TO_INT,
+ frame_->ErrorCode());
+ ASSERT_FALSE(frame_->MessageFullyRead());
+ ASSERT_TRUE(frame_->Error());
+ ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+}
+
+TEST_F(BalsaFrameTest, ResetError) {
+ const char input[] = "HTTP/1.1 InvalidStatusCode OK\r\n"
+ "Content-type: text/plain\r\n"
+ "Content-Length: 14\r\n\r\n"
+ "hello, world\r\n";
+
+ frame_->set_balsa_headers(frame_headers_.get());
+ frame_->set_is_request(false);
+
+ {
+ InSequence s;
+ EXPECT_CALL(*visitor_, HandleHeaderError(frame_.get()));
+ }
+
+ size_t read = frame_->ProcessInput(input, strlen(input));
+ ASSERT_EQ(30u, read);
+ ASSERT_EQ(BalsaFrameEnums::PARSE_ERROR, frame_->ParseState());
+ ASSERT_EQ(BalsaFrameEnums::FAILED_CONVERTING_STATUS_CODE_TO_INT,
+ frame_->ErrorCode());
+ ASSERT_FALSE(frame_->MessageFullyRead());
+ ASSERT_TRUE(frame_->Error());
+ ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+
+ frame_->Reset();
+ ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE,
+ frame_->ParseState());
+ ASSERT_FALSE(frame_->MessageFullyRead());
+ ASSERT_FALSE(frame_->Error());
+}
+
+TEST_F(BalsaFrameTest, RequestURITooLong) {
+ const char input[] = "GET / HTTP/1.0\r\n\r\n";
+
+ frame_->set_balsa_headers(frame_headers_.get());
+ frame_->set_max_request_uri_length(0);
+
+ {
+ InSequence s;
+ EXPECT_CALL(*visitor_, HandleHeaderError(frame_.get()));
+ }
+
+ size_t read = frame_->ProcessInput(input, strlen(input));
+ ASSERT_EQ(15u, read);
+ ASSERT_EQ(BalsaFrameEnums::PARSE_ERROR, frame_->ParseState());
+ ASSERT_EQ(BalsaFrameEnums::REQUEST_URI_TOO_LONG, frame_->ErrorCode());
+ ASSERT_FALSE(frame_->MessageFullyRead());
+ ASSERT_TRUE(frame_->Error());
+ ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+}
+
+TEST_F(BalsaFrameTest, HeadersTooLong) {
+ const char input[] = "GET / HTTP/1.0\r\n\r\n";
+
+ frame_->set_balsa_headers(frame_headers_.get());
+ frame_->set_max_header_length(0);
+
+ {
+ InSequence s;
+ EXPECT_CALL(*visitor_, HandleHeaderError(frame_.get()));
+ }
+
+ size_t read = frame_->ProcessInput(input, strlen(input));
+ ASSERT_EQ(0u, read);
+ ASSERT_EQ(BalsaFrameEnums::PARSE_ERROR, frame_->ParseState());
+ ASSERT_EQ(BalsaFrameEnums::HEADERS_TOO_LONG, frame_->ErrorCode());
+ ASSERT_FALSE(frame_->MessageFullyRead());
+ ASSERT_TRUE(frame_->Error());
+ ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+}
+
+TEST_F(BalsaFrameTest, InvalidHeader) {
+ const char input[] = "GET / HTTP/1.0\r\n"
+ "foo bar baz\r\n"
+ "Content-Type: text/plain\r\n\r\n";
+ const char* line = NULL;
+ size_t line_length = 0;
+ const char* method = NULL;
+ size_t method_length = 0;
+ const char* request_uri = NULL;
+ size_t request_uri_length = 0;
+ const char* version = NULL;
+ size_t version_length = 0;
+
+ frame_->set_balsa_headers(frame_headers_.get());
+
+ {
+ InSequence s;
+ EXPECT_CALL(*visitor_, ProcessRequestFirstLine(_, _, _, _, _, _, _, _))
+ .WillOnce(DoAll(SaveArg<0>(&line),
+ SaveArg<1>(&line_length),
+ SaveArg<2>(&method),
+ SaveArg<3>(&method_length),
+ SaveArg<4>(&request_uri),
+ SaveArg<5>(&request_uri_length),
+ SaveArg<6>(&version),
+ SaveArg<7>(&version_length)));
+ EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _));
+ EXPECT_CALL(*visitor_, HandleHeaderWarning(frame_.get()));
+ EXPECT_CALL(*visitor_, ProcessHeaders(_));
+ EXPECT_CALL(*visitor_, HeaderDone());
+ EXPECT_CALL(*visitor_, MessageDone());
+ }
+
+ size_t read = frame_->ProcessInput(input, strlen(input));
+ ASSERT_EQ(strlen(input), read);
+ ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState());
+ ASSERT_EQ(BalsaFrameEnums::HEADER_MISSING_COLON, frame_->ErrorCode());
+ ASSERT_TRUE(frame_->MessageFullyRead());
+ ASSERT_FALSE(frame_->Error());
+ ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+ ASSERT_EQ("GET / HTTP/1.0", StringPiece(line, line_length));
+ ASSERT_EQ("GET", StringPiece(method, method_length));
+ ASSERT_EQ("/", StringPiece(request_uri, request_uri_length));
+ ASSERT_EQ("HTTP/1.0", StringPiece(version, version_length));
+ ASSERT_EQ(2, std::distance(frame_headers_->header_lines_begin(),
+ frame_headers_->header_lines_end()));
+}
+
+TEST_F(BalsaFrameTest, GetResponseSplit) {
+ const char input[] = "HTTP/1.1 200 OK\r\n"
+ "Content-type: text/plain\r\n"
+ "Content-Length: 14\r\n\r\n"
+ "hello";
+ const char input2[] = ", world\r\n";
+ const char* body1 = NULL;
+ size_t body1_length = 0;
+ const char* body1_data = NULL;
+ size_t body1_data_length = 0;
+ const char* body2 = NULL;
+ size_t body2_length = 0;
+ const char* body2_data = NULL;
+ size_t body2_data_length = 0;
+ testing::MockFunction<void(int)> checkpoint;
+
+ frame_->set_balsa_headers(frame_headers_.get());
+ frame_->set_is_request(false);
+
+ {
+ InSequence s;
+ EXPECT_CALL(*visitor_, ProcessResponseFirstLine(_, _, _, _, _, _, _, _));
+ EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _));
+ EXPECT_CALL(*visitor_, ProcessHeaders(_));
+ EXPECT_CALL(*visitor_, HeaderDone());
+ EXPECT_CALL(checkpoint, Call(0));
+ EXPECT_CALL(*visitor_, ProcessBodyInput(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&body1), SaveArg<1>(&body1_length)));
+ EXPECT_CALL(*visitor_, ProcessBodyData(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&body1_data),
+ SaveArg<1>(&body1_data_length)));
+ EXPECT_CALL(checkpoint, Call(1));
+ EXPECT_CALL(*visitor_, ProcessBodyInput(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&body2), SaveArg<1>(&body2_length)));
+ EXPECT_CALL(*visitor_, ProcessBodyData(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&body2_data),
+ SaveArg<1>(&body2_data_length)));
+ EXPECT_CALL(*visitor_, MessageDone());
+ }
+
+ size_t read = frame_->ProcessInput(input, strlen(input));
+ ASSERT_EQ(65u, read);
+ ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+ checkpoint.Call(0);
+ read += frame_->ProcessInput(&input[read], strlen(input) - read);
+ ASSERT_EQ(strlen(input), read);
+ ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+ checkpoint.Call(1);
+ ASSERT_EQ(9u, frame_->BytesSafeToSplice());
+ read = frame_->ProcessInput(input2, strlen(input2));
+ ASSERT_EQ(strlen(input2), read);
+
+ ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState());
+ ASSERT_TRUE(frame_->MessageFullyRead());
+ ASSERT_FALSE(frame_->Error());
+ ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+ ASSERT_EQ("hello", StringPiece(body1, body1_length));
+ ASSERT_EQ("hello", StringPiece(body1_data, body1_data_length));
+ ASSERT_EQ(", world\r\n", StringPiece(body2, body2_length));
+ ASSERT_EQ(", world\r\n", StringPiece(body2_data, body2_data_length));
+}
+
+TEST_F(BalsaFrameTest, GetResponseBytesSpliced) {
+ const char input[] = "HTTP/1.1 200 OK\r\n"
+ "Content-type: text/plain\r\n"
+ "Content-Length: 14\r\n\r\n"
+ "hello";
+ testing::MockFunction<void(int)> checkpoint;
+
+ frame_->set_balsa_headers(frame_headers_.get());
+ frame_->set_is_request(false);
+
+ {
+ InSequence s;
+ EXPECT_CALL(*visitor_, ProcessResponseFirstLine(_, _, _, _, _, _, _, _));
+ EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _));
+ EXPECT_CALL(*visitor_, ProcessHeaders(_));
+ EXPECT_CALL(*visitor_, HeaderDone());
+ EXPECT_CALL(checkpoint, Call(0));
+ EXPECT_CALL(*visitor_, ProcessBodyInput(_, _));
+ EXPECT_CALL(*visitor_, ProcessBodyData(_, _));
+ EXPECT_CALL(checkpoint, Call(1));
+ EXPECT_CALL(checkpoint, Call(2));
+ EXPECT_CALL(*visitor_, MessageDone());
+ }
+
+ size_t read = frame_->ProcessInput(input, strlen(input));
+ ASSERT_EQ(65u, read);
+ ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+ checkpoint.Call(0);
+ read += frame_->ProcessInput(&input[read], strlen(input) - read);
+ ASSERT_EQ(strlen(input), read);
+ ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+ ASSERT_EQ(9u, frame_->BytesSafeToSplice());
+ checkpoint.Call(1);
+ frame_->BytesSpliced(5);
+ ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+ ASSERT_EQ(4u, frame_->BytesSafeToSplice());
+ checkpoint.Call(2);
+ frame_->BytesSpliced(4);
+ ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, frame_->ParseState());
+
+ ASSERT_TRUE(frame_->MessageFullyRead());
+ ASSERT_FALSE(frame_->Error());
+ ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+}
+
+TEST_F(BalsaFrameTest, GetResponseBytesSplicedTooMany) {
+ const char input[] = "HTTP/1.1 200 OK\r\n"
+ "Content-type: text/plain\r\n"
+ "Content-Length: 14\r\n\r\n"
+ "hello";
+ testing::MockFunction<void(int)> checkpoint;
+
+ frame_->set_balsa_headers(frame_headers_.get());
+ frame_->set_is_request(false);
+
+ {
+ InSequence s;
+ EXPECT_CALL(*visitor_, ProcessResponseFirstLine(_, _, _, _, _, _, _, _));
+ EXPECT_CALL(*visitor_, ProcessHeaderInput(_, _));
+ EXPECT_CALL(*visitor_, ProcessHeaders(_));
+ EXPECT_CALL(*visitor_, HeaderDone());
+ EXPECT_CALL(checkpoint, Call(0));
+ EXPECT_CALL(*visitor_, ProcessBodyInput(_, _));
+ EXPECT_CALL(*visitor_, ProcessBodyData(_, _));
+ EXPECT_CALL(checkpoint, Call(1));
+ EXPECT_CALL(*visitor_, HandleBodyError(frame_.get()));
+ }
+
+ size_t read = frame_->ProcessInput(input, strlen(input));
+ ASSERT_EQ(65u, read);
+ ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+ checkpoint.Call(0);
+ read += frame_->ProcessInput(&input[read], strlen(input) - read);
+ ASSERT_EQ(strlen(input), read);
+ ASSERT_EQ(BalsaFrameEnums::READING_CONTENT, frame_->ParseState());
+ ASSERT_EQ(9u, frame_->BytesSafeToSplice());
+ checkpoint.Call(1);
+ frame_->BytesSpliced(99);
+ ASSERT_EQ(BalsaFrameEnums::PARSE_ERROR, frame_->ParseState());
+ ASSERT_FALSE(frame_->MessageFullyRead());
+ ASSERT_TRUE(frame_->Error());
+ ASSERT_EQ(
+ BalsaFrameEnums::CALLED_BYTES_SPLICED_AND_EXCEEDED_SAFE_SPLICE_AMOUNT,
+ frame_->ErrorCode());
+ ASSERT_EQ(0u, frame_->BytesSafeToSplice());
+}
+
+} // namespace
+
+} // namespace net
diff --git a/net/tools/flip_server/balsa_headers.h b/net/tools/flip_server/balsa_headers.h
index 6fabdd4..2c8b083 100644
--- a/net/tools/flip_server/balsa_headers.h
+++ b/net/tools/flip_server/balsa_headers.h
@@ -64,6 +64,7 @@
// BalsaHeaders implementation, yet be testable.
friend class BalsaBufferTestSpouse;
friend class BalsaHeaders;
+ friend class BalsaBufferTest;
// The BufferBlock is a structure used internally by the
// BalsaBuffer class to store the base buffer pointers to
diff --git a/net/tools/flip_server/balsa_headers_test.cc b/net/tools/flip_server/balsa_headers_test.cc
new file mode 100644
index 0000000..241fee1
--- /dev/null
+++ b/net/tools/flip_server/balsa_headers_test.cc
@@ -0,0 +1,392 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/tools/flip_server/balsa_headers.h"
+
+#include <iterator>
+#include <string>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_piece.h"
+#include "net/tools/flip_server/balsa_enums.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+using ::base::StringPiece;
+
+class BalsaBufferTest : public ::testing::Test {
+ public:
+ virtual void SetUp() OVERRIDE {
+ buffer_.reset(new BalsaBuffer);
+ anotherBuffer_.reset(new BalsaBuffer);
+ }
+
+ protected:
+ scoped_ptr<BalsaBuffer> buffer_;
+ scoped_ptr<BalsaBuffer> anotherBuffer_;
+};
+
+namespace {
+
+class BalsaHeadersTest: public ::testing::Test {
+ public:
+ virtual void SetUp() OVERRIDE {
+ headers_.reset(new BalsaHeaders);
+ }
+
+ protected:
+ scoped_ptr<BalsaHeaders> headers_;
+};
+
+class StringBuffer {
+ public:
+ void Write(const char* p, size_t size) {
+ string_ += std::string(p, size);
+ }
+ const std::string& string() {return string_;}
+
+ private:
+ std::string string_;
+};
+
+TEST_F(BalsaBufferTest, EmptyBuffer) {
+ ASSERT_EQ(1u, buffer_->num_blocks());
+}
+
+TEST_F(BalsaBufferTest, Write) {
+ size_t index1, index2;
+ StringPiece sp1 = buffer_->Write(StringPiece("hello"), &index1);
+ StringPiece sp2 = buffer_->Write(StringPiece(", world"), &index2);
+
+ ASSERT_EQ(2u, buffer_->num_blocks());
+ ASSERT_EQ("hello", sp1);
+ ASSERT_EQ(", world", sp2);
+ ASSERT_EQ(1u, index1);
+ ASSERT_EQ(1u, index2);
+ ASSERT_EQ("hello, world",
+ StringPiece(buffer_->GetPtr(1), buffer_->bytes_used(1)));
+}
+
+TEST_F(BalsaBufferTest, WriteLongData) {
+ size_t index1, index2, index3;
+ std::string as(2, 'a');
+ std::string bs(BalsaBuffer::kDefaultBlocksize + 1, 'b');
+ std::string cs(4, 'c');
+
+ StringPiece sp1 = buffer_->Write(as, &index1);
+ StringPiece sp2 = buffer_->Write(bs, &index2);
+ StringPiece sp3 = buffer_->Write(cs, &index3);
+
+ ASSERT_EQ(3u, buffer_->num_blocks());
+ ASSERT_EQ(as, sp1);
+ ASSERT_EQ(bs, sp2);
+ ASSERT_EQ(cs, sp3);
+ ASSERT_EQ(1u, index1);
+ ASSERT_EQ(2u, index2);
+ ASSERT_EQ(1u, index3);
+ ASSERT_EQ("aacccc", StringPiece(buffer_->GetPtr(1), buffer_->bytes_used(1)));
+ ASSERT_EQ(sp2, StringPiece(buffer_->GetPtr(2), buffer_->bytes_used(2)));
+}
+
+TEST_F(BalsaBufferTest, WriteToContiguousBuffer) {
+ std::string as(2, 'a');
+ std::string bs(BalsaBuffer::kDefaultBlocksize + 1, 'b');
+ std::string cs(4, 'c');
+
+ buffer_->WriteToContiguousBuffer(as);
+ buffer_->WriteToContiguousBuffer(bs);
+ buffer_->WriteToContiguousBuffer(cs);
+
+ ASSERT_EQ(1u, buffer_->num_blocks());
+ ASSERT_EQ(as + bs + cs,
+ StringPiece(buffer_->GetPtr(0), buffer_->bytes_used(0)));
+}
+
+TEST_F(BalsaBufferTest, NoMoreWriteToContiguousBuffer) {
+ size_t index1, index2;
+ StringPiece sp1 = buffer_->Write(StringPiece("hello"), &index1);
+ buffer_->NoMoreWriteToContiguousBuffer();
+ StringPiece sp2 = buffer_->Write(StringPiece(", world"), &index2);
+
+ ASSERT_EQ(2u, buffer_->num_blocks());
+ ASSERT_EQ("hello", sp1);
+ ASSERT_EQ(", world", sp2);
+ ASSERT_EQ(1u, index1);
+ ASSERT_EQ(0u, index2);
+ ASSERT_EQ(sp1, StringPiece(buffer_->GetPtr(1), buffer_->bytes_used(1)));
+ ASSERT_EQ(sp2, StringPiece(buffer_->GetPtr(0), buffer_->bytes_used(0)));
+}
+
+TEST_F(BalsaBufferTest, Clear) {
+ buffer_->Write("hello", NULL);
+ ASSERT_EQ(2u, buffer_->num_blocks());
+ buffer_->Clear();
+ ASSERT_EQ(1u, buffer_->num_blocks());
+}
+
+TEST_F(BalsaBufferTest, Swap) {
+ buffer_->Write("hello", NULL);
+
+ ASSERT_EQ(2u, buffer_->num_blocks());
+ ASSERT_EQ(1u, anotherBuffer_->num_blocks());
+
+ buffer_->Swap(anotherBuffer_.get());
+
+ ASSERT_EQ(1u, buffer_->num_blocks());
+ ASSERT_EQ(2u, anotherBuffer_->num_blocks());
+ ASSERT_EQ("hello",
+ StringPiece(anotherBuffer_->GetPtr(1),
+ anotherBuffer_->bytes_used(1)));
+}
+
+TEST_F(BalsaBufferTest, CopyFrom) {
+ buffer_->Write("hello", NULL);
+
+ ASSERT_EQ(2u, buffer_->num_blocks());
+ ASSERT_EQ(1u, anotherBuffer_->num_blocks());
+
+ anotherBuffer_->CopyFrom(*buffer_);
+
+ ASSERT_EQ(2u, buffer_->num_blocks());
+ ASSERT_EQ(2u, anotherBuffer_->num_blocks());
+ ASSERT_EQ("hello", StringPiece(buffer_->GetPtr(1), buffer_->bytes_used(1)));
+ ASSERT_EQ("hello",
+ StringPiece(anotherBuffer_->GetPtr(1),
+ anotherBuffer_->bytes_used(1)));
+}
+
+TEST_F(BalsaHeadersTest, AppendHeader) {
+ headers_->AppendHeader("key1", "value1");
+ headers_->AppendHeader("key2", "value2");
+ headers_->AppendHeader("key3", "value3");
+ headers_->AppendHeader("key3", "value3.1");
+ headers_->AppendHeader("key3", "value3.2");
+
+ ASSERT_EQ(5, std::distance(headers_->header_lines_begin(),
+ headers_->header_lines_end()));
+ ASSERT_EQ("value1", headers_->GetHeader("key1"));
+ ASSERT_EQ("value2", headers_->GetHeader("key2"));
+ ASSERT_EQ("value3", headers_->GetHeader("key3"));
+
+ std::vector<base::StringPiece> v1, v2, v3;
+ std::string s1, s2, s3;
+ headers_->GetAllOfHeader("key1", &v1);
+ headers_->GetAllOfHeader("key2", &v2);
+ headers_->GetAllOfHeader("key3", &v3);
+ headers_->GetAllOfHeaderAsString("key1", &s1);
+ headers_->GetAllOfHeaderAsString("key2", &s2);
+ headers_->GetAllOfHeaderAsString("key3", &s3);
+
+ ASSERT_EQ(1u, v1.size());
+ ASSERT_EQ(1u, v2.size());
+ ASSERT_EQ(3u, v3.size());
+ ASSERT_EQ("value1", v1[0]);
+ ASSERT_EQ("value2", v2[0]);
+ ASSERT_EQ("value3", v3[0]);
+ ASSERT_EQ("value3.1", v3[1]);
+ ASSERT_EQ("value3.2", v3[2]);
+ ASSERT_EQ("value1", s1);
+ ASSERT_EQ("value2", s2);
+ ASSERT_EQ("value3,value3.1,value3.2", s3);
+}
+
+TEST_F(BalsaHeadersTest, ReplaceOrAppendHeader) {
+ headers_->ReplaceOrAppendHeader("key1", "value1");
+ headers_->ReplaceOrAppendHeader("key1", "value2");
+
+ ASSERT_EQ(1, std::distance(headers_->header_lines_begin(),
+ headers_->header_lines_end()));
+ ASSERT_EQ("value2", headers_->GetHeader("key1"));
+
+ std::vector<base::StringPiece> v;
+ headers_->GetAllOfHeader("key1", &v);
+
+ ASSERT_EQ(1u, v.size());
+ ASSERT_EQ("value2", v[0]);
+}
+
+TEST_F(BalsaHeadersTest, AppendToHeader) {
+ headers_->AppendToHeader("key1", "value1");
+ headers_->AppendToHeader("keY1", "value2");
+
+ ASSERT_EQ(1, std::distance(headers_->header_lines_begin(),
+ headers_->header_lines_end()));
+ ASSERT_EQ("value1,value2", headers_->GetHeader("key1"));
+
+ std::vector<base::StringPiece> v;
+ std::string s;
+ headers_->GetAllOfHeader("key1", &v);
+ headers_->GetAllOfHeaderAsString("keY1", &s);
+
+ ASSERT_EQ(1u, v.size());
+ ASSERT_EQ("value1,value2", v[0]);
+ ASSERT_EQ("value1,value2", s);
+}
+
+TEST_F(BalsaHeadersTest, PrepentToHeader) {
+ headers_->PrependToHeader("key1", "value1");
+ headers_->PrependToHeader("key1", "value2");
+
+ ASSERT_EQ(1, std::distance(headers_->header_lines_begin(),
+ headers_->header_lines_end()));
+ ASSERT_EQ("value2,value1", headers_->GetHeader("key1"));
+
+ std::vector<base::StringPiece> v;
+ std::string s;
+ headers_->GetAllOfHeader("key1", &v);
+ headers_->GetAllOfHeaderAsString("key1", &s);
+
+ ASSERT_EQ(1u, v.size());
+ ASSERT_EQ("value2,value1", v[0]);
+ ASSERT_EQ("value2,value1", s);
+}
+
+TEST_F(BalsaHeadersTest, HasHeader) {
+ headers_->AppendHeader("key1", "value1");
+
+ ASSERT_TRUE(headers_->HasHeader("key1"));
+ ASSERT_FALSE(headers_->HasHeader("value1"));
+ ASSERT_FALSE(headers_->HasHeader("key2"));
+}
+
+TEST_F(BalsaHeadersTest, HasNonEmptyHeader) {
+ headers_->AppendHeader("key1", "value1");
+ headers_->AppendHeader("key2", "");
+
+ ASSERT_TRUE(headers_->HasNonEmptyHeader("key1"));
+ ASSERT_FALSE(headers_->HasNonEmptyHeader("key2"));
+ ASSERT_FALSE(headers_->HasNonEmptyHeader("key3"));
+}
+
+TEST_F(BalsaHeadersTest, GetHeaderPosition) {
+ headers_->AppendHeader("key1", "value1");
+ headers_->AppendHeader("key2", "value2");
+ headers_->AppendHeader("key3", "value3");
+
+ BalsaHeaders::const_header_lines_iterator i =
+ headers_->GetHeaderPosition("key2");
+
+ ASSERT_EQ(headers_->header_lines_end(),
+ headers_->GetHeaderPosition("foobar"));
+ ASSERT_EQ(headers_->header_lines_begin(),
+ headers_->GetHeaderPosition("key1"));
+ ASSERT_NE(headers_->header_lines_end(), i);
+ ASSERT_EQ("key2", i->first);
+ ASSERT_EQ("value2", i->second);
+ ++i;
+ ASSERT_EQ("key3", i->first);
+ ASSERT_EQ("value3", i->second);
+ ++i;
+ ASSERT_EQ(headers_->header_lines_end(), i);
+}
+
+TEST_F(BalsaHeadersTest, GetIteratorForKey) {
+ headers_->AppendHeader("key1", "value1");
+ headers_->AppendHeader("key2", "value2");
+ headers_->AppendHeader("key1", "value1.1");
+ headers_->AppendHeader("key3", "value3");
+ headers_->AppendHeader("KEY1", "value1.2");
+
+ BalsaHeaders::const_header_lines_key_iterator i =
+ headers_->GetIteratorForKey("key1");
+
+ ASSERT_EQ(headers_->header_lines_key_end(),
+ headers_->GetIteratorForKey("foobar"));
+ ASSERT_NE(headers_->header_lines_key_end(), i);
+ ASSERT_EQ("key1", i->first);
+ ASSERT_EQ("value1", i->second);
+ ++i;
+ ASSERT_EQ("key1", i->first);
+ ASSERT_EQ("value1.1", i->second);
+ ++i;
+ ASSERT_EQ("KEY1", i->first);
+ ASSERT_EQ("value1.2", i->second);
+ ++i;
+ ASSERT_EQ(headers_->header_lines_key_end(), i);
+}
+
+TEST_F(BalsaHeadersTest, RemoveAllOfHeader) {
+ headers_->AppendHeader("key1", "value1");
+ headers_->AppendHeader("key2", "value2");
+ headers_->AppendHeader("key1", "value1.1");
+ headers_->AppendHeader("key3", "value3");
+ headers_->AppendHeader("key1", "value1.2");
+ headers_->AppendHeader("kEY1", "value1.3");
+
+ ASSERT_EQ(6, std::distance(headers_->header_lines_begin(),
+ headers_->header_lines_end()));
+ headers_->RemoveAllOfHeader("key1");
+ ASSERT_EQ(2, std::distance(headers_->header_lines_begin(),
+ headers_->header_lines_end()));
+}
+
+TEST_F(BalsaHeadersTest, RemoveAllHeadersWithPrefix) {
+ headers_->AppendHeader("1key", "value1");
+ headers_->AppendHeader("2key", "value2");
+ headers_->AppendHeader("1kEz", "value1.1");
+ headers_->AppendHeader("key3", "value3");
+ headers_->AppendHeader("1KEEjkladf", "value1.2");
+
+ ASSERT_EQ(5, std::distance(headers_->header_lines_begin(),
+ headers_->header_lines_end()));
+ headers_->RemoveAllHeadersWithPrefix("1ke");
+ ASSERT_EQ(2, std::distance(headers_->header_lines_begin(),
+ headers_->header_lines_end()));
+}
+
+TEST_F(BalsaHeadersTest, WriteRequestHeaderAndEndingToBuffer) {
+ headers_->AppendHeader("key1", "value1");
+ headers_->AppendHeader("key2", "value2");
+ headers_->AppendHeader("key1", "value1.1");
+
+ headers_->SetRequestFirstlineFromStringPieces("GET", "/", "HTTP/1.0");
+
+ std::string expected = "GET / HTTP/1.0\r\n"
+ "key1: value1\r\n"
+ "key2: value2\r\n"
+ "key1: value1.1\r\n\r\n";
+ StringBuffer buffer;
+ headers_->WriteHeaderAndEndingToBuffer(&buffer);
+ ASSERT_EQ(expected, buffer.string());
+}
+
+TEST_F(BalsaHeadersTest, WriteResponseHeaderAndEndingToBuffer) {
+ headers_->AppendHeader("key1", "value1");
+ headers_->AppendHeader("key2", "value2");
+ headers_->AppendHeader("key1", "value1.1");
+
+ headers_->SetResponseFirstlineFromStringPieces("HTTP/1.0", "200", "OK");
+
+ std::string expected = "HTTP/1.0 200 OK\r\n"
+ "key1: value1\r\n"
+ "key2: value2\r\n"
+ "key1: value1.1\r\n\r\n";
+ StringBuffer buffer;
+ headers_->WriteHeaderAndEndingToBuffer(&buffer);
+ ASSERT_EQ(expected, buffer.string());
+}
+
+TEST_F(BalsaHeadersTest, RequestFirstLine) {
+ headers_->SetRequestFirstlineFromStringPieces("HEAD", "/path", "HTTP/1.1");
+
+ ASSERT_EQ("HEAD /path HTTP/1.1", headers_->first_line());
+ ASSERT_EQ("HEAD", headers_->request_method());
+ ASSERT_EQ("/path", headers_->request_uri());
+ ASSERT_EQ("HTTP/1.1", headers_->request_version());
+}
+
+TEST_F(BalsaHeadersTest, ResponseFirstLine) {
+ headers_->SetRequestFirstlineFromStringPieces("HTTP/1.0", "403", "FORBIDDEN");
+
+ ASSERT_EQ("HTTP/1.0 403 FORBIDDEN", headers_->first_line());
+ ASSERT_EQ("HTTP/1.0", headers_->response_version());
+ ASSERT_EQ("403", headers_->response_code());
+ ASSERT_EQ("FORBIDDEN", headers_->response_reason_phrase());
+}
+
+} // namespace
+
+} // namespace net
diff --git a/net/tools/flip_server/http_interface.cc b/net/tools/flip_server/http_interface.cc
index 9cd1331..7a44c03 100644
--- a/net/tools/flip_server/http_interface.cc
+++ b/net/tools/flip_server/http_interface.cc
@@ -332,13 +332,13 @@
}
if (!mci->transformed_header) {
mci->bytes_sent = SendSynReply(mci->stream_id,
- *(mci->file_data->headers));
+ *(mci->file_data->headers()));
mci->transformed_header = true;
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput transformed "
<< "header stream_id: [" << mci->stream_id << "]";
return;
}
- if (mci->body_bytes_consumed >= mci->file_data->body.size()) {
+ if (mci->body_bytes_consumed >= mci->file_data->body().size()) {
SendEOF(mci->stream_id);
output_ordering_.RemoveStreamId(mci->stream_id);
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "GetOutput remove_stream_id: ["
@@ -346,12 +346,12 @@
return;
}
size_t num_to_write =
- mci->file_data->body.size() - mci->body_bytes_consumed;
+ mci->file_data->body().size() - mci->body_bytes_consumed;
if (num_to_write > mci->max_segment_size)
num_to_write = mci->max_segment_size;
SendDataFrame(mci->stream_id,
- mci->file_data->body.data() + mci->body_bytes_consumed,
+ mci->file_data->body().data() + mci->body_bytes_consumed,
num_to_write, 0, true);
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput SendDataFrame["
<< mci->stream_id << "]: " << num_to_write;
@@ -360,4 +360,3 @@
}
} // namespace net
-
diff --git a/net/tools/flip_server/mem_cache.cc b/net/tools/flip_server/mem_cache.cc
index 0af21e0..9249208 100644
--- a/net/tools/flip_server/mem_cache.cc
+++ b/net/tools/flip_server/mem_cache.cc
@@ -13,15 +13,19 @@
#include <unistd.h>
#include <deque>
+#include <map>
+#include <string>
-#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
#include "net/tools/dump_cache/url_to_filename_encoder.h"
#include "net/tools/dump_cache/url_utilities.h"
#include "net/tools/flip_server/balsa_frame.h"
#include "net/tools/flip_server/balsa_headers.h"
+namespace {
// The directory where cache locates);
-std::string FLAGS_cache_base_dir = ".";
+const char FLAGS_cache_base_dir[] = ".";
+} // namespace
namespace net {
@@ -46,40 +50,36 @@
HandleError();
}
-FileData::FileData(BalsaHeaders* h, const std::string& b)
- : headers(h), body(b) {
+FileData::FileData(const BalsaHeaders* headers,
+ const std::string& filename,
+ const std::string& body)
+ : filename_(filename)
+ , body_(body) {
+ if (headers) {
+ headers_.reset(new BalsaHeaders);
+ headers_->CopyFrom(*headers);
+ }
}
FileData::FileData() {}
FileData::~FileData() {}
-void FileData::CopyFrom(const FileData& file_data) {
- headers = new BalsaHeaders;
- headers->CopyFrom(*(file_data.headers));
- filename = file_data.filename;
- related_files = file_data.related_files;
- body = file_data.body;
- }
+MemoryCache::MemoryCache() : cwd_(FLAGS_cache_base_dir) {}
-MemoryCache::MemoryCache() {}
-
-MemoryCache::~MemoryCache() {}
+MemoryCache::~MemoryCache() {
+ ClearFiles();
+}
void MemoryCache::CloneFrom(const MemoryCache& mc) {
- for (Files::const_iterator i = mc.files_.begin();
- i != mc.files_.end();
- ++i) {
- Files::iterator out_i =
- files_.insert(make_pair(i->first, FileData())).first;
- out_i->second.CopyFrom(i->second);
- cwd_ = mc.cwd_;
- }
+ DCHECK_NE(this, &mc);
+ ClearFiles();
+ files_ = mc.files_;
+ cwd_ = mc.cwd_;
}
void MemoryCache::AddFiles() {
std::deque<std::string> paths;
- cwd_ = FLAGS_cache_base_dir;
paths.push_back(cwd_ + "/GET_");
DIR* current_dir = NULL;
while (!paths.empty()) {
@@ -192,24 +192,33 @@
"Fri, 30 Aug, 2019 12:00:00 GMT");
}
#endif
- BalsaHeaders* headers = new BalsaHeaders;
- headers->CopyFrom(visitor.headers);
+ DCHECK_GE(std::string(filename).size(), cwd_.size() + 1);
+ DCHECK_EQ(std::string(filename).substr(0, cwd_.size()), cwd_);
+ DCHECK_EQ(filename[cwd_.size()], '/');
std::string filename_stripped = std::string(filename).substr(cwd_.size() + 1);
LOG(INFO) << "Adding file (" << visitor.body.length() << " bytes): "
<< filename_stripped;
- files_[filename_stripped] = FileData();
- FileData& fd = files_[filename_stripped];
- fd = FileData(headers, visitor.body);
- fd.filename = std::string(filename_stripped,
- filename_stripped.find_first_of('/'));
+ size_t slash_pos = filename_stripped.find('/');
+ if (slash_pos == std::string::npos) {
+ slash_pos = filename_stripped.size();
+ }
+ FileData* data =
+ new FileData(&visitor.headers,
+ filename_stripped.substr(0, slash_pos),
+ visitor.body);
+ Files::iterator it = files_.find(filename_stripped);
+ if (it != files_.end()) {
+ delete it->second;
+ it->second = data;
+ } else {
+ files_.insert(std::make_pair(filename_stripped, data));
+ }
}
FileData* MemoryCache::GetFileData(const std::string& filename) {
Files::iterator fi = files_.end();
- if (filename.compare(filename.length() - 5, 5, ".html", 5) == 0) {
- std::string new_filename(filename.data(), filename.size() - 5);
- new_filename += ".http";
- fi = files_.find(new_filename);
+ if (EndsWith(filename, ".html", true)) {
+ fi = files_.find(filename.substr(0, filename.size() - 5) + ".http");
}
if (fi == files_.end())
fi = files_.find(filename);
@@ -217,7 +226,7 @@
if (fi == files_.end()) {
return NULL;
}
- return &(fi->second);
+ return fi->second;
}
bool MemoryCache::AssignFileData(const std::string& filename,
@@ -230,5 +239,11 @@
return true;
}
-} // namespace net
+void MemoryCache::ClearFiles() {
+ for (Files::const_iterator i = files_.begin(); i != files_.end(); ++i) {
+ delete i->second;
+ }
+ files_.clear();
+}
+} // namespace net
diff --git a/net/tools/flip_server/mem_cache.h b/net/tools/flip_server/mem_cache.h
index cf5b9bd..806ae53 100644
--- a/net/tools/flip_server/mem_cache.h
+++ b/net/tools/flip_server/mem_cache.h
@@ -7,9 +7,9 @@
#include <map>
#include <string>
-#include <vector>
#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
#include "net/tools/flip_server/balsa_headers.h"
#include "net/tools/flip_server/balsa_visitor_interface.h"
#include "net/tools/flip_server/constants.h"
@@ -61,18 +61,26 @@
};
////////////////////////////////////////////////////////////////////////////////
-
-struct FileData {
+class FileData {
+ public:
FileData();
- FileData(BalsaHeaders* h, const std::string& b);
+ FileData(const BalsaHeaders* headers,
+ const std::string& filename,
+ const std::string& body);
~FileData();
- void CopyFrom(const FileData& file_data);
- BalsaHeaders* headers;
- std::string filename;
- // priority, filename
- std::vector< std::pair<int, std::string> > related_files;
- std::string body;
+ BalsaHeaders* headers() { return headers_.get(); }
+ const BalsaHeaders* headers() const { return headers_.get(); }
+
+ const std::string& filename() { return filename_; }
+ const std::string& body() { return body_; }
+
+ private:
+ scoped_ptr<BalsaHeaders> headers_;
+ std::string filename_;
+ std::string body_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileData);
};
////////////////////////////////////////////////////////////////////////////////
@@ -108,17 +116,18 @@
class MemoryCache {
public:
- typedef std::map<std::string, FileData> Files;
+ typedef std::map<std::string, FileData*> Files;
public:
MemoryCache();
- ~MemoryCache();
+ virtual ~MemoryCache();
void CloneFrom(const MemoryCache& mc);
void AddFiles();
- void ReadToString(const char* filename, std::string* output);
+ // virtual for unittests
+ virtual void ReadToString(const char* filename, std::string* output);
void ReadAndStoreFileContents(const char* filename);
@@ -126,6 +135,9 @@
bool AssignFileData(const std::string& filename, MemCacheIter* mci);
+ private:
+ void ClearFiles();
+
Files files_;
std::string cwd_;
};
@@ -139,4 +151,3 @@
} // namespace net
#endif // NET_TOOLS_FLIP_SERVER_MEM_CACHE_H_
-
diff --git a/net/tools/flip_server/mem_cache_test.cc b/net/tools/flip_server/mem_cache_test.cc
new file mode 100644
index 0000000..d5601ac
--- /dev/null
+++ b/net/tools/flip_server/mem_cache_test.cc
@@ -0,0 +1,98 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/tools/flip_server/mem_cache.h"
+
+#include "net/tools/flip_server/balsa_headers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+class MemoryCacheWithFakeReadToString : public MemoryCache {
+ public:
+ virtual ~MemoryCacheWithFakeReadToString() {}
+
+ virtual void ReadToString(const char* filename, std::string* output)
+ OVERRIDE {
+ *output = data_map_[filename];
+ }
+
+ std::map<std::string, std::string> data_map_;
+};
+
+class FlipMemoryCacheTest : public ::testing::Test {
+ public:
+ FlipMemoryCacheTest(): mem_cache_(new MemoryCacheWithFakeReadToString) {}
+
+ protected:
+ scoped_ptr<MemoryCacheWithFakeReadToString> mem_cache_;
+};
+
+TEST_F(FlipMemoryCacheTest, EmptyCache) {
+ MemCacheIter mci;
+ mci.stream_id = 0;
+ ASSERT_EQ(NULL, mem_cache_->GetFileData("./foo"));
+ ASSERT_EQ(NULL, mem_cache_->GetFileData("./bar"));
+ ASSERT_FALSE(mem_cache_->AssignFileData("./hello", &mci));
+}
+
+TEST_F(FlipMemoryCacheTest, ReadAndStoreFileContents) {
+ FileData* foo;
+ FileData* hello;
+
+ mem_cache_->data_map_["./foo"] = "bar";
+ mem_cache_->data_map_["./hello"] = "HTTP/1.0 200 OK\r\n"
+ "key1: value1\r\n"
+ "key2: value2\r\n\r\n"
+ "body: body\r\n";
+ mem_cache_->ReadAndStoreFileContents("./foo");
+ mem_cache_->ReadAndStoreFileContents("./hello");
+
+ foo = mem_cache_->GetFileData("foo");
+ hello = mem_cache_->GetFileData("hello");
+
+ // "./foo" content is broken.
+ ASSERT_EQ(NULL, foo);
+ ASSERT_FALSE(NULL == hello);
+ ASSERT_EQ(hello, mem_cache_->GetFileData("hello"));
+
+ // "HTTP/1.0" is rewritten to "HTTP/1.1".
+ ASSERT_EQ("HTTP/1.1", hello->headers()->response_version());
+ ASSERT_EQ("200", hello->headers()->response_code());
+ ASSERT_EQ("OK", hello->headers()->response_reason_phrase());
+ ASSERT_EQ(4, std::distance(hello->headers()->header_lines_begin(),
+ hello->headers()->header_lines_end()));
+ ASSERT_TRUE(hello->headers()->HasHeader("key1"));
+ ASSERT_TRUE(hello->headers()->HasHeader("key2"));
+ ASSERT_TRUE(hello->headers()->HasHeader("transfer-encoding"));
+ ASSERT_TRUE(hello->headers()->HasHeader("connection"));
+ ASSERT_EQ("value1", hello->headers()->GetHeaderPosition("key1")->second);
+ ASSERT_EQ("value2", hello->headers()->GetHeaderPosition("key2")->second);
+ ASSERT_EQ("chunked",
+ hello->headers()->GetHeaderPosition("transfer-encoding")->second);
+ ASSERT_EQ("keep-alive",
+ hello->headers()->GetHeaderPosition("connection")->second);
+ ASSERT_EQ("body: body\r\n", hello->body());
+ ASSERT_EQ("hello", hello->filename());
+}
+
+TEST_F(FlipMemoryCacheTest, GetFileDataForHtmlFile) {
+ FileData* hello_html;
+
+ mem_cache_->data_map_["./hello.http"] = "HTTP/1.0 200 OK\r\n"
+ "key1: value1\r\n"
+ "key2: value2\r\n\r\n"
+ "body: body\r\n";
+
+ mem_cache_->ReadAndStoreFileContents("./hello.http");
+ hello_html = mem_cache_->GetFileData("hello.html");
+ ASSERT_FALSE(NULL == hello_html);
+ ASSERT_EQ(hello_html, mem_cache_->GetFileData("hello.http"));
+}
+
+} // namespace
+
+} // namespace net
diff --git a/net/tools/flip_server/output_ordering.cc b/net/tools/flip_server/output_ordering.cc
index dd11962..22fd08a 100644
--- a/net/tools/flip_server/output_ordering.cc
+++ b/net/tools/flip_server/output_ordering.cc
@@ -99,14 +99,14 @@
double think_time_in_s = server_think_time_in_s_;
std::string x_server_latency =
- mci.file_data->headers->GetHeader("X-Server-Latency").as_string();
+ mci.file_data->headers()->GetHeader("X-Server-Latency").as_string();
if (!x_server_latency.empty()) {
char* endp;
double tmp_think_time_in_s = strtod(x_server_latency.c_str(), &endp);
if (endp != x_server_latency.c_str() + x_server_latency.size()) {
LOG(ERROR) << "Unable to understand X-Server-Latency of: "
<< x_server_latency << " for resource: "
- << mci.file_data->filename.c_str();
+ << mci.file_data->filename().c_str();
} else {
think_time_in_s = tmp_think_time_in_s;
}
diff --git a/net/tools/flip_server/spdy_interface.cc b/net/tools/flip_server/spdy_interface.cc
index 16023a5..b4e36be 100644
--- a/net/tools/flip_server/spdy_interface.cc
+++ b/net/tools/flip_server/spdy_interface.cc
@@ -521,43 +521,43 @@
// this is a server initiated stream.
// Ideally, we'd do a 'syn-push' here, instead of a syn-reply.
BalsaHeaders headers;
- headers.CopyFrom(*(mci->file_data->headers));
+ headers.CopyFrom(*(mci->file_data->headers()));
headers.ReplaceOrAppendHeader("status", "200");
headers.ReplaceOrAppendHeader("version", "http/1.1");
headers.SetRequestFirstlineFromStringPieces("PUSH",
- mci->file_data->filename,
+ mci->file_data->filename(),
"");
mci->bytes_sent = SendSynStream(mci->stream_id, headers);
} else {
BalsaHeaders headers;
- headers.CopyFrom(*(mci->file_data->headers));
+ headers.CopyFrom(*(mci->file_data->headers()));
mci->bytes_sent = SendSynReply(mci->stream_id, headers);
}
return;
}
- if (mci->body_bytes_consumed >= mci->file_data->body.size()) {
+ if (mci->body_bytes_consumed >= mci->file_data->body().size()) {
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: GetOutput "
<< "remove_stream_id: [" << mci->stream_id << "]";
SendEOF(mci->stream_id);
return;
}
size_t num_to_write =
- mci->file_data->body.size() - mci->body_bytes_consumed;
+ mci->file_data->body().size() - mci->body_bytes_consumed;
if (num_to_write > mci->max_segment_size)
num_to_write = mci->max_segment_size;
bool should_compress = false;
- if (!mci->file_data->headers->HasHeader("content-encoding")) {
- if (mci->file_data->headers->HasHeader("content-type")) {
+ if (!mci->file_data->headers()->HasHeader("content-encoding")) {
+ if (mci->file_data->headers()->HasHeader("content-type")) {
std::string content_type =
- mci->file_data->headers->GetHeader("content-type").as_string();
+ mci->file_data->headers()->GetHeader("content-type").as_string();
if (content_type.find("image") == content_type.npos)
should_compress = true;
}
}
SendDataFrame(mci->stream_id,
- mci->file_data->body.data() + mci->body_bytes_consumed,
+ mci->file_data->body().data() + mci->body_bytes_consumed,
num_to_write, 0, should_compress);
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: GetOutput SendDataFrame["
<< mci->stream_id << "]: " << num_to_write;
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index 40449b3..65e50f7 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -422,9 +422,15 @@
return;
}
- // FLAGS_fake_packet_loss_percentage = 30;
+ // Connect with lower fake packet loss than we'd like to test. Until
+ // b/10126687 is fixed, losing handshake packets is pretty brutal.
+ // FLAGS_fake_packet_loss_percentage = 5;
ASSERT_TRUE(Initialize());
+ // Wait for the server SHLO before upping the packet loss.
+ client_->client()->WaitForCryptoHandshakeConfirmed();
+ // FLAGS_fake_packet_loss_percentage = 30;
+
string body;
GenerateBody(&body, 10240);
@@ -493,7 +499,7 @@
HTTPMessage request(HttpConstants::HTTP_1_1,
HttpConstants::POST, "/foo");
request.AddBody(body, true);
- // Force the client to write with a stream ID belonging to a nonexistant
+ // Force the client to write with a stream ID belonging to a nonexistent
// server-side stream.
QuicSessionPeer::SetNextStreamId(client_->client()->session(), 2);
diff --git a/net/tools/quic/quic_epoll_connection_helper.cc b/net/tools/quic/quic_epoll_connection_helper.cc
index ba72087..4db1d4c 100644
--- a/net/tools/quic/quic_epoll_connection_helper.cc
+++ b/net/tools/quic/quic_epoll_connection_helper.cc
@@ -17,80 +17,50 @@
namespace net {
namespace tools {
-// This alarm will be scheduled any time a data-bearing packet is sent out.
-// When the alarm goes off, the connection checks to see if the oldest packets
-// have been acked, and retransmit them if they have not.
-class RetransmissionAlarm : public EpollAlarm {
+namespace {
+
+class QuicEpollAlarm : public QuicAlarm {
public:
- explicit RetransmissionAlarm(QuicConnection* connection)
- : connection_(connection) {
+ QuicEpollAlarm(EpollServer* epoll_server,
+ QuicAlarm::Delegate* delegate)
+ : QuicAlarm(delegate),
+ epoll_server_(epoll_server),
+ epoll_alarm_impl_(this) {}
+
+ protected:
+ virtual void SetImpl() OVERRIDE {
+ DCHECK(deadline().IsInitialized());
+ epoll_server_->RegisterAlarm(
+ deadline().Subtract(QuicTime::Zero()).ToMicroseconds(),
+ &epoll_alarm_impl_);
}
- virtual int64 OnAlarm() OVERRIDE {
- EpollAlarm::OnAlarm();
- // This is safe because this code is Google3 specific, and the
- // Google3 QuicTime's epoch is the unix epoch.
- return connection_->OnRetransmissionTimeout().Subtract(
- QuicTime::Zero()).ToMicroseconds();
+ virtual void CancelImpl() OVERRIDE {
+ DCHECK(!deadline().IsInitialized());
+ epoll_alarm_impl_.UnregisterIfRegistered();
}
private:
- QuicConnection* connection_;
+ class EpollAlarmImpl : public EpollAlarm {
+ public:
+ explicit EpollAlarmImpl(QuicEpollAlarm* alarm) : alarm_(alarm) {}
+
+ virtual int64 OnAlarm() OVERRIDE {
+ EpollAlarm::OnAlarm();
+ alarm_->Fire();
+ // Fire will take care of registering the alarm, if needed.
+ return 0;
+ }
+
+ private:
+ QuicEpollAlarm* alarm_;
+ };
+
+ EpollServer* epoll_server_;
+ EpollAlarmImpl epoll_alarm_impl_;
};
-// An alarm that is scheduled when the sent scheduler requires a
-// a delay before sending packets and fires when the packet may be sent.
-class SendAlarm : public EpollAlarm {
- public:
- explicit SendAlarm(QuicConnection* connection)
- : connection_(connection) {
- }
-
- virtual int64 OnAlarm() OVERRIDE {
- EpollAlarm::OnAlarm();
- connection_->OnCanWrite();
- // Never reschedule the alarm, since OnCanWrite does that.
- return 0;
- }
-
- private:
- QuicConnection* connection_;
-};
-
-// An alarm which fires when the connection may have timed out.
-class TimeoutAlarm : public EpollAlarm {
- public:
- explicit TimeoutAlarm(QuicConnection* connection)
- : connection_(connection) {
- }
-
- virtual int64 OnAlarm() OVERRIDE {
- EpollAlarm::OnAlarm();
- connection_->CheckForTimeout();
- // Never reschedule the alarm, since CheckForTimeout does that.
- return 0;
- }
-
- private:
- QuicConnection* connection_;
-};
-
-// An alarm that is scheduled to send an ack if a timeout occurs.
-class AckAlarm : public EpollAlarm {
- public:
- explicit AckAlarm(QuicConnection* connection)
- : connection_(connection) {
- }
-
- virtual int64 OnAlarm() OVERRIDE {
- EpollAlarm::OnAlarm();
- connection_->SendAck();
- return 0;
- }
-
- private:
- QuicConnection* connection_;
-};
+} // namespace
QuicEpollConnectionHelper::QuicEpollConnectionHelper(
int fd, EpollServer* epoll_server)
@@ -118,10 +88,6 @@
void QuicEpollConnectionHelper::SetConnection(QuicConnection* connection) {
DCHECK(!connection_);
connection_ = connection;
- timeout_alarm_.reset(new TimeoutAlarm(connection));
- send_alarm_.reset(new SendAlarm(connection));
- ack_alarm_.reset(new AckAlarm(connection));
- retransmission_alarm_.reset(new RetransmissionAlarm(connection_));
}
const QuicClock* QuicEpollConnectionHelper::GetClock() const {
@@ -165,43 +131,9 @@
return error == EAGAIN || error == EWOULDBLOCK;
}
-void QuicEpollConnectionHelper::SetRetransmissionAlarm(QuicTime::Delta delay) {
- if (!retransmission_alarm_->registered()) {
- epoll_server_->RegisterAlarmApproximateDelta(delay.ToMicroseconds(),
- retransmission_alarm_.get());
- }
-}
-
-void QuicEpollConnectionHelper::SetAckAlarm(QuicTime::Delta delay) {
- if (!ack_alarm_->registered()) {
- epoll_server_->RegisterAlarmApproximateDelta(
- delay.ToMicroseconds(), ack_alarm_.get());
- }
-}
-
-void QuicEpollConnectionHelper::ClearAckAlarm() {
- ack_alarm_->UnregisterIfRegistered();
-}
-
-void QuicEpollConnectionHelper::SetSendAlarm(QuicTime alarm_time) {
- send_alarm_->UnregisterIfRegistered();
- epoll_server_->RegisterAlarm(
- alarm_time.Subtract(QuicTime::Zero()).ToMicroseconds(),
- send_alarm_.get());
-}
-
-void QuicEpollConnectionHelper::SetTimeoutAlarm(QuicTime::Delta delay) {
- timeout_alarm_->UnregisterIfRegistered();
- epoll_server_->RegisterAlarmApproximateDelta(delay.ToMicroseconds(),
- timeout_alarm_.get());
-}
-
-bool QuicEpollConnectionHelper::IsSendAlarmSet() {
- return send_alarm_->registered();
-}
-
-void QuicEpollConnectionHelper::UnregisterSendAlarmIfRegistered() {
- send_alarm_->UnregisterIfRegistered();
+QuicAlarm* QuicEpollConnectionHelper::CreateAlarm(
+ QuicAlarm::Delegate* delegate) {
+ return new QuicEpollAlarm(epoll_server_, delegate);
}
} // namespace tools
diff --git a/net/tools/quic/quic_epoll_connection_helper.h b/net/tools/quic/quic_epoll_connection_helper.h
index 9ddef2f..5bd526f 100644
--- a/net/tools/quic/quic_epoll_connection_helper.h
+++ b/net/tools/quic/quic_epoll_connection_helper.h
@@ -11,7 +11,6 @@
#include <sys/types.h>
#include <set>
-#include "base/memory/scoped_ptr.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_time.h"
@@ -48,13 +47,7 @@
int* error) OVERRIDE;
virtual bool IsWriteBlockedDataBuffered() OVERRIDE;
virtual bool IsWriteBlocked(int error) OVERRIDE;
- virtual void SetRetransmissionAlarm(QuicTime::Delta delay) OVERRIDE;
- virtual void SetSendAlarm(QuicTime alarm_time) OVERRIDE;
- virtual void SetTimeoutAlarm(QuicTime::Delta delay) OVERRIDE;
- virtual bool IsSendAlarmSet() OVERRIDE;
- virtual void UnregisterSendAlarmIfRegistered() OVERRIDE;
- virtual void SetAckAlarm(QuicTime::Delta delay) OVERRIDE;
- virtual void ClearAckAlarm() OVERRIDE;
+ virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) OVERRIDE;
EpollServer* epoll_server() { return epoll_server_; }
@@ -66,18 +59,6 @@
EpollServer* epoll_server_; // Not owned.
int fd_;
- // An alarm which fires if we've hit a timeout on sending an ack.
- scoped_ptr<AckAlarm> ack_alarm_;
-
- scoped_ptr<RetransmissionAlarm> retransmission_alarm_;
-
- // An alarm which fires when the connection may have timed out.
- scoped_ptr<TimeoutAlarm> timeout_alarm_;
-
- // An alarm that is scheduled when the sent scheduler requires a
- // a delay before sending packets and fires when the packet may be sent.
- scoped_ptr<SendAlarm> send_alarm_;
-
QuicConnection* connection_;
const QuicEpollClock clock_;
QuicRandom* random_generator_;
diff --git a/net/tools/quic/quic_time_wait_list_manager.cc b/net/tools/quic/quic_time_wait_list_manager.cc
index fe538e9..a2fc4f8 100644
--- a/net/tools/quic/quic_time_wait_list_manager.cc
+++ b/net/tools/quic/quic_time_wait_list_manager.cc
@@ -275,7 +275,8 @@
if (error == EAGAIN || error == EWOULDBLOCK) {
is_write_blocked_ = true;
} else {
- LOG(WARNING) << "Received unknown error while sending reset packet:"
+ LOG(WARNING) << "Received unknown error while sending reset packet to "
+ << queued_packet->client_address().ToString() << ": "
<< strerror(error);
}
}
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc
index 03600f2..859d7a5 100644
--- a/net/tools/quic/test_tools/quic_test_client.cc
+++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -26,6 +26,7 @@
public:
// ProofVerifier interface.
virtual net::ProofVerifier::Status VerifyProof(
+ net::QuicVersion version,
const string& hostname,
const string& server_config,
const vector<string>& certs,
diff --git a/ppapi/DEPS b/ppapi/DEPS
index 7d05cd9..4b60426 100644
--- a/ppapi/DEPS
+++ b/ppapi/DEPS
@@ -1,5 +1,4 @@
include_rules = [
- "+media",
"+third_party/WebKit/public/platform",
"+third_party/WebKit/public/web",
"+third_party/skia",
diff --git a/ppapi/api/private/ppb_flash_device_id.idl b/ppapi/api/private/ppb_flash_device_id.idl
index 16b0d3d..b4ba3ca 100644
--- a/ppapi/api/private/ppb_flash_device_id.idl
+++ b/ppapi/api/private/ppb_flash_device_id.idl
@@ -8,8 +8,7 @@
*/
label Chrome {
- M21 = 1.0,
- M29 = 1.1
+ M21 = 1.0
};
// TODO(raymes): This is deprecated by the PPB_Flash_DRM interface. Remove this
@@ -22,7 +21,7 @@
* string in |*id| and will call the completion callback. On failure the
* given var will be PP_VARTYPE_UNDEFINED.
*/
- [version=1.0, deprecate=1.1]
+ [version=1.0]
int32_t GetDeviceID([in] PP_Resource device_id,
[out] PP_Var id,
[in] PP_CompletionCallback callback);
diff --git a/ppapi/host/resource_message_filter.cc b/ppapi/host/resource_message_filter.cc
index 6d947e3..ff56cac 100644
--- a/ppapi/host/resource_message_filter.cc
+++ b/ppapi/host/resource_message_filter.cc
@@ -42,11 +42,16 @@
HostMessageContext* context) {
scoped_refptr<base::TaskRunner> runner = OverrideTaskRunnerForMessage(msg);
if (runner.get()) {
- // TODO(raymes): We need to make a copy so the context can be used on other
- // threads. It would be better to have a thread-safe refcounted context.
- HostMessageContext context_copy = *context;
- runner->PostTask(FROM_HERE, base::Bind(
- &ResourceMessageFilter::DispatchMessage, this, msg, context_copy));
+ if (runner->RunsTasksOnCurrentThread()) {
+ DispatchMessage(msg, *context);
+ } else {
+ // TODO(raymes): We need to make a copy so the context can be used on
+ // other threads. It would be better to have a thread-safe refcounted
+ // context.
+ HostMessageContext context_copy = *context;
+ runner->PostTask(FROM_HERE, base::Bind(
+ &ResourceMessageFilter::DispatchMessage, this, msg, context_copy));
+ }
return true;
}
diff --git a/ppapi/native_client/src/trusted/plugin/module_ppapi.cc b/ppapi/native_client/src/trusted/plugin/module_ppapi.cc
index 90fe0f1..4204ed4 100644
--- a/ppapi/native_client/src/trusted/plugin/module_ppapi.cc
+++ b/ppapi/native_client/src/trusted/plugin/module_ppapi.cc
@@ -8,81 +8,95 @@
#include "native_client/src/shared/platform/nacl_time.h"
#include "native_client/src/trusted/desc/nrd_all_modules.h"
-#include "ppapi/c/private/ppb_nacl_private.h"
-#include "ppapi/cpp/module.h"
+#include "ppapi/native_client/src/trusted/plugin/module_ppapi.h"
#include "ppapi/native_client/src/trusted/plugin/nacl_entry_points.h"
#include "ppapi/native_client/src/trusted/plugin/plugin.h"
namespace plugin {
-class ModulePpapi : public pp::Module {
- public:
- ModulePpapi() : pp::Module(),
- init_was_successful_(false),
- private_interface_(NULL) {
- MODULE_PRINTF(("ModulePpapi::ModulePpapi (this=%p)\n",
- static_cast<void*>(this)));
+ModulePpapi::ModulePpapi() : pp::Module(),
+ init_was_successful_(false),
+ private_interface_(NULL) {
+ MODULE_PRINTF(("ModulePpapi::ModulePpapi (this=%p)\n",
+ static_cast<void*>(this)));
+}
+
+ModulePpapi::~ModulePpapi() {
+ if (init_was_successful_) {
+ NaClSrpcModuleFini();
+ NaClNrdAllModulesFini();
+ }
+ MODULE_PRINTF(("ModulePpapi::~ModulePpapi (this=%p)\n",
+ static_cast<void*>(this)));
+}
+
+bool ModulePpapi::Init() {
+ // Ask the browser for an interface which provides missing functions
+ private_interface_ = reinterpret_cast<const PPB_NaCl_Private*>(
+ GetBrowserInterface(PPB_NACL_PRIVATE_INTERFACE));
+
+ if (NULL == private_interface_) {
+ MODULE_PRINTF(("ModulePpapi::Init failed: "
+ "GetBrowserInterface returned NULL\n"));
+ return false;
}
- virtual ~ModulePpapi() {
- if (init_was_successful_) {
- NaClSrpcModuleFini();
- NaClNrdAllModulesFini();
- }
- MODULE_PRINTF(("ModulePpapi::~ModulePpapi (this=%p)\n",
- static_cast<void*>(this)));
- }
-
- virtual bool Init() {
- // Ask the browser for an interface which provides missing functions
- private_interface_ = reinterpret_cast<const PPB_NaCl_Private*>(
- GetBrowserInterface(PPB_NACL_PRIVATE_INTERFACE));
-
- if (NULL == private_interface_) {
- MODULE_PRINTF(("ModulePpapi::Init failed: "
- "GetBrowserInterface returned NULL\n"));
- return false;
- }
-
- launch_nacl_process = reinterpret_cast<LaunchNaClProcessFunc>(
- private_interface_->LaunchSelLdr);
+ launch_nacl_process = reinterpret_cast<LaunchNaClProcessFunc>(
+ private_interface_->LaunchSelLdr);
#if NACL_LINUX || NACL_OSX
- // Note that currently we do not need random numbers inside the
- // NaCl trusted plugin on Unix, but NaClSecureRngModuleInit() is
- // strict and will raise a fatal error unless we provide it with a
- // /dev/urandom FD beforehand.
- NaClSecureRngModuleSetUrandomFd(dup(private_interface_->UrandomFD()));
+ // Note that currently we do not need random numbers inside the
+ // NaCl trusted plugin on Unix, but NaClSecureRngModuleInit() is
+ // strict and will raise a fatal error unless we provide it with a
+ // /dev/urandom FD beforehand.
+ NaClSecureRngModuleSetUrandomFd(dup(private_interface_->UrandomFD()));
#endif
- // In the plugin, we don't need high resolution time of day.
- NaClAllowLowResolutionTimeOfDay();
- NaClNrdAllModulesInit();
- NaClSrpcModuleInit();
+ // In the plugin, we don't need high resolution time of day.
+ NaClAllowLowResolutionTimeOfDay();
+ NaClNrdAllModulesInit();
+ NaClSrpcModuleInit();
#if NACL_WINDOWS
- NaClSetBrokerDuplicateHandleFunc(private_interface_->BrokerDuplicateHandle);
+ NaClSetBrokerDuplicateHandleFunc(private_interface_->BrokerDuplicateHandle);
#endif
- init_was_successful_ = true;
- return true;
- }
+ init_was_successful_ = true;
+ return true;
+}
- virtual pp::Instance* CreateInstance(PP_Instance pp_instance) {
- MODULE_PRINTF(("ModulePpapi::CreateInstance (pp_instance=%" NACL_PRId32
- ")\n",
- pp_instance));
- Plugin* plugin = Plugin::New(pp_instance);
- MODULE_PRINTF(("ModulePpapi::CreateInstance (return %p)\n",
- static_cast<void* >(plugin)));
- return plugin;
- }
+pp::Instance* ModulePpapi::CreateInstance(PP_Instance pp_instance) {
+ MODULE_PRINTF(("ModulePpapi::CreateInstance (pp_instance=%" NACL_PRId32
+ ")\n",
+ pp_instance));
+ Plugin* plugin = Plugin::New(pp_instance);
+ MODULE_PRINTF(("ModulePpapi::CreateInstance (return %p)\n",
+ static_cast<void* >(plugin)));
+ return plugin;
+}
- private:
- bool init_was_successful_;
- const PPB_NaCl_Private* private_interface_;
-};
+const uint64_t kMaxCrashesPerInterval = 3;
+const uint64_t kCrashesIntervalInSeconds = 120;
+
+void ModulePpapi::RegisterPluginCrash() {
+ PLUGIN_PRINTF(("ModulePpapi::RegisterPluginCrash ()\n"));
+ if (crash_times_.size() == kMaxCrashesPerInterval) {
+ crash_times_.pop_front();
+ }
+ int64_t time = NaClGetTimeOfDayMicroseconds();
+ crash_times_.push_back(time);
+}
+
+bool ModulePpapi::IsPluginUnstable() {
+ PLUGIN_PRINTF(("ModulePpapi::IsPluginUnstable ()\n"));
+ if (crash_times_.size() != kMaxCrashesPerInterval) {
+ return false;
+ }
+ int64_t now = NaClGetTimeOfDayMicroseconds();
+ int64_t delta = now - crash_times_.front();
+ return delta / (1000.0 * 1000.0) <= kCrashesIntervalInSeconds;
+}
} // namespace plugin
diff --git a/ppapi/native_client/src/trusted/plugin/module_ppapi.h b/ppapi/native_client/src/trusted/plugin/module_ppapi.h
new file mode 100644
index 0000000..b2e7564
--- /dev/null
+++ b/ppapi/native_client/src/trusted/plugin/module_ppapi.h
@@ -0,0 +1,45 @@
+/*
+ * 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 <deque>
+
+#include "ppapi/c/private/ppb_nacl_private.h"
+#include "ppapi/cpp/module.h"
+
+namespace plugin {
+
+class ModulePpapi : public pp::Module {
+ public:
+ ModulePpapi();
+
+ virtual ~ModulePpapi();
+
+ virtual bool Init();
+
+ virtual pp::Instance* CreateInstance(PP_Instance pp_instance);
+
+ // NaCl crash throttling. If RegisterPluginCrash is called too many times
+ // within a time period, IsPluginUnstable reports true. As long as
+ // IsPluginUnstable returns true, NaCl modules will fail to load.
+ void RegisterPluginCrash();
+ bool IsPluginUnstable();
+
+ private:
+ bool init_was_successful_;
+ const PPB_NaCl_Private* private_interface_;
+
+ // Crash throttling support.
+ std::deque<int64_t> crash_times_;
+};
+
+} // namespace plugin
+
+
+namespace pp {
+
+Module* CreateModule();
+
+} // namespace pp
diff --git a/ppapi/native_client/src/trusted/plugin/plugin.cc b/ppapi/native_client/src/trusted/plugin/plugin.cc
index 5cbb9d7..a4833ee 100644
--- a/ppapi/native_client/src/trusted/plugin/plugin.cc
+++ b/ppapi/native_client/src/trusted/plugin/plugin.cc
@@ -55,6 +55,7 @@
#include "ppapi/native_client/src/trusted/plugin/file_utils.h"
#include "ppapi/native_client/src/trusted/plugin/json_manifest.h"
+#include "ppapi/native_client/src/trusted/plugin/module_ppapi.h"
#include "ppapi/native_client/src/trusted/plugin/nacl_entry_points.h"
#include "ppapi/native_client/src/trusted/plugin/nacl_subprocess.h"
#include "ppapi/native_client/src/trusted/plugin/nexe_arch.h"
@@ -1009,6 +1010,10 @@
// invocation will just be a no-op, since all the crash log will
// have been received and we'll just get an EOF indication.
CopyCrashLogToJsConsole();
+
+ // Remember the nexe crash time, which helps determine the need to throttle.
+ ModulePpapi* module_ppapi = static_cast<ModulePpapi*>(pp::Module::Get());
+ module_ppapi->RegisterPluginCrash();
}
void Plugin::BitcodeDidTranslate(int32_t pp_error) {
@@ -1204,15 +1209,25 @@
EnqueueProgressEvent(kProgressEventProgress);
if (pnacl_options.translate()) {
if (this->nacl_interface()->IsPnaclEnabled()) {
- pp::CompletionCallback translate_callback =
- callback_factory_.NewCallback(&Plugin::BitcodeDidTranslate);
- // Will always call the callback on success or failure.
- pnacl_coordinator_.reset(
- PnaclCoordinator::BitcodeToNative(this,
- program_url,
- pnacl_options,
- translate_callback));
- return;
+ // Check whether PNaCl has been crashing "frequently". If so, report
+ // a load error.
+ ModulePpapi* module_ppapi =
+ static_cast<ModulePpapi*>(pp::Module::Get());
+ if (module_ppapi->IsPluginUnstable()) {
+ error_info.SetReport(ERROR_PNACL_CRASH_THROTTLED,
+ "PNaCl has been temporarily disabled because too"
+ " many crashes have been observed.");
+ } else {
+ pp::CompletionCallback translate_callback =
+ callback_factory_.NewCallback(&Plugin::BitcodeDidTranslate);
+ // Will always call the callback on success or failure.
+ pnacl_coordinator_.reset(
+ PnaclCoordinator::BitcodeToNative(this,
+ program_url,
+ pnacl_options,
+ translate_callback));
+ return;
+ }
} else {
error_info.SetReport(ERROR_PNACL_NOT_ENABLED,
"PNaCl has been disabled (e.g., by setting "
diff --git a/ppapi/native_client/src/trusted/plugin/plugin_error.h b/ppapi/native_client/src/trusted/plugin/plugin_error.h
index b5eb4d8..ac3fbf4 100644
--- a/ppapi/native_client/src/trusted/plugin/plugin_error.h
+++ b/ppapi/native_client/src/trusted/plugin/plugin_error.h
@@ -96,6 +96,7 @@
ERROR_PNACL_NOT_ENABLED = 68,
ERROR_MANIFEST_NOACCESS_URL = 69,
ERROR_NEXE_NOACCESS_URL = 70,
+ ERROR_PNACL_CRASH_THROTTLED = 71,
// If you add a code, read the enum comment above on how to update histograms.
ERROR_MAX
};
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
index 18b4fae..4362ec4 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
@@ -263,7 +263,7 @@
manifest_(new PnaclManifest()),
pexe_url_(pexe_url),
pnacl_options_(pnacl_options),
- use_new_cache_(false),
+ use_new_cache_(true),
is_cache_hit_(PP_FALSE),
nexe_handle_(PP_kInvalidFileHandle),
error_already_reported_(false),
@@ -275,9 +275,9 @@
PLUGIN_PRINTF(("PnaclCoordinator::PnaclCoordinator (this=%p, plugin=%p)\n",
static_cast<void*>(this), static_cast<void*>(plugin)));
callback_factory_.Initialize(this);
- if (getenv("PNACL_USE_NEW_CACHE")) {
- PLUGIN_PRINTF(("PnaclCoordinator using new translation cache\n"));
- use_new_cache_ = true;
+ if (getenv("PNACL_USE_OLD_CACHE")) {
+ PLUGIN_PRINTF(("PnaclCoordinator using old translation cache\n"));
+ use_new_cache_ = false;
}
}
@@ -397,6 +397,15 @@
// care of caching.
plugin_->nacl_interface()->ReportTranslationFinished(
plugin_->pp_instance(), PP_TRUE);
+
+ // These can maybe move up with the rest of the UMA stats when we remove
+ // the old cache code
+ int64_t total_time = NaClGetTimeOfDayMicroseconds() - pnacl_init_time_;
+ HistogramTime("NaCl.Perf.PNaClLoadTime.TotalUncachedTime",
+ total_time / NACL_MICROS_PER_MILLI);
+ HistogramKBPerSec("NaCl.Perf.PNaClLoadTime.TotalUncachedKBPerSec",
+ pexe_size_ / 1024.0,
+ total_time / 1000000.0);
NexeReadDidOpen(PP_OK);
return;
}
@@ -839,7 +848,7 @@
return;
}
- if (!off_the_record_) {
+ if (!off_the_record_ || use_new_cache_) {
// Get the cache key and try to open an existing entry.
nacl::string headers = streaming_downloader_->GetResponseHeaders();
NaClHttpResponseHeaders parser;
@@ -866,8 +875,9 @@
plugin_->nacl_interface()->GetNexeFd(
plugin_->pp_instance(),
streaming_downloader_->url().c_str(),
- // TODO(dschuff): use the right abi version here.
- 0,
+ // TODO(dschuff): Get this value from the pnacl json file after it
+ // rolls in from NaCl.
+ 1,
pnacl_options_.opt_level(),
parser.GetHeader("last-modified").c_str(),
parser.GetHeader("etag").c_str(),
@@ -912,11 +922,11 @@
"PnaclCoordinator: Got bad temp file handle from GetNexeFd"));
return;
}
+ HistogramEnumerateTranslationCache(is_cache_hit_);
+
if (is_cache_hit_ == PP_TRUE) {
// Cache hit -- no need to stream the rest of the file.
streaming_downloader_.reset(NULL);
- // TODO(dschuff): update UMA stats for hit/miss once there could actually
- // be hits/misses.
// Open it for reading as the cached nexe file.
pp::CompletionCallback cb =
callback_factory_.NewCallback(&PnaclCoordinator::NexeReadDidOpen);
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
index 06ff7c7..42f1207 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
@@ -79,9 +79,6 @@
// TRANSLATION_COMPLETE
// Complete when TranslateFinished is invoked.
//
-// If cache is enabled:
-// TODO: notify browser of finished translation (and re-open read-only?)
-//
// OPEN_NEXE_FOR_SEL_LDR
// Complete when NexeReadDidOpen is invoked.
class PnaclCoordinator: public CallbackSource<FileStreamData> {
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 aa68044..8bb17f7 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
@@ -2699,8 +2699,6 @@
/* End wrapper methods for PPB_Flash_DeviceID_1_0 */
-/* Not generating wrapper methods for PPB_Flash_DeviceID_1_1 */
-
/* Begin wrapper methods for PPB_Flash_DRM_1_0 */
static PP_Resource Pnacl_M29_PPB_Flash_DRM_Create(PP_Instance instance) {
@@ -4616,8 +4614,6 @@
.GetDeviceID = (int32_t (*)(PP_Resource device_id, struct PP_Var* id, struct PP_CompletionCallback callback))&Pnacl_M21_PPB_Flash_DeviceID_GetDeviceID
};
-/* Not generating wrapper interface for PPB_Flash_DeviceID_1_1 */
-
struct PPB_Flash_DRM_1_0 Pnacl_Wrappers_PPB_Flash_DRM_1_0 = {
.Create = (PP_Resource (*)(PP_Instance instance))&Pnacl_M29_PPB_Flash_DRM_Create,
.GetDeviceID = (int32_t (*)(PP_Resource drm, struct PP_Var* id, struct PP_CompletionCallback callback))&Pnacl_M29_PPB_Flash_DRM_GetDeviceID,
diff --git a/ppapi/native_client/src/untrusted/pnacl_irt_shim/shim_ppapi.c b/ppapi/native_client/src/untrusted/pnacl_irt_shim/shim_ppapi.c
index c6409cf..e73326e 100644
--- a/ppapi/native_client/src/untrusted/pnacl_irt_shim/shim_ppapi.c
+++ b/ppapi/native_client/src/untrusted/pnacl_irt_shim/shim_ppapi.c
@@ -70,7 +70,7 @@
NACL_IRT_CLOCK_v0_1,
/* Allowed for debugging purposes: */
NACL_IRT_DEV_FDIO_v0_1,
- NACL_IRT_DEV_FILENAME_v0_1,
+ NACL_IRT_DEV_FILENAME_v0_2,
};
/* Use local strcmp to avoid dependency on libc. */
diff --git a/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_component_crx_gen.py b/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_component_crx_gen.py
index 4a12c4a..3d35b3f 100755
--- a/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_component_crx_gen.py
+++ b/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_component_crx_gen.py
@@ -12,6 +12,7 @@
it depends on the pnacl_irt_shim.
"""
+import json
import logging
import optparse
import os
@@ -121,21 +122,13 @@
######################################################################
-def IsValidVersion(version):
- """ Return true if the version is a valid ID (a quad like 0.0.0.0).
- """
- pat = re.compile('^\d+\.\d+\.\d+\.\d+$')
- return pat.search(version)
-
-
-######################################################################
-
class PnaclPackaging(object):
package_base = os.path.dirname(__file__)
- # Pnacl-specific info - set from the command line.
+ # File paths that are set from the command line.
pnacl_template = None
+ tool_revisions = None
# Agreed-upon name for pnacl-specific info.
pnacl_json = 'pnacl.json'
@@ -145,20 +138,40 @@
PnaclPackaging.pnacl_template = path
@staticmethod
- def GeneratePnaclInfo(target_dir, version, arch, is_installer=False):
- pnacl_template_fd = open(PnaclPackaging.pnacl_template, 'r')
- pnacl_template = pnacl_template_fd.read()
- pnacl_template_fd.close()
- if is_installer:
+ def SetToolsRevisionPath(path):
+ PnaclPackaging.tool_revisions = path
+
+ @staticmethod
+ def PnaclToolsRevision():
+ with open(PnaclPackaging.tool_revisions, 'r') as f:
+ for line in f.read().splitlines():
+ if line.startswith('PNACL_VERSION'):
+ _, version = line.split('=')
+ # CWS happens to use version quads, so make it a quad too.
+ # However, each component of the quad is limited to 64K max.
+ # Try to handle a bit more.
+ max_version = 2 ** 16
+ version = int(version)
+ version_more = version / max_version
+ version = version % max_version
+ return '0.1.%d.%d' % (version_more, version)
+ raise Exception('Cannot find PNACL_VERSION in TOOL_REVISIONS file: %s' %
+ PnaclPackaging.tool_revisions)
+
+ @staticmethod
+ def GeneratePnaclInfo(target_dir, abi_version, arch):
+ # A note on versions: pnacl_version is the version of translator built
+ # by the NaCl repo, while abi_version is bumped when the NaCl sandbox
+ # actually changes.
+ pnacl_version = PnaclPackaging.PnaclToolsRevision()
+ with open(PnaclPackaging.pnacl_template, 'r') as pnacl_template_fd:
+ pnacl_template = json.load(pnacl_template_fd)
out_name = J(target_dir, UseWhitelistedChars(PnaclPackaging.pnacl_json,
None))
- else:
- out_name = J(target_dir, PnaclPackaging.pnacl_json)
- output_fd = open(out_name, 'w')
- output_fd.write(pnacl_template % { "abi-version" : version,
- "arch" : arch, })
- output_fd.close()
-
+ with open(out_name, 'w') as output_fd:
+ pnacl_template['pnacl-arch'] = arch
+ pnacl_template['pnacl-version'] = pnacl_version
+ json.dump(pnacl_template, output_fd, sort_keys=True, indent=4)
######################################################################
@@ -286,8 +299,7 @@
# Hack around the fact that there may be more than one arch, on Windows.
if len(arches) == 1:
arches = arches[0]
- PnaclPackaging.GeneratePnaclInfo(PnaclDirs.OutputDir(), version_quad,
- arches, is_installer=True)
+ PnaclPackaging.GeneratePnaclInfo(PnaclDirs.OutputDir(), version_quad, arches)
######################################################################
@@ -314,6 +326,8 @@
parser.add_option('--info_template_path',
dest='info_template_path', default=None,
help='Path of the info template file')
+ parser.add_option('--tool_revisions_path', dest='tool_revisions_path',
+ default=None, help='Location of NaCl TOOL_REVISIONS file.')
parser.add_option('-v', '--verbose', dest='verbose', default=False,
action='store_true',
help='Print verbose debug messages.')
@@ -336,6 +350,9 @@
if options.info_template_path:
PnaclPackaging.SetPnaclInfoTemplatePath(options.info_template_path)
+ if options.tool_revisions_path:
+ PnaclPackaging.SetToolsRevisionPath(options.tool_revisions_path)
+
lib_overrides = {}
for o in options.lib_overrides:
arch, override_lib = o.split(',')
@@ -353,13 +370,10 @@
parser.print_help()
parser.error('Incorrect number of arguments')
- version_quad = args[0]
- if not IsValidVersion(version_quad):
- print 'Invalid version format: %s\n' % version_quad
- return 1
+ abi_version = int(args[0])
arches = DetermineInstallerArches(options.target_arch)
- BuildInstallerStyle(version_quad, lib_overrides, arches)
+ BuildInstallerStyle(abi_version, lib_overrides, arches)
return 0
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 ece4452..e290eae 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
@@ -19,7 +19,7 @@
'../../../../../native_client/tools.gyp:prep_toolchain',
],
'sources': [
- '../../../../../native_client/pnacl/driver/pnacl_info_template.json',
+ 'pnacl_component_crx_gen.py',
],
# We could use 'copies', but we want to rename the files
# in a white-listed way first. Thus use a script.
@@ -30,6 +30,8 @@
'pnacl_component_crx_gen.py',
# A stamp file representing the contents of pnacl_translator.
'<(DEPTH)/native_client/toolchain/pnacl_translator/SOURCE_SHA1',
+ '<(DEPTH)/native_client/pnacl/driver/pnacl_info_template.json',
+ '<(DEPTH)/native_client/TOOL_REVISIONS',
],
'conditions': [
# On windows we need both ia32 and x64.
@@ -142,9 +144,10 @@
'--dest=<(PRODUCT_DIR)/pnacl',
'<@(lib_overrides)',
'--target_arch=<(target_arch)',
- '--info_template_path=../../../../../native_client/pnacl/driver/pnacl_info_template.json',
+ '--info_template_path=<(DEPTH)/native_client/pnacl/driver/pnacl_info_template.json',
+ '--tool_revisions_path=<(DEPTH)/native_client/TOOL_REVISIONS',
# ABI Version Number.
- '0.0.0.1',
+ '1',
],
},
],
diff --git a/ppapi/ppapi_c.target.darwin-arm.mk b/ppapi/ppapi_c.target.darwin-arm.mk
deleted file mode 100644
index 1ca820d..0000000
--- a/ppapi/ppapi_c.target.darwin-arm.mk
+++ /dev/null
@@ -1,205 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := ppapi_ppapi_c_gyp
-LOCAL_MODULE_STEM := ppapi_c
-LOCAL_MODULE_SUFFIX := .stamp
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES :=
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES :=
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_c_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_c
-ppapi_c: ppapi_ppapi_c_gyp
-
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
- $(hide) echo "Gyp timestamp: $@"
- $(hide) mkdir -p $(dir $@)
- $(hide) touch $@
diff --git a/ppapi/ppapi_c.target.darwin-mips.mk b/ppapi/ppapi_c.target.darwin-mips.mk
deleted file mode 100644
index 12a949b..0000000
--- a/ppapi/ppapi_c.target.darwin-mips.mk
+++ /dev/null
@@ -1,203 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := ppapi_ppapi_c_gyp
-LOCAL_MODULE_STEM := ppapi_c
-LOCAL_MODULE_SUFFIX := .stamp
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES :=
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES :=
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_c_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_c
-ppapi_c: ppapi_ppapi_c_gyp
-
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
- $(hide) echo "Gyp timestamp: $@"
- $(hide) mkdir -p $(dir $@)
- $(hide) touch $@
diff --git a/ppapi/ppapi_c.target.darwin-x86.mk b/ppapi/ppapi_c.target.darwin-x86.mk
deleted file mode 100644
index d8d46e0..0000000
--- a/ppapi/ppapi_c.target.darwin-x86.mk
+++ /dev/null
@@ -1,209 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := ppapi_ppapi_c_gyp
-LOCAL_MODULE_STEM := ppapi_c
-LOCAL_MODULE_SUFFIX := .stamp
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES :=
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES :=
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -fno-stack-protector \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -fno-stack-protector \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer \
- -fno-unwind-tables \
- -fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_c_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_c
-ppapi_c: ppapi_ppapi_c_gyp
-
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
- $(hide) echo "Gyp timestamp: $@"
- $(hide) mkdir -p $(dir $@)
- $(hide) touch $@
diff --git a/ppapi/ppapi_c.target.linux-arm.mk b/ppapi/ppapi_c.target.linux-arm.mk
deleted file mode 100644
index 1ca820d..0000000
--- a/ppapi/ppapi_c.target.linux-arm.mk
+++ /dev/null
@@ -1,205 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := ppapi_ppapi_c_gyp
-LOCAL_MODULE_STEM := ppapi_c
-LOCAL_MODULE_SUFFIX := .stamp
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES :=
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES :=
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_c_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_c
-ppapi_c: ppapi_ppapi_c_gyp
-
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
- $(hide) echo "Gyp timestamp: $@"
- $(hide) mkdir -p $(dir $@)
- $(hide) touch $@
diff --git a/ppapi/ppapi_c.target.linux-mips.mk b/ppapi/ppapi_c.target.linux-mips.mk
deleted file mode 100644
index 12a949b..0000000
--- a/ppapi/ppapi_c.target.linux-mips.mk
+++ /dev/null
@@ -1,203 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := ppapi_ppapi_c_gyp
-LOCAL_MODULE_STEM := ppapi_c
-LOCAL_MODULE_SUFFIX := .stamp
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES :=
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES :=
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_c_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_c
-ppapi_c: ppapi_ppapi_c_gyp
-
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
- $(hide) echo "Gyp timestamp: $@"
- $(hide) mkdir -p $(dir $@)
- $(hide) touch $@
diff --git a/ppapi/ppapi_c.target.linux-x86.mk b/ppapi/ppapi_c.target.linux-x86.mk
deleted file mode 100644
index d8d46e0..0000000
--- a/ppapi/ppapi_c.target.linux-x86.mk
+++ /dev/null
@@ -1,209 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := GYP
-LOCAL_MODULE := ppapi_ppapi_c_gyp
-LOCAL_MODULE_STEM := ppapi_c
-LOCAL_MODULE_SUFFIX := .stamp
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES :=
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES :=
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -fno-stack-protector \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -fno-stack-protector \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer \
- -fno-unwind-tables \
- -fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_c_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_c
-ppapi_c: ppapi_ppapi_c_gyp
-
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
-LOCAL_UNINSTALLABLE_MODULE := true
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
- $(hide) echo "Gyp timestamp: $@"
- $(hide) mkdir -p $(dir $@)
- $(hide) touch $@
diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi
index 884dc15..e700d2c 100644
--- a/ppapi/ppapi_proxy.gypi
+++ b/ppapi/ppapi_proxy.gypi
@@ -113,8 +113,6 @@
'proxy/ppb_buffer_proxy.h',
'proxy/ppb_core_proxy.cc',
'proxy/ppb_core_proxy.h',
- 'proxy/ppb_file_ref_proxy.cc',
- 'proxy/ppb_file_ref_proxy.h',
'proxy/ppb_flash_message_loop_proxy.cc',
'proxy/ppb_flash_message_loop_proxy.h',
'proxy/ppb_graphics_3d_proxy.cc',
diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi
index 1160143..f3129f8 100644
--- a/ppapi/ppapi_shared.gypi
+++ b/ppapi/ppapi_shared.gypi
@@ -23,7 +23,9 @@
'shared_impl/file_io_state_manager.h',
'shared_impl/file_path.cc',
'shared_impl/file_path.h',
+ 'shared_impl/file_ref_create_info.cc',
'shared_impl/file_ref_create_info.h',
+ 'shared_impl/file_ref_detailed_info.h',
'shared_impl/file_ref_util.cc',
'shared_impl/file_ref_util.h',
'shared_impl/file_type_conversion.cc',
@@ -53,8 +55,6 @@
'shared_impl/ppb_crypto_shared.cc',
'shared_impl/ppb_device_ref_shared.cc',
'shared_impl/ppb_device_ref_shared.h',
- 'shared_impl/ppb_file_ref_shared.cc',
- 'shared_impl/ppb_file_ref_shared.h',
'shared_impl/ppb_gamepad_shared.cc',
'shared_impl/ppb_gamepad_shared.h',
'shared_impl/ppb_graphics_3d_shared.cc',
diff --git a/ppapi/ppapi_shared.target.darwin-arm.mk b/ppapi/ppapi_shared.target.darwin-arm.mk
deleted file mode 100644
index 2ad0583..0000000
--- a/ppapi/ppapi_shared.target.darwin-arm.mk
+++ /dev/null
@@ -1,459 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := ppapi_ppapi_shared_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
- $(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- ppapi/shared_impl/array_var.cc \
- ppapi/shared_impl/array_writer.cc \
- ppapi/shared_impl/callback_tracker.cc \
- ppapi/shared_impl/dictionary_var.cc \
- ppapi/shared_impl/file_io_state_manager.cc \
- ppapi/shared_impl/file_path.cc \
- ppapi/shared_impl/file_ref_util.cc \
- ppapi/shared_impl/file_type_conversion.cc \
- ppapi/shared_impl/flash_clipboard_format_registry.cc \
- ppapi/shared_impl/host_resource.cc \
- ppapi/shared_impl/id_assignment.cc \
- ppapi/shared_impl/platform_file.cc \
- ppapi/shared_impl/ppapi_globals.cc \
- ppapi/shared_impl/ppapi_nacl_channel_args.cc \
- ppapi/shared_impl/ppapi_permissions.cc \
- ppapi/shared_impl/ppapi_preferences.cc \
- ppapi/shared_impl/ppapi_switches.cc \
- ppapi/shared_impl/ppb_audio_config_shared.cc \
- ppapi/shared_impl/ppb_audio_shared.cc \
- ppapi/shared_impl/ppb_crypto_shared.cc \
- ppapi/shared_impl/ppb_device_ref_shared.cc \
- ppapi/shared_impl/ppb_file_ref_shared.cc \
- ppapi/shared_impl/ppb_gamepad_shared.cc \
- ppapi/shared_impl/ppb_graphics_3d_shared.cc \
- ppapi/shared_impl/ppb_image_data_shared.cc \
- ppapi/shared_impl/ppb_input_event_shared.cc \
- ppapi/shared_impl/ppb_instance_shared.cc \
- ppapi/shared_impl/ppb_memory_shared.cc \
- ppapi/shared_impl/ppb_message_loop_shared.cc \
- ppapi/shared_impl/ppb_network_list_private_shared.cc \
- ppapi/shared_impl/ppb_opengles2_shared.cc \
- ppapi/shared_impl/ppb_resource_array_shared.cc \
- ppapi/shared_impl/ppb_trace_event_impl.cc \
- ppapi/shared_impl/ppb_url_util_shared.cc \
- ppapi/shared_impl/ppb_var_shared.cc \
- ppapi/shared_impl/ppb_video_decoder_shared.cc \
- ppapi/shared_impl/ppb_view_shared.cc \
- ppapi/shared_impl/ppp_instance_combined.cc \
- ppapi/shared_impl/proxy_lock.cc \
- ppapi/shared_impl/resource.cc \
- ppapi/shared_impl/resource_tracker.cc \
- ppapi/shared_impl/scoped_pp_resource.cc \
- ppapi/shared_impl/scoped_pp_var.cc \
- ppapi/shared_impl/socket_option_data.cc \
- ppapi/shared_impl/tcp_socket_shared.cc \
- ppapi/shared_impl/thread_aware_callback.cc \
- ppapi/shared_impl/time_conversion.cc \
- ppapi/shared_impl/tracked_callback.cc \
- ppapi/shared_impl/url_request_info_data.cc \
- ppapi/shared_impl/url_response_info_data.cc \
- ppapi/shared_impl/var.cc \
- ppapi/shared_impl/var_tracker.cc \
- ppapi/shared_impl/var_value_conversions.cc \
- ppapi/shared_impl/private/net_address_private_impl.cc \
- ppapi/shared_impl/private/net_address_private_impl_constants.cc \
- ppapi/shared_impl/private/ppb_char_set_shared.cc \
- ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc \
- ppapi/shared_impl/private/tcp_socket_private_impl.cc \
- ppapi/thunk/enter.cc \
- ppapi/thunk/ppb_audio_config_thunk.cc \
- ppapi/thunk/ppb_audio_input_dev_thunk.cc \
- ppapi/thunk/ppb_audio_thunk.cc \
- ppapi/thunk/ppb_broker_thunk.cc \
- ppapi/thunk/ppb_browser_font_trusted_thunk.cc \
- ppapi/thunk/ppb_buffer_thunk.cc \
- ppapi/thunk/ppb_char_set_thunk.cc \
- ppapi/thunk/ppb_console_thunk.cc \
- ppapi/thunk/ppb_content_decryptor_private_thunk.cc \
- ppapi/thunk/ppb_cursor_control_thunk.cc \
- ppapi/thunk/ppb_device_ref_dev_thunk.cc \
- ppapi/thunk/ppb_ext_alarms_thunk.cc \
- ppapi/thunk/ppb_ext_crx_file_system_private_thunk.cc \
- ppapi/thunk/ppb_ext_socket_thunk.cc \
- ppapi/thunk/ppb_file_chooser_dev_thunk.cc \
- ppapi/thunk/ppb_file_chooser_trusted_thunk.cc \
- ppapi/thunk/ppb_file_io_private_thunk.cc \
- ppapi/thunk/ppb_file_io_thunk.cc \
- ppapi/thunk/ppb_file_io_trusted_thunk.cc \
- ppapi/thunk/ppb_file_ref_thunk.cc \
- ppapi/thunk/ppb_file_system_thunk.cc \
- ppapi/thunk/ppb_find_dev_thunk.cc \
- ppapi/thunk/ppb_flash_clipboard_thunk.cc \
- ppapi/thunk/ppb_flash_device_id_thunk.cc \
- ppapi/thunk/ppb_flash_drm_thunk.cc \
- ppapi/thunk/ppb_flash_file_fileref_thunk.cc \
- ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc \
- ppapi/thunk/ppb_flash_font_file_thunk.cc \
- ppapi/thunk/ppb_flash_fullscreen_thunk.cc \
- ppapi/thunk/ppb_flash_menu_thunk.cc \
- ppapi/thunk/ppb_flash_message_loop_thunk.cc \
- ppapi/thunk/ppb_flash_print_thunk.cc \
- ppapi/thunk/ppb_flash_thunk.cc \
- ppapi/thunk/ppb_fullscreen_thunk.cc \
- ppapi/thunk/ppb_gamepad_thunk.cc \
- ppapi/thunk/ppb_gles_chromium_texture_mapping_thunk.cc \
- ppapi/thunk/ppb_graphics_2d_dev_thunk.cc \
- ppapi/thunk/ppb_graphics_2d_thunk.cc \
- ppapi/thunk/ppb_graphics_3d_thunk.cc \
- ppapi/thunk/ppb_host_resolver_thunk.cc \
- ppapi/thunk/ppb_host_resolver_private_thunk.cc \
- ppapi/thunk/ppb_image_data_thunk.cc \
- ppapi/thunk/ppb_input_event_thunk.cc \
- ppapi/thunk/ppb_instance_private_thunk.cc \
- ppapi/thunk/ppb_instance_thunk.cc \
- ppapi/thunk/ppb_messaging_thunk.cc \
- ppapi/thunk/ppb_mouse_cursor_thunk.cc \
- ppapi/thunk/ppb_mouse_lock_thunk.cc \
- ppapi/thunk/ppb_net_address_thunk.cc \
- ppapi/thunk/ppb_network_list_private_thunk.cc \
- ppapi/thunk/ppb_network_monitor_private_thunk.cc \
- ppapi/thunk/ppb_network_proxy_thunk.cc \
- ppapi/thunk/ppb_pdf_thunk.cc \
- ppapi/thunk/ppb_printing_dev_thunk.cc \
- ppapi/thunk/ppb_resource_array_dev_thunk.cc \
- ppapi/thunk/ppb_scrollbar_thunk.cc \
- ppapi/thunk/ppb_talk_private_thunk.cc \
- ppapi/thunk/ppb_tcp_server_socket_private_thunk.cc \
- ppapi/thunk/ppb_tcp_socket_private_thunk.cc \
- ppapi/thunk/ppb_tcp_socket_thunk.cc \
- ppapi/thunk/ppb_text_input_thunk.cc \
- ppapi/thunk/ppb_truetype_font_dev_thunk.cc \
- ppapi/thunk/ppb_udp_socket_thunk.cc \
- ppapi/thunk/ppb_udp_socket_private_thunk.cc \
- ppapi/thunk/ppb_url_loader_thunk.cc \
- ppapi/thunk/ppb_url_loader_trusted_thunk.cc \
- ppapi/thunk/ppb_url_request_info_thunk.cc \
- ppapi/thunk/ppb_url_response_info_thunk.cc \
- ppapi/thunk/ppb_url_util_thunk.cc \
- ppapi/thunk/ppb_var_array_thunk.cc \
- ppapi/thunk/ppb_var_dictionary_thunk.cc \
- ppapi/thunk/ppb_video_capture_thunk.cc \
- ppapi/thunk/ppb_video_decoder_thunk.cc \
- ppapi/thunk/ppb_video_destination_private_thunk.cc \
- ppapi/thunk/ppb_video_source_private_thunk.cc \
- ppapi/thunk/ppb_view_dev_thunk.cc \
- ppapi/thunk/ppb_view_thunk.cc \
- ppapi/thunk/ppb_websocket_thunk.cc \
- ppapi/thunk/ppb_widget_dev_thunk.cc \
- ppapi/thunk/ppb_x509_certificate_private_thunk.cc \
- ppapi/thunk/ppb_zoom_dev_thunk.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DPPAPI_SHARED_IMPLEMENTATION' \
- '-DPPAPI_THUNK_IMPLEMENTATION' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/WebKit \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DPPAPI_SHARED_IMPLEMENTATION' \
- '-DPPAPI_THUNK_IMPLEMENTATION' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/WebKit \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -Wl,-z,relro \
- -Wl,-z,now \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--icf=safe \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -Wl,-z,relro \
- -Wl,-z,now \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--icf=safe \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- skia_skia_library_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_shared_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_shared
-ppapi_shared: ppapi_ppapi_shared_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/ppapi/ppapi_shared.target.darwin-mips.mk b/ppapi/ppapi_shared.target.darwin-mips.mk
deleted file mode 100644
index d785a4c..0000000
--- a/ppapi/ppapi_shared.target.darwin-mips.mk
+++ /dev/null
@@ -1,453 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := ppapi_ppapi_shared_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
- $(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- ppapi/shared_impl/array_var.cc \
- ppapi/shared_impl/array_writer.cc \
- ppapi/shared_impl/callback_tracker.cc \
- ppapi/shared_impl/dictionary_var.cc \
- ppapi/shared_impl/file_io_state_manager.cc \
- ppapi/shared_impl/file_path.cc \
- ppapi/shared_impl/file_ref_util.cc \
- ppapi/shared_impl/file_type_conversion.cc \
- ppapi/shared_impl/flash_clipboard_format_registry.cc \
- ppapi/shared_impl/host_resource.cc \
- ppapi/shared_impl/id_assignment.cc \
- ppapi/shared_impl/platform_file.cc \
- ppapi/shared_impl/ppapi_globals.cc \
- ppapi/shared_impl/ppapi_nacl_channel_args.cc \
- ppapi/shared_impl/ppapi_permissions.cc \
- ppapi/shared_impl/ppapi_preferences.cc \
- ppapi/shared_impl/ppapi_switches.cc \
- ppapi/shared_impl/ppb_audio_config_shared.cc \
- ppapi/shared_impl/ppb_audio_shared.cc \
- ppapi/shared_impl/ppb_crypto_shared.cc \
- ppapi/shared_impl/ppb_device_ref_shared.cc \
- ppapi/shared_impl/ppb_file_ref_shared.cc \
- ppapi/shared_impl/ppb_gamepad_shared.cc \
- ppapi/shared_impl/ppb_graphics_3d_shared.cc \
- ppapi/shared_impl/ppb_image_data_shared.cc \
- ppapi/shared_impl/ppb_input_event_shared.cc \
- ppapi/shared_impl/ppb_instance_shared.cc \
- ppapi/shared_impl/ppb_memory_shared.cc \
- ppapi/shared_impl/ppb_message_loop_shared.cc \
- ppapi/shared_impl/ppb_network_list_private_shared.cc \
- ppapi/shared_impl/ppb_opengles2_shared.cc \
- ppapi/shared_impl/ppb_resource_array_shared.cc \
- ppapi/shared_impl/ppb_trace_event_impl.cc \
- ppapi/shared_impl/ppb_url_util_shared.cc \
- ppapi/shared_impl/ppb_var_shared.cc \
- ppapi/shared_impl/ppb_video_decoder_shared.cc \
- ppapi/shared_impl/ppb_view_shared.cc \
- ppapi/shared_impl/ppp_instance_combined.cc \
- ppapi/shared_impl/proxy_lock.cc \
- ppapi/shared_impl/resource.cc \
- ppapi/shared_impl/resource_tracker.cc \
- ppapi/shared_impl/scoped_pp_resource.cc \
- ppapi/shared_impl/scoped_pp_var.cc \
- ppapi/shared_impl/socket_option_data.cc \
- ppapi/shared_impl/tcp_socket_shared.cc \
- ppapi/shared_impl/thread_aware_callback.cc \
- ppapi/shared_impl/time_conversion.cc \
- ppapi/shared_impl/tracked_callback.cc \
- ppapi/shared_impl/url_request_info_data.cc \
- ppapi/shared_impl/url_response_info_data.cc \
- ppapi/shared_impl/var.cc \
- ppapi/shared_impl/var_tracker.cc \
- ppapi/shared_impl/var_value_conversions.cc \
- ppapi/shared_impl/private/net_address_private_impl.cc \
- ppapi/shared_impl/private/net_address_private_impl_constants.cc \
- ppapi/shared_impl/private/ppb_char_set_shared.cc \
- ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc \
- ppapi/shared_impl/private/tcp_socket_private_impl.cc \
- ppapi/thunk/enter.cc \
- ppapi/thunk/ppb_audio_config_thunk.cc \
- ppapi/thunk/ppb_audio_input_dev_thunk.cc \
- ppapi/thunk/ppb_audio_thunk.cc \
- ppapi/thunk/ppb_broker_thunk.cc \
- ppapi/thunk/ppb_browser_font_trusted_thunk.cc \
- ppapi/thunk/ppb_buffer_thunk.cc \
- ppapi/thunk/ppb_char_set_thunk.cc \
- ppapi/thunk/ppb_console_thunk.cc \
- ppapi/thunk/ppb_content_decryptor_private_thunk.cc \
- ppapi/thunk/ppb_cursor_control_thunk.cc \
- ppapi/thunk/ppb_device_ref_dev_thunk.cc \
- ppapi/thunk/ppb_ext_alarms_thunk.cc \
- ppapi/thunk/ppb_ext_crx_file_system_private_thunk.cc \
- ppapi/thunk/ppb_ext_socket_thunk.cc \
- ppapi/thunk/ppb_file_chooser_dev_thunk.cc \
- ppapi/thunk/ppb_file_chooser_trusted_thunk.cc \
- ppapi/thunk/ppb_file_io_private_thunk.cc \
- ppapi/thunk/ppb_file_io_thunk.cc \
- ppapi/thunk/ppb_file_io_trusted_thunk.cc \
- ppapi/thunk/ppb_file_ref_thunk.cc \
- ppapi/thunk/ppb_file_system_thunk.cc \
- ppapi/thunk/ppb_find_dev_thunk.cc \
- ppapi/thunk/ppb_flash_clipboard_thunk.cc \
- ppapi/thunk/ppb_flash_device_id_thunk.cc \
- ppapi/thunk/ppb_flash_drm_thunk.cc \
- ppapi/thunk/ppb_flash_file_fileref_thunk.cc \
- ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc \
- ppapi/thunk/ppb_flash_font_file_thunk.cc \
- ppapi/thunk/ppb_flash_fullscreen_thunk.cc \
- ppapi/thunk/ppb_flash_menu_thunk.cc \
- ppapi/thunk/ppb_flash_message_loop_thunk.cc \
- ppapi/thunk/ppb_flash_print_thunk.cc \
- ppapi/thunk/ppb_flash_thunk.cc \
- ppapi/thunk/ppb_fullscreen_thunk.cc \
- ppapi/thunk/ppb_gamepad_thunk.cc \
- ppapi/thunk/ppb_gles_chromium_texture_mapping_thunk.cc \
- ppapi/thunk/ppb_graphics_2d_dev_thunk.cc \
- ppapi/thunk/ppb_graphics_2d_thunk.cc \
- ppapi/thunk/ppb_graphics_3d_thunk.cc \
- ppapi/thunk/ppb_host_resolver_thunk.cc \
- ppapi/thunk/ppb_host_resolver_private_thunk.cc \
- ppapi/thunk/ppb_image_data_thunk.cc \
- ppapi/thunk/ppb_input_event_thunk.cc \
- ppapi/thunk/ppb_instance_private_thunk.cc \
- ppapi/thunk/ppb_instance_thunk.cc \
- ppapi/thunk/ppb_messaging_thunk.cc \
- ppapi/thunk/ppb_mouse_cursor_thunk.cc \
- ppapi/thunk/ppb_mouse_lock_thunk.cc \
- ppapi/thunk/ppb_net_address_thunk.cc \
- ppapi/thunk/ppb_network_list_private_thunk.cc \
- ppapi/thunk/ppb_network_monitor_private_thunk.cc \
- ppapi/thunk/ppb_network_proxy_thunk.cc \
- ppapi/thunk/ppb_pdf_thunk.cc \
- ppapi/thunk/ppb_printing_dev_thunk.cc \
- ppapi/thunk/ppb_resource_array_dev_thunk.cc \
- ppapi/thunk/ppb_scrollbar_thunk.cc \
- ppapi/thunk/ppb_talk_private_thunk.cc \
- ppapi/thunk/ppb_tcp_server_socket_private_thunk.cc \
- ppapi/thunk/ppb_tcp_socket_private_thunk.cc \
- ppapi/thunk/ppb_tcp_socket_thunk.cc \
- ppapi/thunk/ppb_text_input_thunk.cc \
- ppapi/thunk/ppb_truetype_font_dev_thunk.cc \
- ppapi/thunk/ppb_udp_socket_thunk.cc \
- ppapi/thunk/ppb_udp_socket_private_thunk.cc \
- ppapi/thunk/ppb_url_loader_thunk.cc \
- ppapi/thunk/ppb_url_loader_trusted_thunk.cc \
- ppapi/thunk/ppb_url_request_info_thunk.cc \
- ppapi/thunk/ppb_url_response_info_thunk.cc \
- ppapi/thunk/ppb_url_util_thunk.cc \
- ppapi/thunk/ppb_var_array_thunk.cc \
- ppapi/thunk/ppb_var_dictionary_thunk.cc \
- ppapi/thunk/ppb_video_capture_thunk.cc \
- ppapi/thunk/ppb_video_decoder_thunk.cc \
- ppapi/thunk/ppb_video_destination_private_thunk.cc \
- ppapi/thunk/ppb_video_source_private_thunk.cc \
- ppapi/thunk/ppb_view_dev_thunk.cc \
- ppapi/thunk/ppb_view_thunk.cc \
- ppapi/thunk/ppb_websocket_thunk.cc \
- ppapi/thunk/ppb_widget_dev_thunk.cc \
- ppapi/thunk/ppb_x509_certificate_private_thunk.cc \
- ppapi/thunk/ppb_zoom_dev_thunk.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DPPAPI_SHARED_IMPLEMENTATION' \
- '-DPPAPI_THUNK_IMPLEMENTATION' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/WebKit \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DPPAPI_SHARED_IMPLEMENTATION' \
- '-DPPAPI_THUNK_IMPLEMENTATION' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/WebKit \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -EL \
- -Wl,--no-keep-memory \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -EL \
- -Wl,--no-keep-memory \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- skia_skia_library_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_shared_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_shared
-ppapi_shared: ppapi_ppapi_shared_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/ppapi/ppapi_shared.target.darwin-x86.mk b/ppapi/ppapi_shared.target.darwin-x86.mk
deleted file mode 100644
index 3cac2e9..0000000
--- a/ppapi/ppapi_shared.target.darwin-x86.mk
+++ /dev/null
@@ -1,459 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := ppapi_ppapi_shared_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
- $(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- ppapi/shared_impl/array_var.cc \
- ppapi/shared_impl/array_writer.cc \
- ppapi/shared_impl/callback_tracker.cc \
- ppapi/shared_impl/dictionary_var.cc \
- ppapi/shared_impl/file_io_state_manager.cc \
- ppapi/shared_impl/file_path.cc \
- ppapi/shared_impl/file_ref_util.cc \
- ppapi/shared_impl/file_type_conversion.cc \
- ppapi/shared_impl/flash_clipboard_format_registry.cc \
- ppapi/shared_impl/host_resource.cc \
- ppapi/shared_impl/id_assignment.cc \
- ppapi/shared_impl/platform_file.cc \
- ppapi/shared_impl/ppapi_globals.cc \
- ppapi/shared_impl/ppapi_nacl_channel_args.cc \
- ppapi/shared_impl/ppapi_permissions.cc \
- ppapi/shared_impl/ppapi_preferences.cc \
- ppapi/shared_impl/ppapi_switches.cc \
- ppapi/shared_impl/ppb_audio_config_shared.cc \
- ppapi/shared_impl/ppb_audio_shared.cc \
- ppapi/shared_impl/ppb_crypto_shared.cc \
- ppapi/shared_impl/ppb_device_ref_shared.cc \
- ppapi/shared_impl/ppb_file_ref_shared.cc \
- ppapi/shared_impl/ppb_gamepad_shared.cc \
- ppapi/shared_impl/ppb_graphics_3d_shared.cc \
- ppapi/shared_impl/ppb_image_data_shared.cc \
- ppapi/shared_impl/ppb_input_event_shared.cc \
- ppapi/shared_impl/ppb_instance_shared.cc \
- ppapi/shared_impl/ppb_memory_shared.cc \
- ppapi/shared_impl/ppb_message_loop_shared.cc \
- ppapi/shared_impl/ppb_network_list_private_shared.cc \
- ppapi/shared_impl/ppb_opengles2_shared.cc \
- ppapi/shared_impl/ppb_resource_array_shared.cc \
- ppapi/shared_impl/ppb_trace_event_impl.cc \
- ppapi/shared_impl/ppb_url_util_shared.cc \
- ppapi/shared_impl/ppb_var_shared.cc \
- ppapi/shared_impl/ppb_video_decoder_shared.cc \
- ppapi/shared_impl/ppb_view_shared.cc \
- ppapi/shared_impl/ppp_instance_combined.cc \
- ppapi/shared_impl/proxy_lock.cc \
- ppapi/shared_impl/resource.cc \
- ppapi/shared_impl/resource_tracker.cc \
- ppapi/shared_impl/scoped_pp_resource.cc \
- ppapi/shared_impl/scoped_pp_var.cc \
- ppapi/shared_impl/socket_option_data.cc \
- ppapi/shared_impl/tcp_socket_shared.cc \
- ppapi/shared_impl/thread_aware_callback.cc \
- ppapi/shared_impl/time_conversion.cc \
- ppapi/shared_impl/tracked_callback.cc \
- ppapi/shared_impl/url_request_info_data.cc \
- ppapi/shared_impl/url_response_info_data.cc \
- ppapi/shared_impl/var.cc \
- ppapi/shared_impl/var_tracker.cc \
- ppapi/shared_impl/var_value_conversions.cc \
- ppapi/shared_impl/private/net_address_private_impl.cc \
- ppapi/shared_impl/private/net_address_private_impl_constants.cc \
- ppapi/shared_impl/private/ppb_char_set_shared.cc \
- ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc \
- ppapi/shared_impl/private/tcp_socket_private_impl.cc \
- ppapi/thunk/enter.cc \
- ppapi/thunk/ppb_audio_config_thunk.cc \
- ppapi/thunk/ppb_audio_input_dev_thunk.cc \
- ppapi/thunk/ppb_audio_thunk.cc \
- ppapi/thunk/ppb_broker_thunk.cc \
- ppapi/thunk/ppb_browser_font_trusted_thunk.cc \
- ppapi/thunk/ppb_buffer_thunk.cc \
- ppapi/thunk/ppb_char_set_thunk.cc \
- ppapi/thunk/ppb_console_thunk.cc \
- ppapi/thunk/ppb_content_decryptor_private_thunk.cc \
- ppapi/thunk/ppb_cursor_control_thunk.cc \
- ppapi/thunk/ppb_device_ref_dev_thunk.cc \
- ppapi/thunk/ppb_ext_alarms_thunk.cc \
- ppapi/thunk/ppb_ext_crx_file_system_private_thunk.cc \
- ppapi/thunk/ppb_ext_socket_thunk.cc \
- ppapi/thunk/ppb_file_chooser_dev_thunk.cc \
- ppapi/thunk/ppb_file_chooser_trusted_thunk.cc \
- ppapi/thunk/ppb_file_io_private_thunk.cc \
- ppapi/thunk/ppb_file_io_thunk.cc \
- ppapi/thunk/ppb_file_io_trusted_thunk.cc \
- ppapi/thunk/ppb_file_ref_thunk.cc \
- ppapi/thunk/ppb_file_system_thunk.cc \
- ppapi/thunk/ppb_find_dev_thunk.cc \
- ppapi/thunk/ppb_flash_clipboard_thunk.cc \
- ppapi/thunk/ppb_flash_device_id_thunk.cc \
- ppapi/thunk/ppb_flash_drm_thunk.cc \
- ppapi/thunk/ppb_flash_file_fileref_thunk.cc \
- ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc \
- ppapi/thunk/ppb_flash_font_file_thunk.cc \
- ppapi/thunk/ppb_flash_fullscreen_thunk.cc \
- ppapi/thunk/ppb_flash_menu_thunk.cc \
- ppapi/thunk/ppb_flash_message_loop_thunk.cc \
- ppapi/thunk/ppb_flash_print_thunk.cc \
- ppapi/thunk/ppb_flash_thunk.cc \
- ppapi/thunk/ppb_fullscreen_thunk.cc \
- ppapi/thunk/ppb_gamepad_thunk.cc \
- ppapi/thunk/ppb_gles_chromium_texture_mapping_thunk.cc \
- ppapi/thunk/ppb_graphics_2d_dev_thunk.cc \
- ppapi/thunk/ppb_graphics_2d_thunk.cc \
- ppapi/thunk/ppb_graphics_3d_thunk.cc \
- ppapi/thunk/ppb_host_resolver_thunk.cc \
- ppapi/thunk/ppb_host_resolver_private_thunk.cc \
- ppapi/thunk/ppb_image_data_thunk.cc \
- ppapi/thunk/ppb_input_event_thunk.cc \
- ppapi/thunk/ppb_instance_private_thunk.cc \
- ppapi/thunk/ppb_instance_thunk.cc \
- ppapi/thunk/ppb_messaging_thunk.cc \
- ppapi/thunk/ppb_mouse_cursor_thunk.cc \
- ppapi/thunk/ppb_mouse_lock_thunk.cc \
- ppapi/thunk/ppb_net_address_thunk.cc \
- ppapi/thunk/ppb_network_list_private_thunk.cc \
- ppapi/thunk/ppb_network_monitor_private_thunk.cc \
- ppapi/thunk/ppb_network_proxy_thunk.cc \
- ppapi/thunk/ppb_pdf_thunk.cc \
- ppapi/thunk/ppb_printing_dev_thunk.cc \
- ppapi/thunk/ppb_resource_array_dev_thunk.cc \
- ppapi/thunk/ppb_scrollbar_thunk.cc \
- ppapi/thunk/ppb_talk_private_thunk.cc \
- ppapi/thunk/ppb_tcp_server_socket_private_thunk.cc \
- ppapi/thunk/ppb_tcp_socket_private_thunk.cc \
- ppapi/thunk/ppb_tcp_socket_thunk.cc \
- ppapi/thunk/ppb_text_input_thunk.cc \
- ppapi/thunk/ppb_truetype_font_dev_thunk.cc \
- ppapi/thunk/ppb_udp_socket_thunk.cc \
- ppapi/thunk/ppb_udp_socket_private_thunk.cc \
- ppapi/thunk/ppb_url_loader_thunk.cc \
- ppapi/thunk/ppb_url_loader_trusted_thunk.cc \
- ppapi/thunk/ppb_url_request_info_thunk.cc \
- ppapi/thunk/ppb_url_response_info_thunk.cc \
- ppapi/thunk/ppb_url_util_thunk.cc \
- ppapi/thunk/ppb_var_array_thunk.cc \
- ppapi/thunk/ppb_var_dictionary_thunk.cc \
- ppapi/thunk/ppb_video_capture_thunk.cc \
- ppapi/thunk/ppb_video_decoder_thunk.cc \
- ppapi/thunk/ppb_video_destination_private_thunk.cc \
- ppapi/thunk/ppb_video_source_private_thunk.cc \
- ppapi/thunk/ppb_view_dev_thunk.cc \
- ppapi/thunk/ppb_view_thunk.cc \
- ppapi/thunk/ppb_websocket_thunk.cc \
- ppapi/thunk/ppb_widget_dev_thunk.cc \
- ppapi/thunk/ppb_x509_certificate_private_thunk.cc \
- ppapi/thunk/ppb_zoom_dev_thunk.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -fno-stack-protector \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DPPAPI_SHARED_IMPLEMENTATION' \
- '-DPPAPI_THUNK_IMPLEMENTATION' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/WebKit \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -fno-stack-protector \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer \
- -fno-unwind-tables \
- -fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DPPAPI_SHARED_IMPLEMENTATION' \
- '-DPPAPI_THUNK_IMPLEMENTATION' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/WebKit \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -m32 \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -m32 \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- skia_skia_library_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_shared_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_shared
-ppapi_shared: ppapi_ppapi_shared_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/ppapi/ppapi_shared.target.linux-arm.mk b/ppapi/ppapi_shared.target.linux-arm.mk
deleted file mode 100644
index 2ad0583..0000000
--- a/ppapi/ppapi_shared.target.linux-arm.mk
+++ /dev/null
@@ -1,459 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := ppapi_ppapi_shared_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
- $(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- ppapi/shared_impl/array_var.cc \
- ppapi/shared_impl/array_writer.cc \
- ppapi/shared_impl/callback_tracker.cc \
- ppapi/shared_impl/dictionary_var.cc \
- ppapi/shared_impl/file_io_state_manager.cc \
- ppapi/shared_impl/file_path.cc \
- ppapi/shared_impl/file_ref_util.cc \
- ppapi/shared_impl/file_type_conversion.cc \
- ppapi/shared_impl/flash_clipboard_format_registry.cc \
- ppapi/shared_impl/host_resource.cc \
- ppapi/shared_impl/id_assignment.cc \
- ppapi/shared_impl/platform_file.cc \
- ppapi/shared_impl/ppapi_globals.cc \
- ppapi/shared_impl/ppapi_nacl_channel_args.cc \
- ppapi/shared_impl/ppapi_permissions.cc \
- ppapi/shared_impl/ppapi_preferences.cc \
- ppapi/shared_impl/ppapi_switches.cc \
- ppapi/shared_impl/ppb_audio_config_shared.cc \
- ppapi/shared_impl/ppb_audio_shared.cc \
- ppapi/shared_impl/ppb_crypto_shared.cc \
- ppapi/shared_impl/ppb_device_ref_shared.cc \
- ppapi/shared_impl/ppb_file_ref_shared.cc \
- ppapi/shared_impl/ppb_gamepad_shared.cc \
- ppapi/shared_impl/ppb_graphics_3d_shared.cc \
- ppapi/shared_impl/ppb_image_data_shared.cc \
- ppapi/shared_impl/ppb_input_event_shared.cc \
- ppapi/shared_impl/ppb_instance_shared.cc \
- ppapi/shared_impl/ppb_memory_shared.cc \
- ppapi/shared_impl/ppb_message_loop_shared.cc \
- ppapi/shared_impl/ppb_network_list_private_shared.cc \
- ppapi/shared_impl/ppb_opengles2_shared.cc \
- ppapi/shared_impl/ppb_resource_array_shared.cc \
- ppapi/shared_impl/ppb_trace_event_impl.cc \
- ppapi/shared_impl/ppb_url_util_shared.cc \
- ppapi/shared_impl/ppb_var_shared.cc \
- ppapi/shared_impl/ppb_video_decoder_shared.cc \
- ppapi/shared_impl/ppb_view_shared.cc \
- ppapi/shared_impl/ppp_instance_combined.cc \
- ppapi/shared_impl/proxy_lock.cc \
- ppapi/shared_impl/resource.cc \
- ppapi/shared_impl/resource_tracker.cc \
- ppapi/shared_impl/scoped_pp_resource.cc \
- ppapi/shared_impl/scoped_pp_var.cc \
- ppapi/shared_impl/socket_option_data.cc \
- ppapi/shared_impl/tcp_socket_shared.cc \
- ppapi/shared_impl/thread_aware_callback.cc \
- ppapi/shared_impl/time_conversion.cc \
- ppapi/shared_impl/tracked_callback.cc \
- ppapi/shared_impl/url_request_info_data.cc \
- ppapi/shared_impl/url_response_info_data.cc \
- ppapi/shared_impl/var.cc \
- ppapi/shared_impl/var_tracker.cc \
- ppapi/shared_impl/var_value_conversions.cc \
- ppapi/shared_impl/private/net_address_private_impl.cc \
- ppapi/shared_impl/private/net_address_private_impl_constants.cc \
- ppapi/shared_impl/private/ppb_char_set_shared.cc \
- ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc \
- ppapi/shared_impl/private/tcp_socket_private_impl.cc \
- ppapi/thunk/enter.cc \
- ppapi/thunk/ppb_audio_config_thunk.cc \
- ppapi/thunk/ppb_audio_input_dev_thunk.cc \
- ppapi/thunk/ppb_audio_thunk.cc \
- ppapi/thunk/ppb_broker_thunk.cc \
- ppapi/thunk/ppb_browser_font_trusted_thunk.cc \
- ppapi/thunk/ppb_buffer_thunk.cc \
- ppapi/thunk/ppb_char_set_thunk.cc \
- ppapi/thunk/ppb_console_thunk.cc \
- ppapi/thunk/ppb_content_decryptor_private_thunk.cc \
- ppapi/thunk/ppb_cursor_control_thunk.cc \
- ppapi/thunk/ppb_device_ref_dev_thunk.cc \
- ppapi/thunk/ppb_ext_alarms_thunk.cc \
- ppapi/thunk/ppb_ext_crx_file_system_private_thunk.cc \
- ppapi/thunk/ppb_ext_socket_thunk.cc \
- ppapi/thunk/ppb_file_chooser_dev_thunk.cc \
- ppapi/thunk/ppb_file_chooser_trusted_thunk.cc \
- ppapi/thunk/ppb_file_io_private_thunk.cc \
- ppapi/thunk/ppb_file_io_thunk.cc \
- ppapi/thunk/ppb_file_io_trusted_thunk.cc \
- ppapi/thunk/ppb_file_ref_thunk.cc \
- ppapi/thunk/ppb_file_system_thunk.cc \
- ppapi/thunk/ppb_find_dev_thunk.cc \
- ppapi/thunk/ppb_flash_clipboard_thunk.cc \
- ppapi/thunk/ppb_flash_device_id_thunk.cc \
- ppapi/thunk/ppb_flash_drm_thunk.cc \
- ppapi/thunk/ppb_flash_file_fileref_thunk.cc \
- ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc \
- ppapi/thunk/ppb_flash_font_file_thunk.cc \
- ppapi/thunk/ppb_flash_fullscreen_thunk.cc \
- ppapi/thunk/ppb_flash_menu_thunk.cc \
- ppapi/thunk/ppb_flash_message_loop_thunk.cc \
- ppapi/thunk/ppb_flash_print_thunk.cc \
- ppapi/thunk/ppb_flash_thunk.cc \
- ppapi/thunk/ppb_fullscreen_thunk.cc \
- ppapi/thunk/ppb_gamepad_thunk.cc \
- ppapi/thunk/ppb_gles_chromium_texture_mapping_thunk.cc \
- ppapi/thunk/ppb_graphics_2d_dev_thunk.cc \
- ppapi/thunk/ppb_graphics_2d_thunk.cc \
- ppapi/thunk/ppb_graphics_3d_thunk.cc \
- ppapi/thunk/ppb_host_resolver_thunk.cc \
- ppapi/thunk/ppb_host_resolver_private_thunk.cc \
- ppapi/thunk/ppb_image_data_thunk.cc \
- ppapi/thunk/ppb_input_event_thunk.cc \
- ppapi/thunk/ppb_instance_private_thunk.cc \
- ppapi/thunk/ppb_instance_thunk.cc \
- ppapi/thunk/ppb_messaging_thunk.cc \
- ppapi/thunk/ppb_mouse_cursor_thunk.cc \
- ppapi/thunk/ppb_mouse_lock_thunk.cc \
- ppapi/thunk/ppb_net_address_thunk.cc \
- ppapi/thunk/ppb_network_list_private_thunk.cc \
- ppapi/thunk/ppb_network_monitor_private_thunk.cc \
- ppapi/thunk/ppb_network_proxy_thunk.cc \
- ppapi/thunk/ppb_pdf_thunk.cc \
- ppapi/thunk/ppb_printing_dev_thunk.cc \
- ppapi/thunk/ppb_resource_array_dev_thunk.cc \
- ppapi/thunk/ppb_scrollbar_thunk.cc \
- ppapi/thunk/ppb_talk_private_thunk.cc \
- ppapi/thunk/ppb_tcp_server_socket_private_thunk.cc \
- ppapi/thunk/ppb_tcp_socket_private_thunk.cc \
- ppapi/thunk/ppb_tcp_socket_thunk.cc \
- ppapi/thunk/ppb_text_input_thunk.cc \
- ppapi/thunk/ppb_truetype_font_dev_thunk.cc \
- ppapi/thunk/ppb_udp_socket_thunk.cc \
- ppapi/thunk/ppb_udp_socket_private_thunk.cc \
- ppapi/thunk/ppb_url_loader_thunk.cc \
- ppapi/thunk/ppb_url_loader_trusted_thunk.cc \
- ppapi/thunk/ppb_url_request_info_thunk.cc \
- ppapi/thunk/ppb_url_response_info_thunk.cc \
- ppapi/thunk/ppb_url_util_thunk.cc \
- ppapi/thunk/ppb_var_array_thunk.cc \
- ppapi/thunk/ppb_var_dictionary_thunk.cc \
- ppapi/thunk/ppb_video_capture_thunk.cc \
- ppapi/thunk/ppb_video_decoder_thunk.cc \
- ppapi/thunk/ppb_video_destination_private_thunk.cc \
- ppapi/thunk/ppb_video_source_private_thunk.cc \
- ppapi/thunk/ppb_view_dev_thunk.cc \
- ppapi/thunk/ppb_view_thunk.cc \
- ppapi/thunk/ppb_websocket_thunk.cc \
- ppapi/thunk/ppb_widget_dev_thunk.cc \
- ppapi/thunk/ppb_x509_certificate_private_thunk.cc \
- ppapi/thunk/ppb_zoom_dev_thunk.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DPPAPI_SHARED_IMPLEMENTATION' \
- '-DPPAPI_THUNK_IMPLEMENTATION' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/WebKit \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DPPAPI_SHARED_IMPLEMENTATION' \
- '-DPPAPI_THUNK_IMPLEMENTATION' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/WebKit \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -Wl,-z,relro \
- -Wl,-z,now \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--icf=safe \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -Wl,-z,relro \
- -Wl,-z,now \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--icf=safe \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- skia_skia_library_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_shared_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_shared
-ppapi_shared: ppapi_ppapi_shared_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/ppapi/ppapi_shared.target.linux-mips.mk b/ppapi/ppapi_shared.target.linux-mips.mk
deleted file mode 100644
index d785a4c..0000000
--- a/ppapi/ppapi_shared.target.linux-mips.mk
+++ /dev/null
@@ -1,453 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := ppapi_ppapi_shared_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
- $(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- ppapi/shared_impl/array_var.cc \
- ppapi/shared_impl/array_writer.cc \
- ppapi/shared_impl/callback_tracker.cc \
- ppapi/shared_impl/dictionary_var.cc \
- ppapi/shared_impl/file_io_state_manager.cc \
- ppapi/shared_impl/file_path.cc \
- ppapi/shared_impl/file_ref_util.cc \
- ppapi/shared_impl/file_type_conversion.cc \
- ppapi/shared_impl/flash_clipboard_format_registry.cc \
- ppapi/shared_impl/host_resource.cc \
- ppapi/shared_impl/id_assignment.cc \
- ppapi/shared_impl/platform_file.cc \
- ppapi/shared_impl/ppapi_globals.cc \
- ppapi/shared_impl/ppapi_nacl_channel_args.cc \
- ppapi/shared_impl/ppapi_permissions.cc \
- ppapi/shared_impl/ppapi_preferences.cc \
- ppapi/shared_impl/ppapi_switches.cc \
- ppapi/shared_impl/ppb_audio_config_shared.cc \
- ppapi/shared_impl/ppb_audio_shared.cc \
- ppapi/shared_impl/ppb_crypto_shared.cc \
- ppapi/shared_impl/ppb_device_ref_shared.cc \
- ppapi/shared_impl/ppb_file_ref_shared.cc \
- ppapi/shared_impl/ppb_gamepad_shared.cc \
- ppapi/shared_impl/ppb_graphics_3d_shared.cc \
- ppapi/shared_impl/ppb_image_data_shared.cc \
- ppapi/shared_impl/ppb_input_event_shared.cc \
- ppapi/shared_impl/ppb_instance_shared.cc \
- ppapi/shared_impl/ppb_memory_shared.cc \
- ppapi/shared_impl/ppb_message_loop_shared.cc \
- ppapi/shared_impl/ppb_network_list_private_shared.cc \
- ppapi/shared_impl/ppb_opengles2_shared.cc \
- ppapi/shared_impl/ppb_resource_array_shared.cc \
- ppapi/shared_impl/ppb_trace_event_impl.cc \
- ppapi/shared_impl/ppb_url_util_shared.cc \
- ppapi/shared_impl/ppb_var_shared.cc \
- ppapi/shared_impl/ppb_video_decoder_shared.cc \
- ppapi/shared_impl/ppb_view_shared.cc \
- ppapi/shared_impl/ppp_instance_combined.cc \
- ppapi/shared_impl/proxy_lock.cc \
- ppapi/shared_impl/resource.cc \
- ppapi/shared_impl/resource_tracker.cc \
- ppapi/shared_impl/scoped_pp_resource.cc \
- ppapi/shared_impl/scoped_pp_var.cc \
- ppapi/shared_impl/socket_option_data.cc \
- ppapi/shared_impl/tcp_socket_shared.cc \
- ppapi/shared_impl/thread_aware_callback.cc \
- ppapi/shared_impl/time_conversion.cc \
- ppapi/shared_impl/tracked_callback.cc \
- ppapi/shared_impl/url_request_info_data.cc \
- ppapi/shared_impl/url_response_info_data.cc \
- ppapi/shared_impl/var.cc \
- ppapi/shared_impl/var_tracker.cc \
- ppapi/shared_impl/var_value_conversions.cc \
- ppapi/shared_impl/private/net_address_private_impl.cc \
- ppapi/shared_impl/private/net_address_private_impl_constants.cc \
- ppapi/shared_impl/private/ppb_char_set_shared.cc \
- ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc \
- ppapi/shared_impl/private/tcp_socket_private_impl.cc \
- ppapi/thunk/enter.cc \
- ppapi/thunk/ppb_audio_config_thunk.cc \
- ppapi/thunk/ppb_audio_input_dev_thunk.cc \
- ppapi/thunk/ppb_audio_thunk.cc \
- ppapi/thunk/ppb_broker_thunk.cc \
- ppapi/thunk/ppb_browser_font_trusted_thunk.cc \
- ppapi/thunk/ppb_buffer_thunk.cc \
- ppapi/thunk/ppb_char_set_thunk.cc \
- ppapi/thunk/ppb_console_thunk.cc \
- ppapi/thunk/ppb_content_decryptor_private_thunk.cc \
- ppapi/thunk/ppb_cursor_control_thunk.cc \
- ppapi/thunk/ppb_device_ref_dev_thunk.cc \
- ppapi/thunk/ppb_ext_alarms_thunk.cc \
- ppapi/thunk/ppb_ext_crx_file_system_private_thunk.cc \
- ppapi/thunk/ppb_ext_socket_thunk.cc \
- ppapi/thunk/ppb_file_chooser_dev_thunk.cc \
- ppapi/thunk/ppb_file_chooser_trusted_thunk.cc \
- ppapi/thunk/ppb_file_io_private_thunk.cc \
- ppapi/thunk/ppb_file_io_thunk.cc \
- ppapi/thunk/ppb_file_io_trusted_thunk.cc \
- ppapi/thunk/ppb_file_ref_thunk.cc \
- ppapi/thunk/ppb_file_system_thunk.cc \
- ppapi/thunk/ppb_find_dev_thunk.cc \
- ppapi/thunk/ppb_flash_clipboard_thunk.cc \
- ppapi/thunk/ppb_flash_device_id_thunk.cc \
- ppapi/thunk/ppb_flash_drm_thunk.cc \
- ppapi/thunk/ppb_flash_file_fileref_thunk.cc \
- ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc \
- ppapi/thunk/ppb_flash_font_file_thunk.cc \
- ppapi/thunk/ppb_flash_fullscreen_thunk.cc \
- ppapi/thunk/ppb_flash_menu_thunk.cc \
- ppapi/thunk/ppb_flash_message_loop_thunk.cc \
- ppapi/thunk/ppb_flash_print_thunk.cc \
- ppapi/thunk/ppb_flash_thunk.cc \
- ppapi/thunk/ppb_fullscreen_thunk.cc \
- ppapi/thunk/ppb_gamepad_thunk.cc \
- ppapi/thunk/ppb_gles_chromium_texture_mapping_thunk.cc \
- ppapi/thunk/ppb_graphics_2d_dev_thunk.cc \
- ppapi/thunk/ppb_graphics_2d_thunk.cc \
- ppapi/thunk/ppb_graphics_3d_thunk.cc \
- ppapi/thunk/ppb_host_resolver_thunk.cc \
- ppapi/thunk/ppb_host_resolver_private_thunk.cc \
- ppapi/thunk/ppb_image_data_thunk.cc \
- ppapi/thunk/ppb_input_event_thunk.cc \
- ppapi/thunk/ppb_instance_private_thunk.cc \
- ppapi/thunk/ppb_instance_thunk.cc \
- ppapi/thunk/ppb_messaging_thunk.cc \
- ppapi/thunk/ppb_mouse_cursor_thunk.cc \
- ppapi/thunk/ppb_mouse_lock_thunk.cc \
- ppapi/thunk/ppb_net_address_thunk.cc \
- ppapi/thunk/ppb_network_list_private_thunk.cc \
- ppapi/thunk/ppb_network_monitor_private_thunk.cc \
- ppapi/thunk/ppb_network_proxy_thunk.cc \
- ppapi/thunk/ppb_pdf_thunk.cc \
- ppapi/thunk/ppb_printing_dev_thunk.cc \
- ppapi/thunk/ppb_resource_array_dev_thunk.cc \
- ppapi/thunk/ppb_scrollbar_thunk.cc \
- ppapi/thunk/ppb_talk_private_thunk.cc \
- ppapi/thunk/ppb_tcp_server_socket_private_thunk.cc \
- ppapi/thunk/ppb_tcp_socket_private_thunk.cc \
- ppapi/thunk/ppb_tcp_socket_thunk.cc \
- ppapi/thunk/ppb_text_input_thunk.cc \
- ppapi/thunk/ppb_truetype_font_dev_thunk.cc \
- ppapi/thunk/ppb_udp_socket_thunk.cc \
- ppapi/thunk/ppb_udp_socket_private_thunk.cc \
- ppapi/thunk/ppb_url_loader_thunk.cc \
- ppapi/thunk/ppb_url_loader_trusted_thunk.cc \
- ppapi/thunk/ppb_url_request_info_thunk.cc \
- ppapi/thunk/ppb_url_response_info_thunk.cc \
- ppapi/thunk/ppb_url_util_thunk.cc \
- ppapi/thunk/ppb_var_array_thunk.cc \
- ppapi/thunk/ppb_var_dictionary_thunk.cc \
- ppapi/thunk/ppb_video_capture_thunk.cc \
- ppapi/thunk/ppb_video_decoder_thunk.cc \
- ppapi/thunk/ppb_video_destination_private_thunk.cc \
- ppapi/thunk/ppb_video_source_private_thunk.cc \
- ppapi/thunk/ppb_view_dev_thunk.cc \
- ppapi/thunk/ppb_view_thunk.cc \
- ppapi/thunk/ppb_websocket_thunk.cc \
- ppapi/thunk/ppb_widget_dev_thunk.cc \
- ppapi/thunk/ppb_x509_certificate_private_thunk.cc \
- ppapi/thunk/ppb_zoom_dev_thunk.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DPPAPI_SHARED_IMPLEMENTATION' \
- '-DPPAPI_THUNK_IMPLEMENTATION' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/WebKit \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DPPAPI_SHARED_IMPLEMENTATION' \
- '-DPPAPI_THUNK_IMPLEMENTATION' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/WebKit \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -EL \
- -Wl,--no-keep-memory \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -EL \
- -Wl,--no-keep-memory \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- skia_skia_library_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_shared_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_shared
-ppapi_shared: ppapi_ppapi_shared_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/ppapi/ppapi_shared.target.linux-x86.mk b/ppapi/ppapi_shared.target.linux-x86.mk
deleted file mode 100644
index 3cac2e9..0000000
--- a/ppapi/ppapi_shared.target.linux-x86.mk
+++ /dev/null
@@ -1,459 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := ppapi_ppapi_shared_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
- $(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- ppapi/shared_impl/array_var.cc \
- ppapi/shared_impl/array_writer.cc \
- ppapi/shared_impl/callback_tracker.cc \
- ppapi/shared_impl/dictionary_var.cc \
- ppapi/shared_impl/file_io_state_manager.cc \
- ppapi/shared_impl/file_path.cc \
- ppapi/shared_impl/file_ref_util.cc \
- ppapi/shared_impl/file_type_conversion.cc \
- ppapi/shared_impl/flash_clipboard_format_registry.cc \
- ppapi/shared_impl/host_resource.cc \
- ppapi/shared_impl/id_assignment.cc \
- ppapi/shared_impl/platform_file.cc \
- ppapi/shared_impl/ppapi_globals.cc \
- ppapi/shared_impl/ppapi_nacl_channel_args.cc \
- ppapi/shared_impl/ppapi_permissions.cc \
- ppapi/shared_impl/ppapi_preferences.cc \
- ppapi/shared_impl/ppapi_switches.cc \
- ppapi/shared_impl/ppb_audio_config_shared.cc \
- ppapi/shared_impl/ppb_audio_shared.cc \
- ppapi/shared_impl/ppb_crypto_shared.cc \
- ppapi/shared_impl/ppb_device_ref_shared.cc \
- ppapi/shared_impl/ppb_file_ref_shared.cc \
- ppapi/shared_impl/ppb_gamepad_shared.cc \
- ppapi/shared_impl/ppb_graphics_3d_shared.cc \
- ppapi/shared_impl/ppb_image_data_shared.cc \
- ppapi/shared_impl/ppb_input_event_shared.cc \
- ppapi/shared_impl/ppb_instance_shared.cc \
- ppapi/shared_impl/ppb_memory_shared.cc \
- ppapi/shared_impl/ppb_message_loop_shared.cc \
- ppapi/shared_impl/ppb_network_list_private_shared.cc \
- ppapi/shared_impl/ppb_opengles2_shared.cc \
- ppapi/shared_impl/ppb_resource_array_shared.cc \
- ppapi/shared_impl/ppb_trace_event_impl.cc \
- ppapi/shared_impl/ppb_url_util_shared.cc \
- ppapi/shared_impl/ppb_var_shared.cc \
- ppapi/shared_impl/ppb_video_decoder_shared.cc \
- ppapi/shared_impl/ppb_view_shared.cc \
- ppapi/shared_impl/ppp_instance_combined.cc \
- ppapi/shared_impl/proxy_lock.cc \
- ppapi/shared_impl/resource.cc \
- ppapi/shared_impl/resource_tracker.cc \
- ppapi/shared_impl/scoped_pp_resource.cc \
- ppapi/shared_impl/scoped_pp_var.cc \
- ppapi/shared_impl/socket_option_data.cc \
- ppapi/shared_impl/tcp_socket_shared.cc \
- ppapi/shared_impl/thread_aware_callback.cc \
- ppapi/shared_impl/time_conversion.cc \
- ppapi/shared_impl/tracked_callback.cc \
- ppapi/shared_impl/url_request_info_data.cc \
- ppapi/shared_impl/url_response_info_data.cc \
- ppapi/shared_impl/var.cc \
- ppapi/shared_impl/var_tracker.cc \
- ppapi/shared_impl/var_value_conversions.cc \
- ppapi/shared_impl/private/net_address_private_impl.cc \
- ppapi/shared_impl/private/net_address_private_impl_constants.cc \
- ppapi/shared_impl/private/ppb_char_set_shared.cc \
- ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc \
- ppapi/shared_impl/private/tcp_socket_private_impl.cc \
- ppapi/thunk/enter.cc \
- ppapi/thunk/ppb_audio_config_thunk.cc \
- ppapi/thunk/ppb_audio_input_dev_thunk.cc \
- ppapi/thunk/ppb_audio_thunk.cc \
- ppapi/thunk/ppb_broker_thunk.cc \
- ppapi/thunk/ppb_browser_font_trusted_thunk.cc \
- ppapi/thunk/ppb_buffer_thunk.cc \
- ppapi/thunk/ppb_char_set_thunk.cc \
- ppapi/thunk/ppb_console_thunk.cc \
- ppapi/thunk/ppb_content_decryptor_private_thunk.cc \
- ppapi/thunk/ppb_cursor_control_thunk.cc \
- ppapi/thunk/ppb_device_ref_dev_thunk.cc \
- ppapi/thunk/ppb_ext_alarms_thunk.cc \
- ppapi/thunk/ppb_ext_crx_file_system_private_thunk.cc \
- ppapi/thunk/ppb_ext_socket_thunk.cc \
- ppapi/thunk/ppb_file_chooser_dev_thunk.cc \
- ppapi/thunk/ppb_file_chooser_trusted_thunk.cc \
- ppapi/thunk/ppb_file_io_private_thunk.cc \
- ppapi/thunk/ppb_file_io_thunk.cc \
- ppapi/thunk/ppb_file_io_trusted_thunk.cc \
- ppapi/thunk/ppb_file_ref_thunk.cc \
- ppapi/thunk/ppb_file_system_thunk.cc \
- ppapi/thunk/ppb_find_dev_thunk.cc \
- ppapi/thunk/ppb_flash_clipboard_thunk.cc \
- ppapi/thunk/ppb_flash_device_id_thunk.cc \
- ppapi/thunk/ppb_flash_drm_thunk.cc \
- ppapi/thunk/ppb_flash_file_fileref_thunk.cc \
- ppapi/thunk/ppb_flash_file_modulelocal_thunk.cc \
- ppapi/thunk/ppb_flash_font_file_thunk.cc \
- ppapi/thunk/ppb_flash_fullscreen_thunk.cc \
- ppapi/thunk/ppb_flash_menu_thunk.cc \
- ppapi/thunk/ppb_flash_message_loop_thunk.cc \
- ppapi/thunk/ppb_flash_print_thunk.cc \
- ppapi/thunk/ppb_flash_thunk.cc \
- ppapi/thunk/ppb_fullscreen_thunk.cc \
- ppapi/thunk/ppb_gamepad_thunk.cc \
- ppapi/thunk/ppb_gles_chromium_texture_mapping_thunk.cc \
- ppapi/thunk/ppb_graphics_2d_dev_thunk.cc \
- ppapi/thunk/ppb_graphics_2d_thunk.cc \
- ppapi/thunk/ppb_graphics_3d_thunk.cc \
- ppapi/thunk/ppb_host_resolver_thunk.cc \
- ppapi/thunk/ppb_host_resolver_private_thunk.cc \
- ppapi/thunk/ppb_image_data_thunk.cc \
- ppapi/thunk/ppb_input_event_thunk.cc \
- ppapi/thunk/ppb_instance_private_thunk.cc \
- ppapi/thunk/ppb_instance_thunk.cc \
- ppapi/thunk/ppb_messaging_thunk.cc \
- ppapi/thunk/ppb_mouse_cursor_thunk.cc \
- ppapi/thunk/ppb_mouse_lock_thunk.cc \
- ppapi/thunk/ppb_net_address_thunk.cc \
- ppapi/thunk/ppb_network_list_private_thunk.cc \
- ppapi/thunk/ppb_network_monitor_private_thunk.cc \
- ppapi/thunk/ppb_network_proxy_thunk.cc \
- ppapi/thunk/ppb_pdf_thunk.cc \
- ppapi/thunk/ppb_printing_dev_thunk.cc \
- ppapi/thunk/ppb_resource_array_dev_thunk.cc \
- ppapi/thunk/ppb_scrollbar_thunk.cc \
- ppapi/thunk/ppb_talk_private_thunk.cc \
- ppapi/thunk/ppb_tcp_server_socket_private_thunk.cc \
- ppapi/thunk/ppb_tcp_socket_private_thunk.cc \
- ppapi/thunk/ppb_tcp_socket_thunk.cc \
- ppapi/thunk/ppb_text_input_thunk.cc \
- ppapi/thunk/ppb_truetype_font_dev_thunk.cc \
- ppapi/thunk/ppb_udp_socket_thunk.cc \
- ppapi/thunk/ppb_udp_socket_private_thunk.cc \
- ppapi/thunk/ppb_url_loader_thunk.cc \
- ppapi/thunk/ppb_url_loader_trusted_thunk.cc \
- ppapi/thunk/ppb_url_request_info_thunk.cc \
- ppapi/thunk/ppb_url_response_info_thunk.cc \
- ppapi/thunk/ppb_url_util_thunk.cc \
- ppapi/thunk/ppb_var_array_thunk.cc \
- ppapi/thunk/ppb_var_dictionary_thunk.cc \
- ppapi/thunk/ppb_video_capture_thunk.cc \
- ppapi/thunk/ppb_video_decoder_thunk.cc \
- ppapi/thunk/ppb_video_destination_private_thunk.cc \
- ppapi/thunk/ppb_video_source_private_thunk.cc \
- ppapi/thunk/ppb_view_dev_thunk.cc \
- ppapi/thunk/ppb_view_thunk.cc \
- ppapi/thunk/ppb_websocket_thunk.cc \
- ppapi/thunk/ppb_widget_dev_thunk.cc \
- ppapi/thunk/ppb_x509_certificate_private_thunk.cc \
- ppapi/thunk/ppb_zoom_dev_thunk.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -fno-stack-protector \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DPPAPI_SHARED_IMPLEMENTATION' \
- '-DPPAPI_THUNK_IMPLEMENTATION' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/WebKit \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -fno-stack-protector \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer \
- -fno-unwind-tables \
- -fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DPPAPI_SHARED_IMPLEMENTATION' \
- '-DPPAPI_THUNK_IMPLEMENTATION' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/WebKit \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -m32 \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -m32 \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- skia_skia_library_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: ppapi_ppapi_shared_gyp
-
-# Alias gyp target name.
-.PHONY: ppapi_shared
-ppapi_shared: ppapi_ppapi_shared_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/ppapi/proxy/file_chooser_resource.cc b/ppapi/proxy/file_chooser_resource.cc
index ebd545c..9847e29 100644
--- a/ppapi/proxy/file_chooser_resource.cc
+++ b/ppapi/proxy/file_chooser_resource.cc
@@ -9,8 +9,8 @@
#include "ipc/ipc_message.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/file_ref_resource.h"
#include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
#include "ppapi/shared_impl/var.h"
namespace ppapi {
@@ -100,19 +100,25 @@
void FileChooserResource::OnPluginMsgShowReply(
const ResourceMessageReplyParams& params,
- const std::vector<PPB_FileRef_CreateInfo>& chosen_files) {
+ const std::vector<FileRefCreateInfo>& chosen_files) {
if (output_.is_valid()) {
// Using v0.6 of the API with the output array.
std::vector<PP_Resource> files;
- for (size_t i = 0; i < chosen_files.size(); i++)
- files.push_back(PPB_FileRef_Proxy::DeserializeFileRef(chosen_files[i]));
+ for (size_t i = 0; i < chosen_files.size(); i++) {
+ files.push_back(FileRefResource::CreateFileRef(
+ connection(),
+ pp_instance(),
+ chosen_files[i]));
+ }
output_.StoreResourceVector(files);
} else {
// Convert each of the passed in file infos to resources. These will be
// owned by the FileChooser object until they're passed to the plugin.
DCHECK(file_queue_.empty());
for (size_t i = 0; i < chosen_files.size(); i++) {
- file_queue_.push(PPB_FileRef_Proxy::DeserializeFileRef(
+ file_queue_.push(FileRefResource::CreateFileRef(
+ connection(),
+ pp_instance(),
chosen_files[i]));
}
}
diff --git a/ppapi/proxy/file_chooser_resource.h b/ppapi/proxy/file_chooser_resource.h
index 58331db..b744e91 100644
--- a/ppapi/proxy/file_chooser_resource.h
+++ b/ppapi/proxy/file_chooser_resource.h
@@ -17,7 +17,7 @@
namespace ppapi {
-struct PPB_FileRef_CreateInfo;
+struct FileRefCreateInfo;
namespace proxy {
@@ -56,7 +56,7 @@
private:
void OnPluginMsgShowReply(
const ResourceMessageReplyParams& params,
- const std::vector<PPB_FileRef_CreateInfo>& chosen_files);
+ const std::vector<FileRefCreateInfo>& chosen_files);
int32_t ShowInternal(PP_Bool save_as,
const PP_Var& suggested_file_name,
diff --git a/ppapi/proxy/file_chooser_resource_unittest.cc b/ppapi/proxy/file_chooser_resource_unittest.cc
index a5801ee..e563bf4 100644
--- a/ppapi/proxy/file_chooser_resource_unittest.cc
+++ b/ppapi/proxy/file_chooser_resource_unittest.cc
@@ -5,6 +5,7 @@
#include "base/message_loop/message_loop.h"
#include "ppapi/c/dev/ppb_file_chooser_dev.h"
#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_file_ref.h"
#include "ppapi/proxy/file_chooser_resource.h"
#include "ppapi/proxy/locking_resource_releaser.h"
#include "ppapi/proxy/ppapi_messages.h"
@@ -91,13 +92,13 @@
reply_params.set_result(PP_OK);
// Synthesize a response with one file ref in it. Note that it must have a
- // host resource value set or deserialization will fail. Since there isn't
- // actually a host, this can be whatever we want.
- std::vector<PPB_FileRef_CreateInfo> create_info_array;
- PPB_FileRef_CreateInfo create_info;
- create_info.resource.SetHostResource(pp_instance(), 123);
- create_info.path = "foo/bar";
- create_info.name = "baz";
+ // pending_host_resource_id set. Since there isn't actually a host, this can
+ // be whatever we want.
+ std::vector<FileRefCreateInfo> create_info_array;
+ FileRefCreateInfo create_info;
+ create_info.file_system_type = PP_FILESYSTEMTYPE_EXTERNAL;
+ create_info.display_name = "bar";
+ create_info.pending_host_resource_id = 12;
create_info_array.push_back(create_info);
ASSERT_TRUE(plugin_dispatcher()->OnMessageReceived(
PpapiPluginMsg_ResourceReply(reply_params,
@@ -115,9 +116,8 @@
{
ProxyAutoLock lock;
ScopedPPVar release_name_var(ScopedPPVar::PassRef(), name_var);
- EXPECT_VAR_IS_STRING(create_info.name, name_var);
+ EXPECT_VAR_IS_STRING("bar", name_var);
}
- // Path should be undefined since it's external filesystem.
PP_Var path_var(file_ref_iface->GetPath(dest[0]));
{
ProxyAutoLock lock;
diff --git a/ppapi/proxy/file_io_resource.cc b/ppapi/proxy/file_io_resource.cc
index 7d98356..4459199 100644
--- a/ppapi/proxy/file_io_resource.cc
+++ b/ppapi/proxy/file_io_resource.cc
@@ -5,11 +5,14 @@
#include "ppapi/proxy/file_io_resource.h"
#include "base/bind.h"
+#include "base/task_runner_util.h"
#include "ipc/ipc_message.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/array_writer.h"
+#include "ppapi/shared_impl/file_type_conversion.h"
#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/resource_tracker.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_file_ref_api.h"
@@ -20,22 +23,65 @@
namespace {
+// We must allocate a buffer sized according to the request of the plugin. To
+// reduce the chance of out-of-memory errors, we cap the read size to 32MB.
+// This is OK since the API specifies that it may perform a partial read.
+static const int32_t kMaxReadSize = 32 * 1024 * 1024; // 32MB
+
// An adapter to let Read() share the same implementation with ReadToArray().
void* DummyGetDataBuffer(void* user_data, uint32_t count, uint32_t size) {
return user_data;
}
+// File thread task to close the file handle.
+void DoClose(base::PlatformFile file) {
+ base::ClosePlatformFile(file);
+}
+
} // namespace
namespace ppapi {
namespace proxy {
+FileIOResource::QueryOp::QueryOp(PP_FileHandle file_handle)
+ : file_handle_(file_handle) {
+}
+
+FileIOResource::QueryOp::~QueryOp() {
+}
+
+int32_t FileIOResource::QueryOp::DoWork() {
+ return base::GetPlatformFileInfo(file_handle_, &file_info_) ?
+ PP_OK : PP_ERROR_FAILED;
+}
+
+FileIOResource::ReadOp::ReadOp(PP_FileHandle file_handle,
+ int64_t offset,
+ int32_t bytes_to_read)
+ : file_handle_(file_handle),
+ offset_(offset),
+ bytes_to_read_(bytes_to_read) {
+}
+
+FileIOResource::ReadOp::~ReadOp() {
+}
+
+int32_t FileIOResource::ReadOp::DoWork() {
+ DCHECK(!buffer_.get());
+ buffer_.reset(new char[bytes_to_read_]);
+ return base::ReadPlatformFile(
+ file_handle_, offset_, buffer_.get(), bytes_to_read_);
+}
+
FileIOResource::FileIOResource(Connection connection, PP_Instance instance)
- : PluginResource(connection, instance) {
+ : PluginResource(connection, instance),
+ file_handle_(base::kInvalidPlatformFileValue),
+ file_system_type_(PP_FILESYSTEMTYPE_INVALID) {
SendCreate(RENDERER, PpapiHostMsg_FileIO_Create());
}
FileIOResource::~FileIOResource() {
+ CloseFileHandle();
}
PPB_FileIO_API* FileIOResource::AsPPB_FileIO_API() {
@@ -49,6 +95,17 @@
if (enter.failed())
return PP_ERROR_BADRESOURCE;
+ PPB_FileRef_API* file_ref_api = enter.object();
+ PP_FileSystemType type = file_ref_api->GetFileSystemType();
+ if (type != PP_FILESYSTEMTYPE_LOCALPERSISTENT &&
+ type != PP_FILESYSTEMTYPE_LOCALTEMPORARY &&
+ type != PP_FILESYSTEMTYPE_EXTERNAL &&
+ type != PP_FILESYSTEMTYPE_ISOLATED) {
+ NOTREACHED();
+ return PP_ERROR_FAILED;
+ }
+ file_system_type_ = type;
+
int32_t rv = state_manager_.CheckOperationState(
FileIOStateManager::OPERATION_EXCLUSIVE, false);
if (rv != PP_OK)
@@ -56,7 +113,7 @@
Call<PpapiPluginMsg_FileIO_OpenReply>(RENDERER,
PpapiHostMsg_FileIO_Open(
- enter.resource()->host_resource().host_resource(),
+ file_ref,
open_flags),
base::Bind(&FileIOResource::OnPluginMsgOpenFileComplete, this,
callback));
@@ -71,13 +128,35 @@
FileIOStateManager::OPERATION_EXCLUSIVE, true);
if (rv != PP_OK)
return rv;
-
- Call<PpapiPluginMsg_FileIO_QueryReply>(RENDERER,
- PpapiHostMsg_FileIO_Query(),
- base::Bind(&FileIOResource::OnPluginMsgQueryComplete, this,
- callback, info));
+ if (!info)
+ return PP_ERROR_BADARGUMENT;
+ if (file_handle_ == base::kInvalidPlatformFileValue)
+ return PP_ERROR_FAILED;
state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ scoped_refptr<QueryOp> query_op(new QueryOp(file_handle_));
+
+ // If the callback is blocking, perform the task on the calling thread.
+ if (callback->is_blocking()) {
+ int32_t result;
+ {
+ // Release the proxy lock while making a potentially slow file call.
+ ProxyAutoUnlock unlock;
+ result = query_op->DoWork();
+ }
+ return OnQueryComplete(query_op, info, result);
+ }
+
+ // For the non-blocking case, post a task to the file thread and add a
+ // completion task to write the result.
+ base::PostTaskAndReplyWithResult(
+ PpapiGlobals::Get()->GetFileTaskRunner(pp_instance()),
+ FROM_HERE,
+ Bind(&FileIOResource::QueryOp::DoWork, query_op),
+ RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
+ callback->set_completion_task(
+ Bind(&FileIOResource::OnQueryComplete, this, query_op, info));
+
return PP_OK_COMPLETIONPENDING;
}
@@ -110,7 +189,6 @@
PP_ArrayOutput output_adapter;
output_adapter.GetDataBuffer = &DummyGetDataBuffer;
output_adapter.user_data = buffer;
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ);
return ReadValidated(offset, bytes_to_read, output_adapter, callback);
}
@@ -124,7 +202,6 @@
if (rv != PP_OK)
return rv;
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ);
return ReadValidated(offset, max_read_length, *array_output, callback);
}
@@ -181,6 +258,7 @@
}
void FileIOResource::Close() {
+ CloseFileHandle();
Post(RENDERER, PpapiHostMsg_FileIO_Close());
}
@@ -192,38 +270,6 @@
return file_descriptor;
}
-int32_t FileIOResource::WillWrite(int64_t offset,
- int32_t bytes_to_write,
- scoped_refptr<TrackedCallback> callback) {
- Call<PpapiPluginMsg_FileIO_GeneralReply>(RENDERER,
- PpapiHostMsg_FileIO_WillWrite(offset, bytes_to_write),
- base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
- callback));
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileIOResource::WillSetLength(int64_t length,
- scoped_refptr<TrackedCallback> callback) {
- Call<PpapiPluginMsg_FileIO_GeneralReply>(RENDERER,
- PpapiHostMsg_FileIO_WillSetLength(length),
- base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this,
- callback));
- state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileIOResource::ReadValidated(int64_t offset,
- int32_t bytes_to_read,
- const PP_ArrayOutput& array_output,
- scoped_refptr<TrackedCallback> callback) {
- Call<PpapiPluginMsg_FileIO_ReadReply>(RENDERER,
- PpapiHostMsg_FileIO_Read(offset, bytes_to_read),
- base::Bind(&FileIOResource::OnPluginMsgReadComplete, this,
- callback, array_output));
- return PP_OK_COMPLETIONPENDING;
-}
-
int32_t FileIOResource::RequestOSFileHandle(
PP_FileHandle* handle,
scoped_refptr<TrackedCallback> callback) {
@@ -241,6 +287,111 @@
return PP_OK_COMPLETIONPENDING;
}
+int32_t FileIOResource::WillWrite(int64_t offset,
+ int32_t bytes_to_write,
+ scoped_refptr<TrackedCallback> callback) {
+ Call<PpapiPluginMsg_FileIO_GeneralReply>(RENDERER,
+ PpapiHostMsg_FileIO_WillWrite(offset, bytes_to_write),
+ base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, callback));
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileIOResource::WillSetLength(int64_t length,
+ scoped_refptr<TrackedCallback> callback) {
+ Call<PpapiPluginMsg_FileIO_GeneralReply>(RENDERER,
+ PpapiHostMsg_FileIO_WillSetLength(length),
+ base::Bind(&FileIOResource::OnPluginMsgGeneralComplete, this, callback));
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_EXCLUSIVE);
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t FileIOResource::ReadValidated(int64_t offset,
+ int32_t bytes_to_read,
+ const PP_ArrayOutput& array_output,
+ scoped_refptr<TrackedCallback> callback) {
+ if (bytes_to_read < 0)
+ return PP_ERROR_FAILED;
+ if (file_handle_ == base::kInvalidPlatformFileValue)
+ return PP_ERROR_FAILED;
+
+ state_manager_.SetPendingOperation(FileIOStateManager::OPERATION_READ);
+
+ bytes_to_read = std::min(bytes_to_read, kMaxReadSize);
+ scoped_refptr<ReadOp> read_op(
+ new ReadOp(file_handle_, offset, bytes_to_read));
+ if (callback->is_blocking()) {
+ int32_t result;
+ {
+ // Release the proxy lock while making a potentially slow file call.
+ ProxyAutoUnlock unlock;
+ result = read_op->DoWork();
+ }
+ return OnReadComplete(read_op, array_output, result);
+ }
+
+ // For the non-blocking case, post a task to the file thread.
+ base::PostTaskAndReplyWithResult(
+ PpapiGlobals::Get()->GetFileTaskRunner(pp_instance()),
+ FROM_HERE,
+ Bind(&FileIOResource::ReadOp::DoWork, read_op),
+ RunWhileLocked(Bind(&TrackedCallback::Run, callback)));
+ callback->set_completion_task(
+ Bind(&FileIOResource::OnReadComplete, this, read_op, array_output));
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void FileIOResource::CloseFileHandle() {
+ if (file_handle_ != base::kInvalidPlatformFileValue) {
+ // Close our local fd on the file thread.
+ base::TaskRunner* file_task_runner =
+ PpapiGlobals::Get()->GetFileTaskRunner(pp_instance());
+ file_task_runner->PostTask(FROM_HERE,
+ base::Bind(&DoClose, file_handle_));
+
+ file_handle_ = base::kInvalidPlatformFileValue;
+ }
+}
+
+int32_t FileIOResource::OnQueryComplete(scoped_refptr<QueryOp> query_op,
+ PP_FileInfo* info,
+ int32_t result) {
+ DCHECK(state_manager_.get_pending_operation() ==
+ FileIOStateManager::OPERATION_EXCLUSIVE);
+
+ if (result == PP_OK) {
+ // This writes the file info into the plugin's PP_FileInfo struct.
+ ppapi::PlatformFileInfoToPepperFileInfo(query_op->file_info(),
+ file_system_type_,
+ info);
+ }
+ state_manager_.SetOperationFinished();
+ return result;
+}
+
+int32_t FileIOResource::OnReadComplete(scoped_refptr<ReadOp> read_op,
+ PP_ArrayOutput array_output,
+ int32_t result) {
+ DCHECK(state_manager_.get_pending_operation() ==
+ FileIOStateManager::OPERATION_READ);
+ if (result >= 0) {
+ ArrayWriter output;
+ output.set_pp_array_output(array_output);
+ if (output.is_valid())
+ output.StoreArray(read_op->buffer(), result);
+ else
+ result = PP_ERROR_FAILED;
+ } else {
+ // The read operation failed.
+ result = PP_ERROR_FAILED;
+ }
+ state_manager_.SetOperationFinished();
+ return result;
+}
+
void FileIOResource::OnPluginMsgGeneralComplete(
scoped_refptr<TrackedCallback> callback,
const ResourceMessageReplyParams& params) {
@@ -248,7 +399,8 @@
FileIOStateManager::OPERATION_EXCLUSIVE ||
state_manager_.get_pending_operation() ==
FileIOStateManager::OPERATION_WRITE);
- // End the operation now. The callback may perform another file operation.
+ // End this operation now, so the user's callback can execute another FileIO
+ // operation, assuming there are no other pending operations.
state_manager_.SetOperationFinished();
callback->Run(params.result());
}
@@ -260,45 +412,13 @@
FileIOStateManager::OPERATION_EXCLUSIVE);
if (params.result() == PP_OK)
state_manager_.SetOpenSucceed();
- // End the operation now. The callback may perform another file operation.
- state_manager_.SetOperationFinished();
- callback->Run(params.result());
-}
-void FileIOResource::OnPluginMsgQueryComplete(
- scoped_refptr<TrackedCallback> callback,
- PP_FileInfo* output_info,
- const ResourceMessageReplyParams& params,
- const PP_FileInfo& info) {
- DCHECK(state_manager_.get_pending_operation() ==
- FileIOStateManager::OPERATION_EXCLUSIVE);
- *output_info = info;
- // End the operation now. The callback may perform another file operation.
- state_manager_.SetOperationFinished();
- callback->Run(params.result());
-}
-
-void FileIOResource::OnPluginMsgReadComplete(
- scoped_refptr<TrackedCallback> callback,
- PP_ArrayOutput array_output,
- const ResourceMessageReplyParams& params,
- const std::string& data) {
- DCHECK(state_manager_.get_pending_operation() ==
- FileIOStateManager::OPERATION_READ);
-
- // The result code should contain the data size if it's positive.
int32_t result = params.result();
- DCHECK((result < 0 && data.size() == 0) ||
- result == static_cast<int32_t>(data.size()));
-
- ArrayWriter output;
- output.set_pp_array_output(array_output);
- if (output.is_valid())
- output.StoreArray(data.data(), std::max(0, result));
- else
- result = PP_ERROR_FAILED;
-
- // End the operation now. The callback may perform another file operation.
+ IPC::PlatformFileForTransit transit_file;
+ if ((result == PP_OK) && params.TakeFileHandleAtIndex(0, &transit_file))
+ file_handle_ = IPC::PlatformFileForTransitToPlatformFile(transit_file);
+ // End this operation now, so the user's callback can execute another FileIO
+ // operation, assuming there are no other pending operations.
state_manager_.SetOperationFinished();
callback->Run(result);
}
@@ -321,7 +441,8 @@
result = PP_ERROR_FAILED;
*output_handle = IPC::PlatformFileForTransitToPlatformFile(transit_file);
- // End the operation now. The callback may perform another file operation.
+ // End this operation now, so the user's callback can execute another FileIO
+ // operation, assuming there are no other pending operations.
state_manager_.SetOperationFinished();
callback->Run(result);
}
diff --git a/ppapi/proxy/file_io_resource.h b/ppapi/proxy/file_io_resource.h
index a2b928d..1a888d1 100644
--- a/ppapi/proxy/file_io_resource.h
+++ b/ppapi/proxy/file_io_resource.h
@@ -67,30 +67,74 @@
scoped_refptr<TrackedCallback> callback) OVERRIDE;
private:
+ // Class to perform file query operations across multiple threads.
+ class QueryOp : public base::RefCountedThreadSafe<QueryOp> {
+ public:
+ explicit QueryOp(PP_FileHandle file_handle);
+
+ // Queries the file. Called on the file thread (non-blocking) or the plugin
+ // thread (blocking). This should not be called when we hold the proxy lock.
+ int32_t DoWork();
+
+ const base::PlatformFileInfo& file_info() const { return file_info_; }
+
+ private:
+ friend class base::RefCountedThreadSafe<QueryOp>;
+ ~QueryOp();
+
+ PP_FileHandle file_handle_;
+ base::PlatformFileInfo file_info_;
+ };
+
+ // Class to perform file read operations across multiple threads.
+ class ReadOp : public base::RefCountedThreadSafe<ReadOp> {
+ public:
+ ReadOp(PP_FileHandle file_handle, int64_t offset, int32_t bytes_to_read);
+
+ // Reads the file. Called on the file thread (non-blocking) or the plugin
+ // thread (blocking). This should not be called when we hold the proxy lock.
+ int32_t DoWork();
+
+ char* buffer() const { return buffer_.get(); }
+
+ private:
+ friend class base::RefCountedThreadSafe<ReadOp>;
+ ~ReadOp();
+
+ PP_FileHandle file_handle_;
+ int64_t offset_;
+ int32_t bytes_to_read_;
+ scoped_ptr<char[]> buffer_;
+ };
+
int32_t ReadValidated(int64_t offset,
int32_t bytes_to_read,
const PP_ArrayOutput& array_output,
scoped_refptr<TrackedCallback> callback);
- // Handlers of reply messages. Note that all of them have a callback
- // parameters bound when call to the host.
+ void CloseFileHandle();
+
+
+ // Completion tasks for file operations that are done in the plugin.
+ int32_t OnQueryComplete(scoped_refptr<QueryOp> query_op,
+ PP_FileInfo* info,
+ int32_t result);
+ int32_t OnReadComplete(scoped_refptr<ReadOp> read_op,
+ PP_ArrayOutput array_output,
+ int32_t result);
+
+ // Reply message handlers for operations that are done in the host.
void OnPluginMsgGeneralComplete(scoped_refptr<TrackedCallback> callback,
const ResourceMessageReplyParams& params);
void OnPluginMsgOpenFileComplete(scoped_refptr<TrackedCallback> callback,
const ResourceMessageReplyParams& params);
- void OnPluginMsgQueryComplete(scoped_refptr<TrackedCallback> callback,
- PP_FileInfo* output_info_,
- const ResourceMessageReplyParams& params,
- const PP_FileInfo& info);
- void OnPluginMsgReadComplete(scoped_refptr<TrackedCallback> callback,
- PP_ArrayOutput array_output,
- const ResourceMessageReplyParams& params,
- const std::string& data);
void OnPluginMsgRequestOSFileHandleComplete(
scoped_refptr<TrackedCallback> callback,
PP_FileHandle* output_handle,
const ResourceMessageReplyParams& params);
+ PP_FileHandle file_handle_;
+ PP_FileSystemType file_system_type_;
FileIOStateManager state_manager_;
DISALLOW_COPY_AND_ASSIGN(FileIOResource);
diff --git a/ppapi/proxy/file_ref_resource.cc b/ppapi/proxy/file_ref_resource.cc
index 4c098a5..ae4df85 100644
--- a/ppapi/proxy/file_ref_resource.cc
+++ b/ppapi/proxy/file_ref_resource.cc
@@ -22,7 +22,7 @@
FileRefResource::FileRefResource(
Connection connection,
PP_Instance instance,
- const FileRef_CreateInfo& create_info)
+ const FileRefCreateInfo& create_info)
: PluginResource(connection, instance),
create_info_(create_info),
file_system_resource_(create_info.file_system_plugin_resource) {
@@ -34,7 +34,6 @@
create_info_.internal_path.erase(path_size - 1, 1);
path_var_ = new StringVar(create_info_.internal_path);
-
create_info_.display_name = GetNameForInternalFilePath(
create_info_.internal_path);
}
@@ -57,7 +56,7 @@
PP_Resource FileRefResource::CreateFileRef(
Connection connection,
PP_Instance instance,
- const FileRef_CreateInfo& create_info) {
+ const FileRefCreateInfo& create_info) {
// If we have a valid file_system resource, ensure that its type matches that
// of the fs_type parameter.
if (create_info.file_system_plugin_resource != 0) {
@@ -82,9 +81,7 @@
}
thunk::PPB_FileRef_API* FileRefResource::AsPPB_FileRef_API() {
- // TODO: return "this" once we update PPB_FileRef_API.
- NOTREACHED();
- return NULL;
+ return this;
}
PP_FileSystemType FileRefResource::GetFileSystemType() const {
@@ -111,7 +108,7 @@
pos++;
std::string parent_path = create_info_.internal_path.substr(0, pos);
- ppapi::FileRef_CreateInfo parent_info;
+ ppapi::FileRefCreateInfo parent_info;
parent_info.file_system_type = create_info_.file_system_type;
parent_info.internal_path = parent_path;
parent_info.display_name = GetNameForInternalFilePath(parent_path);
@@ -184,33 +181,9 @@
return PP_OK_COMPLETIONPENDING;
}
-/*
-const FileRef_CreateInfo& FileRefResource::GetCreateInfo() const {
+const FileRefCreateInfo& FileRefResource::GetCreateInfo() const {
return create_info_;
}
-*/
-const PPB_FileRef_CreateInfo& FileRefResource::GetCreateInfo() const {
- // FIXME
- NOTREACHED();
- PPB_FileRef_CreateInfo *info = new PPB_FileRef_CreateInfo();
- return *info;
-}
-
-// TODO(teravest): Remove this when we are finished moving to the new proxy.
-int32_t FileRefResource::QueryInHost(linked_ptr<PP_FileInfo> info,
- scoped_refptr<TrackedCallback> callback) {
- NOTREACHED();
- return PP_ERROR_FAILED;
-}
-
-// TODO(teravest): Remove this when we are finished moving to the new proxy.
-int32_t FileRefResource::ReadDirectoryEntriesInHost(
- linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
- linked_ptr<std::vector<PP_FileType> > file_types,
- scoped_refptr<TrackedCallback> callback) {
- NOTREACHED();
- return PP_ERROR_FAILED;
-}
PP_Var FileRefResource::GetAbsolutePath() {
if (!absolute_path_var_.get()) {
@@ -248,7 +221,7 @@
const PP_ArrayOutput& output,
scoped_refptr<TrackedCallback> callback,
const ResourceMessageReplyParams& params,
- const std::vector<ppapi::FileRef_CreateInfo>& infos,
+ const std::vector<ppapi::FileRefCreateInfo>& infos,
const std::vector<PP_FileType>& file_types) {
if (!TrackedCallback::IsPending(callback))
return;
diff --git a/ppapi/proxy/file_ref_resource.h b/ppapi/proxy/file_ref_resource.h
index 82570fb..f982438 100644
--- a/ppapi/proxy/file_ref_resource.h
+++ b/ppapi/proxy/file_ref_resource.h
@@ -29,7 +29,7 @@
public:
static PP_Resource CreateFileRef(Connection connection,
PP_Instance instance,
- const FileRef_CreateInfo& info);
+ const FileRefCreateInfo& info);
virtual ~FileRefResource();
@@ -55,13 +55,7 @@
virtual int32_t ReadDirectoryEntries(
const PP_ArrayOutput& output,
scoped_refptr<TrackedCallback> callback) OVERRIDE;
- virtual const PPB_FileRef_CreateInfo& GetCreateInfo() const OVERRIDE;
- virtual int32_t QueryInHost(linked_ptr<PP_FileInfo> info,
- scoped_refptr<TrackedCallback> callback) OVERRIDE;
- virtual int32_t ReadDirectoryEntriesInHost(
- linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
- linked_ptr<std::vector<PP_FileType> > file_types,
- scoped_refptr<TrackedCallback> callback) OVERRIDE;
+ virtual const FileRefCreateInfo& GetCreateInfo() const OVERRIDE;
// Private API
virtual PP_Var GetAbsolutePath() OVERRIDE;
@@ -69,7 +63,7 @@
private:
FileRefResource(Connection connection,
PP_Instance instance,
- const FileRef_CreateInfo& info);
+ const FileRefCreateInfo& info);
void RunTrackedCallback(scoped_refptr<TrackedCallback> callback,
const ResourceMessageReplyParams& params);
@@ -83,11 +77,11 @@
const PP_ArrayOutput& output,
scoped_refptr<TrackedCallback> callback,
const ResourceMessageReplyParams& params,
- const std::vector<ppapi::FileRef_CreateInfo>& infos,
+ const std::vector<ppapi::FileRefCreateInfo>& infos,
const std::vector<PP_FileType>& file_types);
// Populated after creation.
- FileRef_CreateInfo create_info_;
+ FileRefCreateInfo create_info_;
// Some file ref operations may fail if the the file system resource inside
// create_info_ is destroyed. Therefore, we explicitly hold a reference to
diff --git a/ppapi/proxy/flash_drm_resource.cc b/ppapi/proxy/flash_drm_resource.cc
index a4be23b..889aa72 100644
--- a/ppapi/proxy/flash_drm_resource.cc
+++ b/ppapi/proxy/flash_drm_resource.cc
@@ -7,9 +7,8 @@
#include "base/bind.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/file_ref_resource.h"
#include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
-#include "ppapi/shared_impl/ppb_file_ref_shared.h"
#include "ppapi/shared_impl/var.h"
namespace ppapi {
@@ -88,10 +87,14 @@
PP_Resource* dest,
scoped_refptr<TrackedCallback> callback,
const ResourceMessageReplyParams& params,
- const PPB_FileRef_CreateInfo& file_info) {
+ const FileRefCreateInfo& file_info) {
if (TrackedCallback::IsPending(callback)) {
- if (params.result() == PP_OK)
- *dest = PPB_FileRef_Proxy::DeserializeFileRef(file_info);
+ if (params.result() == PP_OK) {
+ *dest = FileRefResource::CreateFileRef(
+ connection(),
+ pp_instance(),
+ file_info);
+ }
callback->Run(params.result());
}
}
diff --git a/ppapi/proxy/flash_drm_resource.h b/ppapi/proxy/flash_drm_resource.h
index 12c71e8..9a4b31c 100644
--- a/ppapi/proxy/flash_drm_resource.h
+++ b/ppapi/proxy/flash_drm_resource.h
@@ -11,7 +11,7 @@
#include "ppapi/thunk/ppb_flash_drm_api.h"
namespace ppapi {
-struct PPB_FileRef_CreateInfo;
+struct FileRefCreateInfo;
}
namespace ppapi {
@@ -44,7 +44,7 @@
void OnPluginMsgGetVoucherFileReply(PP_Resource* dest,
scoped_refptr<TrackedCallback> callback,
const ResourceMessageReplyParams& params,
- const PPB_FileRef_CreateInfo& file_info);
+ const FileRefCreateInfo& file_info);
DISALLOW_COPY_AND_ASSIGN(FlashDRMResource);
};
diff --git a/ppapi/proxy/flash_file_resource.cc b/ppapi/proxy/flash_file_resource.cc
index 1387eb7..ce7a2ce 100644
--- a/ppapi/proxy/flash_file_resource.cc
+++ b/ppapi/proxy/flash_file_resource.cc
@@ -13,6 +13,7 @@
#include "ppapi/shared_impl/time_conversion.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_file_ref_api.h"
namespace ppapi {
namespace proxy {
diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc
index d9feb89..49ec0eb 100644
--- a/ppapi/proxy/interface_list.cc
+++ b/ppapi/proxy/interface_list.cc
@@ -101,7 +101,6 @@
#include "ppapi/proxy/ppb_broker_proxy.h"
#include "ppapi/proxy/ppb_buffer_proxy.h"
#include "ppapi/proxy/ppb_core_proxy.h"
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
#include "ppapi/proxy/ppb_flash_message_loop_proxy.h"
#include "ppapi/proxy/ppb_graphics_3d_proxy.h"
#include "ppapi/proxy/ppb_image_data_proxy.h"
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index 7ee568f..c97ae7a 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -57,6 +57,7 @@
#include "ppapi/shared_impl/dir_contents.h"
#include "ppapi/shared_impl/file_path.h"
#include "ppapi/shared_impl/file_ref_create_info.h"
+#include "ppapi/shared_impl/file_ref_detailed_info.h"
#include "ppapi/shared_impl/ppapi_nacl_channel_args.h"
#include "ppapi/shared_impl/ppapi_preferences.h"
#include "ppapi/shared_impl/ppb_device_ref_shared.h"
@@ -202,7 +203,7 @@
IPC_STRUCT_TRAITS_MEMBER(is_dir)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(ppapi::FileRef_CreateInfo)
+IPC_STRUCT_TRAITS_BEGIN(ppapi::FileRefCreateInfo)
IPC_STRUCT_TRAITS_MEMBER(file_system_type)
IPC_STRUCT_TRAITS_MEMBER(internal_path)
IPC_STRUCT_TRAITS_MEMBER(display_name)
@@ -210,6 +211,13 @@
IPC_STRUCT_TRAITS_MEMBER(file_system_plugin_resource)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(ppapi::FileRefDetailedInfo)
+ IPC_STRUCT_TRAITS_MEMBER(resource)
+ IPC_STRUCT_TRAITS_MEMBER(file_system_type)
+ IPC_STRUCT_TRAITS_MEMBER(file_system_url_spec)
+ IPC_STRUCT_TRAITS_MEMBER(external_path)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(ppapi::FlashSiteSetting)
IPC_STRUCT_TRAITS_MEMBER(site)
IPC_STRUCT_TRAITS_MEMBER(permission)
@@ -298,8 +306,7 @@
IPC_STRUCT_TRAITS_BEGIN(ppapi::URLRequestInfoData::BodyItem)
IPC_STRUCT_TRAITS_MEMBER(is_file)
IPC_STRUCT_TRAITS_MEMBER(data)
- // Note: we don't serialize file_ref.
- IPC_STRUCT_TRAITS_MEMBER(file_ref_host_resource)
+ IPC_STRUCT_TRAITS_MEMBER(file_ref_pp_resource)
IPC_STRUCT_TRAITS_MEMBER(start_offset)
IPC_STRUCT_TRAITS_MEMBER(number_of_bytes)
IPC_STRUCT_TRAITS_MEMBER(expected_last_modified_time)
@@ -486,30 +493,6 @@
ppapi::proxy::SerializedHandle /* socket_handle */,
ppapi::proxy::SerializedHandle /* handle */)
-// PPB_FileRef.
-// TODO(teravest): Remove these messages when we've switched over to the "new"
-// proxy.
-IPC_MESSAGE_ROUTED3(
- PpapiMsg_PPBFileRef_CallbackComplete,
- ppapi::HostResource /* resource */,
- uint32_t /* callback_id */,
- int32_t /* result */)
-
-IPC_MESSAGE_ROUTED4(
- PpapiMsg_PPBFileRef_QueryCallbackComplete,
- ppapi::HostResource /* resource */,
- PP_FileInfo /* file_info */,
- uint32_t /* callback_id */,
- int32_t /* result */)
-
-IPC_MESSAGE_ROUTED5(
- PpapiMsg_PPBFileRef_ReadDirectoryEntriesCallbackComplete,
- ppapi::HostResource /* resource */,
- std::vector<ppapi::PPB_FileRef_CreateInfo> /* files */,
- std::vector<PP_FileType> /* file_types */,
- uint32_t /* callback_id */,
- int32_t /* result */)
-
// PPB_FileSystem.
IPC_MESSAGE_ROUTED2(
PpapiMsg_PPBFileSystem_OpenComplete,
@@ -798,43 +781,6 @@
IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBCore_ReleaseResource,
ppapi::HostResource)
-// PPB_FileRef.
-// TODO(teravest): Remove these messages when we've switched over to the "new"
-// proxy.
-IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBFileRef_Create,
- PP_Instance /* instance */,
- PP_Resource /* file_system */,
- std::string /* path */,
- ppapi::PPB_FileRef_CreateInfo /* result */)
-IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFileRef_GetParent,
- ppapi::HostResource /* file_ref */,
- ppapi::PPB_FileRef_CreateInfo /* result */)
-IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBFileRef_MakeDirectory,
- ppapi::HostResource /* file_ref */,
- PP_Bool /* make_ancestors */,
- uint32_t /* callback_id */)
-IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBFileRef_Touch,
- ppapi::HostResource /* file_ref */,
- PP_Time /* last_access */,
- PP_Time /* last_modified */,
- uint32_t /* callback_id */)
-IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFileRef_Delete,
- ppapi::HostResource /* file_ref */,
- uint32_t /* callback_id */)
-IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBFileRef_Rename,
- ppapi::HostResource /* file_ref */,
- ppapi::HostResource /* new_file_ref */,
- uint32_t /* callback_id */)
-IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFileRef_Query,
- ppapi::HostResource /* file_ref */,
- uint32_t /* callback_id */)
-IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFileRef_GetAbsolutePath,
- ppapi::HostResource /* file_ref */,
- ppapi::proxy::SerializedVar /* result */)
-IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBFileRef_ReadDirectoryEntries,
- ppapi::HostResource /* file_ref */,
- uint32_t /* callback_id */)
-
// PPB_Graphics3D.
IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBGraphics3D_Create,
PP_Instance /* instance */,
@@ -1267,7 +1213,6 @@
ppapi::proxy::ResourceMessageReplyParams /* reply_params */,
IPC::Message /* nested_msg */)
-
IPC_SYNC_MESSAGE_CONTROL2_2(PpapiHostMsg_ResourceSyncCall,
ppapi::proxy::ResourceMessageCallParams /* call_params */,
IPC::Message /* nested_msg */,
@@ -1341,7 +1286,7 @@
std::string /* suggested_file_name */,
std::vector<std::string> /* accept_mime_types */)
IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FileChooser_ShowReply,
- std::vector<ppapi::PPB_FileRef_CreateInfo> /* files */)
+ std::vector<ppapi::FileRefCreateInfo> /* files */)
// FileIO
IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_Create)
@@ -1350,15 +1295,9 @@
int32_t /* open_flags */)
IPC_MESSAGE_CONTROL0(PpapiPluginMsg_FileIO_OpenReply)
IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_Close)
-IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileIO_Query)
-IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FileIO_QueryReply, PP_FileInfo /* info */)
IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Touch,
PP_Time /* last_access_time */,
PP_Time /* last_modified_time */)
-IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Read,
- int64_t /* offset */,
- int32_t /* bytes_to_read */)
-IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FileIO_ReadReply, std::string /* data */)
IPC_MESSAGE_CONTROL2(PpapiHostMsg_FileIO_Write,
int64_t /* offset */,
std::string /* data */)
@@ -1423,10 +1362,10 @@
// location indicated by the FileRef.
IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileRef_ReadDirectoryEntries)
-// FileRef_CreateInfo does not provide file type information, so two
+// FileRefCreateInfo does not provide file type information, so two
// corresponding vectors are returned.
IPC_MESSAGE_CONTROL2(PpapiPluginMsg_FileRef_ReadDirectoryEntriesReply,
- std::vector<ppapi::FileRef_CreateInfo> /* files */,
+ std::vector<ppapi::FileRefCreateInfo> /* files */,
std::vector<PP_FileType> /* file_types */)
// Requests that the browser reply with the absolute path to the indicated
@@ -1466,7 +1405,7 @@
// Reply message for GetVoucherFile which contains the CreateInfo for a
// PPB_FileRef which points to the voucher file.
IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetVoucherFileReply,
- ppapi::PPB_FileRef_CreateInfo /* file_info */)
+ ppapi::FileRefCreateInfo /* file_info */)
// Gamepad.
IPC_MESSAGE_CONTROL0(PpapiHostMsg_Gamepad_Create)
@@ -1828,12 +1767,18 @@
// path information in either |file_system_url_spec| (for internal file systems)
// or |external_path| (for external file systems).
// Only sent from the browser to the renderer.
-IPC_MESSAGE_ROUTED5(PpapiHostMsg_FileRef_GetInfoForRendererReply,
- int32_t /* sequence */,
- std::vector<PP_Resource> /* resources */,
- std::vector<PP_FileSystemType> /* fs_type */,
- std::vector<std::string> /* file_system_url_spec */,
- std::vector<base::FilePath> /* external_path */)
+IPC_MESSAGE_ROUTED2(
+ PpapiHostMsg_FileRef_GetInfoForRendererReply,
+ int32_t /* sequence */,
+ std::vector<ppapi::FileRefDetailedInfo> /* detailed_info */)
+
+// A synchronous version of the two above messages. This is required to support
+// some URL loading routes which must be executed synchronously.
+IPC_SYNC_MESSAGE_ROUTED2_1(
+ PpapiHostMsg_FileRef_SyncGetInfoForRenderer,
+ int /* child_process_id */,
+ std::vector<PP_Resource> /* resources */,
+ std::vector<ppapi::FileRefDetailedInfo> /* detailed_info */)
// Flash -----------------------------------------------------------------------
diff --git a/ppapi/proxy/ppapi_param_traits.cc b/ppapi/proxy/ppapi_param_traits.cc
index ca25f82..5d4345f 100644
--- a/ppapi/proxy/ppapi_param_traits.cc
+++ b/ppapi/proxy/ppapi_param_traits.cc
@@ -175,36 +175,6 @@
l->append(" bytes)>");
}
-// TODO(teravest): Remove this when FileRef is moved to the "new" proxy.
-// PPB_FileRef_CreateInfo ------------------------------------------------------
-
-// static
-void ParamTraits<ppapi::PPB_FileRef_CreateInfo>::Write(Message* m,
- const param_type& p) {
- ParamTraits<ppapi::HostResource>::Write(m, p.resource);
- ParamTraits<int>::Write(m, p.file_system_type);
- ParamTraits<std::string>::Write(m, p.path);
- ParamTraits<std::string>::Write(m, p.name);
- ParamTraits<PP_Resource>::Write(m, p.file_system_plugin_resource);
-}
-
-// static
-bool ParamTraits<ppapi::PPB_FileRef_CreateInfo>::Read(const Message* m,
- PickleIterator* iter,
- param_type* r) {
- return
- ParamTraits<ppapi::HostResource>::Read(m, iter, &r->resource) &&
- ParamTraits<int>::Read(m, iter, &r->file_system_type) &&
- ParamTraits<std::string>::Read(m, iter, &r->path) &&
- ParamTraits<std::string>::Read(m, iter, &r->name) &&
- ParamTraits<PP_Resource>::Read(m, iter, &r->file_system_plugin_resource);
-}
-
-// static
-void ParamTraits<ppapi::PPB_FileRef_CreateInfo>::Log(const param_type& p,
- std::string* l) {
-}
-
// HostResource ----------------------------------------------------------------
// static
@@ -274,28 +244,6 @@
std::string* l) {
}
-// std::vector<PPB_FileRef_CreateInfo> -----------------------------------------
-
-void ParamTraits< std::vector<ppapi::PPB_FileRef_CreateInfo> >::Write(
- Message* m,
- const param_type& p) {
- WriteVectorWithoutCopy(m, p);
-}
-
-// static
-bool ParamTraits< std::vector<ppapi::PPB_FileRef_CreateInfo> >::Read(
- const Message* m,
- PickleIterator* iter,
- param_type* r) {
- return ReadVectorWithoutCopy(m, iter, r);
-}
-
-// static
-void ParamTraits< std::vector<ppapi::PPB_FileRef_CreateInfo> >::Log(
- const param_type& p,
- std::string* l) {
-}
-
// ppapi::PpapiPermissions -----------------------------------------------------
void ParamTraits<ppapi::PpapiPermissions>::Write(Message* m,
diff --git a/ppapi/proxy/ppapi_param_traits.h b/ppapi/proxy/ppapi_param_traits.h
index f56415a..b56ec3e 100644
--- a/ppapi/proxy/ppapi_param_traits.h
+++ b/ppapi/proxy/ppapi_param_traits.h
@@ -17,7 +17,6 @@
#include "ppapi/shared_impl/file_path.h"
#include "ppapi/shared_impl/file_ref_create_info.h"
#include "ppapi/shared_impl/ppapi_permissions.h"
-#include "ppapi/shared_impl/ppb_file_ref_shared.h"
#include "ppapi/shared_impl/socket_option_data.h"
struct PP_FileInfo;
@@ -77,15 +76,6 @@
static void Log(const param_type& p, std::string* l);
};
-// TODO(teravest): Remove this when we've switched over to the new proxy.
-template<>
-struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::PPB_FileRef_CreateInfo> {
- typedef ppapi::PPB_FileRef_CreateInfo param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, PickleIterator* iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
template<>
struct PPAPI_PROXY_EXPORT ParamTraits<
ppapi::proxy::PPBURLLoader_UpdateProgress_Params> {
@@ -154,15 +144,6 @@
};
template<>
-struct PPAPI_PROXY_EXPORT ParamTraits< std::vector<
- ppapi::PPB_FileRef_CreateInfo> > {
- typedef std::vector<ppapi::PPB_FileRef_CreateInfo> param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, PickleIterator* iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-template<>
struct PPAPI_PROXY_EXPORT ParamTraits<ppapi::PpapiPermissions> {
typedef ppapi::PpapiPermissions param_type;
static void Write(Message* m, const param_type& p);
diff --git a/ppapi/proxy/ppb_file_ref_proxy.cc b/ppapi/proxy/ppb_file_ref_proxy.cc
deleted file mode 100644
index 62c55da..0000000
--- a/ppapi/proxy/ppb_file_ref_proxy.cc
+++ /dev/null
@@ -1,549 +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 "ppapi/proxy/ppb_file_ref_proxy.h"
-
-#include <map>
-
-#include "base/bind.h"
-#include "ppapi/c/pp_directory_entry.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/c/ppb_file_ref.h"
-#include "ppapi/c/private/ppb_file_ref_private.h"
-#include "ppapi/c/private/ppb_proxy_private.h"
-#include "ppapi/proxy/enter_proxy.h"
-#include "ppapi/proxy/host_dispatcher.h"
-#include "ppapi/proxy/plugin_dispatcher.h"
-#include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/proxy/serialized_var.h"
-#include "ppapi/shared_impl/array_writer.h"
-#include "ppapi/shared_impl/ppb_file_ref_shared.h"
-#include "ppapi/shared_impl/scoped_pp_resource.h"
-#include "ppapi/shared_impl/tracked_callback.h"
-#include "ppapi/thunk/resource_creation_api.h"
-#include "ppapi/thunk/thunk.h"
-
-using ppapi::thunk::EnterResourceNoLock;
-using ppapi::thunk::PPB_FileRef_API;
-using ppapi::thunk::ResourceCreationAPI;
-
-namespace ppapi {
-namespace proxy {
-
-namespace {
-
-void ReleaseEntries(const std::vector<PP_DirectoryEntry>& entries) {
- ResourceTracker* tracker = PpapiGlobals::Get()->GetResourceTracker();
- for (std::vector<PP_DirectoryEntry>::const_iterator it = entries.begin();
- it != entries.end(); ++it)
- tracker->ReleaseResource(it->file_ref);
-}
-
-} // namespace
-
-class FileRef : public PPB_FileRef_Shared {
- public:
- explicit FileRef(const PPB_FileRef_CreateInfo& info);
- virtual ~FileRef();
-
- // Resource overrides.
- virtual void LastPluginRefWasDeleted() OVERRIDE;
-
- // PPB_FileRef_API implementation (not provided by PPB_FileRef_Shared).
- virtual PP_Resource GetParent() OVERRIDE;
- virtual int32_t MakeDirectory(
- PP_Bool make_ancestors,
- scoped_refptr<TrackedCallback> callback) OVERRIDE;
- virtual int32_t Touch(PP_Time last_access_time,
- PP_Time last_modified_time,
- scoped_refptr<TrackedCallback> callback) OVERRIDE;
- virtual int32_t Delete(scoped_refptr<TrackedCallback> callback) OVERRIDE;
- virtual int32_t Rename(PP_Resource new_file_ref,
- scoped_refptr<TrackedCallback> callback) OVERRIDE;
- virtual int32_t Query(PP_FileInfo* info,
- scoped_refptr<TrackedCallback> callback) OVERRIDE;
- virtual int32_t ReadDirectoryEntries(
- const PP_ArrayOutput& output,
- scoped_refptr<TrackedCallback> callback) OVERRIDE;
- virtual int32_t QueryInHost(
- linked_ptr<PP_FileInfo> info,
- scoped_refptr<TrackedCallback> callback) OVERRIDE;
- virtual int32_t ReadDirectoryEntriesInHost(
- linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
- linked_ptr<std::vector<PP_FileType> > file_types,
- scoped_refptr<TrackedCallback> callback) OVERRIDE;
- virtual PP_Var GetAbsolutePath() OVERRIDE;
-
- // Executes the pending callback with the given ID. See pending_callbacks_.
- void ExecuteCallback(uint32_t callback_id, int32_t result);
- int32_t SetFileInfo(uint32_t callback_id, const PP_FileInfo& info);
- int32_t SetReadDirectoryEntriesOutput(
- uint32_t callback_id,
- const std::vector<ppapi::PPB_FileRef_CreateInfo>& infos,
- const std::vector<PP_FileType>& file_types);
-
- private:
- PluginDispatcher* GetDispatcher() const {
- return PluginDispatcher::GetForResource(this);
- }
-
- // Adds a callback to the list and returns its ID.
- uint32_t SendCallback(scoped_refptr<TrackedCallback> callback);
-
- // This class can have any number of out-standing requests with completion
- // callbacks, in contrast to most resources which have one possible pending
- // callback pending (like a Flush callback).
- //
- // To keep track of them, assign integer IDs to the callbacks, which is how
- // the callback will be identified when it's passed to the host and then
- // back here. Use unsigned so that overflow is well-defined.
- uint32_t next_callback_id_;
- typedef std::map<uint32_t,
- scoped_refptr<TrackedCallback> > PendingCallbackMap;
- PendingCallbackMap pending_callbacks_;
-
- // Used to keep pointers to PP_FileInfo instances that are written before
- // callbacks are invoked. The id of a pending file info will match that of
- // the corresponding callback.
- typedef std::map<uint32_t, PP_FileInfo*> PendingFileInfoMap;
- PendingFileInfoMap pending_file_infos_;
-
- // Used to keep PP_ArrayOutput instances that are written before callbacks
- // are invoked. The id of a pending array output will match that of the
- // corresponding callback.
- typedef std::map<uint32_t, PP_ArrayOutput>
- PendingReadDirectoryEntriesOutputMap;
- PendingReadDirectoryEntriesOutputMap pending_read_entries_outputs_;
-
- // Holds a reference on plugin side when running out of process, so that
- // FileSystem won't die before FileRef. See PPB_FileRef_Impl for
- // corresponding code for in-process mode. Note that this workaround will
- // be no longer needed after FileRef refactoring.
- ScopedPPResource file_system_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(FileRef);
-};
-
-FileRef::FileRef(const PPB_FileRef_CreateInfo& info)
- : PPB_FileRef_Shared(OBJECT_IS_PROXY, info),
- next_callback_id_(0u),
- file_system_(info.file_system_plugin_resource) {
-}
-
-FileRef::~FileRef() {
- // The callbacks map should have been cleared by LastPluginRefWasDeleted.
- DCHECK(pending_callbacks_.empty());
- DCHECK(pending_file_infos_.empty());
- DCHECK(pending_read_entries_outputs_.empty());
-}
-
-void FileRef::LastPluginRefWasDeleted() {
- // The callback tracker will abort our callbacks for us.
- pending_callbacks_.clear();
- pending_file_infos_.clear();
- pending_read_entries_outputs_.clear();
-}
-
-PP_Resource FileRef::GetParent() {
- PPB_FileRef_CreateInfo create_info;
- GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetParent(
- API_ID_PPB_FILE_REF, host_resource(), &create_info));
- return PPB_FileRef_Proxy::DeserializeFileRef(create_info);
-}
-
-int32_t FileRef::MakeDirectory(PP_Bool make_ancestors,
- scoped_refptr<TrackedCallback> callback) {
- GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_MakeDirectory(
- API_ID_PPB_FILE_REF, host_resource(), make_ancestors,
- SendCallback(callback)));
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileRef::Touch(PP_Time last_access_time,
- PP_Time last_modified_time,
- scoped_refptr<TrackedCallback> callback) {
- GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Touch(
- API_ID_PPB_FILE_REF, host_resource(), last_access_time,
- last_modified_time, SendCallback(callback)));
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileRef::Delete(scoped_refptr<TrackedCallback> callback) {
- GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Delete(
- API_ID_PPB_FILE_REF, host_resource(), SendCallback(callback)));
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileRef::Rename(PP_Resource new_file_ref,
- scoped_refptr<TrackedCallback> callback) {
- Resource* new_file_ref_object =
- PpapiGlobals::Get()->GetResourceTracker()->GetResource(new_file_ref);
- if (!new_file_ref_object ||
- new_file_ref_object->host_resource().instance() != pp_instance())
- return PP_ERROR_BADRESOURCE;
-
- GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Rename(
- API_ID_PPB_FILE_REF, host_resource(),
- new_file_ref_object->host_resource(), SendCallback(callback)));
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileRef::Query(PP_FileInfo* info,
- scoped_refptr<TrackedCallback> callback) {
- // Store the pending file info id.
- uint32_t id = SendCallback(callback);
- pending_file_infos_[id] = info;
- GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_Query(
- API_ID_PPB_FILE_REF, host_resource(), id));
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileRef::ReadDirectoryEntries(
- const PP_ArrayOutput& output,
- scoped_refptr<TrackedCallback> callback) {
- // Store the pending read entries output id.
- uint32_t id = SendCallback(callback);
- pending_read_entries_outputs_[id] = output;
- GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_ReadDirectoryEntries(
- API_ID_PPB_FILE_REF, host_resource(), id));
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t FileRef::QueryInHost(
- linked_ptr<PP_FileInfo> info,
- scoped_refptr<TrackedCallback> callback) {
- NOTREACHED();
- return PP_ERROR_FAILED;
-}
-
-int32_t FileRef::ReadDirectoryEntriesInHost(
- linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
- linked_ptr<std::vector<PP_FileType> > file_types,
- scoped_refptr<TrackedCallback> callback) {
- NOTREACHED();
- return PP_ERROR_FAILED;
-}
-
-PP_Var FileRef::GetAbsolutePath() {
- ReceiveSerializedVarReturnValue result;
- GetDispatcher()->Send(new PpapiHostMsg_PPBFileRef_GetAbsolutePath(
- API_ID_PPB_FILE_REF, host_resource(), &result));
- return result.Return(GetDispatcher());
-}
-
-void FileRef::ExecuteCallback(uint32_t callback_id, int32_t result) {
- PendingCallbackMap::iterator found = pending_callbacks_.find(callback_id);
- if (found == pending_callbacks_.end()) {
- // This will happen when the plugin deletes its resource with a pending
- // callback. The callback will be locally issued with an ABORTED call while
- // the operation may still be pending in the renderer.
- return;
- }
-
- // Executing the callback may mutate the callback list.
- scoped_refptr<TrackedCallback> callback = found->second;
- pending_callbacks_.erase(found);
- callback->Run(result);
-}
-
-int32_t FileRef::SetFileInfo(uint32_t callback_id, const PP_FileInfo& info) {
- PendingFileInfoMap::iterator found = pending_file_infos_.find(callback_id);
- if (found == pending_file_infos_.end())
- return PP_ERROR_FAILED;
- PP_FileInfo* target_info = found->second;
- *target_info = info;
- pending_file_infos_.erase(found);
- return PP_OK;
-}
-
-int32_t FileRef::SetReadDirectoryEntriesOutput(
- uint32_t callback_id,
- const std::vector<ppapi::PPB_FileRef_CreateInfo>& infos,
- const std::vector<PP_FileType>& file_types) {
- PendingReadDirectoryEntriesOutputMap::iterator found =
- pending_read_entries_outputs_.find(callback_id);
- if (found == pending_read_entries_outputs_.end())
- return PP_ERROR_FAILED;
-
- PP_ArrayOutput output = found->second;
- pending_read_entries_outputs_.erase(found);
-
- std::vector<PP_DirectoryEntry> entries;
- for (size_t i = 0; i < infos.size(); ++i) {
- PP_DirectoryEntry entry;
- entry.file_ref = PPB_FileRef_Proxy::DeserializeFileRef(infos[i]);
- entry.file_type = file_types[i];
- entries.push_back(entry);
- }
-
- ArrayWriter writer(output);
- if (!writer.is_valid()) {
- ReleaseEntries(entries);
- return PP_ERROR_BADARGUMENT;
- }
-
- writer.StoreVector(entries);
- return PP_OK;
-}
-
-uint32_t FileRef::SendCallback(scoped_refptr<TrackedCallback> callback) {
- // In extreme cases the IDs may wrap around, so avoid duplicates.
- while (pending_callbacks_.count(next_callback_id_))
- ++next_callback_id_;
-
- pending_callbacks_[next_callback_id_] = callback;
- return next_callback_id_++;
-}
-
-PPB_FileRef_Proxy::PPB_FileRef_Proxy(Dispatcher* dispatcher)
- : InterfaceProxy(dispatcher),
- callback_factory_(this) {
-}
-
-PPB_FileRef_Proxy::~PPB_FileRef_Proxy() {
-}
-
-// static
-PP_Resource PPB_FileRef_Proxy::CreateProxyResource(PP_Instance instance,
- PP_Resource file_system,
- const char* path) {
- PPB_FileRef_CreateInfo create_info;
- PluginDispatcher::GetForInstance(instance)->Send(
- new PpapiHostMsg_PPBFileRef_Create(
- API_ID_PPB_FILE_REF, instance, file_system, path, &create_info));
- return PPB_FileRef_Proxy::DeserializeFileRef(create_info);
-}
-
-bool PPB_FileRef_Proxy::OnMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(PPB_FileRef_Proxy, msg)
-#if !defined(OS_NACL)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Create, OnMsgCreate)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_GetParent, OnMsgGetParent)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_MakeDirectory,
- OnMsgMakeDirectory)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Touch, OnMsgTouch)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Delete, OnMsgDelete)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Rename, OnMsgRename)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_Query, OnMsgQuery)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_ReadDirectoryEntries,
- OnMsgReadDirectoryEntries)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFileRef_GetAbsolutePath,
- OnMsgGetAbsolutePath)
-#endif // !defined(OS_NACL)
-
- IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileRef_CallbackComplete,
- OnMsgCallbackComplete)
- IPC_MESSAGE_HANDLER(PpapiMsg_PPBFileRef_QueryCallbackComplete,
- OnMsgQueryCallbackComplete)
- IPC_MESSAGE_HANDLER(
- PpapiMsg_PPBFileRef_ReadDirectoryEntriesCallbackComplete,
- OnMsgReadDirectoryEntriesCallbackComplete)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-// static
-void PPB_FileRef_Proxy::SerializeFileRef(PP_Resource file_ref,
- PPB_FileRef_CreateInfo* result) {
- EnterResourceNoLock<PPB_FileRef_API> enter(file_ref, false);
- if (enter.succeeded())
- *result = enter.object()->GetCreateInfo();
-}
-
-// static
-PP_Resource PPB_FileRef_Proxy::DeserializeFileRef(
- const PPB_FileRef_CreateInfo& serialized) {
- if (serialized.resource.is_null())
- return 0; // Resource invalid.
- return (new FileRef(serialized))->GetReference();
-}
-
-#if !defined(OS_NACL)
-void PPB_FileRef_Proxy::OnMsgCreate(PP_Instance pp_instance,
- PP_Resource file_system,
- const std::string& path,
- PPB_FileRef_CreateInfo* result) {
- thunk::EnterResourceCreation enter(pp_instance);
- if (enter.failed())
- return;
-
- PP_Resource resource = enter.functions()->CreateFileRef(
- pp_instance, file_system, path.c_str());
- if (!resource)
- return; // CreateInfo default constructor initializes to 0.
- SerializeFileRef(resource, result);
-}
-
-void PPB_FileRef_Proxy::OnMsgGetParent(const HostResource& host_resource,
- PPB_FileRef_CreateInfo* result) {
- EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource);
- if (enter.succeeded())
- SerializeFileRef(enter.object()->GetParent(), result);
-}
-
-void PPB_FileRef_Proxy::OnMsgMakeDirectory(const HostResource& host_resource,
- PP_Bool make_ancestors,
- uint32_t callback_id) {
- EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
- host_resource, callback_factory_,
- &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id);
- if (enter.succeeded()) {
- enter.SetResult(enter.object()->MakeDirectory(make_ancestors,
- enter.callback()));
- }
-}
-
-void PPB_FileRef_Proxy::OnMsgTouch(const HostResource& host_resource,
- PP_Time last_access,
- PP_Time last_modified,
- uint32_t callback_id) {
- EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
- host_resource, callback_factory_,
- &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id);
- if (enter.succeeded()) {
- enter.SetResult(enter.object()->Touch(last_access, last_modified,
- enter.callback()));
- }
-}
-
-void PPB_FileRef_Proxy::OnMsgDelete(const HostResource& host_resource,
- uint32_t callback_id) {
- EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
- host_resource, callback_factory_,
- &PPB_FileRef_Proxy::OnCallbackCompleteInHost, host_resource, callback_id);
- if (enter.succeeded())
- enter.SetResult(enter.object()->Delete(enter.callback()));
-}
-
-void PPB_FileRef_Proxy::OnMsgRename(const HostResource& file_ref,
- const HostResource& new_file_ref,
- uint32_t callback_id) {
- EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
- file_ref, callback_factory_,
- &PPB_FileRef_Proxy::OnCallbackCompleteInHost, file_ref, callback_id);
- if (enter.succeeded()) {
- enter.SetResult(enter.object()->Rename(new_file_ref.host_resource(),
- enter.callback()));
- }
-}
-
-void PPB_FileRef_Proxy::OnMsgQuery(const HostResource& file_ref,
- uint32_t callback_id) {
- linked_ptr<PP_FileInfo> info(new PP_FileInfo());
- EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
- file_ref, callback_factory_,
- &PPB_FileRef_Proxy::OnQueryCallbackCompleteInHost, file_ref,
- info, callback_id);
- if (enter.succeeded())
- enter.SetResult(enter.object()->QueryInHost(info, enter.callback()));
-}
-
-void PPB_FileRef_Proxy::OnMsgGetAbsolutePath(const HostResource& host_resource,
- SerializedVarReturnValue result) {
- EnterHostFromHostResource<PPB_FileRef_API> enter(host_resource);
- if (enter.succeeded())
- result.Return(dispatcher(), enter.object()->GetAbsolutePath());
-}
-
-void PPB_FileRef_Proxy::OnMsgReadDirectoryEntries(const HostResource& file_ref,
- uint32_t callback_id) {
- linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files(
- new std::vector<ppapi::PPB_FileRef_CreateInfo>());
- linked_ptr<std::vector<PP_FileType> > file_types(
- new std::vector<PP_FileType>());
- HostCallbackParams params(file_ref, callback_id);
- EnterHostFromHostResourceForceCallback<PPB_FileRef_API> enter(
- file_ref, callback_factory_,
- &PPB_FileRef_Proxy::OnReadDirectoryEntriesCallbackCompleteInHost,
- params, files, file_types);
- if (enter.succeeded()) {
- enter.SetResult(enter.object()->ReadDirectoryEntriesInHost(
- files, file_types, enter.callback()));
- }
-}
-
-#endif // !defined(OS_NACL)
-
-void PPB_FileRef_Proxy::OnMsgCallbackComplete(
- const HostResource& host_resource,
- uint32_t callback_id,
- int32_t result) {
- // Forward the callback info to the plugin resource.
- EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource);
- if (enter.succeeded())
- static_cast<FileRef*>(enter.object())->ExecuteCallback(callback_id, result);
-}
-
-void PPB_FileRef_Proxy::OnMsgQueryCallbackComplete(
- const HostResource& host_resource,
- const PP_FileInfo& info,
- uint32_t callback_id,
- int32_t result) {
- EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource);
- if (!enter.succeeded())
- return;
-
- if (result == PP_OK) {
- result = static_cast<FileRef*>(enter.object())->SetFileInfo(
- callback_id, info);
- }
- static_cast<FileRef*>(enter.object())->ExecuteCallback(callback_id, result);
-}
-
-void PPB_FileRef_Proxy::OnMsgReadDirectoryEntriesCallbackComplete(
- const HostResource& host_resource,
- const std::vector<ppapi::PPB_FileRef_CreateInfo>& infos,
- const std::vector<PP_FileType>& file_types,
- uint32_t callback_id,
- int32_t result) {
- CHECK_EQ(infos.size(), file_types.size());
-
- EnterPluginFromHostResource<PPB_FileRef_API> enter(host_resource);
- if (!enter.succeeded())
- return;
-
- if (result == PP_OK) {
- result =
- static_cast<FileRef*>(enter.object())->SetReadDirectoryEntriesOutput(
- callback_id, infos, file_types);
- }
- static_cast<FileRef*>(enter.object())->ExecuteCallback(
- callback_id, result);
-}
-
-#if !defined(OS_NACL)
-void PPB_FileRef_Proxy::OnCallbackCompleteInHost(
- int32_t result,
- const HostResource& host_resource,
- uint32_t callback_id) {
- // Execute OnMsgCallbackComplete in the plugin process.
- Send(new PpapiMsg_PPBFileRef_CallbackComplete(
- API_ID_PPB_FILE_REF, host_resource, callback_id, result));
-}
-
-void PPB_FileRef_Proxy::OnQueryCallbackCompleteInHost(
- int32_t result,
- const HostResource& host_resource,
- linked_ptr<PP_FileInfo> info,
- uint32_t callback_id) {
- Send(new PpapiMsg_PPBFileRef_QueryCallbackComplete(
- API_ID_PPB_FILE_REF, host_resource, *info, callback_id, result));
-}
-
-void PPB_FileRef_Proxy::OnReadDirectoryEntriesCallbackCompleteInHost(
- int32_t result,
- HostCallbackParams params,
- linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
- linked_ptr<std::vector<PP_FileType> > file_types) {
- Send(new PpapiMsg_PPBFileRef_ReadDirectoryEntriesCallbackComplete(
- API_ID_PPB_FILE_REF, params.host_resource,
- *files, *file_types, params.callback_id, result));
-}
-
-#endif // !defined(OS_NACL)
-
-} // namespace proxy
-} // namespace ppapi
diff --git a/ppapi/proxy/ppb_file_ref_proxy.h b/ppapi/proxy/ppb_file_ref_proxy.h
deleted file mode 100644
index cbfadb5..0000000
--- a/ppapi/proxy/ppb_file_ref_proxy.h
+++ /dev/null
@@ -1,138 +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.
-
-#ifndef PPAPI_PROXY_PPB_FILE_REF_PROXY_H_
-#define PPAPI_PROXY_PPB_FILE_REF_PROXY_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/linked_ptr.h"
-#include "ppapi/c/pp_file_info.h"
-#include "ppapi/c/pp_module.h"
-#include "ppapi/c/pp_resource.h"
-#include "ppapi/c/pp_time.h"
-#include "ppapi/proxy/interface_proxy.h"
-#include "ppapi/proxy/ppapi_proxy_export.h"
-#include "ppapi/proxy/proxy_completion_callback_factory.h"
-#include "ppapi/shared_impl/host_resource.h"
-#include "ppapi/utility/completion_callback_factory.h"
-
-namespace ppapi {
-
-struct PPB_FileRef_CreateInfo;
-
-namespace proxy {
-
-class SerializedVarReturnValue;
-
-class PPAPI_PROXY_EXPORT PPB_FileRef_Proxy
- : public NON_EXPORTED_BASE(InterfaceProxy) {
- public:
- explicit PPB_FileRef_Proxy(Dispatcher* dispatcher);
- virtual ~PPB_FileRef_Proxy();
-
- static PP_Resource CreateProxyResource(PP_Instance instance,
- PP_Resource file_system,
- const char* path);
- static PP_Resource CreateProxyResource(
- const PPB_FileRef_CreateInfo& serialized);
-
- // InterfaceProxy implementation.
- virtual bool OnMessageReceived(const IPC::Message& msg);
-
- // Takes a resource in the host and converts it into a serialized file ref
- // "create info" for reconstitution in the plugin. This struct contains all
- // the necessary information about the file ref.
- //
- // Various PPAPI functions return file refs from various interfaces, so this
- // function is public so anybody can send a file ref.
- static void SerializeFileRef(PP_Resource file_ref,
- PPB_FileRef_CreateInfo* result);
-
- // Creates a plugin resource from the given CreateInfo sent from the host.
- // The value will be the result of calling SerializeFileRef on the host.
- // This represents passing the resource ownership to the plugin. This
- // function also checks the validity of the result and returns 0 on failure.
- //
- // Various PPAPI functions return file refs from various interfaces, so this
- // function is public so anybody can receive a file ref.
- static PP_Resource DeserializeFileRef(
- const PPB_FileRef_CreateInfo& serialized);
-
- static const ApiID kApiID = API_ID_PPB_FILE_REF;
-
- private:
- // Plugin -> host message handlers.
- void OnMsgCreate(PP_Instance instance,
- PP_Resource file_system,
- const std::string& path,
- PPB_FileRef_CreateInfo* result);
- void OnMsgGetParent(const HostResource& host_resource,
- PPB_FileRef_CreateInfo* result);
- void OnMsgMakeDirectory(const HostResource& host_resource,
- PP_Bool make_ancestors,
- uint32_t callback_id);
- void OnMsgTouch(const HostResource& host_resource,
- PP_Time last_access,
- PP_Time last_modified,
- uint32_t callback_id);
- void OnMsgDelete(const HostResource& host_resource,
- uint32_t callback_id);
- void OnMsgRename(const HostResource& file_ref,
- const HostResource& new_file_ref,
- uint32_t callback_id);
- void OnMsgQuery(const HostResource& file_ref,
- uint32_t callback_id);
- void OnMsgGetAbsolutePath(const HostResource& host_resource,
- SerializedVarReturnValue result);
- void OnMsgReadDirectoryEntries(const HostResource& file_ref,
- uint32_t callback_id);
-
- // Host -> Plugin message handlers.
- void OnMsgCallbackComplete(const HostResource& host_resource,
- uint32_t callback_id,
- int32_t result);
- void OnMsgQueryCallbackComplete(const HostResource& host_resource,
- const PP_FileInfo& info,
- uint32_t callback_id,
- int32_t result);
- void OnMsgReadDirectoryEntriesCallbackComplete(
- const HostResource& host_resource,
- const std::vector<ppapi::PPB_FileRef_CreateInfo>& infos,
- const std::vector<PP_FileType>& file_types,
- uint32_t callback_id,
- int32_t result);
-
- struct HostCallbackParams {
- HostCallbackParams(const HostResource& host_res, uint32_t cb_id)
- : host_resource(host_res), callback_id(cb_id) {
- }
- HostResource host_resource;
- uint32_t callback_id;
- };
-
- void OnCallbackCompleteInHost(int32_t result,
- const HostResource& host_resource,
- uint32_t callback_id);
- void OnQueryCallbackCompleteInHost(
- int32_t result,
- const HostResource& host_resource,
- linked_ptr<PP_FileInfo> info,
- uint32_t callback_id);
- void OnReadDirectoryEntriesCallbackCompleteInHost(
- int32_t result,
- HostCallbackParams params,
- linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
- linked_ptr<std::vector<PP_FileType> > file_types);
-
- ProxyCompletionCallbackFactory<PPB_FileRef_Proxy> callback_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(PPB_FileRef_Proxy);
-};
-
-} // namespace proxy
-} // namespace ppapi
-
-#endif // PPAPI_PROXY_PPB_FILE_REF_PROXY_H_
diff --git a/ppapi/proxy/resource_creation_proxy.cc b/ppapi/proxy/resource_creation_proxy.cc
index 53cade1..8b7eb11 100644
--- a/ppapi/proxy/resource_creation_proxy.cc
+++ b/ppapi/proxy/resource_creation_proxy.cc
@@ -11,6 +11,7 @@
#include "ppapi/proxy/ext_crx_file_system_private_resource.h"
#include "ppapi/proxy/file_chooser_resource.h"
#include "ppapi/proxy/file_io_resource.h"
+#include "ppapi/proxy/file_ref_resource.h"
#include "ppapi/proxy/file_system_resource.h"
#include "ppapi/proxy/flash_drm_resource.h"
#include "ppapi/proxy/flash_font_file_resource.h"
@@ -26,7 +27,6 @@
#include "ppapi/proxy/ppb_audio_proxy.h"
#include "ppapi/proxy/ppb_broker_proxy.h"
#include "ppapi/proxy/ppb_buffer_proxy.h"
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
#include "ppapi/proxy/ppb_flash_message_loop_proxy.h"
#include "ppapi/proxy/ppb_graphics_3d_proxy.h"
#include "ppapi/proxy/ppb_image_data_proxy.h"
@@ -78,15 +78,10 @@
return (new FileIOResource(GetConnection(), instance))->GetReference();
}
-PP_Resource ResourceCreationProxy::CreateFileRef(PP_Instance instance,
- PP_Resource file_system,
- const char* path) {
- return PPB_FileRef_Proxy::CreateProxyResource(instance, file_system, path);
-}
-
PP_Resource ResourceCreationProxy::CreateFileRef(
- const PPB_FileRef_CreateInfo& create_info) {
- return PPB_FileRef_Proxy::DeserializeFileRef(create_info);
+ PP_Instance instance,
+ const FileRefCreateInfo& create_info) {
+ return FileRefResource::CreateFileRef(GetConnection(), instance, create_info);
}
PP_Resource ResourceCreationProxy::CreateFileSystem(
diff --git a/ppapi/proxy/resource_creation_proxy.h b/ppapi/proxy/resource_creation_proxy.h
index 47b40a8..2cd86d5 100644
--- a/ppapi/proxy/resource_creation_proxy.h
+++ b/ppapi/proxy/resource_creation_proxy.h
@@ -38,11 +38,9 @@
// ResourceCreationAPI (called in plugin).
virtual PP_Resource CreateFileIO(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateFileRef(PP_Instance instance,
- PP_Resource file_system,
- const char* path) OVERRIDE;
virtual PP_Resource CreateFileRef(
- const PPB_FileRef_CreateInfo& create_info) OVERRIDE;
+ PP_Instance instance,
+ const FileRefCreateInfo& create_info) OVERRIDE;
virtual PP_Resource CreateFileSystem(PP_Instance instance,
PP_FileSystemType type) OVERRIDE;
virtual PP_Resource CreateIsolatedFileSystem(
diff --git a/ppapi/proxy/url_loader_resource.cc b/ppapi/proxy/url_loader_resource.cc
index 5bbc937..1ff0a5e 100644
--- a/ppapi/proxy/url_loader_resource.cc
+++ b/ppapi/proxy/url_loader_resource.cc
@@ -9,8 +9,8 @@
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppb_url_loader.h"
#include "ppapi/proxy/dispatch_reply_message.h"
+#include "ppapi/proxy/file_ref_resource.h"
#include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
#include "ppapi/proxy/url_request_info_resource.h"
#include "ppapi/proxy/url_response_info_resource.h"
#include "ppapi/shared_impl/ppapi_globals.h"
@@ -158,9 +158,14 @@
int32_t rv = ValidateCallback(callback);
if (rv != PP_OK)
return rv;
- if (!response_info_.get() ||
- !response_info_->data().body_as_file_ref.resource.is_null())
+ if (!response_info_.get())
return PP_ERROR_FAILED;
+
+ // Fail if we have a valid file ref.
+ // ReadResponseBody() is for reading to a user-provided buffer.
+ if (response_info_->data().body_as_file_ref.IsValid())
+ return PP_ERROR_FAILED;
+
if (bytes_to_read <= 0 || !buffer)
return PP_ERROR_BADARGUMENT;
@@ -186,8 +191,11 @@
int32_t rv = ValidateCallback(callback);
if (rv != PP_OK)
return rv;
- if (!response_info_.get() ||
- response_info_->data().body_as_file_ref.resource.is_null())
+ if (!response_info_.get())
+ return PP_ERROR_FAILED;
+
+ // Fail if we do not have a valid file ref.
+ if (!response_info_->data().body_as_file_ref.IsValid())
return PP_ERROR_FAILED;
// We may have already reached EOF.
@@ -357,10 +365,10 @@
void URLLoaderResource::SaveResponseInfo(const URLResponseInfoData& data) {
// Create a proxy resource for the the file ref host resource if needed.
PP_Resource body_as_file_ref = 0;
- if (!data.body_as_file_ref.resource.is_null()) {
- thunk::EnterResourceCreationNoLock enter(pp_instance());
- body_as_file_ref =
- enter.functions()->CreateFileRef(data.body_as_file_ref);
+ if (data.body_as_file_ref.IsValid()) {
+ body_as_file_ref = FileRefResource::CreateFileRef(connection(),
+ pp_instance(),
+ data.body_as_file_ref);
}
response_info_ = new URLResponseInfoResource(
connection(), pp_instance(), data, body_as_file_ref);
@@ -389,4 +397,4 @@
}
} // namespace proxy
-} // namespace ppapi
\ No newline at end of file
+} // namespace ppapi
diff --git a/ppapi/proxy/url_response_info_resource.cc b/ppapi/proxy/url_response_info_resource.cc
index 85dae9a..315b4a1 100644
--- a/ppapi/proxy/url_response_info_resource.cc
+++ b/ppapi/proxy/url_response_info_resource.cc
@@ -4,7 +4,7 @@
#include "ppapi/proxy/url_response_info_resource.h"
-#include "ppapi/proxy/ppb_file_ref_proxy.h"
+#include "ppapi/proxy/file_ref_resource.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/resource_creation_api.h"
diff --git a/ppapi/shared_impl/DEPS b/ppapi/shared_impl/DEPS
index 313cbac..ca43b89 100644
--- a/ppapi/shared_impl/DEPS
+++ b/ppapi/shared_impl/DEPS
@@ -2,6 +2,7 @@
"+base",
"+gpu",
"+media/audio",
+ "+media/base",
"+skia",
"+webkit/common/webpreferences.h",
diff --git a/ppapi/shared_impl/file_ref_create_info.cc b/ppapi/shared_impl/file_ref_create_info.cc
new file mode 100644
index 0000000..68c3f17
--- /dev/null
+++ b/ppapi/shared_impl/file_ref_create_info.cc
@@ -0,0 +1,48 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/shared_impl/file_ref_create_info.h"
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "ppapi/c/pp_file_info.h"
+
+namespace ppapi {
+
+namespace {
+
+std::string GetNameForExternalFilePath(const base::FilePath& in_path) {
+ const base::FilePath::StringType& path = in_path.value();
+ size_t pos = path.rfind(base::FilePath::kSeparators[0]);
+ CHECK(pos != base::FilePath::StringType::npos);
+#if defined(OS_WIN)
+ return base::WideToUTF8(path.substr(pos + 1));
+#elif defined(OS_POSIX)
+ return path.substr(pos + 1);
+#else
+#error "Unsupported platform."
+#endif
+}
+
+} // namespace
+
+bool FileRefCreateInfo::IsValid() const {
+ return file_system_type != PP_FILESYSTEMTYPE_INVALID;
+}
+
+FileRefCreateInfo
+MakeExternalFileRefCreateInfo(const base::FilePath& external_path,
+ const std::string& display_name,
+ int pending_host_resource_id) {
+ FileRefCreateInfo info;
+ info.file_system_type = PP_FILESYSTEMTYPE_EXTERNAL;
+ if (!display_name.empty())
+ info.display_name = display_name;
+ else
+ info.display_name = GetNameForExternalFilePath(external_path);
+ info.pending_host_resource_id = pending_host_resource_id;
+ return info;
+}
+
+} // namespace ppapi
diff --git a/ppapi/shared_impl/file_ref_create_info.h b/ppapi/shared_impl/file_ref_create_info.h
index a3599f7..ae570e6 100644
--- a/ppapi/shared_impl/file_ref_create_info.h
+++ b/ppapi/shared_impl/file_ref_create_info.h
@@ -10,12 +10,19 @@
#include "base/files/file_path.h"
#include "ppapi/c/pp_file_info.h"
#include "ppapi/c/pp_resource.h"
+#include "ppapi/shared_impl/ppapi_shared_export.h"
namespace ppapi {
// FileRefs are created in a number of places and they include a number of
// return values. This struct encapsulates everything in one place.
-struct FileRef_CreateInfo {
+struct FileRefCreateInfo {
+ FileRefCreateInfo() : file_system_type(PP_FILESYSTEMTYPE_INVALID),
+ pending_host_resource_id(0),
+ file_system_plugin_resource(0) { }
+
+ PPAPI_SHARED_EXPORT bool IsValid() const;
+
PP_FileSystemType file_system_type;
std::string internal_path;
std::string display_name;
@@ -24,10 +31,18 @@
int pending_host_resource_id;
// Since FileRef needs to hold a FileSystem reference, we need to pass the
- // resource in this CreateInfo.
+ // resource in this CreateInfo. This struct doesn't hold any refrence on the
+ // file_system_plugin_resource.
PP_Resource file_system_plugin_resource;
};
+// Used in the renderer when sending a FileRefCreateInfo to a plugin for a
+// FileRef on an external filesystem.
+PPAPI_SHARED_EXPORT FileRefCreateInfo
+MakeExternalFileRefCreateInfo(const base::FilePath& external_path,
+ const std::string& display_name,
+ int pending_host_resource_id);
+
} // namespace ppapi
#endif // PPAPI_SHARED_IMPL_FILE_REF_CREATE_INFO_H
diff --git a/ppapi/shared_impl/file_ref_detailed_info.h b/ppapi/shared_impl/file_ref_detailed_info.h
new file mode 100644
index 0000000..ddf4370
--- /dev/null
+++ b/ppapi/shared_impl/file_ref_detailed_info.h
@@ -0,0 +1,28 @@
+// 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 PPAPI_SHARED_IMPL_FILE_REF_DETAILED_INFO_H
+#define PPAPI_SHARED_IMPL_FILE_REF_DETAILED_INFO_H
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "ppapi/c/pp_file_info.h"
+#include "ppapi/c/pp_resource.h"
+
+namespace ppapi {
+
+// This structure is only used for exchanging information about FileRefs from
+// the browser to the renderer.
+struct FileRefDetailedInfo {
+ // This struct doesn't hold a ref on this resource.
+ PP_Resource resource;
+ PP_FileSystemType file_system_type;
+ std::string file_system_url_spec;
+ base::FilePath external_path;
+};
+
+} // namespace ppapi
+
+#endif // PPAPI_SHARED_IMPL_FILE_REF_DETAILED_INFO_H
diff --git a/ppapi/shared_impl/ppb_file_ref_shared.cc b/ppapi/shared_impl/ppb_file_ref_shared.cc
deleted file mode 100644
index a47cdb8..0000000
--- a/ppapi/shared_impl/ppb_file_ref_shared.cc
+++ /dev/null
@@ -1,54 +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 "ppapi/shared_impl/ppb_file_ref_shared.h"
-
-#include "base/logging.h"
-#include "ppapi/shared_impl/var.h"
-
-namespace ppapi {
-
-PPB_FileRef_Shared::PPB_FileRef_Shared(ResourceObjectType type,
- const PPB_FileRef_CreateInfo& info)
- : Resource(type, info.resource),
- create_info_(info) {
- if (type == OBJECT_IS_IMPL) {
- // Resource's constructor assigned a PP_Resource, so we can fill out our
- // host resource now.
- create_info_.resource = host_resource();
- }
-}
-
-PPB_FileRef_Shared::~PPB_FileRef_Shared() {
-}
-
-thunk::PPB_FileRef_API* PPB_FileRef_Shared::AsPPB_FileRef_API() {
- return this;
-}
-
-PP_FileSystemType PPB_FileRef_Shared::GetFileSystemType() const {
- return static_cast<PP_FileSystemType>(create_info_.file_system_type);
-}
-
-PP_Var PPB_FileRef_Shared::GetName() const {
- if (!name_var_.get()) {
- name_var_ = new StringVar(create_info_.name);
- }
- return name_var_->GetPPVar();
-}
-
-PP_Var PPB_FileRef_Shared::GetPath() const {
- if (create_info_.file_system_type == PP_FILESYSTEMTYPE_EXTERNAL)
- return PP_MakeUndefined();
- if (!path_var_.get()) {
- path_var_ = new StringVar(create_info_.path);
- }
- return path_var_->GetPPVar();
-}
-
-const PPB_FileRef_CreateInfo& PPB_FileRef_Shared::GetCreateInfo() const {
- return create_info_;
-}
-
-} // namespace ppapi
diff --git a/ppapi/shared_impl/ppb_file_ref_shared.h b/ppapi/shared_impl/ppb_file_ref_shared.h
deleted file mode 100644
index 5025eb3..0000000
--- a/ppapi/shared_impl/ppb_file_ref_shared.h
+++ /dev/null
@@ -1,70 +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 PPAPI_SHARED_IMPL_PPB_FILE_REF_SHARED_H_
-#define PPAPI_SHARED_IMPL_PPB_FILE_REF_SHARED_H_
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "ppapi/shared_impl/resource.h"
-#include "ppapi/thunk/ppb_file_ref_api.h"
-
-namespace ppapi {
-
-class StringVar;
-
-// FileRefs are created in a number of places and they include a number of
-// return values. This struct encapsulates everything in one place.
-struct PPB_FileRef_CreateInfo {
- PPB_FileRef_CreateInfo()
- : file_system_type(PP_FILESYSTEMTYPE_EXTERNAL),
- file_system_plugin_resource(0) {}
-
- ppapi::HostResource resource;
- int file_system_type; // One of PP_FileSystemType values.
- std::string path;
- std::string name;
-
- // Since FileRef needs to hold a FileSystem reference, we need to pass the
- // resource in this CreateInfo. Note that this is a plugin resource as
- // FileSystem is already in new design.
- PP_Resource file_system_plugin_resource;
-};
-
-// This class provides the shared implementation of a FileRef. The functions
-// that actually "do stuff" like Touch and MakeDirectory are implemented
-// differently for the proxied and non-proxied derived classes.
-class PPAPI_SHARED_EXPORT PPB_FileRef_Shared
- : public Resource,
- public thunk::PPB_FileRef_API {
- public:
- PPB_FileRef_Shared(ResourceObjectType type,
- const PPB_FileRef_CreateInfo& info);
- virtual ~PPB_FileRef_Shared();
-
- // Resource overrides.
- virtual thunk::PPB_FileRef_API* AsPPB_FileRef_API() OVERRIDE;
-
- // PPB_FileRef_API implementation (partial).
- virtual PP_FileSystemType GetFileSystemType() const OVERRIDE;
- virtual PP_Var GetName() const OVERRIDE;
- virtual PP_Var GetPath() const OVERRIDE;
- virtual const PPB_FileRef_CreateInfo& GetCreateInfo() const OVERRIDE;
- virtual PP_Var GetAbsolutePath() = 0;
-
- private:
- PPB_FileRef_CreateInfo create_info_;
-
- // Lazily initialized vars created from the create_info_. This is so we can
- // return the identical string object every time they're requested.
- mutable scoped_refptr<StringVar> name_var_;
- mutable scoped_refptr<StringVar> path_var_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(PPB_FileRef_Shared);
-};
-
-} // namespace ppapi
-
-#endif // PPAPI_SHARED_IMPL_PPB_FILE_REF_SHARED_H_
diff --git a/ppapi/shared_impl/tracked_callback.cc b/ppapi/shared_impl/tracked_callback.cc
index 854e9df..1a3ac21 100644
--- a/ppapi/shared_impl/tracked_callback.cc
+++ b/ppapi/shared_impl/tracked_callback.cc
@@ -27,6 +27,14 @@
PpapiGlobals::Get()->GetMainThreadMessageLoop()->BelongsToCurrentThread();
}
+int32_t RunCompletionTask(TrackedCallback::CompletionTask completion_task,
+ int32_t result) {
+ int32_t task_result = completion_task.Run(result);
+ if (result != PP_ERROR_ABORTED)
+ result = task_result;
+ return result;
+}
+
} // namespace
// TrackedCallback -------------------------------------------------------------
@@ -128,11 +136,18 @@
PostRun(result);
return;
}
- // Copy |callback_| now, since |MarkAsCompleted()| may delete us.
+
+ // Copy callback fields now, since |MarkAsCompleted()| may delete us.
PP_CompletionCallback callback = callback_;
- // Do this before running the callback in case of reentrancy (which
- // shouldn't happen, but avoid strange failures).
+ CompletionTask completion_task = completion_task_;
+ completion_task_.Reset();
+ // Do this before running the callback in case of reentrancy from running
+ // the completion task.
MarkAsCompleted();
+
+ if (!completion_task.is_null())
+ result = RunCompletionTask(completion_task, result);
+
// TODO(dmichael): Associate a message loop with the callback; if it's not
// the same as the current thread's loop, then post it to the right loop.
CallWhileUnlocked(PP_RunCompletionCallback, &callback, result);
@@ -164,6 +179,12 @@
is_scheduled_ = true;
}
+void TrackedCallback::set_completion_task(
+ const CompletionTask& completion_task) {
+ DCHECK(completion_task_.is_null());
+ completion_task_ = completion_task;
+}
+
// static
bool TrackedCallback::IsPending(
const scoped_refptr<TrackedCallback>& callback) {
@@ -195,6 +216,12 @@
while (!completed())
operation_completed_condvar_->Wait();
+
+ if (!completion_task_.is_null()) {
+ result_for_blocked_callback_ =
+ RunCompletionTask(completion_task_, result_for_blocked_callback_);
+ completion_task_.Reset();
+ }
return result_for_blocked_callback_;
}
diff --git a/ppapi/shared_impl/tracked_callback.h b/ppapi/shared_impl/tracked_callback.h
index c4bf5cf..92af19b 100644
--- a/ppapi/shared_impl/tracked_callback.h
+++ b/ppapi/shared_impl/tracked_callback.h
@@ -9,6 +9,7 @@
#include <set>
#include "base/basictypes.h"
+#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/condition_variable.h"
@@ -84,7 +85,16 @@
// callback is targeted to run, it will *not* be run immediately.
void PostRun(int32_t result);
- void BlockUntilRun();
+ // A task to perform cleanup or write output parameters before the callback
+ // returns a result to the plugin. The |result| parameter has the result so
+ // far, e.g. whether the callback has been aborted. If the callback hasn't
+ // been aborted the return value of the task will become the callback result.
+ // The task is always called on the same thread as the callback to the plugin.
+ typedef base::Callback<int32_t(int32_t /* result */)> CompletionTask;
+
+ // Sets a task that is run just before calling back into the plugin. This
+ // should only be called once.
+ void set_completion_task(const CompletionTask& completion_task);
// Returns the ID of the resource which "owns" the callback, or 0 if the
// callback is not associated with any resource.
@@ -157,6 +167,9 @@
bool aborted_;
PP_CompletionCallback callback_;
+ // Task to run just before calling back into the plugin.
+ CompletionTask completion_task_;
+
// The MessageLoopShared on which this callback should be run. This will be
// NULL if we're in-process.
scoped_refptr<MessageLoopShared> target_loop_;
diff --git a/ppapi/shared_impl/tracked_callback_unittest.cc b/ppapi/shared_impl/tracked_callback_unittest.cc
index a9961f0..9ceb96e 100644
--- a/ppapi/shared_impl/tracked_callback_unittest.cc
+++ b/ppapi/shared_impl/tracked_callback_unittest.cc
@@ -2,6 +2,7 @@
// 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/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "ppapi/c/pp_completion_callback.h"
@@ -37,11 +38,20 @@
PP_Instance pp_instance_;
};
+// All valid results (PP_OK, PP_ERROR_...) are nonpositive.
+const int32_t kInitializedResultValue = 1;
+const int32_t kOverrideResultValue = 2;
+
struct CallbackRunInfo {
- // All valid results (PP_OK, PP_ERROR_...) are nonpositive.
- CallbackRunInfo() : run_count(0), result(1) {}
+ CallbackRunInfo()
+ : run_count(0),
+ result(kInitializedResultValue),
+ completion_task_run_count(0),
+ completion_task_result(kInitializedResultValue) {}
unsigned run_count;
int32_t result;
+ unsigned completion_task_run_count;
+ int32_t completion_task_result;
};
void TestCallback(void* user_data, int32_t result) {
@@ -144,18 +154,38 @@
this,
PP_MakeCompletionCallback(&TestCallback, &info_did_run_));
EXPECT_EQ(0U, info_did_run_.run_count);
+ EXPECT_EQ(0U, info_did_run_.completion_task_run_count);
+
+ // In order to test that the completion task can override the callback
+ // result, we need to test callbacks with and without a completion task.
+ callback_did_run_with_completion_task_ = new TrackedCallback(
+ this,
+ PP_MakeCompletionCallback(&TestCallback,
+ &info_did_run_with_completion_task_));
+ callback_did_run_with_completion_task_->set_completion_task(
+ Bind(&CallbackMockResource::CompletionTask, this,
+ &info_did_run_with_completion_task_));
+ EXPECT_EQ(0U, info_did_run_with_completion_task_.run_count);
+ EXPECT_EQ(0U, info_did_run_with_completion_task_.completion_task_run_count);
callback_did_abort_ = new TrackedCallback(
this,
PP_MakeCompletionCallback(&TestCallback, &info_did_abort_));
+ callback_did_abort_->set_completion_task(
+ Bind(&CallbackMockResource::CompletionTask, this, &info_did_abort_));
EXPECT_EQ(0U, info_did_abort_.run_count);
+ EXPECT_EQ(0U, info_did_abort_.completion_task_run_count);
callback_didnt_run_ = new TrackedCallback(
this,
PP_MakeCompletionCallback(&TestCallback, &info_didnt_run_));
+ callback_didnt_run_->set_completion_task(
+ Bind(&CallbackMockResource::CompletionTask, this, &info_didnt_run_));
EXPECT_EQ(0U, info_didnt_run_.run_count);
+ EXPECT_EQ(0U, info_didnt_run_.completion_task_run_count);
callback_did_run_->Run(PP_OK);
+ callback_did_run_with_completion_task_->Run(PP_OK);
callback_did_abort_->Abort();
CheckIntermediateState();
@@ -163,13 +193,34 @@
return resource_id;
}
+ int32_t CompletionTask(CallbackRunInfo* info, int32_t result) {
+ // We should run before the callback.
+ EXPECT_EQ(0U, info->run_count);
+ info->completion_task_run_count++;
+ if (info->completion_task_run_count == 1)
+ info->completion_task_result = result;
+ return kOverrideResultValue;
+ }
+
void CheckIntermediateState() {
EXPECT_EQ(1U, info_did_run_.run_count);
EXPECT_EQ(PP_OK, info_did_run_.result);
+ EXPECT_EQ(0U, info_did_run_.completion_task_run_count);
+
+ EXPECT_EQ(1U, info_did_run_with_completion_task_.run_count);
+ // completion task should override the result.
+ EXPECT_EQ(kOverrideResultValue, info_did_run_with_completion_task_.result);
+ EXPECT_EQ(1U, info_did_run_with_completion_task_.completion_task_run_count);
+ EXPECT_EQ(PP_OK,
+ info_did_run_with_completion_task_.completion_task_result);
EXPECT_EQ(1U, info_did_abort_.run_count);
+ // completion task shouldn't override an abort.
EXPECT_EQ(PP_ERROR_ABORTED, info_did_abort_.result);
+ EXPECT_EQ(1U, info_did_abort_.completion_task_run_count);
+ EXPECT_EQ(PP_ERROR_ABORTED, info_did_abort_.completion_task_result);
+ EXPECT_EQ(0U, info_didnt_run_.completion_task_run_count);
EXPECT_EQ(0U, info_didnt_run_.run_count);
}
@@ -185,6 +236,9 @@
scoped_refptr<TrackedCallback> callback_did_run_;
CallbackRunInfo info_did_run_;
+ scoped_refptr<TrackedCallback> callback_did_run_with_completion_task_;
+ CallbackRunInfo info_did_run_with_completion_task_;
+
scoped_refptr<TrackedCallback> callback_did_abort_;
CallbackRunInfo info_did_abort_;
diff --git a/ppapi/shared_impl/url_request_info_data.cc b/ppapi/shared_impl/url_request_info_data.cc
index 8bb02a4..15b2787 100644
--- a/ppapi/shared_impl/url_request_info_data.cc
+++ b/ppapi/shared_impl/url_request_info_data.cc
@@ -17,6 +17,7 @@
URLRequestInfoData::BodyItem::BodyItem()
: is_file(false),
+ file_ref_pp_resource(0),
start_offset(0),
number_of_bytes(-1),
expected_last_modified_time(0.0) {
@@ -25,6 +26,7 @@
URLRequestInfoData::BodyItem::BodyItem(const std::string& data)
: is_file(false),
data(data),
+ file_ref_pp_resource(0),
start_offset(0),
number_of_bytes(-1),
expected_last_modified_time(0.0) {
@@ -36,8 +38,8 @@
int64_t number_of_bytes,
PP_Time expected_last_modified_time)
: is_file(true),
- file_ref(file_ref),
- file_ref_host_resource(file_ref->host_resource()),
+ file_ref_resource(file_ref),
+ file_ref_pp_resource(file_ref->pp_resource()),
start_offset(start_offset),
number_of_bytes(number_of_bytes),
expected_last_modified_time(expected_last_modified_time) {
diff --git a/ppapi/shared_impl/url_request_info_data.h b/ppapi/shared_impl/url_request_info_data.h
index 501251a..d0acf4b 100644
--- a/ppapi/shared_impl/url_request_info_data.h
+++ b/ppapi/shared_impl/url_request_info_data.h
@@ -9,10 +9,12 @@
#include <vector>
#include "base/memory/ref_counted.h"
+#include "ppapi/c/pp_resource.h"
#include "ppapi/c/pp_stdint.h"
#include "ppapi/c/pp_time.h"
-#include "ppapi/shared_impl/host_resource.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/ppapi_shared_export.h"
+#include "ppapi/shared_impl/resource_tracker.h"
namespace ppapi {
@@ -32,19 +34,12 @@
std::string data;
- // Is is_file is set, these variables are set. Note that the resource
- // may still be NULL in some cases, such as deserialization errors.
- //
- // This is a bit tricky. In the plugin side of the proxy, both the file ref
- // and the file_ref_host_resource will be set and valid. The scoped_refptr
- // ensures that the resource is alive for as long as the BodyItem is.
- //
- // When we deserialize this in the renderer, only the
- // file_ref_host_resource's are serialized over IPC. The file_refs won't be
- // valid until the host resources are converted to Resource pointers in the
- // PPB_URLRequestInfo_Impl.
- scoped_refptr<Resource> file_ref;
- HostResource file_ref_host_resource;
+ // Only set on the plugin-side, for refcounting purposes. Only valid when
+ // |is_file| is set.
+ scoped_refptr<Resource> file_ref_resource;
+ // This struct holds no ref to this resource. Only valid when |is_file| is
+ // set.
+ PP_Resource file_ref_pp_resource;
int64_t start_offset;
int64_t number_of_bytes;
diff --git a/ppapi/shared_impl/url_response_info_data.h b/ppapi/shared_impl/url_response_info_data.h
index a40ca50..c6f7dbd 100644
--- a/ppapi/shared_impl/url_response_info_data.h
+++ b/ppapi/shared_impl/url_response_info_data.h
@@ -8,7 +8,7 @@
#include <string>
#include "ppapi/c/pp_stdint.h"
-#include "ppapi/shared_impl/ppb_file_ref_shared.h"
+#include "ppapi/shared_impl/file_ref_create_info.h"
#include "ppapi/shared_impl/ppapi_shared_export.h"
namespace ppapi {
@@ -23,8 +23,8 @@
std::string status_text;
std::string redirect_url;
- // Nonzero when streaming to a file.
- PPB_FileRef_CreateInfo body_as_file_ref;
+ // Valid when streaming to a file.
+ FileRefCreateInfo body_as_file_ref;
};
} // namespace ppapi
diff --git a/ppapi/tests/test_file_io.cc b/ppapi/tests/test_file_io.cc
index ed2183b..443f786 100644
--- a/ppapi/tests/test_file_io.cc
+++ b/ppapi/tests/test_file_io.cc
@@ -568,10 +568,14 @@
CHECK_CALLBACK_BEHAVIOR(callback);
ASSERT_EQ(4, callback.result());
- // last_access_time's granularity is 1 day
- // last_modified_time's granularity is 2 seconds
const PP_Time last_access_time = 123 * 24 * 3600.0;
- const PP_Time last_modified_time = 246.0;
+ // last_modified_time's granularity is 2 seconds
+ // NOTE: In NaCl on Windows, NaClDescIO uses _fstat64 to retrieve file info.
+ // This function returns strange values for very small time values (near the
+ // Unix Epoch). For a value like 246.0, it returns -1. For larger values, it
+ // returns values that are exactly an hour less. The value below is handled
+ // correctly, and is only 100 days after the start of Unix time.
+ const PP_Time last_modified_time = 100 * 24 * 3600.0;
callback.WaitForResult(file_io.Touch(last_access_time, last_modified_time,
callback.GetCallback()));
CHECK_CALLBACK_BEHAVIOR(callback);
diff --git a/ppapi/tests/test_file_ref.cc b/ppapi/tests/test_file_ref.cc
index 04e8ce1..d1448ec 100644
--- a/ppapi/tests/test_file_ref.cc
+++ b/ppapi/tests/test_file_ref.cc
@@ -365,10 +365,10 @@
ASSERT_EQ(4, callback.result());
// Touch.
- // last_access_time's granularity is 1 day
- // last_modified_time's granularity is 2 seconds
const PP_Time last_access_time = 123 * 24 * 3600.0;
- const PP_Time last_modified_time = 246.0;
+ // last_modified_time's granularity is 2 seconds
+ // See note in test_file_io.cc for why we use this time.
+ const PP_Time last_modified_time = 100 * 24 * 3600.0;
callback.WaitForResult(file_ref.Touch(last_access_time, last_modified_time,
callback.GetCallback()));
CHECK_CALLBACK_BEHAVIOR(callback);
diff --git a/ppapi/thunk/interfaces_ppb_private.h b/ppapi/thunk/interfaces_ppb_private.h
index 3e0289c..391904d 100644
--- a/ppapi/thunk/interfaces_ppb_private.h
+++ b/ppapi/thunk/interfaces_ppb_private.h
@@ -33,7 +33,7 @@
PPB_FileChooserTrusted_0_5)
PROXIED_IFACE(NoAPIName, PPB_FILECHOOSER_TRUSTED_INTERFACE_0_6,
PPB_FileChooserTrusted_0_6)
-PROXIED_IFACE(PPB_FileRef, PPB_FILEREFPRIVATE_INTERFACE_0_1,
+PROXIED_IFACE(NoAPIName, PPB_FILEREFPRIVATE_INTERFACE_0_1,
PPB_FileRefPrivate_0_1)
// TODO(xhwang): Move PPB_Flash_DeviceID back to interfaces_ppb_private_flash.h.
PROXIED_IFACE(NoAPIName, PPB_FLASH_DEVICEID_INTERFACE_1_0,
diff --git a/ppapi/thunk/interfaces_ppb_public_stable.h b/ppapi/thunk/interfaces_ppb_public_stable.h
index b0918a3..eac850e 100644
--- a/ppapi/thunk/interfaces_ppb_public_stable.h
+++ b/ppapi/thunk/interfaces_ppb_public_stable.h
@@ -19,7 +19,6 @@
// that exist in the webkit/plugins/ppapi/*_impl.h, but not in the proxy.
PROXIED_API(PPB_Audio)
PROXIED_API(PPB_Core)
-PROXIED_API(PPB_FileRef)
PROXIED_API(PPB_Graphics3D)
PROXIED_API(PPB_ImageData)
PROXIED_API(PPB_Instance)
@@ -46,8 +45,8 @@
// interface string.
// Note: Core is special and is registered manually.
PROXIED_IFACE(PPB_Audio, PPB_AUDIO_INTERFACE_1_0, PPB_Audio_1_0)
-PROXIED_IFACE(PPB_FileRef, PPB_FILEREF_INTERFACE_1_0, PPB_FileRef_1_0)
-PROXIED_IFACE(PPB_FileRef, PPB_FILEREF_INTERFACE_1_1, PPB_FileRef_1_1)
+PROXIED_IFACE(NoAPIName, PPB_FILEREF_INTERFACE_1_0, PPB_FileRef_1_0)
+PROXIED_IFACE(NoAPIName, PPB_FILEREF_INTERFACE_1_1, PPB_FileRef_1_1)
PROXIED_IFACE(NoAPIName, PPB_FILESYSTEM_INTERFACE_1_0, PPB_FileSystem_1_0)
PROXIED_IFACE(PPB_Graphics3D, PPB_GRAPHICS_3D_INTERFACE_1_0, PPB_Graphics3D_1_0)
PROXIED_IFACE(PPB_ImageData, PPB_IMAGEDATA_INTERFACE_1_0, PPB_ImageData_1_0)
diff --git a/ppapi/thunk/ppb_file_ref_api.h b/ppapi/thunk/ppb_file_ref_api.h
index ba92b63..b473ae2 100644
--- a/ppapi/thunk/ppb_file_ref_api.h
+++ b/ppapi/thunk/ppb_file_ref_api.h
@@ -10,11 +10,12 @@
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "ppapi/c/ppb_file_ref.h"
+#include "ppapi/shared_impl/file_ref_create_info.h"
#include "ppapi/thunk/ppapi_thunk_export.h"
namespace ppapi {
-struct PPB_FileRef_CreateInfo;
+struct FileRefCreateInfo;
class TrackedCallback;
namespace thunk {
@@ -40,25 +41,10 @@
virtual int32_t ReadDirectoryEntries(
const PP_ArrayOutput& output,
scoped_refptr<TrackedCallback> callback) = 0;
- // We define variants of Query and ReadDirectoryEntries because
- // 1. we need to take linked_ptr instead of raw pointers to avoid
- // use-after-free, and 2. we don't use PP_ArrayOutput for the
- // communication between renderers and the browser in
- // ReadDirectoryEntries. The *InHost functions must not be called in
- // plugins, and Query and ReadDirectoryEntries must not be called in
- // renderers.
- // TODO(hamaji): These functions must be removed when we move
- // FileRef to the new resource design. http://crbug.com/225441
- virtual int32_t QueryInHost(linked_ptr<PP_FileInfo> info,
- scoped_refptr<TrackedCallback> callback) = 0;
- virtual int32_t ReadDirectoryEntriesInHost(
- linked_ptr<std::vector<ppapi::PPB_FileRef_CreateInfo> > files,
- linked_ptr<std::vector<PP_FileType> > file_types,
- scoped_refptr<TrackedCallback> callback) = 0;
// Internal function for use in proxying. Returns the internal CreateInfo
// (the contained resource does not carry a ref on behalf of the caller).
- virtual const PPB_FileRef_CreateInfo& GetCreateInfo() const = 0;
+ virtual const FileRefCreateInfo& GetCreateInfo() const = 0;
// Private API
virtual PP_Var GetAbsolutePath() = 0;
diff --git a/ppapi/thunk/ppb_file_ref_thunk.cc b/ppapi/thunk/ppb_file_ref_thunk.cc
index beb0e41..8910faf 100644
--- a/ppapi/thunk/ppb_file_ref_thunk.cc
+++ b/ppapi/thunk/ppb_file_ref_thunk.cc
@@ -7,6 +7,7 @@
#include "ppapi/c/pp_completion_callback.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_file_ref_private.h"
+#include "ppapi/shared_impl/file_ref_create_info.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/tracked_callback.h"
#include "ppapi/thunk/enter.h"
@@ -32,7 +33,12 @@
EnterResourceCreationNoLock enter(instance);
if (enter.failed())
return 0;
- return enter.functions()->CreateFileRef(instance, file_system, path);
+ FileRefCreateInfo info;
+ info.file_system_type = enter_file_system.object()->GetType();
+ info.internal_path = std::string(path);
+ info.pending_host_resource_id = 0;
+ info.file_system_plugin_resource = file_system;
+ return enter.functions()->CreateFileRef(instance, info);
}
PP_Bool IsFileRef(PP_Resource resource) {
diff --git a/ppapi/thunk/resource_creation_api.h b/ppapi/thunk/resource_creation_api.h
index 082f1cc..bab3bb9 100644
--- a/ppapi/thunk/resource_creation_api.h
+++ b/ppapi/thunk/resource_creation_api.h
@@ -33,7 +33,7 @@
namespace ppapi {
-struct PPB_FileRef_CreateInfo;
+struct FileRefCreateInfo;
struct URLRequestInfoData;
struct URLResponseInfoData;
@@ -49,15 +49,9 @@
virtual ~ResourceCreationAPI() {}
virtual PP_Resource CreateFileIO(PP_Instance instance) = 0;
- virtual PP_Resource CreateFileRef(PP_Instance instance,
- PP_Resource file_system,
- const char* path) = 0;
- // Like the above version but takes a serialized file ref. The resource
- // in the serialized file ref is passed into this, which takes ownership of
- // the reference. In the proxy, the return value will be a plugin resource.
- // In the impl, the return value will be the same resource ID.
virtual PP_Resource CreateFileRef(
- const PPB_FileRef_CreateInfo& serialized) = 0;
+ PP_Instance instance,
+ const FileRefCreateInfo& serialized) = 0;
virtual PP_Resource CreateFileSystem(PP_Instance instance,
PP_FileSystemType type) = 0;
virtual PP_Resource CreateIsolatedFileSystem(PP_Instance instance,
diff --git a/remoting/android/java/AndroidManifest.xml b/remoting/android/java/AndroidManifest.xml
index ff27b57..7a21b2d 100644
--- a/remoting/android/java/AndroidManifest.xml
+++ b/remoting/android/java/AndroidManifest.xml
@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.chromium.chromoting"
- android:versionCode="9"
- android:versionName="0.09">
+ android:versionCode="11"
+ android:versionName="0.11">
<uses-sdk android:minSdkVersion="14"
android:targetSdkVersion="14"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>
<application android:label="@string/app_name"
android:icon="@drawable/chromoting128">
diff --git a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
index cfcbf49..07d896f 100644
--- a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
+++ b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
@@ -69,6 +69,9 @@
/** List of hosts. */
private JSONArray mHosts;
+ /** Refresh button. */
+ private MenuItem mRefreshButton;
+
/** Account switcher. */
private MenuItem mAccountSwitcher;
@@ -139,8 +142,21 @@
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.chromoting_actionbar, menu);
+ mRefreshButton = menu.findItem(R.id.actionbar_directoryrefresh);
mAccountSwitcher = menu.findItem(R.id.actionbar_accountswitcher);
- if (mAccount != null) {
+
+ Account[] usableAccounts = AccountManager.get(this).getAccountsByType(ACCOUNT_TYPE);
+ if (usableAccounts.length == 1 && usableAccounts[0].equals(mAccount)) {
+ // If we're using the only available account, don't offer account switching.
+ // (If there are *no* accounts available, clicking this allows you to add a new one.)
+ mAccountSwitcher.setEnabled(false);
+ }
+
+ if (mAccount == null) {
+ // If no account has been chosen, don't allow the user to refresh the listing.
+ mRefreshButton.setEnabled(false);
+ } else {
+ // If the user has picked an account, show its name directly on the account switcher.
mAccountSwitcher.setTitle(mAccount.name);
}
@@ -150,17 +166,25 @@
/** Called whenever an action bar button is pressed. */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- // The only button is the account switcher, so defer to the android accounts system now.
- AccountManager.get(this).getAuthTokenByFeatures(
- ACCOUNT_TYPE,
- TOKEN_SCOPE,
- null,
- this,
- null,
- null,
- new HostListDirectoryGrabber(this),
- mNetwork
- );
+ if (item == mAccountSwitcher) {
+ // The account switcher triggers a listing of all available accounts.
+ AccountManager.get(this).getAuthTokenByFeatures(
+ ACCOUNT_TYPE,
+ TOKEN_SCOPE,
+ null,
+ this,
+ null,
+ null,
+ new HostListDirectoryGrabber(this),
+ mNetwork
+ );
+ }
+ else {
+ // The refresh button simply makes use of the currently-chosen account.
+ AccountManager.get(this).getAuthToken(mAccount, TOKEN_SCOPE, null, this,
+ new HostListDirectoryGrabber(this), mNetwork);
+ }
+
return true;
}
@@ -235,23 +259,31 @@
} else if (ex instanceof AuthenticatorException) {
explanation = getString(R.string.error_no_accounts);
} else if (ex instanceof IOException) {
- if (!mAlreadyTried) { // This was our first connection attempt.
- Log.w("auth", "Unable to authenticate with (expired?) token");
+ if (!mAlreadyTried) {
+ // This was our first connection attempt.
- // Ask system to renew the auth token in case it expired.
- AccountManager authenticator = AccountManager.get(mUi);
synchronized (mUi) {
- authenticator.invalidateAuthToken(mAccount.type, mToken);
- mToken = null;
- Log.i("auth", "Requesting auth token renewal");
- authenticator.getAuthToken(
- mAccount, TOKEN_SCOPE, null, mUi, this, mNetwork);
+ if (mAccount != null) {
+ // We got an account, but couldn't log into it. We'll retry in case
+ // the system's cached authentication token had already expired.
+ AccountManager authenticator = AccountManager.get(mUi);
+ mAlreadyTried = true;
+
+ Log.w("auth", "Requesting renewal of rejected auth token");
+ authenticator.invalidateAuthToken(mAccount.type, mToken);
+ mToken = null;
+ authenticator.getAuthToken(
+ mAccount, TOKEN_SCOPE, null, mUi, this, mNetwork);
+
+ // We're not in an error state *yet*.
+ return;
+ }
}
- // We're not in an error state *yet*.
- mAlreadyTried = true;
- return;
- } else { // Authentication truly failed.
+ // We didn't even get an account, so the auth server is likely unreachable.
+ explanation = getString(R.string.error_bad_connection);
+ } else {
+ // Authentication truly failed.
Log.e("auth", "Fresh auth token was also rejected");
explanation = getString(R.string.error_auth_failed);
}
@@ -287,7 +319,10 @@
@Override
public void run() {
synchronized (mUi) {
- mAccountSwitcher.setTitle(mAccount.name);
+ mRefreshButton.setEnabled(mAccount != null);
+ if (mAccount != null) {
+ mAccountSwitcher.setTitle(mAccount.name);
+ }
}
if (mHosts == null) {
diff --git a/remoting/android/java/src/org/chromium/chromoting/Desktop.java b/remoting/android/java/src/org/chromium/chromoting/Desktop.java
index 3d59961..8a9917d 100644
--- a/remoting/android/java/src/org/chromium/chromoting/Desktop.java
+++ b/remoting/android/java/src/org/chromium/chromoting/Desktop.java
@@ -96,12 +96,6 @@
default:
// We try to send all other key codes to the host directly.
JniInterface.keyboardAction(event.getKeyCode(), depressed);
-
- if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER ||
- event.getKeyCode() == KeyEvent.KEYCODE_NUMPAD_ENTER) {
- // We stop this key from propagating to prevent the keyboard from closing.
- return true;
- }
}
return super.dispatchKeyEvent(event);
diff --git a/remoting/android/java/src/org/chromium/chromoting/DesktopView.java b/remoting/android/java/src/org/chromium/chromoting/DesktopView.java
index 1e18f91..b1eac42 100644
--- a/remoting/android/java/src/org/chromium/chromoting/DesktopView.java
+++ b/remoting/android/java/src/org/chromium/chromoting/DesktopView.java
@@ -13,12 +13,15 @@
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Looper;
+import android.text.InputType;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
import org.chromium.chromoting.jni.JniInterface;
@@ -81,6 +84,10 @@
public DesktopView(Activity context) {
super(context);
+
+ // Give this view keyboard focus, allowing us to customize the soft keyboard's settings.
+ setFocusableInTouchMode(true);
+
mActionBar = context.getActionBar();
getHolder().addCallback(this);
@@ -265,6 +272,24 @@
JniInterface.provideRedrawCallback(null);
}
+ /** Called when a software keyboard is requested, and specifies its options. */
+ @Override
+ public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+ // Disables rich input support and instead requests simple key events.
+ outAttrs.inputType = InputType.TYPE_NULL;
+
+ // Prevents most third-party IMEs from ignoring our Activity's adjustResize preference.
+ outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_FULLSCREEN;
+
+ // Ensures that keyboards will not decide to hide the remote desktop on small displays.
+ outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI;
+
+ // Stops software keyboards from closing as soon as the enter key is pressed.
+ outAttrs.imeOptions |= EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION;
+
+ return null;
+ }
+
/** Called when a mouse action is made. */
private void handleMouseMovement(float x, float y, int button, boolean pressed) {
float[] coordinates = {x, y};
diff --git a/remoting/base/scoped_reg_key_win.h b/remoting/base/scoped_reg_key_win.h
deleted file mode 100644
index c68b99f..0000000
--- a/remoting/base/scoped_reg_key_win.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef REMOTING_BASE_SCOPED_REG_KEY_WIN_H_
-#define REMOTING_BASE_SCOPED_REG_KEY_WIN_H_
-
-#include <windows.h>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/win/scoped_handle.h"
-
-namespace remoting {
-
-// The traits class for Win32 registry handles.
-class RegKeyTraits {
- public:
- typedef HKEY Handle;
-
- static bool CloseHandle(HKEY handle) {
- return RegCloseKey(handle) == ERROR_SUCCESS;
- }
-
- static bool IsHandleValid(HKEY handle) {
- return handle != NULL;
- }
-
- static HKEY NullHandle() {
- return NULL;
- }
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(RegKeyTraits);
-};
-
-typedef base::win::GenericScopedHandle<
- RegKeyTraits, base::win::DummyVerifierTraits> ScopedRegKey;
-
-} // namespace remoting
-
-#endif // REMOTING_BASE_SCOPED_REG_KEY_WIN_H_
diff --git a/remoting/client/jni/android_keymap.cc b/remoting/client/jni/android_keymap.cc
index 743e15e..45d67c4 100644
--- a/remoting/client/jni/android_keymap.cc
+++ b/remoting/client/jni/android_keymap.cc
@@ -199,12 +199,15 @@
0x0700b7, // NUMPAD_RIGHT_PAREN
};
-}
+} // namespace
namespace remoting {
uint32 AndroidKeycodeToUsbKeycode(size_t android) {
- DCHECK_LT(android, sizeof (usb_keycodes) / sizeof (uint32));
+ if (android >= sizeof (usb_keycodes) / sizeof (uint32)) {
+ LOG(WARNING) << "Attempted to decode out-of-range Android keycode";
+ return 0;
+ }
return usb_keycodes[android];
}
diff --git a/remoting/client/jni/chromoting_jni_instance.cc b/remoting/client/jni/chromoting_jni_instance.cc
index 3e11b2f..b68aab9 100644
--- a/remoting/client/jni/chromoting_jni_instance.cc
+++ b/remoting/client/jni/chromoting_jni_instance.cc
@@ -132,8 +132,7 @@
action.set_usb_keycode(usb_code);
action.set_pressed(key_down);
connection_->input_stub()->InjectKeyEvent(action);
- }
- else {
+ } else {
LOG(WARNING) << "Ignoring unknown keycode: " << key_code;
}
}
diff --git a/remoting/client/jni/chromoting_jni_runtime.cc b/remoting/client/jni/chromoting_jni_runtime.cc
index 8fa9018..8d51a83 100644
--- a/remoting/client/jni/chromoting_jni_runtime.cc
+++ b/remoting/client/jni/chromoting_jni_runtime.cc
@@ -7,6 +7,7 @@
#include "base/android/base_jni_registrar.h"
#include "base/android/jni_android.h"
#include "base/memory/singleton.h"
+#include "base/synchronization/waitable_event.h"
#include "media/base/yuv_convert.h"
#include "net/android/net_jni_registrar.h"
#include "remoting/base/url_request_context.h"
@@ -68,8 +69,19 @@
JNIEnv* env = base::android::AttachCurrentThread();
env->DeleteGlobalRef(class_);
- // TODO(solb): Detach all threads from JVM here.
- // crbug.com/259594
+
+ base::WaitableEvent done_event(false, false);
+ network_task_runner_->PostTask(FROM_HERE, base::Bind(
+ &ChromotingJniRuntime::DetachFromVmAndSignal,
+ base::Unretained(this),
+ &done_event));
+ done_event.Wait();
+ display_task_runner_->PostTask(FROM_HERE, base::Bind(
+ &ChromotingJniRuntime::DetachFromVmAndSignal,
+ base::Unretained(this),
+ &done_event));
+ done_event.Wait();
+ base::android::DetachFromVM();
}
void ChromotingJniRuntime::ConnectToHost(const char* username,
@@ -178,4 +190,9 @@
env->GetStaticMethodID(class_, "redrawGraphicsInternal", "()V"));
}
+void ChromotingJniRuntime::DetachFromVmAndSignal(base::WaitableEvent* waiter) {
+ base::android::DetachFromVM();
+ waiter->Signal();
+}
+
} // namespace remoting
diff --git a/remoting/client/jni/chromoting_jni_runtime.h b/remoting/client/jni/chromoting_jni_runtime.h
index 1a6952b..93f933f 100644
--- a/remoting/client/jni/chromoting_jni_runtime.h
+++ b/remoting/client/jni/chromoting_jni_runtime.h
@@ -6,6 +6,7 @@
#define REMOTING_CLIENT_JNI_CHROMOTING_JNI_RUNTIME_H_
#include <jni.h>
+#include <string>
#include "base/at_exit.h"
#include "net/url_request/url_request_context_getter.h"
@@ -94,6 +95,9 @@
// cross-thread calls on the class.
virtual ~ChromotingJniRuntime();
+ // Detaches JVM from the current thread, then signals. Doesn't own |waiter|.
+ void DetachFromVmAndSignal(base::WaitableEvent* waiter);
+
// Reference to the Java class into which we make JNI calls.
jclass class_;
diff --git a/remoting/host/host_main.cc b/remoting/host/host_main.cc
index ffff5bf..25e01e6 100644
--- a/remoting/host/host_main.cc
+++ b/remoting/host/host_main.cc
@@ -13,6 +13,7 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/logging.h"
+#include "base/strings/string_util.h"
#include "base/strings/stringize_macros.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
@@ -20,6 +21,7 @@
#include "remoting/base/resources.h"
#include "remoting/host/host_exit_codes.h"
#include "remoting/host/logging.h"
+#include "remoting/host/setup/native_messaging_host.h"
#include "remoting/host/usage_stats_consent.h"
#if defined(OS_MACOSX)
@@ -47,8 +49,11 @@
const char kProcessTypeDaemon[] = "daemon";
const char kProcessTypeDesktop[] = "desktop";
const char kProcessTypeHost[] = "host";
+const char kProcessTypeNativeMessagingHost[] = "native_messaging_host";
const char kProcessTypeRdpDesktopSession[] = "rdp_desktop_session";
+const char kExtensionOriginPrefix[] = "chrome-extension://";
+
namespace {
typedef int (*MainRoutineFn)();
@@ -83,8 +88,7 @@
int RunElevated() {
const CommandLine::SwitchMap& switches =
CommandLine::ForCurrentProcess()->GetSwitches();
- const CommandLine::StringVector& args =
- CommandLine::ForCurrentProcess()->GetArgs();
+ CommandLine::StringVector args = CommandLine::ForCurrentProcess()->GetArgs();
// Create the child process command line by copying switches from the current
// command line.
@@ -161,6 +165,8 @@
main_routine = &RdpDesktopSessionMain;
} else if (process_type == kProcessTypeHost) {
main_routine = &HostProcessMain;
+ } else if (process_type == kProcessTypeNativeMessagingHost) {
+ main_routine = &NativeMessagingHostMain;
}
return main_routine;
@@ -223,6 +229,20 @@
std::string process_type = kProcessTypeHost;
if (command_line->HasSwitch(kProcessTypeSwitchName)) {
process_type = command_line->GetSwitchValueASCII(kProcessTypeSwitchName);
+ } else {
+ // Assume that it is the native messaging host starting if "--type" is
+ // missing and the first argument looks like an origin that represents
+ // an extension.
+ CommandLine::StringVector args = command_line->GetArgs();
+#if defined(OS_WIN)
+ std::string origin = UTF16ToUTF8(args[0]);
+#else
+ std::string origin = args[0];
+#endif
+ if (!args.empty() &&
+ StartsWithASCII(origin, kExtensionOriginPrefix, true)) {
+ process_type = kProcessTypeNativeMessagingHost;
+ }
}
MainRoutineFn main_routine = SelectMainRoutine(process_type);
diff --git a/remoting/host/host_main.h b/remoting/host/host_main.h
index 527e4b3..95ac3e9 100644
--- a/remoting/host/host_main.h
+++ b/remoting/host/host_main.h
@@ -20,6 +20,7 @@
extern const char kProcessTypeDaemon[];
extern const char kProcessTypeDesktop[];
extern const char kProcessTypeHost[];
+extern const char kProcessTypeNativeMessagingHost[];
extern const char kProcessTypeRdpDesktopSession[];
// The common entry point exported from remoting_core.dll. It uses
diff --git a/remoting/host/installer/linux/Makefile b/remoting/host/installer/linux/Makefile
index 3bbeece..9fc36be 100644
--- a/remoting/host/installer/linux/Makefile
+++ b/remoting/host/installer/linux/Makefile
@@ -12,7 +12,6 @@
INSTALL_DIR = $(DESTDIR)/opt/google/chrome-remote-desktop
CHROME_MANIFEST_DIR = $(DESTDIR)/etc/opt/chrome/native-messaging-hosts
MANIFEST = $(CHROME_MANIFEST_DIR)/com.google.chrome.remote_desktop.json
-NM_HOST_PATH = /opt/google/chrome-remote-desktop/native-messaging-host
ME2ME_PROGNAME = $(RELEASE)/remoting_me2me_host
ME2ME_DEBUGFILE = $(ME2ME_PROGNAME).debug
@@ -31,9 +30,8 @@
"$(INSTALL_DIR)/chrome-remote-desktop"
install "$(TOOLS)/is-remoting-session" "$(INSTALL_DIR)"
- install -T "$(SRC)/remoting/host/setup/native_messaging_manifest.json" \
+ install -T "$(RELEASE)/remoting/native_messaging_manifest.json" \
-m 0644 "$(MANIFEST)"
- sed -i -e "s:NATIVE_MESSAGING_HOST_PATH:$(NM_HOST_PATH):g" "$(MANIFEST)"
eu-strip -f "$(ME2ME_DEBUGFILE)" "$(ME2ME_PROGNAME)"
install "$(ME2ME_PROGNAME)" \
diff --git a/remoting/host/pairing_registry_delegate_linux.cc b/remoting/host/pairing_registry_delegate_linux.cc
index 0f1517a..c8c09e7 100644
--- a/remoting/host/pairing_registry_delegate_linux.cc
+++ b/remoting/host/pairing_registry_delegate_linux.cc
@@ -96,7 +96,13 @@
return PairingRegistry::Pairing();
}
- return PairingRegistry::Pairing::CreateFromValue(*pairing);
+ base::DictionaryValue* pairing_dictionary;
+ if (!pairing->GetAsDictionary(&pairing_dictionary)) {
+ LOG(WARNING) << "Failed to parse pairing information: not a dictionary.";
+ return PairingRegistry::Pairing();
+ }
+
+ return PairingRegistry::Pairing::CreateFromValue(*pairing_dictionary);
}
bool PairingRegistryDelegateLinux::Save(
diff --git a/remoting/host/pairing_registry_delegate_linux_unittest.cc b/remoting/host/pairing_registry_delegate_linux_unittest.cc
index 5596e3b..70cd558 100644
--- a/remoting/host/pairing_registry_delegate_linux_unittest.cc
+++ b/remoting/host/pairing_registry_delegate_linux_unittest.cc
@@ -63,8 +63,8 @@
// Verify that the only value that left is |pairing2|.
EXPECT_EQ(delegate->LoadAll()->GetSize(), 1u);
scoped_ptr<base::ListValue> pairings = delegate->LoadAll();
- base::Value* json;
- EXPECT_TRUE(pairings->Get(0, &json));
+ base::DictionaryValue* json;
+ EXPECT_TRUE(pairings->GetDictionary(0, &json));
EXPECT_EQ(PairingRegistry::Pairing::CreateFromValue(*json), pairing2);
// Delete the rest and verify.
diff --git a/remoting/host/pairing_registry_delegate_win.cc b/remoting/host/pairing_registry_delegate_win.cc
index d0527ab..c7f11d9 100644
--- a/remoting/host/pairing_registry_delegate_win.cc
+++ b/remoting/host/pairing_registry_delegate_win.cc
@@ -4,6 +4,7 @@
#include "remoting/host/pairing_registry_delegate_win.h"
+#include "base/json/json_string_value_serializer.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
@@ -13,14 +14,10 @@
namespace {
-const wchar_t kClientNameKey[] = L"clientName";
-const wchar_t kCreatedTimeKey[] = L"createdTime";
-const wchar_t kSharedSecretKey[] = L"sharedSecret";
-
// Duplicates a registry key handle (returned by RegCreateXxx/RegOpenXxx).
// The returned handle cannot be inherited and has the same permissions as
// the source one.
-bool DuplicateKeyHandle(HKEY source, ScopedRegKey* dest) {
+bool DuplicateKeyHandle(HKEY source, base::win::RegKey* dest) {
HANDLE handle;
if (!DuplicateHandle(GetCurrentProcess(),
source,
@@ -37,6 +34,66 @@
return true;
}
+// Reads value |value_name| from |key| as a JSON string and returns it as
+// |base::Value|.
+scoped_ptr<base::DictionaryValue> ReadValue(const base::win::RegKey& key,
+ const wchar_t* value_name) {
+ // presubmit: allow wstring
+ std::wstring value_json;
+ LONG result = key.ReadValue(value_name, &value_json);
+ if (result != ERROR_SUCCESS) {
+ SetLastError(result);
+ PLOG(ERROR) << "Cannot read value '" << value_name << "'";
+ return scoped_ptr<base::DictionaryValue>();
+ }
+
+ // Parse the value.
+ std::string value_json_utf8 = WideToUTF8(value_json);
+ JSONStringValueSerializer serializer(&value_json_utf8);
+ int error_code;
+ std::string error_message;
+ scoped_ptr<base::Value> value(serializer.Deserialize(&error_code,
+ &error_message));
+ if (!value) {
+ LOG(ERROR) << "Failed to parse '" << value_name << "': " << error_message
+ << " (" << error_code << ").";
+ return scoped_ptr<base::DictionaryValue>();
+ }
+
+ if (value->GetType() != base::Value::TYPE_DICTIONARY) {
+ LOG(ERROR) << "Failed to parse '" << value_name << "': not a dictionary.";
+ return scoped_ptr<base::DictionaryValue>();
+ }
+
+ return scoped_ptr<base::DictionaryValue>(
+ static_cast<base::DictionaryValue*>(value.release()));
+}
+
+// Serializes |value| into a JSON string and writes it as value |value_name|
+// under |key|.
+bool WriteValue(base::win::RegKey& key,
+ const wchar_t* value_name,
+ scoped_ptr<base::DictionaryValue> value) {
+ std::string value_json_utf8;
+ JSONStringValueSerializer serializer(&value_json_utf8);
+ if (!serializer.Serialize(*value)) {
+ LOG(ERROR) << "Failed to serialize '" << value_name << "'";
+ return false;
+ }
+
+ // presubmit: allow wstring
+ std::wstring value_json = UTF8ToWide(value_json_utf8);
+ LONG result = key.WriteValue(value_name,
+ UTF8ToWide(value_json_utf8).c_str());
+ if (result != ERROR_SUCCESS) {
+ SetLastError(result);
+ PLOG(ERROR) << "Cannot write value '" << value_name << "'";
+ return false;
+ }
+
+ return true;
+}
+
} // namespace
using protocol::PairingRegistry;
@@ -49,8 +106,8 @@
bool PairingRegistryDelegateWin::SetRootKeys(HKEY privileged,
HKEY unprivileged) {
- DCHECK(!privileged_);
- DCHECK(!unprivileged_);
+ DCHECK(!privileged_.Valid());
+ DCHECK(!unprivileged_.Valid());
DCHECK(unprivileged);
if (!DuplicateKeyHandle(unprivileged, &unprivileged_))
@@ -67,146 +124,95 @@
scoped_ptr<base::ListValue> PairingRegistryDelegateWin::LoadAll() {
scoped_ptr<base::ListValue> pairings(new base::ListValue());
- DWORD index = 0;
- for (LONG result = ERROR_SUCCESS; result == ERROR_SUCCESS; ++index) {
- wchar_t name[MAX_PATH];
- result = RegEnumKey(unprivileged_, index, name, arraysize(name));
- if (result == ERROR_SUCCESS) {
- PairingRegistry::Pairing pairing = Load(WideToUTF8(name));
- if (pairing.is_valid())
- pairings->Append(pairing.ToValue().release());
+ // Enumerate and parse all values under the unprivileged key.
+ DWORD count = unprivileged_.GetValueCount();
+ for (DWORD index = 0; index < count; ++index) {
+ // presubmit: allow wstring
+ std::wstring value_name;
+ LONG result = unprivileged_.GetValueNameAt(index, &value_name);
+ if (result != ERROR_SUCCESS) {
+ SetLastError(result);
+ PLOG(ERROR) << "Cannot get the name of value " << index;
+ continue;
}
+
+ PairingRegistry::Pairing pairing = Load(WideToUTF8(value_name));
+ if (pairing.is_valid())
+ pairings->Append(pairing.ToValue().release());
}
return pairings.Pass();
}
bool PairingRegistryDelegateWin::DeleteAll() {
- LONG result = ERROR_SUCCESS;
- bool success = true;
- while (result == ERROR_SUCCESS) {
- wchar_t name[MAX_PATH];
- result = RegEnumKey(unprivileged_, 0, name, arraysize(name));
- if (result == ERROR_SUCCESS)
- success = success && Delete(WideToUTF8(name));
+ if (!privileged_.Valid()) {
+ LOG(ERROR) << "Cannot delete pairings: the delegate is read-only.";
+ return false;
}
- success = success && result == ERROR_NO_MORE_ITEMS;
+ bool success = true;
+ DWORD count = unprivileged_.GetValueCount();
+ while (count > 0) {
+ // presubmit: allow wstring
+ std::wstring value_name;
+ LONG result = unprivileged_.GetValueNameAt(0, &value_name);
+ if (result == ERROR_SUCCESS)
+ result = unprivileged_.DeleteValue(value_name.c_str());
+
+ success = success && (result == ERROR_SUCCESS);
+ count = unprivileged_.GetValueCount();
+ }
+
return success;
}
PairingRegistry::Pairing PairingRegistryDelegateWin::Load(
const std::string& client_id) {
- string16 key_name = UTF8ToUTF16(client_id);
-
- FILETIME created_time;
- string16 client_name;
- string16 shared_secret;
+ // presubmit: allow wstring
+ std::wstring value_name = UTF8ToWide(client_id);
// Read unprivileged fields first.
- base::win::RegKey pairing_key;
- LONG result = pairing_key.Open(unprivileged_, key_name.c_str(), KEY_READ);
- if (result != ERROR_SUCCESS) {
- SetLastError(result);
- PLOG(ERROR) << "Cannot open pairing entry '" << client_id << "'";
+ scoped_ptr<base::DictionaryValue> pairing = ReadValue(unprivileged_,
+ value_name.c_str());
+ if (!pairing)
return PairingRegistry::Pairing();
- }
- result = pairing_key.ReadValue(kClientNameKey, &client_name);
- if (result != ERROR_SUCCESS) {
- SetLastError(result);
- PLOG(ERROR) << "Cannot read '" << client_id << "/" << kClientNameKey << "'";
- return PairingRegistry::Pairing();
- }
- DWORD size = sizeof(created_time);
- DWORD type;
- result = pairing_key.ReadValue(kCreatedTimeKey,
- &created_time,
- &size,
- &type);
- if (result != ERROR_SUCCESS ||
- size != sizeof(created_time) ||
- type != REG_QWORD) {
- SetLastError(result);
- PLOG(ERROR) << "Cannot read '" << client_id << "/" << kCreatedTimeKey
- << "'";
- return PairingRegistry::Pairing();
- }
// Read the shared secret.
- if (privileged_.IsValid()) {
- result = pairing_key.Open(privileged_, key_name.c_str(), KEY_READ);
- if (result != ERROR_SUCCESS) {
- SetLastError(result);
- PLOG(ERROR) << "Cannot open pairing entry '" << client_id << "'";
+ if (privileged_.Valid()) {
+ scoped_ptr<base::DictionaryValue> secret = ReadValue(privileged_,
+ value_name.c_str());
+ if (!secret)
return PairingRegistry::Pairing();
- }
- result = pairing_key.ReadValue(kSharedSecretKey, &shared_secret);
- if (result != ERROR_SUCCESS) {
- SetLastError(result);
- PLOG(ERROR) << "Cannot read '" << client_id << "/" << kSharedSecretKey
- << "'";
- return PairingRegistry::Pairing();
- }
+
+ // Merge the two dictionaries.
+ pairing->MergeDictionary(secret.get());
}
- return PairingRegistry::Pairing(base::Time::FromFileTime(created_time),
- UTF16ToUTF8(client_name),
- client_id,
- UTF16ToUTF8(shared_secret));
+ return PairingRegistry::Pairing::CreateFromValue(*pairing);
}
bool PairingRegistryDelegateWin::Save(const PairingRegistry::Pairing& pairing) {
- string16 key_name = UTF8ToUTF16(pairing.client_id());
-
- if (!privileged_.IsValid()) {
+ if (!privileged_.Valid()) {
LOG(ERROR) << "Cannot save pairing entry '" << pairing.client_id()
<< "': the delegate is read-only.";
return false;
}
- // Store the shared secret first.
- base::win::RegKey pairing_key;
- LONG result = pairing_key.Create(privileged_, key_name.c_str(), KEY_WRITE);
- if (result != ERROR_SUCCESS) {
- SetLastError(result);
- PLOG(ERROR) << "Cannot save pairing entry '" << pairing.client_id()
- << "'";
- return false;
- }
- result = pairing_key.WriteValue(kSharedSecretKey,
- UTF8ToUTF16(pairing.shared_secret()).c_str());
- if (result != ERROR_SUCCESS) {
- SetLastError(result);
- PLOG(ERROR) << "Cannot write '" << pairing.client_id() << "/"
- << kSharedSecretKey << "'";
- return false;
- }
+ // Convert pairing to JSON.
+ scoped_ptr<base::DictionaryValue> pairing_json = pairing.ToValue();
- // Store the rest of the fields.
- result = pairing_key.Create(unprivileged_, key_name.c_str(), KEY_WRITE);
- if (result != ERROR_SUCCESS) {
- SetLastError(result);
- PLOG(ERROR) << "Cannot save pairing entry '" << pairing.client_id()
- << "'";
- return false;
- }
- result = pairing_key.WriteValue(kClientNameKey,
- UTF8ToUTF16(pairing.client_name()).c_str());
- if (result != ERROR_SUCCESS) {
- SetLastError(result);
- PLOG(ERROR) << "Cannot write '" << pairing.client_id() << "/"
- << kClientNameKey << "'";
- return false;
- }
- FILETIME created_time = pairing.created_time().ToFileTime();
- result = pairing_key.WriteValue(kCreatedTimeKey,
- &created_time,
- sizeof(created_time),
- REG_QWORD);
- if (result != ERROR_SUCCESS) {
- SetLastError(result);
- PLOG(ERROR) << "Cannot write '" << pairing.client_id() << "/"
- << kCreatedTimeKey << "'";
+ // Extract the shared secret to a separate dictionary.
+ scoped_ptr<base::Value> secret_key;
+ CHECK(pairing_json->Remove(PairingRegistry::kSharedSecretKey, &secret_key));
+ scoped_ptr<base::DictionaryValue> secret_json(new base::DictionaryValue());
+ secret_json->Set(PairingRegistry::kSharedSecretKey, secret_key.release());
+
+ // presubmit: allow wstring
+ std::wstring value_name = UTF8ToWide(pairing.client_id());
+
+ // Write pairing to the registry.
+ if (!WriteValue(privileged_, value_name.c_str(), secret_json.Pass()) ||
+ !WriteValue(unprivileged_, value_name.c_str(), pairing_json.Pass())) {
return false;
}
@@ -214,15 +220,15 @@
}
bool PairingRegistryDelegateWin::Delete(const std::string& client_id) {
- string16 key_name = UTF8ToUTF16(client_id);
-
- if (!privileged_.IsValid()) {
+ if (!privileged_.Valid()) {
LOG(ERROR) << "Cannot delete pairing entry '" << client_id
<< "': the delegate is read-only.";
return false;
}
- LONG result = RegDeleteKey(privileged_, key_name.c_str());
+ // presubmit: allow wstring
+ std::wstring value_name = UTF8ToWide(client_id);
+ LONG result = privileged_.DeleteValue(value_name.c_str());
if (result != ERROR_SUCCESS &&
result != ERROR_FILE_NOT_FOUND &&
result != ERROR_PATH_NOT_FOUND) {
@@ -231,7 +237,7 @@
return false;
}
- result = RegDeleteKey(unprivileged_, key_name.c_str());
+ result = unprivileged_.DeleteValue(value_name.c_str());
if (result != ERROR_SUCCESS &&
result != ERROR_FILE_NOT_FOUND &&
result != ERROR_PATH_NOT_FOUND) {
diff --git a/remoting/host/pairing_registry_delegate_win.h b/remoting/host/pairing_registry_delegate_win.h
index 8dac568..ecbd4a2 100644
--- a/remoting/host/pairing_registry_delegate_win.h
+++ b/remoting/host/pairing_registry_delegate_win.h
@@ -10,7 +10,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "remoting/base/scoped_reg_key_win.h"
+#include "base/win/registry.h"
#include "remoting/protocol/pairing_registry.h"
namespace base {
@@ -49,8 +49,8 @@
virtual bool Delete(const std::string& client_id) OVERRIDE;
private:
- ScopedRegKey privileged_;
- ScopedRegKey unprivileged_;
+ base::win::RegKey privileged_;
+ base::win::RegKey unprivileged_;
DISALLOW_COPY_AND_ASSIGN(PairingRegistryDelegateWin);
};
diff --git a/remoting/host/pairing_registry_delegate_win_unittest.cc b/remoting/host/pairing_registry_delegate_win_unittest.cc
index 8ba6bb1..b8b3953 100644
--- a/remoting/host/pairing_registry_delegate_win_unittest.cc
+++ b/remoting/host/pairing_registry_delegate_win_unittest.cc
@@ -75,8 +75,8 @@
// Verify that the only remaining value is |pairing2|.
EXPECT_EQ(delegate->LoadAll()->GetSize(), 1u);
scoped_ptr<base::ListValue> pairings = delegate->LoadAll();
- base::Value* json;
- EXPECT_TRUE(pairings->Get(0, &json));
+ base::DictionaryValue* json;
+ EXPECT_TRUE(pairings->GetDictionary(0, &json));
EXPECT_EQ(PairingRegistry::Pairing::CreateFromValue(*json), pairing2);
// Delete the rest and verify.
diff --git a/remoting/host/setup/native_messaging_host.cc b/remoting/host/setup/native_messaging_host.cc
index 2240558..7bf6b7c 100644
--- a/remoting/host/setup/native_messaging_host.cc
+++ b/remoting/host/setup/native_messaging_host.cc
@@ -11,14 +11,22 @@
#include "base/callback.h"
#include "base/json/json_string_value_serializer.h"
#include "base/location.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/strings/stringize_macros.h"
#include "base/values.h"
#include "net/base/net_util.h"
#include "remoting/base/rsa_key_pair.h"
+#include "remoting/host/host_exit_codes.h"
+#include "remoting/host/pairing_registry_delegate.h"
#include "remoting/host/pairing_registry_delegate.h"
#include "remoting/host/pin_hash.h"
#include "remoting/protocol/pairing_registry.h"
+#if defined(OS_POSIX)
+#include <unistd.h>
+#endif
+
namespace {
// Features supported in addition to the base protocol.
@@ -407,4 +415,29 @@
SendResponse(response.Pass());
}
+int NativeMessagingHostMain() {
+#if defined(OS_WIN)
+ base::PlatformFile read_file = GetStdHandle(STD_INPUT_HANDLE);
+ base::PlatformFile write_file = GetStdHandle(STD_OUTPUT_HANDLE);
+#elif defined(OS_POSIX)
+ base::PlatformFile read_file = STDIN_FILENO;
+ base::PlatformFile write_file = STDOUT_FILENO;
+#else
+#error Not implemented.
+#endif
+
+ base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
+ base::RunLoop run_loop;
+ scoped_refptr<protocol::PairingRegistry> pairing_registry =
+ CreatePairingRegistry(message_loop.message_loop_proxy());
+ remoting::NativeMessagingHost host(remoting::DaemonController::Create(),
+ pairing_registry,
+ read_file, write_file,
+ message_loop.message_loop_proxy(),
+ run_loop.QuitClosure());
+ host.Start();
+ run_loop.Run();
+ return kSuccessExitCode;
+}
+
} // namespace remoting
diff --git a/remoting/host/setup/native_messaging_host.h b/remoting/host/setup/native_messaging_host.h
index 2dd7af4..309d63c 100644
--- a/remoting/host/setup/native_messaging_host.h
+++ b/remoting/host/setup/native_messaging_host.h
@@ -126,6 +126,10 @@
DISALLOW_COPY_AND_ASSIGN(NativeMessagingHost);
};
+// Creates a NativeMessagingHost instance, attaches it to stdin/stdout and runs
+// the message loop until NativeMessagingHost signals shutdown.
+int NativeMessagingHostMain();
+
} // namespace remoting
#endif // REMOTING_HOST_SETUP_NATIVE_MESSAGING_HOST_H_
diff --git a/remoting/host/setup/native_messaging_host_main.cc b/remoting/host/setup/native_messaging_host_main.cc
index c227033..d9db325 100644
--- a/remoting/host/setup/native_messaging_host_main.cc
+++ b/remoting/host/setup/native_messaging_host_main.cc
@@ -2,21 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "remoting/host/setup/native_messaging_host.h"
-
#include "base/at_exit.h"
#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
#include "remoting/host/logging.h"
-#include "remoting/host/pairing_registry_delegate.h"
-#include "remoting/protocol/pairing_registry.h"
-
-#if defined(OS_POSIX)
-#include <unistd.h>
-#endif
-
-using remoting::protocol::PairingRegistry;
+#include "remoting/host/setup/native_messaging_host.h"
int main(int argc, char** argv) {
// This object instance is required by Chrome code (such as MessageLoop).
@@ -25,26 +14,5 @@
CommandLine::Init(argc, argv);
remoting::InitHostLogging();
-#if defined(OS_WIN)
- base::PlatformFile read_file = GetStdHandle(STD_INPUT_HANDLE);
- base::PlatformFile write_file = GetStdHandle(STD_OUTPUT_HANDLE);
-#elif defined(OS_POSIX)
- base::PlatformFile read_file = STDIN_FILENO;
- base::PlatformFile write_file = STDOUT_FILENO;
-#else
-#error Not implemented.
-#endif
-
- base::MessageLoop message_loop(base::MessageLoop::TYPE_IO);
- base::RunLoop run_loop;
- scoped_refptr<PairingRegistry> pairing_registry =
- remoting::CreatePairingRegistry(message_loop.message_loop_proxy());
- remoting::NativeMessagingHost host(remoting::DaemonController::Create(),
- pairing_registry,
- read_file, write_file,
- message_loop.message_loop_proxy(),
- run_loop.QuitClosure());
- host.Start();
- run_loop.Run();
- return 0;
+ return remoting::NativeMessagingHostMain();
}
diff --git a/remoting/host/setup/native_messaging_manifest.json b/remoting/host/setup/native_messaging_manifest.json
index 875ba04..84884a2 100644
--- a/remoting/host/setup/native_messaging_manifest.json
+++ b/remoting/host/setup/native_messaging_manifest.json
@@ -1,8 +1,8 @@
{
"name": "com.google.chrome.remote_desktop",
- "description": "Chrome Remote Desktop Host",
+ "description": "{% trans %}REMOTING_HOST_PLUGIN_NAME{% endtrans %}",
"type": "stdio",
- "path": "NATIVE_MESSAGING_HOST_PATH",
+ "path": "{{ NATIVE_MESSAGING_HOST_PATH }}",
"allowed_origins": [
"chrome-extension://ljacajndfccfgnfohlgkdphmbnpkjflk/",
"chrome-extension://gbchcmhmhahfdphkhkmpfmihenigjmpp/",
diff --git a/remoting/host/win/entry_point.cc b/remoting/host/win/entry_point.cc
index 26ab33d..3b54069 100644
--- a/remoting/host/win/entry_point.cc
+++ b/remoting/host/win/entry_point.cc
@@ -6,8 +6,8 @@
#include "remoting/host/host_main.h"
-// The common entry point for all Me2Me host binaries. In order to be really
-// small the app doesn't link against the CRT.
+// The common entry point for remoting_host.exe and remoting_desktop.exe. In
+// order to be really small the app doesn't link against the CRT.
void HostEntryPoint() {
// CommandLine::Init() ignores the passed parameters on Windows, so it is safe
// to pass NULL here.
diff --git a/remoting/protocol/pairing_registry.cc b/remoting/protocol/pairing_registry.cc
index a6e7327..c159ce6 100644
--- a/remoting/protocol/pairing_registry.cc
+++ b/remoting/protocol/pairing_registry.cc
@@ -57,21 +57,15 @@
}
PairingRegistry::Pairing PairingRegistry::Pairing::CreateFromValue(
- const base::Value& pairing_json) {
- const base::DictionaryValue* pairing = NULL;
- if (!pairing_json.GetAsDictionary(&pairing)) {
- LOG(ERROR) << "Failed to load pairing information: not a dictionary.";
- return Pairing();
- }
-
+ const base::DictionaryValue& pairing) {
std::string client_name, client_id;
double created_time_value;
- if (pairing->GetDouble(kCreatedTimeKey, &created_time_value) &&
- pairing->GetString(kClientNameKey, &client_name) &&
- pairing->GetString(kClientIdKey, &client_id)) {
+ if (pairing.GetDouble(kCreatedTimeKey, &created_time_value) &&
+ pairing.GetString(kClientNameKey, &client_name) &&
+ pairing.GetString(kClientIdKey, &client_id)) {
// The shared secret is optional.
std::string shared_secret;
- pairing->GetString(kSharedSecretKey, &shared_secret);
+ pairing.GetString(kSharedSecretKey, &shared_secret);
base::Time created_time = base::Time::FromJsTime(created_time_value);
return Pairing(created_time, client_name, client_id, shared_secret);
}
@@ -80,14 +74,14 @@
return Pairing();
}
-scoped_ptr<base::Value> PairingRegistry::Pairing::ToValue() const {
+scoped_ptr<base::DictionaryValue> PairingRegistry::Pairing::ToValue() const {
scoped_ptr<base::DictionaryValue> pairing(new base::DictionaryValue());
pairing->SetDouble(kCreatedTimeKey, created_time().ToJsTime());
pairing->SetString(kClientNameKey, client_name());
pairing->SetString(kClientIdKey, client_id());
if (!shared_secret().empty())
pairing->SetString(kSharedSecretKey, shared_secret());
- return pairing.PassAs<base::Value>();
+ return pairing.Pass();
}
bool PairingRegistry::Pairing::operator==(const Pairing& other) const {
diff --git a/remoting/protocol/pairing_registry.h b/remoting/protocol/pairing_registry.h
index ddcd736..e9ff1ff 100644
--- a/remoting/protocol/pairing_registry.h
+++ b/remoting/protocol/pairing_registry.h
@@ -17,8 +17,8 @@
#include "base/time/time.h"
namespace base {
+class DictionaryValue;
class ListValue;
-class Value;
class SingleThreadTaskRunner;
} // namespace base
@@ -49,9 +49,9 @@
~Pairing();
static Pairing Create(const std::string& client_name);
- static Pairing CreateFromValue(const base::Value& pairing_json);
+ static Pairing CreateFromValue(const base::DictionaryValue& pairing);
- scoped_ptr<base::Value> ToValue() const;
+ scoped_ptr<base::DictionaryValue> ToValue() const;
bool operator==(const Pairing& other) const;
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 48bcf44..f81cfd3 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -840,31 +840,6 @@
},
],
}, # end of target 'remoting_infoplist_strings'
-
- {
- 'target_name': 'remoting_native_messaging_host',
- 'type': 'executable',
- 'variables': { 'enable_wexit_time_destructors': 1, },
- 'dependencies': [
- '../base/base.gyp:base',
- 'remoting_host',
- 'remoting_host_logging',
- 'remoting_host_setup_base',
- ],
- 'defines': [
- 'VERSION=<(version_full)',
- ],
- 'sources': [
- 'host/setup/native_messaging_host_main.cc',
- ],
- 'conditions': [
- ['OS=="linux" and linux_use_tcmalloc==1', {
- 'dependencies': [
- '../base/allocator/allocator.gyp:allocator',
- ],
- }],
- ],
- }, # end of target 'remoting_native_messaging_host'
], # end of 'targets'
}], # 'enable_remoting_host==1'
@@ -957,6 +932,7 @@
'remoting_host',
'remoting_host_event_logger',
'remoting_host_logging',
+ 'remoting_host_setup_base',
'remoting_infoplist_strings',
'remoting_jingle_glue',
'remoting_me2me_host_static',
@@ -1035,7 +1011,31 @@
}], # OS=linux
], # end of 'conditions'
}, # end of target 'remoting_me2me_host'
-
+ {
+ 'target_name': 'remoting_native_messaging_host',
+ 'type': 'executable',
+ 'variables': { 'enable_wexit_time_destructors': 1, },
+ 'dependencies': [
+ '../base/base.gyp:base',
+ 'remoting_host',
+ 'remoting_host_logging',
+ 'remoting_host_setup_base',
+ 'remoting_native_messaging_manifest',
+ ],
+ 'defines': [
+ 'VERSION=<(version_full)',
+ ],
+ 'sources': [
+ 'host/setup/native_messaging_host_main.cc',
+ ],
+ 'conditions': [
+ ['OS=="linux" and linux_use_tcmalloc==1', {
+ 'dependencies': [
+ '../base/allocator/allocator.gyp:allocator',
+ ],
+ }],
+ ],
+ }, # end of target 'remoting_native_messaging_host'
], # end of 'targets'
}], # 'OS!="win" and enable_remoting_host==1'
@@ -1511,13 +1511,13 @@
'../ipc/ipc.gyp:ipc',
'../net/net.gyp:net',
'../third_party/webrtc/modules/modules.gyp:desktop_capture',
- '../third_party/webrtc/modules/modules.gyp:desktop_capture',
'remoting_base',
'remoting_breakpad',
'remoting_core_resources',
'remoting_host',
'remoting_host_event_logger',
'remoting_host_logging',
+ 'remoting_host_setup_base',
'remoting_lib_idl',
'remoting_lib_ps',
'remoting_lib_rc',
@@ -1937,6 +1937,7 @@
'remoting_core',
'remoting_desktop',
'remoting_host_exe',
+ 'remoting_native_messaging_manifest',
],
'compiled_inputs': [
'<(PRODUCT_DIR)/remoting_core.dll',
@@ -1968,11 +1969,13 @@
'generated_files': [
'<@(_compiled_inputs)',
'<(sas_dll_path)/sas.dll',
+ '<(PRODUCT_DIR)/remoting/native_messaging_manifest.json',
'resources/chromoting.ico',
],
'generated_files_dst': [
'<@(_compiled_inputs_dst)',
'files/sas.dll',
+ 'files/native_messaging_manifest.json',
'files/chromoting.ico',
],
'zip_path': '<(PRODUCT_DIR)/remoting-me2me-host-<(OS).zip',
@@ -2282,6 +2285,53 @@
],
}, # end of target 'remoting_webapp'
+ # Generates 'native_messaging_manifest.json' to be included in the
+ # installation.
+ {
+ 'target_name': 'remoting_native_messaging_manifest',
+ 'type': 'none',
+ 'dependencies': [
+ 'remoting_resources',
+ ],
+ 'variables': {
+ 'input': 'host/setup/native_messaging_manifest.json',
+ 'output': '<(PRODUCT_DIR)/remoting/native_messaging_manifest.json',
+ },
+ 'conditions': [
+ [ 'OS=="win"', {
+ 'variables': {
+ 'native_messaging_host_path': 'remoting_host.exe',
+ },
+ }, {
+ 'variables': {
+ 'native_messaging_host_path': '/opt/google/chrome-remote-desktop/native-messaging-host',
+ },
+ }],
+ ],
+ 'actions': [
+ {
+ 'action_name': 'generate_manifest',
+ 'inputs': [
+ '<(remoting_localize_path)',
+ '<(input)',
+ ],
+ 'outputs': [
+ '<(output)',
+ ],
+ 'action': [
+ 'python',
+ '<(remoting_localize_path)',
+ '--define', 'NATIVE_MESSAGING_HOST_PATH=<(native_messaging_host_path)',
+ '--locale_dir', '<(webapp_locale_dir)',
+ '--template', '<(input)',
+ '--locale_output',
+ '<(output)',
+ '--encoding', 'utf-8',
+ 'en',
+ ],
+ },
+ ],
+ }, # end of target 'remoting_native_messaging_manifest'
{
'target_name': 'remoting_resources',
'type': 'none',
@@ -2418,7 +2468,6 @@
'base/rsa_key_pair.h',
'base/running_average.cc',
'base/running_average.h',
- 'base/scoped_reg_key_win.h',
'base/scoped_sc_handle_win.h',
'base/socket_reader.cc',
'base/socket_reader.h',
diff --git a/remoting/resources/menu/chromoting_actionbar.xml b/remoting/resources/menu/chromoting_actionbar.xml
index 1507dd4..e602a36 100644
--- a/remoting/resources/menu/chromoting_actionbar.xml
+++ b/remoting/resources/menu/chromoting_actionbar.xml
@@ -1,6 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!--Action bar buttons for the Android app's host listing-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/actionbar_directoryrefresh"
+ android:title="@string/actionbar_directoryrefresh"
+ android:icon="@android:drawable/ic_popup_sync"
+ android:showAsAction="ifRoom"/>
<item android:id="@+id/actionbar_accountswitcher"
android:title="@string/actionbar_accountswitcher"
android:icon="@android:drawable/ic_menu_more"
diff --git a/remoting/resources/strings.xml b/remoting/resources/strings.xml
index 949a2aa..a2c2095 100644
--- a/remoting/resources/strings.xml
+++ b/remoting/resources/strings.xml
@@ -18,6 +18,7 @@
<string name="pin_entry_cancel">Cancel</string>
<!--Action bar buttons-->
+ <string name="actionbar_directoryrefresh">Refresh</string>
<string name="actionbar_accountswitcher">Accounts</string>
<string name="actionbar_hide">Hide</string>
<string name="actionbar_keyboard">Keyboard</string>
@@ -31,6 +32,7 @@
<string name="error_auth_canceled">Authentication prompt canceled by user</string>
<string name="error_no_accounts">Device not linked to any Google accounts</string>
<string name="error_auth_failed">Authentication with specified account failed</string>
+ <string name="error_bad_connection">No network connection</string>
<string name="error_cataloging_hosts">Unable to display host list</string>
<string name="error_displaying_host">Unable to display host entry</string>
<string name="error_unexpected_response">Account has no remote desktop hosts registered</string>
diff --git a/remoting/webapp/appsv2.patch b/remoting/webapp/appsv2.patch
index 0e643db..f03a317 100644
--- a/remoting/webapp/appsv2.patch
+++ b/remoting/webapp/appsv2.patch
@@ -42,8 +42,8 @@
"clipboardWrite",
- "nativeMessaging"
+ "nativeMessaging",
-+ "experimental",
+ "fullscreen"
++ "identity",
],
- "plugins": [
- { "path": "remoting_host_plugin.dll", "public": false },
diff --git a/remoting/webapp/client_screen.js b/remoting/webapp/client_screen.js
index b2b22fe..11f6d74 100644
--- a/remoting/webapp/client_screen.js
+++ b/remoting/webapp/client_screen.js
@@ -356,6 +356,7 @@
}
};
remoting.HostSettings.save(clientSession.hostId, pairingInfo);
+ remoting.connector.updatePairingInfo(clientId, sharedSecret);
};
// Use the platform name as a proxy for the local computer name.
// TODO(jamiewalch): Use a descriptive name for the local computer, for
diff --git a/remoting/webapp/clipboard.js b/remoting/webapp/clipboard.js
index 4b18d57..6a29dcd 100644
--- a/remoting/webapp/clipboard.js
+++ b/remoting/webapp/clipboard.js
@@ -75,6 +75,7 @@
*/
remoting.Clipboard.prototype.toHost = function(clipboardData) {
if (!clipboardData || !clipboardData.types || !clipboardData.getData) {
+ console.log('Got invalid clipboardData.');
return;
}
if (!remoting.clientSession || !remoting.clientSession.plugin) {
@@ -83,17 +84,22 @@
var plugin = remoting.clientSession.plugin;
for (var i = 0; i < clipboardData.types.length; i++) {
var type = clipboardData.types[i];
+ var item = clipboardData.getData(type);
+ if (!item) {
+ item = "";
+ }
+ console.log('Got clipboard from OS, type: ' + type +
+ ' length: ' + item.length + ' new: ' +
+ (item != this.previousContent) + ' blocking-send: ' +
+ this.blockOneClipboardSend_);
// The browser presents text clipboard items as 'text/plain'.
if (type == this.ItemTypes.TEXT_TYPE) {
- var item = clipboardData.getData(type);
- if (!item) {
- item = "";
- }
// Don't send the same item more than once. Otherwise the item may be
// sent to and fro indefinitely.
if (item != this.previousContent) {
if (!this.blockOneClipboardSend_) {
// The plugin's JSON reader emits UTF-8.
+ console.log('Sending clipboard to host.');
plugin.sendClipboardItem(this.ItemTypes.TEXT_UTF8_TYPE, item);
}
this.previousContent = item;
@@ -114,6 +120,9 @@
remoting.Clipboard.prototype.fromHost = function(mimeType, item) {
// The plugin's JSON layer will correctly convert only UTF-8 data sent from
// the host.
+ console.log('Got clipboard from host, type: ' + mimeType +
+ ' length: ' + item.length + ' new: ' +
+ (item != this.previousContent));
if (mimeType != this.ItemTypes.TEXT_UTF8_TYPE) {
return;
}
@@ -134,12 +143,14 @@
*/
remoting.Clipboard.prototype.toOs = function(clipboardData) {
if (!this.itemFromHostTextPending) {
+ console.log('Got unexpected clipboard copy event.');
return false;
}
// The JSON layer between the plugin and this webapp converts UTF-8 to the
// JS string encoding. The browser will convert JS strings to the correct
// encoding, per OS and locale conventions, provided the data type is
// 'text/plain'.
+ console.log('Setting OS clipboard, length: ' + this.previousContent.length);
clipboardData.setData(this.ItemTypes.TEXT_TYPE, this.previousContent);
this.itemFromHostTextPending = false;
return true;
@@ -156,6 +167,7 @@
remoting.Clipboard.prototype.initiateToHost = function() {
// It would be cleaner to send a paste command to the plugin element,
// but that's not supported.
+ console.log('Initiating clipboard paste.');
document.execCommand("paste");
};
@@ -170,6 +182,7 @@
remoting.Clipboard.prototype.initiateToOs = function() {
// It would be cleaner to send a paste command to the plugin element,
// but that's not supported.
+ console.log('Initiating clipboard copy.');
document.execCommand("copy");
};
diff --git a/remoting/webapp/identity.js b/remoting/webapp/identity.js
index cc832f2..e30e143 100644
--- a/remoting/webapp/identity.js
+++ b/remoting/webapp/identity.js
@@ -51,7 +51,7 @@
remoting.Identity.prototype.callWithToken = function(onOk, onError) {
this.pendingCallbacks_.push(new remoting.Identity.Callbacks(onOk, onError));
if (this.pendingCallbacks_.length == 1) {
- chrome.experimental.identity.getAuthToken(
+ chrome.identity.getAuthToken(
{ 'interactive': false },
this.onAuthComplete_.bind(this, false));
}
@@ -132,7 +132,7 @@
* @private
*/
remoting.Identity.prototype.onAuthContinue_ = function() {
- chrome.experimental.identity.getAuthToken(
+ chrome.identity.getAuthToken(
{ 'interactive': true },
this.onAuthComplete_.bind(this, true));
};
diff --git a/remoting/webapp/jscompiler_hacks.js b/remoting/webapp/jscompiler_hacks.js
index 911d321..ad4d755 100644
--- a/remoting/webapp/jscompiler_hacks.js
+++ b/remoting/webapp/jscompiler_hacks.js
@@ -122,10 +122,7 @@
};
/** @type {Object} */
-chrome.experimental = {};
-
-/** @type {Object} */
-chrome.experimental.identity = {
+chrome.identity = {
/**
* @param {Object.<string>} parameters
* @param {function(string):void} callback
diff --git a/remoting/webapp/session_connector.js b/remoting/webapp/session_connector.js
index a5facb5..5febaab 100644
--- a/remoting/webapp/session_connector.js
+++ b/remoting/webapp/session_connector.js
@@ -194,6 +194,18 @@
};
/**
+ * Update the pairing info so that the reconnect function will work correctly.
+ *
+ * @param {string} clientId The paired client id.
+ * @param {string} sharedSecret The shared secret.
+ */
+remoting.SessionConnector.prototype.updatePairingInfo =
+ function(clientId, sharedSecret) {
+ this.clientPairingId_ = clientId;
+ this.clientPairedSecret_ = sharedSecret;
+};
+
+/**
* Initiate a Me2Me connection.
*
* @param {string} hostId ID of the Me2Me host.
@@ -224,8 +236,6 @@
this.cancel();
this.hostId_ = hostId;
- this.clientPairingId_ = clientPairingId;
- this.clientPairedSecret_ = clientPairedSecret;
this.hostJid_ = hostJid;
this.hostPublicKey_ = hostPublicKey;
this.fetchPin_ = fetchPin;
@@ -233,6 +243,7 @@
this.hostDisplayName_ = hostDisplayName;
this.connectionMode_ = remoting.ClientSession.Mode.ME2ME;
this.refreshHostJidIfOffline_ = refreshHostJidIfOffline;
+ this.updatePairingInfo(clientPairingId, clientPairedSecret);
this.createSessionIfReady_();
};
diff --git a/remoting/webapp/third_party_token_fetcher.js b/remoting/webapp/third_party_token_fetcher.js
index ffe9120..9c8cce1 100644
--- a/remoting/webapp/third_party_token_fetcher.js
+++ b/remoting/webapp/third_party_token_fetcher.js
@@ -44,7 +44,7 @@
this.xsrfToken_ = remoting.generateXsrfToken();
this.tokenUrlPatterns_ = tokenUrlPatterns;
this.hostPublicKey_ = hostPublicKey;
- if (chrome.experimental && chrome.experimental.identity) {
+ if (chrome.identity) {
/** @type {function():void}
* @private */
this.fetchTokenInternal_ = this.fetchTokenIdentityApi_.bind(this);
@@ -93,9 +93,9 @@
function(responseUrl) {
var token = '';
var sharedSecret = '';
- if (responseUrl &&
- responseUrl.search(this.redirectUri_ + '#') == 0) {
- var query = responseUrl.substring(this.redirectUri_.length + 1);
+
+ if (responseUrl && responseUrl.search('#') >= 0) {
+ var query = responseUrl.substring(responseUrl.search('#') + 1);
var parts = query.split('&');
/** @type {Object.<string>} */
var queryArgs = {};
@@ -105,8 +105,7 @@
}
// Check that 'state' contains the same XSRF token we sent in the request.
- var xsrfToken = queryArgs['state'];
- if (xsrfToken == this.xsrfToken_ &&
+ if ('state' in queryArgs && queryArgs['state'] == this.xsrfToken_ &&
'code' in queryArgs && 'access_token' in queryArgs) {
// Terminology note:
// In the OAuth code/token exchange semantics, 'code' refers to the value
@@ -169,8 +168,7 @@
*/
remoting.ThirdPartyTokenFetcher.prototype.fetchTokenIdentityApi_ = function() {
var fullTokenUrl = this.getFullTokenUrl_();
- // TODO(rmsousa): chrome.identity.launchWebAuthFlow is experimental.
- chrome.experimental.identity.launchWebAuthFlow(
+ chrome.identity.launchWebAuthFlow(
{'url': fullTokenUrl, 'interactive': true},
this.parseRedirectUrl_.bind(this));
};
\ No newline at end of file
diff --git a/skia/skia_chrome.target.darwin-arm.mk b/skia/skia_chrome.target.darwin-arm.mk
index f5c66a3..6d86040 100644
--- a/skia/skia_chrome.target.darwin-arm.mk
+++ b/skia/skia_chrome.target.darwin-arm.mk
@@ -101,6 +101,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
@@ -202,6 +203,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome.target.darwin-mips.mk b/skia/skia_chrome.target.darwin-mips.mk
index 749ff01..3e2989c 100644
--- a/skia/skia_chrome.target.darwin-mips.mk
+++ b/skia/skia_chrome.target.darwin-mips.mk
@@ -101,6 +101,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
@@ -202,6 +203,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome.target.darwin-x86.mk b/skia/skia_chrome.target.darwin-x86.mk
index 210fa9e..d55ec3b 100644
--- a/skia/skia_chrome.target.darwin-x86.mk
+++ b/skia/skia_chrome.target.darwin-x86.mk
@@ -103,6 +103,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
@@ -207,6 +208,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome.target.linux-arm.mk b/skia/skia_chrome.target.linux-arm.mk
index f5c66a3..6d86040 100644
--- a/skia/skia_chrome.target.linux-arm.mk
+++ b/skia/skia_chrome.target.linux-arm.mk
@@ -101,6 +101,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
@@ -202,6 +203,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome.target.linux-mips.mk b/skia/skia_chrome.target.linux-mips.mk
index 749ff01..3e2989c 100644
--- a/skia/skia_chrome.target.linux-mips.mk
+++ b/skia/skia_chrome.target.linux-mips.mk
@@ -101,6 +101,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
@@ -202,6 +203,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome.target.linux-x86.mk b/skia/skia_chrome.target.linux-x86.mk
index 210fa9e..d55ec3b 100644
--- a/skia/skia_chrome.target.linux-x86.mk
+++ b/skia/skia_chrome.target.linux-x86.mk
@@ -103,6 +103,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
@@ -207,6 +208,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
diff --git a/skia/skia_library.gypi b/skia/skia_library.gypi
index 2dca283..6d3f1c5 100644
--- a/skia/skia_library.gypi
+++ b/skia/skia_library.gypi
@@ -261,9 +261,10 @@
}],
[ 'OS != "ios"', {
'dependencies': [
- # FIXME: Add a dependency on
- # '<(DEPTH)/third_party/WebKit/public/blink_skia_config.gyp:blink_skia_config'
- # once https://codereview.chromium.org/21137002 rolls into Chromium.
+ '../third_party/WebKit/public/blink_skia_config.gyp:blink_skia_config',
+ ],
+ 'export_dependent_settings': [
+ '../third_party/WebKit/public/blink_skia_config.gyp:blink_skia_config',
],
}],
[ 'OS != "mac"', {
diff --git a/skia/skia_library.target.darwin-arm.mk b/skia/skia_library.target.darwin-arm.mk
index 7d2cb16..86d43cc 100644
--- a/skia/skia_library.target.darwin-arm.mk
+++ b/skia/skia_library.target.darwin-arm.mk
@@ -11,6 +11,7 @@
# Make sure our deps are built first.
GYP_TARGET_DEPENDENCIES := \
+ $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp
GYP_GENERATED_OUTPUTS :=
@@ -107,6 +108,7 @@
third_party/skia/src/core/SkFilterShader.cpp \
third_party/skia/src/core/SkFlattenable.cpp \
third_party/skia/src/core/SkFlattenableBuffers.cpp \
+ third_party/skia/src/core/SkFlattenableSerialization.cpp \
third_party/skia/src/core/SkFloat.cpp \
third_party/skia/src/core/SkFloatBits.cpp \
third_party/skia/src/core/SkFontHost.cpp \
@@ -246,6 +248,7 @@
third_party/skia/src/effects/SkDashPathEffect.cpp \
third_party/skia/src/effects/SkDiscretePathEffect.cpp \
third_party/skia/src/effects/SkDisplacementMapEffect.cpp \
+ third_party/skia/src/effects/SkDropShadowImageFilter.cpp \
third_party/skia/src/effects/SkEmbossMask.cpp \
third_party/skia/src/effects/SkEmbossMaskFilter.cpp \
third_party/skia/src/effects/SkGpuBlurUtils.cpp \
@@ -431,6 +434,7 @@
'-DSK_GAMMA_CONTRAST=0.0' \
'-DSK_USE_POSIX_THREADS' \
'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
@@ -553,6 +557,7 @@
'-DSK_GAMMA_CONTRAST=0.0' \
'-DSK_USE_POSIX_THREADS' \
'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
diff --git a/skia/skia_library.target.darwin-mips.mk b/skia/skia_library.target.darwin-mips.mk
index 34fe628..8365e9c 100644
--- a/skia/skia_library.target.darwin-mips.mk
+++ b/skia/skia_library.target.darwin-mips.mk
@@ -11,6 +11,7 @@
# Make sure our deps are built first.
GYP_TARGET_DEPENDENCIES := \
+ $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp
GYP_GENERATED_OUTPUTS :=
@@ -107,6 +108,7 @@
third_party/skia/src/core/SkFilterShader.cpp \
third_party/skia/src/core/SkFlattenable.cpp \
third_party/skia/src/core/SkFlattenableBuffers.cpp \
+ third_party/skia/src/core/SkFlattenableSerialization.cpp \
third_party/skia/src/core/SkFloat.cpp \
third_party/skia/src/core/SkFloatBits.cpp \
third_party/skia/src/core/SkFontHost.cpp \
@@ -246,6 +248,7 @@
third_party/skia/src/effects/SkDashPathEffect.cpp \
third_party/skia/src/effects/SkDiscretePathEffect.cpp \
third_party/skia/src/effects/SkDisplacementMapEffect.cpp \
+ third_party/skia/src/effects/SkDropShadowImageFilter.cpp \
third_party/skia/src/effects/SkEmbossMask.cpp \
third_party/skia/src/effects/SkEmbossMaskFilter.cpp \
third_party/skia/src/effects/SkGpuBlurUtils.cpp \
@@ -429,6 +432,7 @@
'-DSK_GAMMA_EXPONENT=1.4' \
'-DSK_GAMMA_CONTRAST=0.0' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
@@ -550,6 +554,7 @@
'-DSK_GAMMA_EXPONENT=1.4' \
'-DSK_GAMMA_CONTRAST=0.0' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
diff --git a/skia/skia_library.target.darwin-x86.mk b/skia/skia_library.target.darwin-x86.mk
index 69b4e75..22fbdae 100644
--- a/skia/skia_library.target.darwin-x86.mk
+++ b/skia/skia_library.target.darwin-x86.mk
@@ -11,6 +11,7 @@
# Make sure our deps are built first.
GYP_TARGET_DEPENDENCIES := \
+ $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp
GYP_GENERATED_OUTPUTS :=
@@ -108,6 +109,7 @@
third_party/skia/src/core/SkFilterShader.cpp \
third_party/skia/src/core/SkFlattenable.cpp \
third_party/skia/src/core/SkFlattenableBuffers.cpp \
+ third_party/skia/src/core/SkFlattenableSerialization.cpp \
third_party/skia/src/core/SkFloat.cpp \
third_party/skia/src/core/SkFloatBits.cpp \
third_party/skia/src/core/SkFontHost.cpp \
@@ -247,6 +249,7 @@
third_party/skia/src/effects/SkDashPathEffect.cpp \
third_party/skia/src/effects/SkDiscretePathEffect.cpp \
third_party/skia/src/effects/SkDisplacementMapEffect.cpp \
+ third_party/skia/src/effects/SkDropShadowImageFilter.cpp \
third_party/skia/src/effects/SkEmbossMask.cpp \
third_party/skia/src/effects/SkEmbossMaskFilter.cpp \
third_party/skia/src/effects/SkGpuBlurUtils.cpp \
@@ -432,6 +435,7 @@
'-DSK_GAMMA_EXPONENT=1.4' \
'-DSK_GAMMA_CONTRAST=0.0' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
@@ -556,6 +560,7 @@
'-DSK_GAMMA_EXPONENT=1.4' \
'-DSK_GAMMA_CONTRAST=0.0' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
diff --git a/skia/skia_library.target.linux-arm.mk b/skia/skia_library.target.linux-arm.mk
index 7d2cb16..86d43cc 100644
--- a/skia/skia_library.target.linux-arm.mk
+++ b/skia/skia_library.target.linux-arm.mk
@@ -11,6 +11,7 @@
# Make sure our deps are built first.
GYP_TARGET_DEPENDENCIES := \
+ $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp
GYP_GENERATED_OUTPUTS :=
@@ -107,6 +108,7 @@
third_party/skia/src/core/SkFilterShader.cpp \
third_party/skia/src/core/SkFlattenable.cpp \
third_party/skia/src/core/SkFlattenableBuffers.cpp \
+ third_party/skia/src/core/SkFlattenableSerialization.cpp \
third_party/skia/src/core/SkFloat.cpp \
third_party/skia/src/core/SkFloatBits.cpp \
third_party/skia/src/core/SkFontHost.cpp \
@@ -246,6 +248,7 @@
third_party/skia/src/effects/SkDashPathEffect.cpp \
third_party/skia/src/effects/SkDiscretePathEffect.cpp \
third_party/skia/src/effects/SkDisplacementMapEffect.cpp \
+ third_party/skia/src/effects/SkDropShadowImageFilter.cpp \
third_party/skia/src/effects/SkEmbossMask.cpp \
third_party/skia/src/effects/SkEmbossMaskFilter.cpp \
third_party/skia/src/effects/SkGpuBlurUtils.cpp \
@@ -431,6 +434,7 @@
'-DSK_GAMMA_CONTRAST=0.0' \
'-DSK_USE_POSIX_THREADS' \
'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
@@ -553,6 +557,7 @@
'-DSK_GAMMA_CONTRAST=0.0' \
'-DSK_USE_POSIX_THREADS' \
'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
diff --git a/skia/skia_library.target.linux-mips.mk b/skia/skia_library.target.linux-mips.mk
index 34fe628..8365e9c 100644
--- a/skia/skia_library.target.linux-mips.mk
+++ b/skia/skia_library.target.linux-mips.mk
@@ -11,6 +11,7 @@
# Make sure our deps are built first.
GYP_TARGET_DEPENDENCIES := \
+ $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp
GYP_GENERATED_OUTPUTS :=
@@ -107,6 +108,7 @@
third_party/skia/src/core/SkFilterShader.cpp \
third_party/skia/src/core/SkFlattenable.cpp \
third_party/skia/src/core/SkFlattenableBuffers.cpp \
+ third_party/skia/src/core/SkFlattenableSerialization.cpp \
third_party/skia/src/core/SkFloat.cpp \
third_party/skia/src/core/SkFloatBits.cpp \
third_party/skia/src/core/SkFontHost.cpp \
@@ -246,6 +248,7 @@
third_party/skia/src/effects/SkDashPathEffect.cpp \
third_party/skia/src/effects/SkDiscretePathEffect.cpp \
third_party/skia/src/effects/SkDisplacementMapEffect.cpp \
+ third_party/skia/src/effects/SkDropShadowImageFilter.cpp \
third_party/skia/src/effects/SkEmbossMask.cpp \
third_party/skia/src/effects/SkEmbossMaskFilter.cpp \
third_party/skia/src/effects/SkGpuBlurUtils.cpp \
@@ -429,6 +432,7 @@
'-DSK_GAMMA_EXPONENT=1.4' \
'-DSK_GAMMA_CONTRAST=0.0' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
@@ -550,6 +554,7 @@
'-DSK_GAMMA_EXPONENT=1.4' \
'-DSK_GAMMA_CONTRAST=0.0' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
diff --git a/skia/skia_library.target.linux-x86.mk b/skia/skia_library.target.linux-x86.mk
index 69b4e75..22fbdae 100644
--- a/skia/skia_library.target.linux-x86.mk
+++ b/skia/skia_library.target.linux-x86.mk
@@ -11,6 +11,7 @@
# Make sure our deps are built first.
GYP_TARGET_DEPENDENCIES := \
+ $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp
GYP_GENERATED_OUTPUTS :=
@@ -108,6 +109,7 @@
third_party/skia/src/core/SkFilterShader.cpp \
third_party/skia/src/core/SkFlattenable.cpp \
third_party/skia/src/core/SkFlattenableBuffers.cpp \
+ third_party/skia/src/core/SkFlattenableSerialization.cpp \
third_party/skia/src/core/SkFloat.cpp \
third_party/skia/src/core/SkFloatBits.cpp \
third_party/skia/src/core/SkFontHost.cpp \
@@ -247,6 +249,7 @@
third_party/skia/src/effects/SkDashPathEffect.cpp \
third_party/skia/src/effects/SkDiscretePathEffect.cpp \
third_party/skia/src/effects/SkDisplacementMapEffect.cpp \
+ third_party/skia/src/effects/SkDropShadowImageFilter.cpp \
third_party/skia/src/effects/SkEmbossMask.cpp \
third_party/skia/src/effects/SkEmbossMaskFilter.cpp \
third_party/skia/src/effects/SkGpuBlurUtils.cpp \
@@ -432,6 +435,7 @@
'-DSK_GAMMA_EXPONENT=1.4' \
'-DSK_GAMMA_CONTRAST=0.0' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
@@ -556,6 +560,7 @@
'-DSK_GAMMA_EXPONENT=1.4' \
'-DSK_GAMMA_CONTRAST=0.0' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
'-DUSE_STLPORT=1' \
diff --git a/sync/android/java/src/org/chromium/sync/internal_api/pub/base/ModelType.java b/sync/android/java/src/org/chromium/sync/internal_api/pub/base/ModelType.java
index a7d4797..afec46c 100644
--- a/sync/android/java/src/org/chromium/sync/internal_api/pub/base/ModelType.java
+++ b/sync/android/java/src/org/chromium/sync/internal_api/pub/base/ModelType.java
@@ -6,14 +6,12 @@
import android.util.Log;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;
import com.google.ipc.invalidation.external.client.types.ObjectId;
import com.google.protos.ipc.invalidation.Types;
import java.util.Collection;
-import java.util.HashSet;
import java.util.Set;
/**
@@ -63,7 +61,7 @@
/**
* A proxy tabs object (placeholder for sessions).
*/
- PROXY_TABS("NULL"),
+ PROXY_TABS("NULL", true),
/**
* A favicon image object.
*/
@@ -80,10 +78,25 @@
private final String mModelType;
- ModelType(String modelType) {
+ private final boolean mNonInvalidationType;
+
+ ModelType(String modelType, boolean nonInvalidationType) {
mModelType = modelType;
+ mNonInvalidationType = nonInvalidationType;
}
+ ModelType(String modelType) {
+ this(modelType, false);
+ }
+
+ /**
+ * Returns the {@link ObjectId} representation of this {@link ModelType}.
+ *
+ * This should be used with caution, since it converts even {@link ModelType} instances with
+ * |mNonInvalidationType| set. For automatically stripping such {@link ModelType} entries out,
+ * use {@link ModelType#modelTypesToObjectIds(java.util.Set)} instead.
+ */
+ @VisibleForTesting
public ObjectId toObjectId() {
return ObjectId.newInstance(Types.ObjectSource.Type.CHROME_SYNC.getNumber(),
mModelType.getBytes());
@@ -124,11 +137,26 @@
}
}
- /** Converts a set of {@link ModelType} to a set of {@link ObjectId}. */
+ /**
+ * Converts a set of sync types {@link String} to a set of {@link ObjectId}.
+ *
+ * This strips out any {@link ModelType} that is not an invalidation type.
+ */
+ public static Set<ObjectId> syncTypesToObjectIds(Collection<String> syncTypes) {
+ return modelTypesToObjectIds(syncTypesToModelTypes(syncTypes));
+ }
+
+ /**
+ * Converts a set of {@link ModelType} to a set of {@link ObjectId}.
+ *
+ * This strips out any {@link ModelType} that is not an invalidation type.
+ */
public static Set<ObjectId> modelTypesToObjectIds(Set<ModelType> modelTypes) {
Set<ObjectId> objectIds = Sets.newHashSetWithExpectedSize(modelTypes.size());
for (ModelType modelType : modelTypes) {
- objectIds.add(modelType.toObjectId());
+ if (!modelType.mNonInvalidationType) {
+ objectIds.add(modelType.toObjectId());
+ }
}
return objectIds;
}
diff --git a/sync/android/java/src/org/chromium/sync/notifier/InvalidationController.java b/sync/android/java/src/org/chromium/sync/notifier/InvalidationController.java
index b912599..03255d1 100644
--- a/sync/android/java/src/org/chromium/sync/notifier/InvalidationController.java
+++ b/sync/android/java/src/org/chromium/sync/notifier/InvalidationController.java
@@ -100,11 +100,7 @@
* @param types Set of types for which to register. Ignored if {@code allTypes == true}.
*/
public void setRegisteredTypes(Account account, boolean allTypes, Set<ModelType> types) {
- Set<ModelType> typesToRegister = types;
- // Proxy types should never receive notifications.
- typesToRegister.remove(ModelType.PROXY_TABS);
- Intent registerIntent = IntentProtocol.createRegisterIntent(account, allTypes,
- typesToRegister);
+ Intent registerIntent = IntentProtocol.createRegisterIntent(account, allTypes, types);
registerIntent.setClass(mContext, InvalidationService.class);
mContext.startService(registerIntent);
}
diff --git a/sync/android/java/src/org/chromium/sync/notifier/InvalidationService.java b/sync/android/java/src/org/chromium/sync/notifier/InvalidationService.java
index 92ac257..963c417 100644
--- a/sync/android/java/src/org/chromium/sync/notifier/InvalidationService.java
+++ b/sync/android/java/src/org/chromium/sync/notifier/InvalidationService.java
@@ -292,16 +292,8 @@
@VisibleForTesting
Set<ObjectId> readRegistrationsFromPrefs() {
Set<String> savedTypes = new InvalidationPreferences(this).getSavedSyncedTypes();
- if (savedTypes == null) {
- return Collections.emptySet();
- } else {
- Set<ModelType> modelTypes = ModelType.syncTypesToModelTypes(savedTypes);
- Set<ObjectId> objectIds = Sets.newHashSetWithExpectedSize(modelTypes.size());
- for (ModelType modelType : modelTypes) {
- objectIds.add(modelType.toObjectId());
- }
- return objectIds;
- }
+ if (savedTypes == null) return Collections.emptySet();
+ else return ModelType.syncTypesToObjectIds(savedTypes);
}
/**
@@ -337,13 +329,11 @@
// expansion of the ALL_TYPES_TYPE wildcard.
// NOTE: syncTypes MUST NOT be used below this line, since it contains an unexpanded
// wildcard.
- Set<ModelType> newRegisteredTypes = ModelType.syncTypesToModelTypes(syncTypes);
-
List<ObjectId> unregistrations = Lists.newArrayList();
List<ObjectId> registrations = Lists.newArrayList();
computeRegistrationOps(existingRegistrations,
- ModelType.modelTypesToObjectIds(newRegisteredTypes), registrations,
- unregistrations);
+ ModelType.syncTypesToObjectIds(syncTypes),
+ registrations, unregistrations);
unregister(sClientId, unregistrations);
register(sClientId, registrations);
}
diff --git a/sync/android/javatests/src/org/chromium/sync/notifier/InvalidationServiceTest.java b/sync/android/javatests/src/org/chromium/sync/notifier/InvalidationServiceTest.java
index 0cff98e..db27879 100644
--- a/sync/android/javatests/src/org/chromium/sync/notifier/InvalidationServiceTest.java
+++ b/sync/android/javatests/src/org/chromium/sync/notifier/InvalidationServiceTest.java
@@ -521,6 +521,70 @@
@SmallTest
@Feature({"Sync"})
+ public void testRegistrationIntentNoProxyTabsUsingReady() {
+ getService().setShouldRunStates(true, true);
+ getService().onCreate();
+
+ // Send register Intent.
+ Account account = AccountManagerHelper.createAccountFromName("test@example.com");
+ Intent registrationIntent = IntentProtocol.createRegisterIntent(account, true, null);
+ getService().onHandleIntent(registrationIntent);
+
+ // Verify client started and state written.
+ assertTrue(InvalidationService.getIsClientStartedForTest());
+ InvalidationPreferences invPrefs = new InvalidationPreferences(getContext());
+ assertEquals(account, invPrefs.getSavedSyncedAccount());
+ assertEquals(ImmutableSet.of(ModelType.ALL_TYPES_TYPE), invPrefs.getSavedSyncedTypes());
+ assertEquals(1, mStartServiceIntents.size());
+ assertTrue(isAndroidListenerStartIntent(mStartServiceIntents.get(0)));
+
+ // Set client to be ready. This triggers registrations.
+ getService().ready(CLIENT_ID);
+ assertTrue(Arrays.equals(CLIENT_ID, InvalidationService.getClientIdForTest()));
+
+ // Ensure registrations are correct.
+ Set<ObjectId> expectedTypes =
+ ModelType.modelTypesToObjectIds(Sets.newHashSet(ModelType.values()));
+ assertEquals(expectedTypes, Sets.newHashSet(getService().mRegistrations.get(0)));
+ }
+
+ @SmallTest
+ @Feature({"Sync"})
+ public void testRegistrationIntentNoProxyTabsAlreadyWithClientId() {
+ getService().setShouldRunStates(true, true);
+ getService().onCreate();
+
+ // Send register Intent with no desired types.
+ Account account = AccountManagerHelper.createAccountFromName("test@example.com");
+ Intent registrationIntent =
+ IntentProtocol.createRegisterIntent(account, false, Sets.<ModelType>newHashSet());
+ getService().onHandleIntent(registrationIntent);
+
+ // Verify client started and state written.
+ assertTrue(InvalidationService.getIsClientStartedForTest());
+ InvalidationPreferences invPrefs = new InvalidationPreferences(getContext());
+ assertEquals(account, invPrefs.getSavedSyncedAccount());
+ assertEquals(Sets.<String>newHashSet(), invPrefs.getSavedSyncedTypes());
+ assertEquals(1, mStartServiceIntents.size());
+ assertTrue(isAndroidListenerStartIntent(mStartServiceIntents.get(0)));
+
+ // Make sure client is ready.
+ getService().ready(CLIENT_ID);
+ assertTrue(Arrays.equals(CLIENT_ID, InvalidationService.getClientIdForTest()));
+
+ // Choose to register for all types in an already ready client.
+ registrationIntent = IntentProtocol.createRegisterIntent(account, true, null);
+ getService().onHandleIntent(registrationIntent);
+
+ // Ensure registrations are correct.
+ assertEquals(1, getService().mRegistrations.size());
+ Set<ObjectId> expectedTypes =
+ ModelType.modelTypesToObjectIds(Sets.newHashSet(ModelType.values()));
+ assertEquals(expectedTypes, Sets.newHashSet(getService().mRegistrations.get(0)));
+ }
+
+ @SmallTest
+ @Feature({"Sync"})
public void testRegistrationIntentWhenClientShouldNotBeRunning() {
/*
* Test plan: send a registration change event when the client should not be running.
diff --git a/sync/protocol/proto_value_conversions.cc b/sync/protocol/proto_value_conversions.cc
index c145269..21db7b2 100644
--- a/sync/protocol/proto_value_conversions.cc
+++ b/sync/protocol/proto_value_conversions.cc
@@ -240,8 +240,36 @@
return value;
}
-// TODO(petewil): I will need new functions here for the SyncedNotifications
-// subtypes.
+base::DictionaryValue* SimpleCollapsedLayoutToValue(
+ const sync_pb::SimpleCollapsedLayout& proto) {
+ base::DictionaryValue* value = new base::DictionaryValue();
+ SET_STR(heading);
+ SET_STR(description);
+ return value;
+}
+
+base::DictionaryValue* CollapsedInfoToValue(
+ const sync_pb::CollapsedInfo& proto) {
+ base::DictionaryValue* value = new base::DictionaryValue();
+ SET(simple_collapsed_layout, SimpleCollapsedLayoutToValue);
+ return value;
+}
+
+base::DictionaryValue* RenderInfoToValue(
+ const sync_pb::SyncedNotificationRenderInfo& proto) {
+ base::DictionaryValue* value = new base::DictionaryValue();
+ SET(collapsed_info, CollapsedInfoToValue);
+ return value;
+}
+
+base::DictionaryValue* CoalescedNotificationToValue(
+ const sync_pb::CoalescedSyncedNotification& proto) {
+ base::DictionaryValue* value = new base::DictionaryValue();
+ SET_STR(key);
+ SET_INT32(read_state);
+ SET(render_info, RenderInfoToValue);
+ return value;
+}
base::DictionaryValue* AppNotificationToValue(
const sync_pb::AppNotification& proto) {
@@ -488,8 +516,11 @@
base::DictionaryValue* SyncedNotificationSpecificsToValue(
const sync_pb::SyncedNotificationSpecifics& proto) {
+ // There is a lot of data, for now just use heading, description, key, and
+ // the read state.
+ // TODO(petewil): Eventually add more data here.
base::DictionaryValue* value = new base::DictionaryValue();
- // TODO(petewil): Adjust this once we add actual types in protobuf.
+ SET(coalesced_notification, CoalescedNotificationToValue);
return value;
}
diff --git a/sync/protocol/proto_value_conversions.h b/sync/protocol/proto_value_conversions.h
index 8bcc26d..39b8e0e 100644
--- a/sync/protocol/proto_value_conversions.h
+++ b/sync/protocol/proto_value_conversions.h
@@ -24,6 +24,8 @@
class ClientConfigParams;
class ClientToServerMessage;
class ClientToServerResponse;
+class CoalescedSyncedNotification;
+class CollapsedInfo;
class DatatypeAssociationStats;
class DebugEventInfo;
class DebugInfo;
@@ -53,7 +55,9 @@
class SessionSpecifics;
class SessionTab;
class SessionWindow;
+class SimpleCollapsedLayout;
class SyncCycleCompletedEventInfo;
+class SyncedNotificationRenderInfo;
class SyncedNotificationSpecifics;
class TabNavigation;
class ThemeSpecifics;
@@ -120,6 +124,20 @@
base::DictionaryValue* KeystoreEncryptionToValue(
const sync_pb::KeystoreEncryptionFlagsSpecifics& proto);
+// Sub protocols of SyncedNotifications.
+
+base::DictionaryValue* SimpleCollapsedLayoutToValue(
+ const sync_pb::SimpleCollapsedLayout& proto);
+
+base::DictionaryValue* CollapsedInfoToValue(
+ const sync_pb::CollapsedInfo& proto);
+
+base::DictionaryValue* RenderInfoToValue(
+ const sync_pb::SyncedNotificationRenderInfo& proto);
+
+base::DictionaryValue* CoalescedNotificationToValue(
+ const sync_pb::CoalescedSyncedNotification& proto);
+
// Main *SpecificsToValue functions.
SYNC_EXPORT_PRIVATE base::DictionaryValue* AppNotificationToValue(
diff --git a/third_party/android_testrunner/run_command.py b/third_party/android_testrunner/run_command.py
index 5c82c61..6b84156 100644
--- a/third_party/android_testrunner/run_command.py
+++ b/third_party/android_testrunner/run_command.py
@@ -22,7 +22,6 @@
import tempfile
import threading
import time
-import sys
# local imports
import errors
@@ -94,15 +93,12 @@
stdin_dest = subprocess.PIPE
else:
stdin_dest = None
- stderr_dest = subprocess.STDOUT
- if os.environ.get('ADB_TRACE'):
- stderr_dest = sys.stdout
pipe = subprocess.Popen(
cmd,
executable='/bin/bash',
stdin=stdin_dest,
stdout=output_dest,
- stderr=stderr_dest,
+ stderr=subprocess.STDOUT,
shell=True, close_fds=True,
preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL))
diff --git a/third_party/cld/encodings/compact_lang_det/cldutil.cc b/third_party/cld/encodings/compact_lang_det/cldutil.cc
index 06e9e97..9221d70 100644
--- a/third_party/cld/encodings/compact_lang_det/cldutil.cc
+++ b/third_party/cld/encodings/compact_lang_det/cldutil.cc
@@ -815,9 +815,10 @@
if (lscript == ULScript_Common) {
// We don't know the script (only happens with second-chance score)
// Look for first non-zero mean value
- for (int i = 0; i < 3; ++i) {
+ for (int i = 2; i >= 0; --i) {
if (kMeanScore[lang * 4 + i] > 0) {
expected_score = kMeanScore[lang * 4 + i];
+ break;
}
}
}
@@ -843,9 +844,10 @@
if (lscript == ULScript_Common) {
// We don't know the script (only happens with second-chance score)
// Look for first non-zero mean value
- for (int i = 0; i < 3; ++i) {
+ for (int i = 2; i >= 0; --i) {
if (kMeanScore[cur_lang * 4 + i] > 0) {
mean_score = kMeanScore[cur_lang * 4 + i];
+ break;
}
}
}
diff --git a/third_party/libjingle/README.chromium b/third_party/libjingle/README.chromium
index 5443592..45814ea 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: 4490
+Revision: 4520
License: BSD
License File: source/talk/COPYING
Security Critical: yes
diff --git a/third_party/libjingle/libjingle.gyp b/third_party/libjingle/libjingle.gyp
index 37585dc..28e15c9 100644
--- a/third_party/libjingle/libjingle.gyp
+++ b/third_party/libjingle/libjingle.gyp
@@ -687,6 +687,8 @@
'<(libjingle_source)/talk/app/webrtc/webrtcsdp.h',
'<(libjingle_source)/talk/app/webrtc/webrtcsession.cc',
'<(libjingle_source)/talk/app/webrtc/webrtcsession.h',
+ '<(libjingle_source)/talk/app/webrtc/webrtcsessiondescriptionfactory.cc',
+ '<(libjingle_source)/talk/app/webrtc/webrtcsessiondescriptionfactory.h',
'<(libjingle_source)/talk/media/base/audiorenderer.h',
'<(libjingle_source)/talk/media/base/capturemanager.cc',
'<(libjingle_source)/talk/media/base/capturemanager.h',
diff --git a/third_party/mach_override/README.chromium b/third_party/mach_override/README.chromium
index ae82f29..adb7d47 100644
--- a/third_party/mach_override/README.chromium
+++ b/third_party/mach_override/README.chromium
@@ -16,4 +16,6 @@
implementations at run time.
-Local Modifications: None
+Local Modifications:
+Ensure no rwx pages remain after mach_override_ptr:
+https://codereview.chromium.org/21208002/
diff --git a/third_party/mach_override/mach_override.c b/third_party/mach_override/mach_override.c
index 549409d..ea41569 100644
--- a/third_party/mach_override/mach_override.c
+++ b/third_party/mach_override/mach_override.c
@@ -156,7 +156,7 @@
mach_error_t err = err_none;
uintptr_t page = (uintptr_t)address & ~(uintptr_t)(kPageSize-1);
int e = err_none;
- e |= mprotect((void *)page, kPageSize, PROT_EXEC | PROT_READ | PROT_WRITE);
+ e |= mprotect((void *)page, kPageSize, PROT_EXEC | PROT_READ);
e |= msync((void *)page, kPageSize, MS_INVALIDATE );
if (e) {
err = err_cannot_override;
@@ -335,6 +335,12 @@
#endif
if ( !err )
atomic_mov64((uint64_t *)originalFunctionPtr, jumpRelativeInstruction);
+
+ mach_error_t prot_err = err_none;
+ prot_err = vm_protect( mach_task_self(),
+ (vm_address_t) originalFunctionPtr, 8, false,
+ (VM_PROT_READ | VM_PROT_EXECUTE) );
+ if (prot_err) fprintf(stderr, "err = %x %s:%d\n", prot_err, __FILE__, __LINE__);
}
#endif
diff --git a/third_party/protobuf/CHANGES.txt b/third_party/protobuf/CHANGES.txt
index 737f865..a21e956 100644
--- a/third_party/protobuf/CHANGES.txt
+++ b/third_party/protobuf/CHANGES.txt
@@ -1,3 +1,61 @@
+2012-09-19 version 2.5.0:
+
+ General
+ * New notion "import public" that allows a proto file to forward the content
+ it imports to its importers. For example,
+ // foo.proto
+ import public "bar.proto";
+ import "baz.proto";
+
+ // qux.proto
+ import "foo.proto";
+ // Stuff defined in bar.proto may be used in this file, but stuff from
+ // baz.proto may NOT be used without importing it explicitly.
+ This is useful for moving proto files. To move a proto file, just leave
+ a single "import public" in the old proto file.
+ * New enum option "allow_alias" that specifies whether different symbols can
+ be assigned the same numeric value. Default value is "true". Setting it to
+ false causes the compiler to reject enum definitions where multiple symbols
+ have the same numeric value.
+
+ C++
+ * New generated method set_allocated_foo(Type* foo) for message and string
+ fields. This method allows you to set the field to a pre-allocated object
+ and the containing message takes the ownership of that object.
+ * Added SetAllocatedExtension() and ReleaseExtension() to extensions API.
+ * Custom options are now formatted correctly when descriptors are printed in
+ text format.
+ * Various speed optimizations.
+
+ Java
+ * Comments in proto files are now collected and put into generated code as
+ comments for corresponding classes and data members.
+ * Added Parser to parse directly into messages without a Builder. For
+ example,
+ Foo foo = Foo.getParser().ParseFrom(input);
+ Using Parser is ~25% faster than using Builder to parse messages.
+ * Added getters/setters to access the underlying ByteString of a string field
+ directly.
+ * ByteString now supports more operations: substring(), prepend(), and
+ append(). The implementation of ByteString uses a binary tree structure
+ to support these operations efficiently.
+ * New method findInitializationErrors() that lists all missing required
+ fields.
+ * Various code size and speed optimizations.
+
+ Python
+ * Added support for dynamic message creation. DescriptorDatabase,
+ DescriptorPool, and MessageFactory work like their C++ couterparts to
+ simplify Descriptor construction from *DescriptorProtos, and MessageFactory
+ provides a message instance from a Descriptor.
+ * Added pickle support for protobuf messages.
+ * Unknown fields are now preserved after parsing.
+ * Fixed bug where custom options were not correctly populated. Custom
+ options can be accessed now.
+ * Added EnumTypeWrapper that provides better accessibility to enum types.
+ * Added ParseMessage(descriptor, bytes) to generate a new Message instance
+ from a descriptor and a byte string.
+
2011-05-01 version 2.4.1:
C++
diff --git a/third_party/protobuf/README.chromium b/third_party/protobuf/README.chromium
index e15fcae..c8e411f 100644
--- a/third_party/protobuf/README.chromium
+++ b/third_party/protobuf/README.chromium
@@ -4,7 +4,7 @@
License: BSD
License File: COPYING.txt
Version: unknown
-Revision: r423
+Revision: r428
Security Critical: yes
Local files (not taken from upstream):
@@ -26,9 +26,7 @@
targets that depend on it can be componentized. See http://crbug.com/172800 for
details, and r179806 for the patch.
-Revisions r427, r430, r475, r476 and 504 were cherry-picked from upstream.
-Patch from http://code.google.com/p/protobuf/issues/detail?id=425 was
-cherry-picked from upstream.
+Revisions r430, r475, r476 and 504 were cherry-picked from upstream.
Notes about Java:
We have not forked the Java version of protobuf-lite, so the Java version does
diff --git a/third_party/protobuf/java/pom.xml b/third_party/protobuf/java/pom.xml
index e28d6db..7ec6d91 100644
--- a/third_party/protobuf/java/pom.xml
+++ b/third_party/protobuf/java/pom.xml
@@ -102,6 +102,7 @@
<arg value="--proto_path=src/test/java" />
<arg value="../src/google/protobuf/unittest.proto" />
<arg value="../src/google/protobuf/unittest_import.proto" />
+ <arg value="../src/google/protobuf/unittest_import_public.proto" />
<arg value="../src/google/protobuf/unittest_mset.proto" />
<arg
value="src/test/java/com/google/protobuf/multiple_files_test.proto" />
@@ -117,6 +118,7 @@
value="../src/google/protobuf/unittest_custom_options.proto" />
<arg value="../src/google/protobuf/unittest_lite.proto" />
<arg value="../src/google/protobuf/unittest_import_lite.proto" />
+ <arg value="../src/google/protobuf/unittest_import_public_lite.proto" />
<arg value="../src/google/protobuf/unittest_lite_imports_nonlite.proto" />
<arg value="../src/google/protobuf/unittest_enormous_descriptor.proto" />
<arg value="../src/google/protobuf/unittest_no_generic_services.proto" />
@@ -158,6 +160,13 @@
<include>**/UninitializedMessageException.java</include>
<include>**/UnmodifiableLazyStringList.java</include>
<include>**/WireFormat.java</include>
+ <include>**/Parser.java</include>
+ <include>**/AbstractParser.java</include>
+ <include>**/BoundedByteString.java</include>
+ <include>**/LiteralByteString.java</include>
+ <include>**/RopeByteString.java</include>
+ <include>**/Utf8.java</include>
+ <include>**/LazyField.java</include>
</includes>
<testIncludes>
<testInclude>**/LiteTest.java</testInclude>
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessage.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessage.java
index b9d8301..f4d115d 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -32,6 +32,7 @@
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.GeneratedMessage.ExtendableBuilder;
import com.google.protobuf.Internal.EnumLite;
import java.io.IOException;
@@ -81,6 +82,25 @@
return true;
}
+ public List<String> findInitializationErrors() {
+ return Builder.findMissingFields(this);
+ }
+
+ public String getInitializationErrorString() {
+ return delimitWithCommas(findInitializationErrors());
+ }
+
+ private static String delimitWithCommas(List<String> parts) {
+ StringBuilder result = new StringBuilder();
+ for (String part : parts) {
+ if (result.length() > 0) {
+ result.append(", ");
+ }
+ result.append(part);
+ }
+ return result.toString();
+ }
+
@Override
public final String toString() {
return TextFormat.printToString(this);
@@ -209,6 +229,15 @@
}
/**
+ * Package private helper method for AbstractParser to create
+ * UninitializedMessageException with missing field information.
+ */
+ @Override
+ UninitializedMessageException newUninitializedMessageException() {
+ return Builder.newUninitializedMessageException(this);
+ }
+
+ /**
* Helper method for implementing {@link Message#hashCode()}.
* <p>
* This is needed because {@link java.lang.Enum#hashCode()} is final, but we
@@ -251,6 +280,14 @@
return (BuilderType) this;
}
+ public List<String> findInitializationErrors() {
+ return findMissingFields(this);
+ }
+
+ public String getInitializationErrorString() {
+ return delimitWithCommas(findInitializationErrors());
+ }
+
public BuilderType mergeFrom(final Message other) {
if (other.getDescriptorForType() != getDescriptorForType()) {
throw new IllegalArgumentException(
@@ -314,7 +351,7 @@
}
if (!mergeFieldFrom(input, unknownFields, extensionRegistry,
- this, tag)) {
+ getDescriptorForType(), this, null, tag)) {
// end group tag
break;
}
@@ -323,25 +360,93 @@
return (BuilderType) this;
}
+ /** helper method to handle {@code builder} and {@code extensions}. */
+ private static void addRepeatedField(
+ Message.Builder builder,
+ FieldSet<FieldDescriptor> extensions,
+ FieldDescriptor field,
+ Object value) {
+ if (builder != null) {
+ builder.addRepeatedField(field, value);
+ } else {
+ extensions.addRepeatedField(field, value);
+ }
+ }
+
+ /** helper method to handle {@code builder} and {@code extensions}. */
+ private static void setField(
+ Message.Builder builder,
+ FieldSet<FieldDescriptor> extensions,
+ FieldDescriptor field,
+ Object value) {
+ if (builder != null) {
+ builder.setField(field, value);
+ } else {
+ extensions.setField(field, value);
+ }
+ }
+
+ /** helper method to handle {@code builder} and {@code extensions}. */
+ private static boolean hasOriginalMessage(
+ Message.Builder builder,
+ FieldSet<FieldDescriptor> extensions,
+ FieldDescriptor field) {
+ if (builder != null) {
+ return builder.hasField(field);
+ } else {
+ return extensions.hasField(field);
+ }
+ }
+
+ /** helper method to handle {@code builder} and {@code extensions}. */
+ private static Message getOriginalMessage(
+ Message.Builder builder,
+ FieldSet<FieldDescriptor> extensions,
+ FieldDescriptor field) {
+ if (builder != null) {
+ return (Message) builder.getField(field);
+ } else {
+ return (Message) extensions.getField(field);
+ }
+ }
+
+ /** helper method to handle {@code builder} and {@code extensions}. */
+ private static void mergeOriginalMessage(
+ Message.Builder builder,
+ FieldSet<FieldDescriptor> extensions,
+ FieldDescriptor field,
+ Message.Builder subBuilder) {
+ Message originalMessage = getOriginalMessage(builder, extensions, field);
+ if (originalMessage != null) {
+ subBuilder.mergeFrom(originalMessage);
+ }
+ }
+
/**
- * Like {@link #mergeFrom(CodedInputStream, UnknownFieldSet.Builder,
- * ExtensionRegistryLite, Message.Builder)}, but parses a single field.
+ * Like {@link #mergeFrom(CodedInputStream, ExtensionRegistryLite)}, but
+ * parses a single field.
+ *
+ * When {@code builder} is not null, the method will parse and merge the
+ * field into {@code builder}. Otherwise, it will try to parse the field
+ * into {@code extensions}, when it's called by the parsing constructor in
+ * generated classes.
+ *
* Package-private because it is used by GeneratedMessage.ExtendableMessage.
* @param tag The tag, which should have already been read.
* @return {@code true} unless the tag is an end-group tag.
*/
static boolean mergeFieldFrom(
- final CodedInputStream input,
- final UnknownFieldSet.Builder unknownFields,
- final ExtensionRegistryLite extensionRegistry,
- final Message.Builder builder,
- final int tag) throws IOException {
- final Descriptor type = builder.getDescriptorForType();
-
+ CodedInputStream input,
+ UnknownFieldSet.Builder unknownFields,
+ ExtensionRegistryLite extensionRegistry,
+ Descriptor type,
+ Message.Builder builder,
+ FieldSet<FieldDescriptor> extensions,
+ int tag) throws IOException {
if (type.getOptions().getMessageSetWireFormat() &&
tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
mergeMessageSetExtensionFromCodedStream(
- input, unknownFields, extensionRegistry, builder);
+ input, unknownFields, extensionRegistry, type, builder, extensions);
return true;
}
@@ -376,8 +481,10 @@
} else {
field = null;
}
- } else {
+ } else if (builder != null) {
field = type.findFieldByNumber(fieldNumber);
+ } else {
+ field = null;
}
boolean unknown = false;
@@ -413,13 +520,13 @@
// enum, drop it (don't even add it to unknownFields).
return true;
}
- builder.addRepeatedField(field, value);
+ addRepeatedField(builder, extensions, field, value);
}
} else {
while (input.getBytesUntilLimit() > 0) {
final Object value =
FieldSet.readPrimitiveField(input, field.getLiteType());
- builder.addRepeatedField(field, value);
+ addRepeatedField(builder, extensions, field, value);
}
}
input.popLimit(limit);
@@ -434,10 +541,10 @@
subBuilder = builder.newBuilderForField(field);
}
if (!field.isRepeated()) {
- subBuilder.mergeFrom((Message) builder.getField(field));
+ mergeOriginalMessage(builder, extensions, field, subBuilder);
}
input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
- value = subBuilder.build();
+ value = subBuilder.buildPartial();
break;
}
case MESSAGE: {
@@ -448,10 +555,10 @@
subBuilder = builder.newBuilderForField(field);
}
if (!field.isRepeated()) {
- subBuilder.mergeFrom((Message) builder.getField(field));
+ mergeOriginalMessage(builder, extensions, field, subBuilder);
}
input.readMessage(subBuilder, extensionRegistry);
- value = subBuilder.build();
+ value = subBuilder.buildPartial();
break;
}
case ENUM:
@@ -470,22 +577,28 @@
}
if (field.isRepeated()) {
- builder.addRepeatedField(field, value);
+ addRepeatedField(builder, extensions, field, value);
} else {
- builder.setField(field, value);
+ setField(builder, extensions, field, value);
}
}
return true;
}
- /** Called by {@code #mergeFieldFrom()} to parse a MessageSet extension. */
+ /**
+ * Called by {@code #mergeFieldFrom()} to parse a MessageSet extension.
+ * If {@code builder} is not null, this method will merge MessageSet into
+ * the builder. Otherwise, it will merge the MessageSet into {@code
+ * extensions}.
+ */
private static void mergeMessageSetExtensionFromCodedStream(
- final CodedInputStream input,
- final UnknownFieldSet.Builder unknownFields,
- final ExtensionRegistryLite extensionRegistry,
- final Message.Builder builder) throws IOException {
- final Descriptor type = builder.getDescriptorForType();
+ CodedInputStream input,
+ UnknownFieldSet.Builder unknownFields,
+ ExtensionRegistryLite extensionRegistry,
+ Descriptor type,
+ Message.Builder builder,
+ FieldSet<FieldDescriptor> extensions) throws IOException {
// The wire format for MessageSet is:
// message MessageSet {
@@ -504,10 +617,11 @@
// should be prepared to accept them.
int typeId = 0;
- ByteString rawBytes = null; // If we encounter "message" before "typeId"
- Message.Builder subBuilder = null;
- FieldDescriptor field = null;
+ ByteString rawBytes = null; // If we encounter "message" before "typeId"
+ ExtensionRegistry.ExtensionInfo extension = null;
+ // Read bytes from input, if we get it's type first then parse it eagerly,
+ // otherwise we store the raw bytes in a local variable.
while (true) {
final int tag = input.readTag();
if (tag == 0) {
@@ -516,75 +630,121 @@
if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
typeId = input.readUInt32();
- // Zero is not a valid type ID.
if (typeId != 0) {
- final ExtensionRegistry.ExtensionInfo extension;
-
// extensionRegistry may be either ExtensionRegistry or
- // ExtensionRegistryLite. Since the type we are parsing is a full
+ // ExtensionRegistryLite. Since the type we are parsing is a full
// message, only a full ExtensionRegistry could possibly contain
- // extensions of it. Otherwise we will treat the registry as if it
+ // extensions of it. Otherwise we will treat the registry as if it
// were empty.
if (extensionRegistry instanceof ExtensionRegistry) {
extension = ((ExtensionRegistry) extensionRegistry)
.findExtensionByNumber(type, typeId);
- } else {
- extension = null;
}
+ }
- if (extension != null) {
- field = extension.descriptor;
- subBuilder = extension.defaultInstance.newBuilderForType();
- final Message originalMessage = (Message)builder.getField(field);
- if (originalMessage != null) {
- subBuilder.mergeFrom(originalMessage);
- }
- if (rawBytes != null) {
- // We already encountered the message. Parse it now.
- subBuilder.mergeFrom(
- CodedInputStream.newInstance(rawBytes.newInput()));
- rawBytes = null;
- }
- } else {
- // Unknown extension number. If we already saw data, put it
- // in rawBytes.
- if (rawBytes != null) {
- unknownFields.mergeField(typeId,
- UnknownFieldSet.Field.newBuilder()
- .addLengthDelimited(rawBytes)
- .build());
- rawBytes = null;
- }
+ } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
+ if (typeId != 0) {
+ if (extension != null && ExtensionRegistryLite.isEagerlyParseMessageSets()) {
+ // We already know the type, so we can parse directly from the
+ // input with no copying. Hooray!
+ eagerlyMergeMessageSetExtension(
+ input, extension, extensionRegistry, builder, extensions);
+ rawBytes = null;
+ continue;
}
}
- } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
- if (typeId == 0) {
- // We haven't seen a type ID yet, so we have to store the raw bytes
- // for now.
- rawBytes = input.readBytes();
- } else if (subBuilder == null) {
- // We don't know how to parse this. Ignore it.
- unknownFields.mergeField(typeId,
- UnknownFieldSet.Field.newBuilder()
- .addLengthDelimited(input.readBytes())
- .build());
- } else {
- // We already know the type, so we can parse directly from the input
- // with no copying. Hooray!
- input.readMessage(subBuilder, extensionRegistry);
- }
- } else {
- // Unknown tag. Skip it.
+ // We haven't seen a type ID yet or we want parse message lazily.
+ rawBytes = input.readBytes();
+
+ } else { // Unknown tag. Skip it.
if (!input.skipField(tag)) {
- break; // end of group
+ break; // End of group
}
}
}
-
input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
- if (subBuilder != null) {
- builder.setField(field, subBuilder.build());
+ // Process the raw bytes.
+ if (rawBytes != null && typeId != 0) { // Zero is not a valid type ID.
+ if (extension != null) { // We known the type
+ mergeMessageSetExtensionFromBytes(
+ rawBytes, extension, extensionRegistry, builder, extensions);
+ } else { // We don't know how to parse this. Ignore it.
+ if (rawBytes != null) {
+ unknownFields.mergeField(typeId, UnknownFieldSet.Field.newBuilder()
+ .addLengthDelimited(rawBytes).build());
+ }
+ }
+ }
+ }
+
+ private static void eagerlyMergeMessageSetExtension(
+ CodedInputStream input,
+ ExtensionRegistry.ExtensionInfo extension,
+ ExtensionRegistryLite extensionRegistry,
+ Message.Builder builder,
+ FieldSet<FieldDescriptor> extensions) throws IOException {
+
+ FieldDescriptor field = extension.descriptor;
+ Message value = null;
+ if (hasOriginalMessage(builder, extensions, field)) {
+ Message originalMessage =
+ getOriginalMessage(builder, extensions, field);
+ Message.Builder subBuilder = originalMessage.toBuilder();
+ input.readMessage(subBuilder, extensionRegistry);
+ value = subBuilder.buildPartial();
+ } else {
+ value = input.readMessage(extension.defaultInstance.getParserForType(),
+ extensionRegistry);
+ }
+
+ if (builder != null) {
+ builder.setField(field, value);
+ } else {
+ extensions.setField(field, value);
+ }
+ }
+
+ private static void mergeMessageSetExtensionFromBytes(
+ ByteString rawBytes,
+ ExtensionRegistry.ExtensionInfo extension,
+ ExtensionRegistryLite extensionRegistry,
+ Message.Builder builder,
+ FieldSet<FieldDescriptor> extensions) throws IOException {
+
+ FieldDescriptor field = extension.descriptor;
+ boolean hasOriginalValue = hasOriginalMessage(builder, extensions, field);
+
+ if (hasOriginalValue || ExtensionRegistryLite.isEagerlyParseMessageSets()) {
+ // If the field already exists, we just parse the field.
+ Message value = null;
+ if (hasOriginalValue) {
+ Message originalMessage =
+ getOriginalMessage(builder, extensions, field);
+ Message.Builder subBuilder= originalMessage.toBuilder();
+ subBuilder.mergeFrom(rawBytes, extensionRegistry);
+ value = subBuilder.buildPartial();
+ } else {
+ value = extension.defaultInstance.getParserForType()
+ .parsePartialFrom(rawBytes, extensionRegistry);
+ }
+ setField(builder, extensions, field, value);
+ } else {
+ // Use LazyField to load MessageSet lazily.
+ LazyField lazyField = new LazyField(
+ extension.defaultInstance, extensionRegistry, rawBytes);
+ if (builder != null) {
+ // TODO(xiangl): it looks like this method can only be invoked by
+ // ExtendableBuilder, but I'm not sure. So I double check the type of
+ // builder here. It may be useless and need more investigation.
+ if (builder instanceof ExtendableBuilder) {
+ builder.setField(field, lazyField);
+ } else {
+ builder.setField(field, lazyField.getValue());
+ }
+ } else {
+ extensions.setField(field, lazyField);
+ }
}
}
@@ -596,6 +756,11 @@
return (BuilderType) this;
}
+ public Message.Builder getFieldBuilder(final FieldDescriptor field) {
+ throw new UnsupportedOperationException(
+ "getFieldBuilder() called on an unsupported message type.");
+ }
+
/**
* Construct an UninitializedMessageException reporting missing fields in
* the given message.
@@ -609,14 +774,15 @@
* Populates {@code this.missingFields} with the full "path" of each
* missing required field in the given message.
*/
- private static List<String> findMissingFields(final Message message) {
+ private static List<String> findMissingFields(
+ final MessageOrBuilder message) {
final List<String> results = new ArrayList<String>();
findMissingFields(message, "", results);
return results;
}
/** Recursive helper implementing {@link #findMissingFields(Message)}. */
- private static void findMissingFields(final Message message,
+ private static void findMissingFields(final MessageOrBuilder message,
final String prefix,
final List<String> results) {
for (final FieldDescriptor field :
@@ -635,13 +801,13 @@
if (field.isRepeated()) {
int i = 0;
for (final Object element : (List) value) {
- findMissingFields((Message) element,
+ findMissingFields((MessageOrBuilder) element,
subMessagePrefix(prefix, field, i++),
results);
}
} else {
if (message.hasField(field)) {
- findMissingFields((Message) value,
+ findMissingFields((MessageOrBuilder) value,
subMessagePrefix(prefix, field, -1),
results);
}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessageLite.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
index 77b2737..9926f3d 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
@@ -92,6 +92,14 @@
}
/**
+ * Package private helper method for AbstractParser to create
+ * UninitializedMessageException.
+ */
+ UninitializedMessageException newUninitializedMessageException() {
+ return new UninitializedMessageException(this);
+ }
+
+ /**
* A partial implementation of the {@link Message.Builder} interface which
* implements as many methods of that interface as possible in terms of
* other methods.
@@ -307,10 +315,12 @@
*/
protected static <T> void addAll(final Iterable<T> values,
final Collection<? super T> list) {
- for (final T value : values) {
- if (value == null) {
- throw new NullPointerException();
- }
+ if (values instanceof LazyStringList) {
+ // For StringOrByteStringLists, check the underlying elements to avoid
+ // forcing conversions of ByteStrings to Strings.
+ checkForNullValues(((LazyStringList) values).getUnderlyingElements());
+ } else {
+ checkForNullValues(values);
}
if (values instanceof Collection) {
final Collection<T> collection = (Collection<T>) values;
@@ -321,5 +331,13 @@
}
}
}
+
+ private static void checkForNullValues(final Iterable<?> values) {
+ for (final Object value : values) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ }
+ }
}
}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractParser.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractParser.java
new file mode 100644
index 0000000..9bd9d39
--- /dev/null
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/AbstractParser.java
@@ -0,0 +1,261 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A partial implementation of the {@link Parser} interface which implements
+ * as many methods of that interface as possible in terms of other methods.
+ *
+ * Note: This class implements all the convenience methods in the
+ * {@link Parser} interface. See {@link Parser} for related javadocs.
+ * Subclasses need to implement
+ * {@link Parser#parsePartialFrom(CodedInputStream, ExtensionRegistryLite)}
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+public abstract class AbstractParser<MessageType extends MessageLite>
+ implements Parser<MessageType> {
+ /**
+ * Creates an UninitializedMessageException for MessageType.
+ */
+ private UninitializedMessageException
+ newUninitializedMessageException(MessageType message) {
+ if (message instanceof AbstractMessageLite) {
+ return ((AbstractMessageLite) message).newUninitializedMessageException();
+ }
+ return new UninitializedMessageException(message);
+ }
+
+ /**
+ * Helper method to check if message is initialized.
+ *
+ * @throws InvalidProtocolBufferException if it is not initialized.
+ * @return The message to check.
+ */
+ private MessageType checkMessageInitialized(MessageType message)
+ throws InvalidProtocolBufferException {
+ if (message != null && !message.isInitialized()) {
+ throw newUninitializedMessageException(message)
+ .asInvalidProtocolBufferException()
+ .setUnfinishedMessage(message);
+ }
+ return message;
+ }
+
+ private static final ExtensionRegistryLite EMPTY_REGISTRY
+ = ExtensionRegistryLite.getEmptyRegistry();
+
+ public MessageType parsePartialFrom(CodedInputStream input)
+ throws InvalidProtocolBufferException {
+ return parsePartialFrom(input, EMPTY_REGISTRY);
+ }
+
+ public MessageType parseFrom(CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialFrom(input, extensionRegistry));
+ }
+
+ public MessageType parseFrom(CodedInputStream input)
+ throws InvalidProtocolBufferException {
+ return parseFrom(input, EMPTY_REGISTRY);
+ }
+
+ public MessageType parsePartialFrom(ByteString data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ MessageType message;
+ try {
+ CodedInputStream input = data.newCodedInput();
+ message = parsePartialFrom(input, extensionRegistry);
+ try {
+ input.checkLastTagWas(0);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(message);
+ }
+ return message;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Reading from a ByteString threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ public MessageType parsePartialFrom(ByteString data)
+ throws InvalidProtocolBufferException {
+ return parsePartialFrom(data, EMPTY_REGISTRY);
+ }
+
+ public MessageType parseFrom(ByteString data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(parsePartialFrom(data, extensionRegistry));
+ }
+
+ public MessageType parseFrom(ByteString data)
+ throws InvalidProtocolBufferException {
+ return parseFrom(data, EMPTY_REGISTRY);
+ }
+
+ public MessageType parsePartialFrom(byte[] data, int off, int len,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ try {
+ CodedInputStream input = CodedInputStream.newInstance(data, off, len);
+ MessageType message = parsePartialFrom(input, extensionRegistry);
+ try {
+ input.checkLastTagWas(0);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(message);
+ }
+ return message;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Reading from a byte array threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ public MessageType parsePartialFrom(byte[] data, int off, int len)
+ throws InvalidProtocolBufferException {
+ return parsePartialFrom(data, off, len, EMPTY_REGISTRY);
+ }
+
+ public MessageType parsePartialFrom(byte[] data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return parsePartialFrom(data, 0, data.length, extensionRegistry);
+ }
+
+ public MessageType parsePartialFrom(byte[] data)
+ throws InvalidProtocolBufferException {
+ return parsePartialFrom(data, 0, data.length, EMPTY_REGISTRY);
+ }
+
+ public MessageType parseFrom(byte[] data, int off, int len,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialFrom(data, off, len, extensionRegistry));
+ }
+
+ public MessageType parseFrom(byte[] data, int off, int len)
+ throws InvalidProtocolBufferException {
+ return parseFrom(data, off, len, EMPTY_REGISTRY);
+ }
+
+ public MessageType parseFrom(byte[] data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return parseFrom(data, 0, data.length, extensionRegistry);
+ }
+
+ public MessageType parseFrom(byte[] data)
+ throws InvalidProtocolBufferException {
+ return parseFrom(data, EMPTY_REGISTRY);
+ }
+
+ public MessageType parsePartialFrom(InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ CodedInputStream codedInput = CodedInputStream.newInstance(input);
+ MessageType message = parsePartialFrom(codedInput, extensionRegistry);
+ try {
+ codedInput.checkLastTagWas(0);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(message);
+ }
+ return message;
+ }
+
+ public MessageType parsePartialFrom(InputStream input)
+ throws InvalidProtocolBufferException {
+ return parsePartialFrom(input, EMPTY_REGISTRY);
+ }
+
+ public MessageType parseFrom(InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialFrom(input, extensionRegistry));
+ }
+
+ public MessageType parseFrom(InputStream input)
+ throws InvalidProtocolBufferException {
+ return parseFrom(input, EMPTY_REGISTRY);
+ }
+
+ public MessageType parsePartialDelimitedFrom(
+ InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ int size;
+ try {
+ int firstByte = input.read();
+ if (firstByte == -1) {
+ return null;
+ }
+ size = CodedInputStream.readRawVarint32(firstByte, input);
+ } catch (IOException e) {
+ throw new InvalidProtocolBufferException(e.getMessage());
+ }
+ InputStream limitedInput = new LimitedInputStream(input, size);
+ return parsePartialFrom(limitedInput, extensionRegistry);
+ }
+
+ public MessageType parsePartialDelimitedFrom(InputStream input)
+ throws InvalidProtocolBufferException {
+ return parsePartialDelimitedFrom(input, EMPTY_REGISTRY);
+ }
+
+ public MessageType parseDelimitedFrom(
+ InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialDelimitedFrom(input, extensionRegistry));
+ }
+
+ public MessageType parseDelimitedFrom(InputStream input)
+ throws InvalidProtocolBufferException {
+ return parseDelimitedFrom(input, EMPTY_REGISTRY);
+ }
+}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/BoundedByteString.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/BoundedByteString.java
new file mode 100644
index 0000000..cd4982c
--- /dev/null
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/BoundedByteString.java
@@ -0,0 +1,163 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.util.NoSuchElementException;
+
+/**
+ * This class is used to represent the substring of a {@link ByteString} over a
+ * single byte array. In terms of the public API of {@link ByteString}, you end
+ * up here by calling {@link ByteString#copyFrom(byte[])} followed by {@link
+ * ByteString#substring(int, int)}.
+ *
+ * <p>This class contains most of the overhead involved in creating a substring
+ * from a {@link LiteralByteString}. The overhead involves some range-checking
+ * and two extra fields.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+class BoundedByteString extends LiteralByteString {
+
+ private final int bytesOffset;
+ private final int bytesLength;
+
+ /**
+ * Creates a {@code BoundedByteString} backed by the sub-range of given array,
+ * without copying.
+ *
+ * @param bytes array to wrap
+ * @param offset index to first byte to use in bytes
+ * @param length number of bytes to use from bytes
+ * @throws IllegalArgumentException if {@code offset < 0}, {@code length < 0},
+ * or if {@code offset + length >
+ * bytes.length}.
+ */
+ BoundedByteString(byte[] bytes, int offset, int length) {
+ super(bytes);
+ if (offset < 0) {
+ throw new IllegalArgumentException("Offset too small: " + offset);
+ }
+ if (length < 0) {
+ throw new IllegalArgumentException("Length too small: " + offset);
+ }
+ if ((long) offset + length > bytes.length) {
+ throw new IllegalArgumentException(
+ "Offset+Length too large: " + offset + "+" + length);
+ }
+
+ this.bytesOffset = offset;
+ this.bytesLength = length;
+ }
+
+ /**
+ * Gets the byte at the given index.
+ * Throws {@link ArrayIndexOutOfBoundsException}
+ * for backwards-compatibility reasons although it would more properly be
+ * {@link IndexOutOfBoundsException}.
+ *
+ * @param index index of byte
+ * @return the value
+ * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
+ */
+ @Override
+ public byte byteAt(int index) {
+ // We must check the index ourselves as we cannot rely on Java array index
+ // checking for substrings.
+ if (index < 0) {
+ throw new ArrayIndexOutOfBoundsException("Index too small: " + index);
+ }
+ if (index >= size()) {
+ throw new ArrayIndexOutOfBoundsException(
+ "Index too large: " + index + ", " + size());
+ }
+
+ return bytes[bytesOffset + index];
+ }
+
+ @Override
+ public int size() {
+ return bytesLength;
+ }
+
+ @Override
+ protected int getOffsetIntoBytes() {
+ return bytesOffset;
+ }
+
+ // =================================================================
+ // ByteString -> byte[]
+
+ @Override
+ protected void copyToInternal(byte[] target, int sourceOffset,
+ int targetOffset, int numberToCopy) {
+ System.arraycopy(bytes, getOffsetIntoBytes() + sourceOffset, target,
+ targetOffset, numberToCopy);
+ }
+
+ // =================================================================
+ // ByteIterator
+
+ @Override
+ public ByteIterator iterator() {
+ return new BoundedByteIterator();
+ }
+
+ private class BoundedByteIterator implements ByteIterator {
+
+ private int position;
+ private final int limit;
+
+ private BoundedByteIterator() {
+ position = getOffsetIntoBytes();
+ limit = position + size();
+ }
+
+ public boolean hasNext() {
+ return (position < limit);
+ }
+
+ public Byte next() {
+ // Boxing calls Byte.valueOf(byte), which does not instantiate.
+ return nextByte();
+ }
+
+ public byte nextByte() {
+ if (position >= limit) {
+ throw new NoSuchElementException();
+ }
+ return bytes[position++];
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/ByteString.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/ByteString.java
index 9135635..1b18169 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/ByteString.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/ByteString.java
@@ -30,140 +30,413 @@
package com.google.protobuf;
-import java.io.InputStream;
-import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
+import java.util.NoSuchElementException;
/**
- * Immutable array of bytes.
+ * Immutable sequence of bytes. Substring is supported by sharing the reference
+ * to the immutable underlying bytes, as with {@link String}. Concatenation is
+ * likewise supported without copying (long strings) by building a tree of
+ * pieces in {@link RopeByteString}.
+ * <p>
+ * Like {@link String}, the contents of a {@link ByteString} can never be
+ * observed to change, not even in the presence of a data race or incorrect
+ * API usage in the client code.
*
* @author crazybob@google.com Bob Lee
* @author kenton@google.com Kenton Varda
+ * @author carlanton@google.com Carl Haverl
+ * @author martinrb@google.com Martin Buchholz
*/
-public final class ByteString {
- private final byte[] bytes;
-
- private ByteString(final byte[] bytes) {
- this.bytes = bytes;
- }
+public abstract class ByteString implements Iterable<Byte> {
/**
- * Gets the byte at the given index.
+ * When two strings to be concatenated have a combined length shorter than
+ * this, we just copy their bytes on {@link #concat(ByteString)}.
+ * The trade-off is copy size versus the overhead of creating tree nodes
+ * in {@link RopeByteString}.
+ */
+ static final int CONCATENATE_BY_COPY_SIZE = 128;
+
+ /**
+ * When copying an InputStream into a ByteString with .readFrom(),
+ * the chunks in the underlying rope start at 256 bytes, but double
+ * each iteration up to 8192 bytes.
+ */
+ static final int MIN_READ_FROM_CHUNK_SIZE = 0x100; // 256b
+ static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000; // 8k
+
+ /**
+ * Empty {@code ByteString}.
+ */
+ public static final ByteString EMPTY = new LiteralByteString(new byte[0]);
+
+ // This constructor is here to prevent subclassing outside of this package,
+ ByteString() {}
+
+ /**
+ * Gets the byte at the given index. This method should be used only for
+ * random access to individual bytes. To access bytes sequentially, use the
+ * {@link ByteIterator} returned by {@link #iterator()}, and call {@link
+ * #substring(int, int)} first if necessary.
*
+ * @param index index of byte
+ * @return the value
* @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
*/
- public byte byteAt(final int index) {
- return bytes[index];
+ public abstract byte byteAt(int index);
+
+ /**
+ * Return a {@link ByteString.ByteIterator} over the bytes in the ByteString.
+ * To avoid auto-boxing, you may get the iterator manually and call
+ * {@link ByteIterator#nextByte()}.
+ *
+ * @return the iterator
+ */
+ public abstract ByteIterator iterator();
+
+ /**
+ * This interface extends {@code Iterator<Byte>}, so that we can return an
+ * unboxed {@code byte}.
+ */
+ public interface ByteIterator extends Iterator<Byte> {
+ /**
+ * An alternative to {@link Iterator#next()} that returns an
+ * unboxed primitive {@code byte}.
+ *
+ * @return the next {@code byte} in the iteration
+ * @throws NoSuchElementException if the iteration has no more elements
+ */
+ byte nextByte();
}
/**
* Gets the number of bytes.
+ *
+ * @return size in bytes
*/
- public int size() {
- return bytes.length;
- }
+ public abstract int size();
/**
* Returns {@code true} if the size is {@code 0}, {@code false} otherwise.
+ *
+ * @return true if this is zero bytes long
*/
public boolean isEmpty() {
- return bytes.length == 0;
+ return size() == 0;
+ }
+
+ // =================================================================
+ // ByteString -> substring
+
+ /**
+ * Return the substring from {@code beginIndex}, inclusive, to the end of the
+ * string.
+ *
+ * @param beginIndex start at this index
+ * @return substring sharing underlying data
+ * @throws IndexOutOfBoundsException if {@code beginIndex < 0} or
+ * {@code beginIndex > size()}.
+ */
+ public ByteString substring(int beginIndex) {
+ return substring(beginIndex, size());
+ }
+
+ /**
+ * Return the substring from {@code beginIndex}, inclusive, to {@code
+ * endIndex}, exclusive.
+ *
+ * @param beginIndex start at this index
+ * @param endIndex the last character is the one before this index
+ * @return substring sharing underlying data
+ * @throws IndexOutOfBoundsException if {@code beginIndex < 0},
+ * {@code endIndex > size()}, or {@code beginIndex > endIndex}.
+ */
+ public abstract ByteString substring(int beginIndex, int endIndex);
+
+ /**
+ * Tests if this bytestring starts with the specified prefix.
+ * Similar to {@link String#startsWith(String)}
+ *
+ * @param prefix the prefix.
+ * @return <code>true</code> if the byte sequence represented by the
+ * argument is a prefix of the byte sequence represented by
+ * this string; <code>false</code> otherwise.
+ */
+ public boolean startsWith(ByteString prefix) {
+ return size() >= prefix.size() &&
+ substring(0, prefix.size()).equals(prefix);
}
// =================================================================
// byte[] -> ByteString
/**
- * Empty ByteString.
- */
- public static final ByteString EMPTY = new ByteString(new byte[0]);
-
- /**
* Copies the given bytes into a {@code ByteString}.
+ *
+ * @param bytes source array
+ * @param offset offset in source array
+ * @param size number of bytes to copy
+ * @return new {@code ByteString}
*/
- public static ByteString copyFrom(final byte[] bytes, final int offset,
- final int size) {
- final byte[] copy = new byte[size];
+ public static ByteString copyFrom(byte[] bytes, int offset, int size) {
+ byte[] copy = new byte[size];
System.arraycopy(bytes, offset, copy, 0, size);
- return new ByteString(copy);
+ return new LiteralByteString(copy);
}
/**
* Copies the given bytes into a {@code ByteString}.
+ *
+ * @param bytes to copy
+ * @return new {@code ByteString}
*/
- public static ByteString copyFrom(final byte[] bytes) {
+ public static ByteString copyFrom(byte[] bytes) {
return copyFrom(bytes, 0, bytes.length);
}
/**
- * Copies {@code size} bytes from a {@code java.nio.ByteBuffer} into
+ * Copies the next {@code size} bytes from a {@code java.nio.ByteBuffer} into
* a {@code ByteString}.
+ *
+ * @param bytes source buffer
+ * @param size number of bytes to copy
+ * @return new {@code ByteString}
*/
- public static ByteString copyFrom(final ByteBuffer bytes, final int size) {
- final byte[] copy = new byte[size];
+ public static ByteString copyFrom(ByteBuffer bytes, int size) {
+ byte[] copy = new byte[size];
bytes.get(copy);
- return new ByteString(copy);
+ return new LiteralByteString(copy);
}
/**
* Copies the remaining bytes from a {@code java.nio.ByteBuffer} into
* a {@code ByteString}.
+ *
+ * @param bytes sourceBuffer
+ * @return new {@code ByteString}
*/
- public static ByteString copyFrom(final ByteBuffer bytes) {
+ public static ByteString copyFrom(ByteBuffer bytes) {
return copyFrom(bytes, bytes.remaining());
}
/**
* Encodes {@code text} into a sequence of bytes using the named charset
* and returns the result as a {@code ByteString}.
+ *
+ * @param text source string
+ * @param charsetName encoding to use
+ * @return new {@code ByteString}
+ * @throws UnsupportedEncodingException if the encoding isn't found
*/
- public static ByteString copyFrom(final String text, final String charsetName)
+ public static ByteString copyFrom(String text, String charsetName)
throws UnsupportedEncodingException {
- return new ByteString(text.getBytes(charsetName));
+ return new LiteralByteString(text.getBytes(charsetName));
}
/**
* Encodes {@code text} into a sequence of UTF-8 bytes and returns the
* result as a {@code ByteString}.
+ *
+ * @param text source string
+ * @return new {@code ByteString}
*/
- public static ByteString copyFromUtf8(final String text) {
+ public static ByteString copyFromUtf8(String text) {
try {
- return new ByteString(text.getBytes("UTF-8"));
+ return new LiteralByteString(text.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 not supported?", e);
}
}
+ // =================================================================
+ // InputStream -> ByteString
+
/**
- * Concatenates all byte strings in the list and returns the result.
+ * Completely reads the given stream's bytes into a
+ * {@code ByteString}, blocking if necessary until all bytes are
+ * read through to the end of the stream.
+ *
+ * <b>Performance notes:</b> The returned {@code ByteString} is an
+ * immutable tree of byte arrays ("chunks") of the stream data. The
+ * first chunk is small, with subsequent chunks each being double
+ * the size, up to 8K. If the caller knows the precise length of
+ * the stream and wishes to avoid all unnecessary copies and
+ * allocations, consider using the two-argument version of this
+ * method, below.
+ *
+ * @param streamToDrain The source stream, which is read completely
+ * but not closed.
+ * @return A new {@code ByteString} which is made up of chunks of
+ * various sizes, depending on the behavior of the underlying
+ * stream.
+ * @throws IOException IOException is thrown if there is a problem
+ * reading the underlying stream.
+ */
+ public static ByteString readFrom(InputStream streamToDrain)
+ throws IOException {
+ return readFrom(
+ streamToDrain, MIN_READ_FROM_CHUNK_SIZE, MAX_READ_FROM_CHUNK_SIZE);
+ }
+
+ /**
+ * Completely reads the given stream's bytes into a
+ * {@code ByteString}, blocking if necessary until all bytes are
+ * read through to the end of the stream.
+ *
+ * <b>Performance notes:</b> The returned {@code ByteString} is an
+ * immutable tree of byte arrays ("chunks") of the stream data. The
+ * chunkSize parameter sets the size of these byte arrays. In
+ * particular, if the chunkSize is precisely the same as the length
+ * of the stream, unnecessary allocations and copies will be
+ * avoided. Otherwise, the chunks will be of the given size, except
+ * for the last chunk, which will be resized (via a reallocation and
+ * copy) to contain the remainder of the stream.
+ *
+ * @param streamToDrain The source stream, which is read completely
+ * but not closed.
+ * @param chunkSize The size of the chunks in which to read the
+ * stream.
+ * @return A new {@code ByteString} which is made up of chunks of
+ * the given size.
+ * @throws IOException IOException is thrown if there is a problem
+ * reading the underlying stream.
+ */
+ public static ByteString readFrom(InputStream streamToDrain, int chunkSize)
+ throws IOException {
+ return readFrom(streamToDrain, chunkSize, chunkSize);
+ }
+
+ // Helper method that takes the chunk size range as a parameter.
+ public static ByteString readFrom(InputStream streamToDrain, int minChunkSize,
+ int maxChunkSize) throws IOException {
+ Collection<ByteString> results = new ArrayList<ByteString>();
+
+ // copy the inbound bytes into a list of chunks; the chunk size
+ // grows exponentially to support both short and long streams.
+ int chunkSize = minChunkSize;
+ while (true) {
+ ByteString chunk = readChunk(streamToDrain, chunkSize);
+ if (chunk == null) {
+ break;
+ }
+ results.add(chunk);
+ chunkSize = Math.min(chunkSize * 2, maxChunkSize);
+ }
+
+ return ByteString.copyFrom(results);
+ }
+
+ /**
+ * Blocks until a chunk of the given size can be made from the
+ * stream, or EOF is reached. Calls read() repeatedly in case the
+ * given stream implementation doesn't completely fill the given
+ * buffer in one read() call.
+ *
+ * @return A chunk of the desired size, or else a chunk as large as
+ * was available when end of stream was reached. Returns null if the
+ * given stream had no more data in it.
+ */
+ private static ByteString readChunk(InputStream in, final int chunkSize)
+ throws IOException {
+ final byte[] buf = new byte[chunkSize];
+ int bytesRead = 0;
+ while (bytesRead < chunkSize) {
+ final int count = in.read(buf, bytesRead, chunkSize - bytesRead);
+ if (count == -1) {
+ break;
+ }
+ bytesRead += count;
+ }
+
+ if (bytesRead == 0) {
+ return null;
+ } else {
+ return ByteString.copyFrom(buf, 0, bytesRead);
+ }
+ }
+
+ // =================================================================
+ // Multiple ByteStrings -> One ByteString
+
+ /**
+ * Concatenate the given {@code ByteString} to this one. Short concatenations,
+ * of total size smaller than {@link ByteString#CONCATENATE_BY_COPY_SIZE}, are
+ * produced by copying the underlying bytes (as per Rope.java, <a
+ * href="http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol25/issue12/spe986.pdf">
+ * BAP95 </a>. In general, the concatenate involves no copying.
+ *
+ * @param other string to concatenate
+ * @return a new {@code ByteString} instance
+ */
+ public ByteString concat(ByteString other) {
+ int thisSize = size();
+ int otherSize = other.size();
+ if ((long) thisSize + otherSize >= Integer.MAX_VALUE) {
+ throw new IllegalArgumentException("ByteString would be too long: " +
+ thisSize + "+" + otherSize);
+ }
+
+ return RopeByteString.concatenate(this, other);
+ }
+
+ /**
+ * Concatenates all byte strings in the iterable and returns the result.
+ * This is designed to run in O(list size), not O(total bytes).
*
* <p>The returned {@code ByteString} is not necessarily a unique object.
* If the list is empty, the returned object is the singleton empty
* {@code ByteString}. If the list has only one element, that
* {@code ByteString} will be returned without copying.
+ *
+ * @param byteStrings strings to be concatenated
+ * @return new {@code ByteString}
*/
- public static ByteString copyFrom(List<ByteString> list) {
- if (list.size() == 0) {
- return EMPTY;
- } else if (list.size() == 1) {
- return list.get(0);
+ public static ByteString copyFrom(Iterable<ByteString> byteStrings) {
+ Collection<ByteString> collection;
+ if (!(byteStrings instanceof Collection)) {
+ collection = new ArrayList<ByteString>();
+ for (ByteString byteString : byteStrings) {
+ collection.add(byteString);
+ }
+ } else {
+ collection = (Collection<ByteString>) byteStrings;
}
+ ByteString result;
+ if (collection.isEmpty()) {
+ result = EMPTY;
+ } else {
+ result = balancedConcat(collection.iterator(), collection.size());
+ }
+ return result;
+ }
- int size = 0;
- for (ByteString str : list) {
- size += str.size();
+ // Internal function used by copyFrom(Iterable<ByteString>).
+ // Create a balanced concatenation of the next "length" elements from the
+ // iterable.
+ private static ByteString balancedConcat(Iterator<ByteString> iterator,
+ int length) {
+ assert length >= 1;
+ ByteString result;
+ if (length == 1) {
+ result = iterator.next();
+ } else {
+ int halfLength = length >>> 1;
+ ByteString left = balancedConcat(iterator, halfLength);
+ ByteString right = balancedConcat(iterator, length - halfLength);
+ result = left.concat(right);
}
- byte[] bytes = new byte[size];
- int pos = 0;
- for (ByteString str : list) {
- System.arraycopy(str.bytes, 0, bytes, pos, str.size());
- pos += str.size();
- }
- return new ByteString(bytes);
+ return result;
}
// =================================================================
@@ -174,206 +447,446 @@
*
* @param target buffer to copy into
* @param offset in the target buffer
+ * @throws IndexOutOfBoundsException if the offset is negative or too large
*/
- public void copyTo(final byte[] target, final int offset) {
- System.arraycopy(bytes, 0, target, offset, bytes.length);
+ public void copyTo(byte[] target, int offset) {
+ copyTo(target, 0, offset, size());
}
/**
* Copies bytes into a buffer.
*
- * @param target buffer to copy into
+ * @param target buffer to copy into
* @param sourceOffset offset within these bytes
* @param targetOffset offset within the target buffer
- * @param size number of bytes to copy
+ * @param numberToCopy number of bytes to copy
+ * @throws IndexOutOfBoundsException if an offset or size is negative or too
+ * large
*/
- public void copyTo(final byte[] target, final int sourceOffset,
- final int targetOffset,
- final int size) {
- System.arraycopy(bytes, sourceOffset, target, targetOffset, size);
+ public void copyTo(byte[] target, int sourceOffset, int targetOffset,
+ int numberToCopy) {
+ if (sourceOffset < 0) {
+ throw new IndexOutOfBoundsException("Source offset < 0: " + sourceOffset);
+ }
+ if (targetOffset < 0) {
+ throw new IndexOutOfBoundsException("Target offset < 0: " + targetOffset);
+ }
+ if (numberToCopy < 0) {
+ throw new IndexOutOfBoundsException("Length < 0: " + numberToCopy);
+ }
+ if (sourceOffset + numberToCopy > size()) {
+ throw new IndexOutOfBoundsException(
+ "Source end offset < 0: " + (sourceOffset + numberToCopy));
+ }
+ if (targetOffset + numberToCopy > target.length) {
+ throw new IndexOutOfBoundsException(
+ "Target end offset < 0: " + (targetOffset + numberToCopy));
+ }
+ if (numberToCopy > 0) {
+ copyToInternal(target, sourceOffset, targetOffset, numberToCopy);
+ }
}
/**
+ * Internal (package private) implementation of
+ * @link{#copyTo(byte[],int,int,int}.
+ * It assumes that all error checking has already been performed and that
+ * @code{numberToCopy > 0}.
+ */
+ protected abstract void copyToInternal(byte[] target, int sourceOffset,
+ int targetOffset, int numberToCopy);
+
+ /**
* Copies bytes into a ByteBuffer.
*
* @param target ByteBuffer to copy into.
- * @throws ReadOnlyBufferException if the {@code target} is read-only
- * @throws BufferOverflowException if the {@code target}'s remaining()
- * space is not large enough to hold the data.
+ * @throws java.nio.ReadOnlyBufferException if the {@code target} is read-only
+ * @throws java.nio.BufferOverflowException if the {@code target}'s
+ * remaining() space is not large enough to hold the data.
*/
- public void copyTo(ByteBuffer target) {
- target.put(bytes, 0, bytes.length);
- }
+ public abstract void copyTo(ByteBuffer target);
/**
* Copies bytes to a {@code byte[]}.
+ *
+ * @return copied bytes
*/
public byte[] toByteArray() {
- final int size = bytes.length;
- final byte[] copy = new byte[size];
- System.arraycopy(bytes, 0, copy, 0, size);
- return copy;
+ int size = size();
+ byte[] result = new byte[size];
+ copyToInternal(result, 0, 0, size);
+ return result;
}
/**
- * Constructs a new read-only {@code java.nio.ByteBuffer} with the
- * same backing byte array.
+ * Writes the complete contents of this byte string to
+ * the specified output stream argument.
+ *
+ * @param out the output stream to which to write the data.
+ * @throws IOException if an I/O error occurs.
*/
- public ByteBuffer asReadOnlyByteBuffer() {
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- return byteBuffer.asReadOnlyBuffer();
- }
+ public abstract void writeTo(OutputStream out) throws IOException;
+
+ /**
+ * Constructs a read-only {@code java.nio.ByteBuffer} whose content
+ * is equal to the contents of this byte string.
+ * The result uses the same backing array as the byte string, if possible.
+ *
+ * @return wrapped bytes
+ */
+ public abstract ByteBuffer asReadOnlyByteBuffer();
+
+ /**
+ * Constructs a list of read-only {@code java.nio.ByteBuffer} objects
+ * such that the concatenation of their contents is equal to the contents
+ * of this byte string. The result uses the same backing arrays as the
+ * byte string.
+ * <p>
+ * By returning a list, implementations of this method may be able to avoid
+ * copying even when there are multiple backing arrays.
+ *
+ * @return a list of wrapped bytes
+ */
+ public abstract List<ByteBuffer> asReadOnlyByteBufferList();
/**
* Constructs a new {@code String} by decoding the bytes using the
* specified charset.
+ *
+ * @param charsetName encode using this charset
+ * @return new string
+ * @throws UnsupportedEncodingException if charset isn't recognized
*/
- public String toString(final String charsetName)
- throws UnsupportedEncodingException {
- return new String(bytes, charsetName);
- }
+ public abstract String toString(String charsetName)
+ throws UnsupportedEncodingException;
+
+ // =================================================================
+ // UTF-8 decoding
/**
* Constructs a new {@code String} by decoding the bytes as UTF-8.
+ *
+ * @return new string using UTF-8 encoding
*/
public String toStringUtf8() {
try {
- return new String(bytes, "UTF-8");
+ return toString("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 not supported?", e);
}
}
+ /**
+ * Tells whether this {@code ByteString} represents a well-formed UTF-8
+ * byte sequence, such that the original bytes can be converted to a
+ * String object and then round tripped back to bytes without loss.
+ *
+ * <p>More precisely, returns {@code true} whenever: <pre> {@code
+ * Arrays.equals(byteString.toByteArray(),
+ * new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
+ * }</pre>
+ *
+ * <p>This method returns {@code false} for "overlong" byte sequences,
+ * as well as for 3-byte sequences that would map to a surrogate
+ * character, in accordance with the restricted definition of UTF-8
+ * introduced in Unicode 3.1. Note that the UTF-8 decoder included in
+ * Oracle's JDK has been modified to also reject "overlong" byte
+ * sequences, but (as of 2011) still accepts 3-byte surrogate
+ * character byte sequences.
+ *
+ * <p>See the Unicode Standard,</br>
+ * Table 3-6. <em>UTF-8 Bit Distribution</em>,</br>
+ * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
+ *
+ * @return whether the bytes in this {@code ByteString} are a
+ * well-formed UTF-8 byte sequence
+ */
+ public abstract boolean isValidUtf8();
+
+ /**
+ * Tells whether the given byte sequence is a well-formed, malformed, or
+ * incomplete UTF-8 byte sequence. This method accepts and returns a partial
+ * state result, allowing the bytes for a complete UTF-8 byte sequence to be
+ * composed from multiple {@code ByteString} segments.
+ *
+ * @param state either {@code 0} (if this is the initial decoding operation)
+ * or the value returned from a call to a partial decoding method for the
+ * previous bytes
+ * @param offset offset of the first byte to check
+ * @param length number of bytes to check
+ *
+ * @return {@code -1} if the partial byte sequence is definitely malformed,
+ * {@code 0} if it is well-formed (no additional input needed), or, if the
+ * byte sequence is "incomplete", i.e. apparently terminated in the middle of
+ * a character, an opaque integer "state" value containing enough information
+ * to decode the character when passed to a subsequent invocation of a
+ * partial decoding method.
+ */
+ protected abstract int partialIsValidUtf8(int state, int offset, int length);
+
// =================================================================
// equals() and hashCode()
@Override
- public boolean equals(final Object o) {
- if (o == this) {
- return true;
- }
+ public abstract boolean equals(Object o);
- if (!(o instanceof ByteString)) {
- return false;
- }
-
- final ByteString other = (ByteString) o;
- final int size = bytes.length;
- if (size != other.bytes.length) {
- return false;
- }
-
- final byte[] thisBytes = bytes;
- final byte[] otherBytes = other.bytes;
- for (int i = 0; i < size; i++) {
- if (thisBytes[i] != otherBytes[i]) {
- return false;
- }
- }
-
- return true;
- }
-
- private volatile int hash = 0;
-
+ /**
+ * Return a non-zero hashCode depending only on the sequence of bytes
+ * in this ByteString.
+ *
+ * @return hashCode value for this object
+ */
@Override
- public int hashCode() {
- int h = hash;
-
- if (h == 0) {
- final byte[] thisBytes = bytes;
- final int size = bytes.length;
-
- h = size;
- for (int i = 0; i < size; i++) {
- h = h * 31 + thisBytes[i];
- }
- if (h == 0) {
- h = 1;
- }
-
- hash = h;
- }
-
- return h;
- }
+ public abstract int hashCode();
// =================================================================
// Input stream
/**
* Creates an {@code InputStream} which can be used to read the bytes.
+ * <p>
+ * The {@link InputStream} returned by this method is guaranteed to be
+ * completely non-blocking. The method {@link InputStream#available()}
+ * returns the number of bytes remaining in the stream. The methods
+ * {@link InputStream#read(byte[]), {@link InputStream#read(byte[],int,int)}
+ * and {@link InputStream#skip(long)} will read/skip as many bytes as are
+ * available.
+ * <p>
+ * The methods in the returned {@link InputStream} might <b>not</b> be
+ * thread safe.
+ *
+ * @return an input stream that returns the bytes of this byte string.
*/
- public InputStream newInput() {
- return new ByteArrayInputStream(bytes);
- }
+ public abstract InputStream newInput();
/**
* Creates a {@link CodedInputStream} which can be used to read the bytes.
- * Using this is more efficient than creating a {@link CodedInputStream}
- * wrapping the result of {@link #newInput()}.
+ * Using this is often more efficient than creating a {@link CodedInputStream}
+ * that wraps the result of {@link #newInput()}.
+ *
+ * @return stream based on wrapped data
*/
- public CodedInputStream newCodedInput() {
- // We trust CodedInputStream not to modify the bytes, or to give anyone
- // else access to them.
- return CodedInputStream.newInstance(bytes);
- }
+ public abstract CodedInputStream newCodedInput();
// =================================================================
// Output stream
/**
- * Creates a new {@link Output} with the given initial capacity.
+ * Creates a new {@link Output} with the given initial capacity. Call {@link
+ * Output#toByteString()} to create the {@code ByteString} instance.
+ * <p>
+ * A {@link ByteString.Output} offers the same functionality as a
+ * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString}
+ * rather than a {@code byte} array.
+ *
+ * @param initialCapacity estimate of number of bytes to be written
+ * @return {@code OutputStream} for building a {@code ByteString}
*/
- public static Output newOutput(final int initialCapacity) {
- return new Output(new ByteArrayOutputStream(initialCapacity));
+ public static Output newOutput(int initialCapacity) {
+ return new Output(initialCapacity);
}
/**
- * Creates a new {@link Output}.
+ * Creates a new {@link Output}. Call {@link Output#toByteString()} to create
+ * the {@code ByteString} instance.
+ * <p>
+ * A {@link ByteString.Output} offers the same functionality as a
+ * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString}
+ * rather than a {@code byte array}.
+ *
+ * @return {@code OutputStream} for building a {@code ByteString}
*/
public static Output newOutput() {
- return newOutput(32);
+ return new Output(CONCATENATE_BY_COPY_SIZE);
}
/**
* Outputs to a {@code ByteString} instance. Call {@link #toByteString()} to
* create the {@code ByteString} instance.
*/
- public static final class Output extends FilterOutputStream {
- private final ByteArrayOutputStream bout;
+ public static final class Output extends OutputStream {
+ // Implementation note.
+ // The public methods of this class must be synchronized. ByteStrings
+ // are guaranteed to be immutable. Without some sort of locking, it could
+ // be possible for one thread to call toByteSring(), while another thread
+ // is still modifying the underlying byte array.
+
+ private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+ // argument passed by user, indicating initial capacity.
+ private final int initialCapacity;
+ // ByteStrings to be concatenated to create the result
+ private final ArrayList<ByteString> flushedBuffers;
+ // Total number of bytes in the ByteStrings of flushedBuffers
+ private int flushedBuffersTotalBytes;
+ // Current buffer to which we are writing
+ private byte[] buffer;
+ // Location in buffer[] to which we write the next byte.
+ private int bufferPos;
/**
- * Constructs a new output with the given initial capacity.
+ * Creates a new ByteString output stream with the specified
+ * initial capacity.
+ *
+ * @param initialCapacity the initial capacity of the output stream.
*/
- private Output(final ByteArrayOutputStream bout) {
- super(bout);
- this.bout = bout;
+ Output(int initialCapacity) {
+ if (initialCapacity < 0) {
+ throw new IllegalArgumentException("Buffer size < 0");
+ }
+ this.initialCapacity = initialCapacity;
+ this.flushedBuffers = new ArrayList<ByteString>();
+ this.buffer = new byte[initialCapacity];
+ }
+
+ @Override
+ public synchronized void write(int b) {
+ if (bufferPos == buffer.length) {
+ flushFullBuffer(1);
+ }
+ buffer[bufferPos++] = (byte)b;
+ }
+
+ @Override
+ public synchronized void write(byte[] b, int offset, int length) {
+ if (length <= buffer.length - bufferPos) {
+ // The bytes can fit into the current buffer.
+ System.arraycopy(b, offset, buffer, bufferPos, length);
+ bufferPos += length;
+ } else {
+ // Use up the current buffer
+ int copySize = buffer.length - bufferPos;
+ System.arraycopy(b, offset, buffer, bufferPos, copySize);
+ offset += copySize;
+ length -= copySize;
+ // Flush the buffer, and get a new buffer at least big enough to cover
+ // what we still need to output
+ flushFullBuffer(length);
+ System.arraycopy(b, offset, buffer, 0 /* count */, length);
+ bufferPos = length;
+ }
}
/**
- * Creates a {@code ByteString} instance from this {@code Output}.
+ * Creates a byte string. Its size is the current size of this output
+ * stream and its output has been copied to it.
+ *
+ * @return the current contents of this output stream, as a byte string.
*/
- public ByteString toByteString() {
- final byte[] byteArray = bout.toByteArray();
- return new ByteString(byteArray);
+ public synchronized ByteString toByteString() {
+ flushLastBuffer();
+ return ByteString.copyFrom(flushedBuffers);
+ }
+
+ /**
+ * Writes the complete contents of this byte array output stream to
+ * the specified output stream argument.
+ *
+ * @param out the output stream to which to write the data.
+ * @throws IOException if an I/O error occurs.
+ */
+ public void writeTo(OutputStream out) throws IOException {
+ ByteString[] cachedFlushBuffers;
+ byte[] cachedBuffer;
+ int cachedBufferPos;
+ synchronized (this) {
+ // Copy the information we need into local variables so as to hold
+ // the lock for as short a time as possible.
+ cachedFlushBuffers =
+ flushedBuffers.toArray(new ByteString[flushedBuffers.size()]);
+ cachedBuffer = buffer;
+ cachedBufferPos = bufferPos;
+ }
+ for (ByteString byteString : cachedFlushBuffers) {
+ byteString.writeTo(out);
+ }
+
+ out.write(Arrays.copyOf(cachedBuffer, cachedBufferPos));
+ }
+
+ /**
+ * Returns the current size of the output stream.
+ *
+ * @return the current size of the output stream
+ */
+ public synchronized int size() {
+ return flushedBuffersTotalBytes + bufferPos;
+ }
+
+ /**
+ * Resets this stream, so that all currently accumulated output in the
+ * output stream is discarded. The output stream can be used again,
+ * reusing the already allocated buffer space.
+ */
+ public synchronized void reset() {
+ flushedBuffers.clear();
+ flushedBuffersTotalBytes = 0;
+ bufferPos = 0;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("<ByteString.Output@%s size=%d>",
+ Integer.toHexString(System.identityHashCode(this)), size());
+ }
+
+ /**
+ * Internal function used by writers. The current buffer is full, and the
+ * writer needs a new buffer whose size is at least the specified minimum
+ * size.
+ */
+ private void flushFullBuffer(int minSize) {
+ flushedBuffers.add(new LiteralByteString(buffer));
+ flushedBuffersTotalBytes += buffer.length;
+ // We want to increase our total capacity by 50%, but as a minimum,
+ // the new buffer should also at least be >= minSize and
+ // >= initial Capacity.
+ int newSize = Math.max(initialCapacity,
+ Math.max(minSize, flushedBuffersTotalBytes >>> 1));
+ buffer = new byte[newSize];
+ bufferPos = 0;
+ }
+
+ /**
+ * Internal function used by {@link #toByteString()}. The current buffer may
+ * or may not be full, but it needs to be flushed.
+ */
+ private void flushLastBuffer() {
+ if (bufferPos < buffer.length) {
+ if (bufferPos > 0) {
+ byte[] bufferCopy = Arrays.copyOf(buffer, bufferPos);
+ flushedBuffers.add(new LiteralByteString(bufferCopy));
+ }
+ // We reuse this buffer for further writes.
+ } else {
+ // Buffer is completely full. Huzzah.
+ flushedBuffers.add(new LiteralByteString(buffer));
+ // 99% of the time, we're not going to use this OutputStream again.
+ // We set buffer to an empty byte stream so that we're handling this
+ // case without wasting space. In the rare case that more writes
+ // *do* occur, this empty buffer will be flushed and an appropriately
+ // sized new buffer will be created.
+ buffer = EMPTY_BYTE_ARRAY;
+ }
+ flushedBuffersTotalBytes += bufferPos;
+ bufferPos = 0;
}
}
/**
- * Constructs a new ByteString builder, which allows you to efficiently
- * construct a {@code ByteString} by writing to a {@link CodedOutputStream}.
- * Using this is much more efficient than calling {@code newOutput()} and
- * wrapping that in a {@code CodedOutputStream}.
+ * Constructs a new {@code ByteString} builder, which allows you to
+ * efficiently construct a {@code ByteString} by writing to a {@link
+ * CodedOutputStream}. Using this is much more efficient than calling {@code
+ * newOutput()} and wrapping that in a {@code CodedOutputStream}.
*
* <p>This is package-private because it's a somewhat confusing interface.
* Users can call {@link Message#toByteString()} instead of calling this
* directly.
*
- * @param size The target byte size of the {@code ByteString}. You must
- * write exactly this many bytes before building the result.
+ * @param size The target byte size of the {@code ByteString}. You must write
+ * exactly this many bytes before building the result.
+ * @return the builder
*/
- static CodedBuilder newCodedBuilder(final int size) {
+ static CodedBuilder newCodedBuilder(int size) {
return new CodedBuilder(size);
}
@@ -382,7 +895,7 @@
private final CodedOutputStream output;
private final byte[] buffer;
- private CodedBuilder(final int size) {
+ private CodedBuilder(int size) {
buffer = new byte[size];
output = CodedOutputStream.newInstance(buffer);
}
@@ -393,11 +906,57 @@
// We can be confident that the CodedOutputStream will not modify the
// underlying bytes anymore because it already wrote all of them. So,
// no need to make a copy.
- return new ByteString(buffer);
+ return new LiteralByteString(buffer);
}
public CodedOutputStream getCodedOutput() {
return output;
}
}
+
+ // =================================================================
+ // Methods {@link RopeByteString} needs on instances, which aren't part of the
+ // public API.
+
+ /**
+ * Return the depth of the tree representing this {@code ByteString}, if any,
+ * whose root is this node. If this is a leaf node, return 0.
+ *
+ * @return tree depth or zero
+ */
+ protected abstract int getTreeDepth();
+
+ /**
+ * Return {@code true} if this ByteString is literal (a leaf node) or a
+ * flat-enough tree in the sense of {@link RopeByteString}.
+ *
+ * @return true if the tree is flat enough
+ */
+ protected abstract boolean isBalanced();
+
+ /**
+ * Return the cached hash code if available.
+ *
+ * @return value of cached hash code or 0 if not computed yet
+ */
+ protected abstract int peekCachedHashCode();
+
+ /**
+ * Compute the hash across the value bytes starting with the given hash, and
+ * return the result. This is used to compute the hash across strings
+ * represented as a set of pieces by allowing the hash computation to be
+ * continued from piece to piece.
+ *
+ * @param h starting hash value
+ * @param offset offset into this value to start looking at data values
+ * @param length number of data values to include in the hash computation
+ * @return ending hash value
+ */
+ protected abstract int partialHash(int h, int offset, int length);
+
+ @Override
+ public String toString() {
+ return String.format("<ByteString@%s size=%d>",
+ Integer.toHexString(System.identityHashCode(this)), size());
+ }
}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedInputStream.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedInputStream.java
index b3e0855..33417a7 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -243,6 +243,23 @@
--recursionDepth;
}
+ /** Read a {@code group} field value from the stream. */
+ public <T extends MessageLite> T readGroup(
+ final int fieldNumber,
+ final Parser<T> parser,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferException.recursionLimitExceeded();
+ }
+ ++recursionDepth;
+ T result = parser.parsePartialFrom(this, extensionRegistry);
+ checkLastTagWas(
+ WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
+ --recursionDepth;
+ return result;
+ }
+
/**
* Reads a {@code group} field value from the stream and merges it into the
* given {@link UnknownFieldSet}.
@@ -278,6 +295,24 @@
popLimit(oldLimit);
}
+ /** Read an embedded message field value from the stream. */
+ public <T extends MessageLite> T readMessage(
+ final Parser<T> parser,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ int length = readRawVarint32();
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferException.recursionLimitExceeded();
+ }
+ final int oldLimit = pushLimit(length);
+ ++recursionDepth;
+ T result = parser.parsePartialFrom(this, extensionRegistry);
+ checkLastTagWas(0);
+ --recursionDepth;
+ popLimit(oldLimit);
+ return result;
+ }
+
/** Read a {@code bytes} field value from the stream. */
public ByteString readBytes() throws IOException {
final int size = readRawVarint32();
@@ -601,7 +636,7 @@
* refreshing its buffer. If you need to prevent reading past a certain
* point in the underlying {@code InputStream} (e.g. because you expect it to
* contain more data after the end of the message which you need to handle
- * differently) then you must place a wrapper around you {@code InputStream}
+ * differently) then you must place a wrapper around your {@code InputStream}
* which limits the amount of data that can be read from it.
*
* @return the old limit.
@@ -676,7 +711,7 @@
/**
* Called with {@code this.buffer} is empty to read more bytes from the
- * input. If {@code mustSucceed} is true, refillBuffer() gurantees that
+ * input. If {@code mustSucceed} is true, refillBuffer() guarantees that
* either there will be at least one byte in the buffer when it returns
* or it will throw an exception. If {@code mustSucceed} is false,
* refillBuffer() returns false if no more bytes were available.
@@ -879,7 +914,7 @@
refillBuffer(true);
}
- bufferPos = size - pos;
+ bufferPos = size - pos;
}
}
}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedOutputStream.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedOutputStream.java
index ac5f2d3..ca24638 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedOutputStream.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -30,10 +30,10 @@
package com.google.protobuf;
-import java.io.OutputStream;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
/**
* Encodes and writes protocol message fields.
@@ -540,6 +540,15 @@
}
/**
+ * Compute the number of bytes that would be needed to encode an
+ * embedded message in lazy field, including tag.
+ */
+ public static int computeLazyFieldSize(final int fieldNumber,
+ final LazyField value) {
+ return computeTagSize(fieldNumber) + computeLazyFieldSizeNoTag(value);
+ }
+
+ /**
* Compute the number of bytes that would be needed to encode a
* {@code uint32} field, including tag.
*/
@@ -614,6 +623,18 @@
computeBytesSize(WireFormat.MESSAGE_SET_MESSAGE, value);
}
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * lazily parsed MessageSet extension field to the stream. For
+ * historical reasons, the wire format differs from normal fields.
+ */
+ public static int computeLazyFieldMessageSetExtensionSize(
+ final int fieldNumber, final LazyField value) {
+ return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 +
+ computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) +
+ computeLazyFieldSize(WireFormat.MESSAGE_SET_MESSAGE, value);
+ }
+
// -----------------------------------------------------------------
/**
@@ -730,6 +751,15 @@
}
/**
+ * Compute the number of bytes that would be needed to encode an embedded
+ * message stored in lazy field.
+ */
+ public static int computeLazyFieldSizeNoTag(final LazyField value) {
+ final int size = value.getSerializedSize();
+ return computeRawVarint32Size(size) + size;
+ }
+
+ /**
* Compute the number of bytes that would be needed to encode a
* {@code bytes} field.
*/
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/Descriptors.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/Descriptors.java
index 2ee8459..a491305 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/Descriptors.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/Descriptors.java
@@ -35,8 +35,10 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.io.UnsupportedEncodingException;
/**
@@ -106,6 +108,11 @@
return Collections.unmodifiableList(Arrays.asList(dependencies));
}
+ /** Get a list of this file's public dependencies (public imports). */
+ public List<FileDescriptor> getPublicDependencies() {
+ return Collections.unmodifiableList(Arrays.asList(publicDependencies));
+ }
+
/**
* Find a message type in the file by name. Does not find nested types.
*
@@ -216,7 +223,7 @@
public static FileDescriptor buildFrom(final FileDescriptorProto proto,
final FileDescriptor[] dependencies)
throws DescriptorValidationException {
- // Building decsriptors involves two steps: translating and linking.
+ // Building descriptors involves two steps: translating and linking.
// In the translation step (implemented by FileDescriptor's
// constructor), we build an object tree mirroring the
// FileDescriptorProto's tree and put all of the descriptors into the
@@ -317,12 +324,12 @@
* {@link FileDescriptor#internalBuildGeneratedFileFrom}, the caller
* provides a callback implementing this interface. The callback is called
* after the FileDescriptor has been constructed, in order to assign all
- * the global variales defined in the generated code which point at parts
+ * the global variables defined in the generated code which point at parts
* of the FileDescriptor. The callback returns an ExtensionRegistry which
* contains any extensions which might be used in the descriptor -- that
* is, extensions of the various "Options" messages defined in
* descriptor.proto. The callback may also return null to indicate that
- * no extensions are used in the decsriptor.
+ * no extensions are used in the descriptor.
*/
public interface InternalDescriptorAssigner {
ExtensionRegistry assignDescriptors(FileDescriptor root);
@@ -334,6 +341,7 @@
private final ServiceDescriptor[] services;
private final FieldDescriptor[] extensions;
private final FileDescriptor[] dependencies;
+ private final FileDescriptor[] publicDependencies;
private final DescriptorPool pool;
private FileDescriptor(final FileDescriptorProto proto,
@@ -343,6 +351,17 @@
this.pool = pool;
this.proto = proto;
this.dependencies = dependencies.clone();
+ this.publicDependencies =
+ new FileDescriptor[proto.getPublicDependencyCount()];
+ for (int i = 0; i < proto.getPublicDependencyCount(); i++) {
+ int index = proto.getPublicDependency(i);
+ if (index < 0 || index >= this.dependencies.length) {
+ throw new DescriptorValidationException(this,
+ "Invalid public dependency index.");
+ }
+ this.publicDependencies[i] =
+ this.dependencies[proto.getPublicDependency(i)];
+ }
pool.addPackage(getPackage(), this);
@@ -390,7 +409,7 @@
* in the original. This method is needed for bootstrapping when a file
* defines custom options. The options may be defined in the file itself,
* so we can't actually parse them until we've constructed the descriptors,
- * but to construct the decsriptors we have to have parsed the descriptor
+ * but to construct the descriptors we have to have parsed the descriptor
* protos. So, we have to parse the descriptor protos a second time after
* constructing the descriptors.
*/
@@ -641,7 +660,7 @@
FieldSet.FieldDescriptorLite<FieldDescriptor> {
/**
* Get the index of this descriptor within its parent.
- * @see Descriptor#getIndex()
+ * @see Descriptors.Descriptor#getIndex()
*/
public int getIndex() { return index; }
@@ -656,7 +675,7 @@
/**
* Get the field's fully-qualified name.
- * @see Descriptor#getFullName()
+ * @see Descriptors.Descriptor#getFullName()
*/
public String getFullName() { return fullName; }
@@ -943,7 +962,8 @@
private void crossLink() throws DescriptorValidationException {
if (proto.hasExtendee()) {
final GenericDescriptor extendee =
- file.pool.lookupSymbol(proto.getExtendee(), this);
+ file.pool.lookupSymbol(proto.getExtendee(), this,
+ DescriptorPool.SearchFilter.TYPES_ONLY);
if (!(extendee instanceof Descriptor)) {
throw new DescriptorValidationException(this,
'\"' + proto.getExtendee() + "\" is not a message type.");
@@ -960,7 +980,8 @@
if (proto.hasTypeName()) {
final GenericDescriptor typeDescriptor =
- file.pool.lookupSymbol(proto.getTypeName(), this);
+ file.pool.lookupSymbol(proto.getTypeName(), this,
+ DescriptorPool.SearchFilter.TYPES_ONLY);
if (!proto.hasType()) {
// Choose field type based on symbol.
@@ -1149,7 +1170,7 @@
implements GenericDescriptor, Internal.EnumLiteMap<EnumValueDescriptor> {
/**
* Get the index of this descriptor within its parent.
- * @see Descriptor#getIndex()
+ * @see Descriptors.Descriptor#getIndex()
*/
public int getIndex() { return index; }
@@ -1161,7 +1182,7 @@
/**
* Get the type's fully-qualified name.
- * @see Descriptor#getFullName()
+ * @see Descriptors.Descriptor#getFullName()
*/
public String getFullName() { return fullName; }
@@ -1182,7 +1203,7 @@
/**
* Find an enum value by name.
* @param name The unqualified name of the value (e.g. "FOO").
- * @return the value's decsriptor, or {@code null} if not found.
+ * @return the value's descriptor, or {@code null} if not found.
*/
public EnumValueDescriptor findValueByName(final String name) {
final GenericDescriptor result =
@@ -1198,7 +1219,7 @@
* Find an enum value by number. If multiple enum values have the same
* number, this returns the first defined value with that number.
* @param number The value's number.
- * @return the value's decsriptor, or {@code null} if not found.
+ * @return the value's descriptor, or {@code null} if not found.
*/
public EnumValueDescriptor findValueByNumber(final int number) {
return file.pool.enumValuesByNumber.get(
@@ -1261,7 +1282,7 @@
implements GenericDescriptor, Internal.EnumLite {
/**
* Get the index of this descriptor within its parent.
- * @see Descriptor#getIndex()
+ * @see Descriptors.Descriptor#getIndex()
*/
public int getIndex() { return index; }
@@ -1276,7 +1297,7 @@
/**
* Get the value's fully-qualified name.
- * @see Descriptor#getFullName()
+ * @see Descriptors.Descriptor#getFullName()
*/
public String getFullName() { return fullName; }
@@ -1337,7 +1358,7 @@
/**
* Get the type's fully-qualified name.
- * @see Descriptor#getFullName()
+ * @see Descriptors.Descriptor#getFullName()
*/
public String getFullName() { return fullName; }
@@ -1355,7 +1376,7 @@
/**
* Find a method by name.
* @param name The unqualified name of the method (e.g. "Foo").
- * @return the method's decsriptor, or {@code null} if not found.
+ * @return the method's descriptor, or {@code null} if not found.
*/
public MethodDescriptor findMethodByName(final String name) {
final GenericDescriptor result =
@@ -1427,7 +1448,7 @@
/**
* Get the method's fully-qualified name.
- * @see Descriptor#getFullName()
+ * @see Descriptors.Descriptor#getFullName()
*/
public String getFullName() { return fullName; }
@@ -1475,7 +1496,8 @@
private void crossLink() throws DescriptorValidationException {
final GenericDescriptor input =
- file.pool.lookupSymbol(proto.getInputType(), this);
+ file.pool.lookupSymbol(proto.getInputType(), this,
+ DescriptorPool.SearchFilter.TYPES_ONLY);
if (!(input instanceof Descriptor)) {
throw new DescriptorValidationException(this,
'\"' + proto.getInputType() + "\" is not a message type.");
@@ -1483,7 +1505,8 @@
inputType = (Descriptor)input;
final GenericDescriptor output =
- file.pool.lookupSymbol(proto.getOutputType(), this);
+ file.pool.lookupSymbol(proto.getOutputType(), this,
+ DescriptorPool.SearchFilter.TYPES_ONLY);
if (!(output instanceof Descriptor)) {
throw new DescriptorValidationException(this,
'\"' + proto.getOutputType() + "\" is not a message type.");
@@ -1535,7 +1558,7 @@
public String getProblemSymbolName() { return name; }
/**
- * Gets the the protocol message representation of the invalid descriptor.
+ * Gets the protocol message representation of the invalid descriptor.
*/
public Message getProblemProto() { return proto; }
@@ -1590,14 +1613,22 @@
* descriptors defined in a particular file.
*/
private static final class DescriptorPool {
+
+ /** Defines what subclass of descriptors to search in the descriptor pool.
+ */
+ enum SearchFilter {
+ TYPES_ONLY, AGGREGATES_ONLY, ALL_SYMBOLS
+ }
+
DescriptorPool(final FileDescriptor[] dependencies) {
- this.dependencies = new DescriptorPool[dependencies.length];
+ this.dependencies = new HashSet<FileDescriptor>();
- for (int i = 0; i < dependencies.length; i++) {
- this.dependencies[i] = dependencies[i].pool;
+ for (int i = 0; i < dependencies.length; i++) {
+ this.dependencies.add(dependencies[i]);
+ importPublicDependencies(dependencies[i]);
}
- for (final FileDescriptor dependency : dependencies) {
+ for (final FileDescriptor dependency : this.dependencies) {
try {
addPackage(dependency.getPackage(), dependency);
} catch (DescriptorValidationException e) {
@@ -1609,7 +1640,16 @@
}
}
- private final DescriptorPool[] dependencies;
+ /** Find and put public dependencies of the file into dependencies set.*/
+ private void importPublicDependencies(final FileDescriptor file) {
+ for (FileDescriptor dependency : file.getPublicDependencies()) {
+ if (dependencies.add(dependency)) {
+ importPublicDependencies(dependency);
+ }
+ }
+ }
+
+ private final Set<FileDescriptor> dependencies;
private final Map<String, GenericDescriptor> descriptorsByName =
new HashMap<String, GenericDescriptor>();
@@ -1620,39 +1660,81 @@
/** Find a generic descriptor by fully-qualified name. */
GenericDescriptor findSymbol(final String fullName) {
+ return findSymbol(fullName, SearchFilter.ALL_SYMBOLS);
+ }
+
+ /** Find a descriptor by fully-qualified name and given option to only
+ * search valid field type descriptors.
+ */
+ GenericDescriptor findSymbol(final String fullName,
+ final SearchFilter filter) {
GenericDescriptor result = descriptorsByName.get(fullName);
if (result != null) {
- return result;
+ if ((filter==SearchFilter.ALL_SYMBOLS) ||
+ ((filter==SearchFilter.TYPES_ONLY) && isType(result)) ||
+ ((filter==SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) {
+ return result;
+ }
}
- for (final DescriptorPool dependency : dependencies) {
- result = dependency.descriptorsByName.get(fullName);
+ for (final FileDescriptor dependency : dependencies) {
+ result = dependency.pool.descriptorsByName.get(fullName);
if (result != null) {
- return result;
+ if ((filter==SearchFilter.ALL_SYMBOLS) ||
+ ((filter==SearchFilter.TYPES_ONLY) && isType(result)) ||
+ ((filter==SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) {
+ return result;
+ }
}
}
return null;
}
+ /** Checks if the descriptor is a valid type for a message field. */
+ boolean isType(GenericDescriptor descriptor) {
+ return (descriptor instanceof Descriptor) ||
+ (descriptor instanceof EnumDescriptor);
+ }
+
+ /** Checks if the descriptor is a valid namespace type. */
+ boolean isAggregate(GenericDescriptor descriptor) {
+ return (descriptor instanceof Descriptor) ||
+ (descriptor instanceof EnumDescriptor) ||
+ (descriptor instanceof PackageDescriptor) ||
+ (descriptor instanceof ServiceDescriptor);
+ }
+
/**
- * Look up a descriptor by name, relative to some other descriptor.
+ * Look up a type descriptor by name, relative to some other descriptor.
* The name may be fully-qualified (with a leading '.'),
* partially-qualified, or unqualified. C++-like name lookup semantics
* are used to search for the matching descriptor.
*/
GenericDescriptor lookupSymbol(final String name,
- final GenericDescriptor relativeTo)
+ final GenericDescriptor relativeTo,
+ final DescriptorPool.SearchFilter filter)
throws DescriptorValidationException {
// TODO(kenton): This could be optimized in a number of ways.
GenericDescriptor result;
if (name.startsWith(".")) {
// Fully-qualified name.
- result = findSymbol(name.substring(1));
+ result = findSymbol(name.substring(1), filter);
} else {
// If "name" is a compound identifier, we want to search for the
// first component of it, then search within it for the rest.
+ // If name is something like "Foo.Bar.baz", and symbols named "Foo" are
+ // defined in multiple parent scopes, we only want to find "Bar.baz" in
+ // the innermost one. E.g., the following should produce an error:
+ // message Bar { message Baz {} }
+ // message Foo {
+ // message Bar {
+ // }
+ // optional Bar.Baz baz = 1;
+ // }
+ // So, we look for just "Foo" first, then look for "Bar.baz" within it
+ // if found.
final int firstPartLength = name.indexOf('.');
final String firstPart;
if (firstPartLength == -1) {
@@ -1670,14 +1752,15 @@
// Chop off the last component of the scope.
final int dotpos = scopeToTry.lastIndexOf(".");
if (dotpos == -1) {
- result = findSymbol(name);
+ result = findSymbol(name, filter);
break;
} else {
scopeToTry.setLength(dotpos + 1);
- // Append firstPart and try to find.
+ // Append firstPart and try to find
scopeToTry.append(firstPart);
- result = findSymbol(scopeToTry.toString());
+ result = findSymbol(scopeToTry.toString(),
+ DescriptorPool.SearchFilter.AGGREGATES_ONLY);
if (result != null) {
if (firstPartLength != -1) {
@@ -1686,7 +1769,7 @@
// searching parent scopes.
scopeToTry.setLength(dotpos + 1);
scopeToTry.append(name);
- result = findSymbol(scopeToTry.toString());
+ result = findSymbol(scopeToTry.toString(), filter);
}
break;
}
@@ -1817,7 +1900,7 @@
/**
* Adds a field to the fieldsByNumber table. Throws an exception if a
- * field with hte same containing type and number already exists.
+ * field with the same containing type and number already exists.
*/
void addFieldByNumber(final FieldDescriptor field)
throws DescriptorValidationException {
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/DynamicMessage.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/DynamicMessage.java
index c106b66..c0c9fc9 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -35,6 +35,7 @@
import java.io.InputStream;
import java.io.IOException;
+import java.util.Collections;
import java.util.Map;
/**
@@ -160,7 +161,9 @@
verifyContainingType(field);
Object result = fields.getField(field);
if (result == null) {
- if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ if (field.isRepeated()) {
+ result = Collections.emptyList();
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
result = getDefaultInstance(field.getMessageType());
} else {
result = field.getDefaultValue();
@@ -198,10 +201,12 @@
return fields.isInitialized();
}
+ @Override
public boolean isInitialized() {
return isInitialized(type, fields);
}
+ @Override
public void writeTo(CodedOutputStream output) throws IOException {
if (type.getOptions().getMessageSetWireFormat()) {
fields.writeMessageSetTo(output);
@@ -212,6 +217,7 @@
}
}
+ @Override
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) return size;
@@ -236,6 +242,26 @@
return newBuilderForType().mergeFrom(this);
}
+ public Parser<DynamicMessage> getParserForType() {
+ return new AbstractParser<DynamicMessage>() {
+ public DynamicMessage parsePartialFrom(
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ Builder builder = newBuilder(type);
+ try {
+ builder.mergeFrom(input, extensionRegistry);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(builder.buildPartial());
+ } catch (IOException e) {
+ throw new InvalidProtocolBufferException(e.getMessage())
+ .setUnfinishedMessage(builder.buildPartial());
+ }
+ return builder.buildPartial();
+ }
+ };
+ }
+
/** Verifies that the field is a field of this message. */
private void verifyContainingType(FieldDescriptor field) {
if (field.getContainingType() != type) {
@@ -264,14 +290,18 @@
// ---------------------------------------------------------------
// Implementation of Message.Builder interface.
+ @Override
public Builder clear() {
- if (fields == null) {
- throw new IllegalStateException("Cannot call clear() after build().");
+ if (fields.isImmutable()) {
+ fields = FieldSet.newFieldSet();
+ } else {
+ fields.clear();
}
- fields.clear();
+ unknownFields = UnknownFieldSet.getDefaultInstance();
return this;
}
+ @Override
public Builder mergeFrom(Message other) {
if (other instanceof DynamicMessage) {
// This should be somewhat faster than calling super.mergeFrom().
@@ -280,6 +310,7 @@
throw new IllegalArgumentException(
"mergeFrom(Message) can only merge messages of the same type.");
}
+ ensureIsMutable();
fields.mergeFrom(otherDynamicMessage.fields);
mergeUnknownFields(otherDynamicMessage.unknownFields);
return this;
@@ -289,8 +320,7 @@
}
public DynamicMessage build() {
- // If fields == null, we'll throw an appropriate exception later.
- if (fields != null && !isInitialized()) {
+ if (!isInitialized()) {
throw newUninitializedMessageException(
new DynamicMessage(type, fields, unknownFields));
}
@@ -312,21 +342,17 @@
}
public DynamicMessage buildPartial() {
- if (fields == null) {
- throw new IllegalStateException(
- "build() has already been called on this Builder.");
- }
fields.makeImmutable();
DynamicMessage result =
new DynamicMessage(type, fields, unknownFields);
- fields = null;
- unknownFields = null;
return result;
}
+ @Override
public Builder clone() {
Builder result = new Builder(type);
result.fields.mergeFrom(fields);
+ result.mergeUnknownFields(unknownFields);
return result;
}
@@ -377,12 +403,14 @@
public Builder setField(FieldDescriptor field, Object value) {
verifyContainingType(field);
+ ensureIsMutable();
fields.setField(field, value);
return this;
}
public Builder clearField(FieldDescriptor field) {
verifyContainingType(field);
+ ensureIsMutable();
fields.clearField(field);
return this;
}
@@ -400,12 +428,14 @@
public Builder setRepeatedField(FieldDescriptor field,
int index, Object value) {
verifyContainingType(field);
+ ensureIsMutable();
fields.setRepeatedField(field, index, value);
return this;
}
public Builder addRepeatedField(FieldDescriptor field, Object value) {
verifyContainingType(field);
+ ensureIsMutable();
fields.addRepeatedField(field, value);
return this;
}
@@ -419,6 +449,7 @@
return this;
}
+ @Override
public Builder mergeUnknownFields(UnknownFieldSet unknownFields) {
this.unknownFields =
UnknownFieldSet.newBuilder(this.unknownFields)
@@ -434,5 +465,18 @@
"FieldDescriptor does not match message type.");
}
}
+
+ private void ensureIsMutable() {
+ if (fields.isImmutable()) {
+ fields = fields.clone();
+ }
+ }
+
+ @Override
+ public com.google.protobuf.Message.Builder getFieldBuilder(FieldDescriptor field) {
+ // TODO(xiangl): need implementation for dynamic message
+ throw new UnsupportedOperationException(
+ "getFieldBuilder() called on a dynamic message type.");
+ }
}
}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
index d5288dd..1e1289d 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
@@ -43,7 +43,7 @@
* make sense to mix the two, since if you have any regular types in your
* program, you then require the full runtime and lose all the benefits of
* the lite runtime, so you might as well make all your types be regular types.
- * However, in some cases (e.g. when depending on multiple third-patry libraries
+ * However, in some cases (e.g. when depending on multiple third-party libraries
* where one uses lite types and one uses regular), you may find yourself
* wanting to mix the two. In this case things get more complicated.
* <p>
@@ -71,6 +71,22 @@
* @author kenton@google.com Kenton Varda
*/
public class ExtensionRegistryLite {
+
+ // Set true to enable lazy parsing feature for MessageSet.
+ //
+ // TODO(xiangl): Now we use a global flag to control whether enable lazy
+ // parsing feature for MessageSet, which may be too crude for some
+ // applications. Need to support this feature on smaller granularity.
+ private static volatile boolean eagerlyParseMessageSets = false;
+
+ public static boolean isEagerlyParseMessageSets() {
+ return eagerlyParseMessageSets;
+ }
+
+ public static void setEagerlyParseMessageSets(boolean isEagerlyParse) {
+ eagerlyParseMessageSets = isEagerlyParse;
+ }
+
/** Construct a new, empty instance. */
public static ExtensionRegistryLite newInstance() {
return new ExtensionRegistryLite();
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/FieldSet.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/FieldSet.java
index a85dbaa..2663694 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/FieldSet.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/FieldSet.java
@@ -30,12 +30,14 @@
package com.google.protobuf;
+import com.google.protobuf.LazyField.LazyIterator;
+
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.io.IOException;
/**
* A class which represents an arbitrary set of fields of some message type.
@@ -68,6 +70,7 @@
private final SmallSortedMap<FieldDescriptorType, Object> fields;
private boolean isImmutable;
+ private boolean hasLazyField = false;
/** Construct a new FieldSet. */
private FieldSet() {
@@ -95,7 +98,7 @@
FieldSet<T> emptySet() {
return DEFAULT_INSTANCE;
}
- @SuppressWarnings("unchecked")
+ @SuppressWarnings("rawtypes")
private static final FieldSet DEFAULT_INSTANCE = new FieldSet(true);
/** Make this FieldSet immutable from this point forward. */
@@ -109,7 +112,7 @@
}
/**
- * Retuns whether the FieldSet is immutable. This is true if it is the
+ * Returns whether the FieldSet is immutable. This is true if it is the
* {@link #emptySet} or if {@link #makeImmutable} were called.
*
* @return whether the FieldSet is immutable.
@@ -139,6 +142,7 @@
FieldDescriptorType descriptor = entry.getKey();
clone.setField(descriptor, entry.getValue());
}
+ clone.hasLazyField = hasLazyField;
return clone;
}
@@ -147,21 +151,52 @@
/** See {@link Message.Builder#clear()}. */
public void clear() {
fields.clear();
+ hasLazyField = false;
}
/**
* Get a simple map containing all the fields.
*/
public Map<FieldDescriptorType, Object> getAllFields() {
+ if (hasLazyField) {
+ SmallSortedMap<FieldDescriptorType, Object> result =
+ SmallSortedMap.newFieldMap(16);
+ for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+ cloneFieldEntry(result, fields.getArrayEntryAt(i));
+ }
+ for (Map.Entry<FieldDescriptorType, Object> entry :
+ fields.getOverflowEntries()) {
+ cloneFieldEntry(result, entry);
+ }
+ if (fields.isImmutable()) {
+ result.makeImmutable();
+ }
+ return result;
+ }
return fields.isImmutable() ? fields : Collections.unmodifiableMap(fields);
}
+ private void cloneFieldEntry(Map<FieldDescriptorType, Object> map,
+ Map.Entry<FieldDescriptorType, Object> entry) {
+ FieldDescriptorType key = entry.getKey();
+ Object value = entry.getValue();
+ if (value instanceof LazyField) {
+ map.put(key, ((LazyField) value).getValue());
+ } else {
+ map.put(key, value);
+ }
+ }
+
/**
* Get an iterator to the field map. This iterator should not be leaked out
- * of the protobuf library as it is not protected from mutation when
- * fields is not immutable.
+ * of the protobuf library as it is not protected from mutation when fields
+ * is not immutable.
*/
public Iterator<Map.Entry<FieldDescriptorType, Object>> iterator() {
+ if (hasLazyField) {
+ return new LazyIterator<FieldDescriptorType>(
+ fields.entrySet().iterator());
+ }
return fields.entrySet().iterator();
}
@@ -185,14 +220,18 @@
* to the caller to fetch the field's default value.
*/
public Object getField(final FieldDescriptorType descriptor) {
- return fields.get(descriptor);
+ Object o = fields.get(descriptor);
+ if (o instanceof LazyField) {
+ return ((LazyField) o).getValue();
+ }
+ return o;
}
/**
* Useful for implementing
* {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}.
*/
- @SuppressWarnings("unchecked")
+ @SuppressWarnings({"unchecked", "rawtypes"})
public void setField(final FieldDescriptorType descriptor,
Object value) {
if (descriptor.isRepeated()) {
@@ -204,7 +243,7 @@
// Wrap the contents in a new list so that the caller cannot change
// the list's contents after setting it.
final List newList = new ArrayList();
- newList.addAll((List)value);
+ newList.addAll((List) value);
for (final Object element : newList) {
verifyType(descriptor.getLiteType(), element);
}
@@ -213,6 +252,9 @@
verifyType(descriptor.getLiteType(), value);
}
+ if (value instanceof LazyField) {
+ hasLazyField = true;
+ }
fields.put(descriptor, value);
}
@@ -222,6 +264,9 @@
*/
public void clearField(final FieldDescriptorType descriptor) {
fields.remove(descriptor);
+ if (fields.isEmpty()) {
+ hasLazyField = false;
+ }
}
/**
@@ -234,7 +279,7 @@
"getRepeatedField() can only be called on repeated fields.");
}
- final Object value = fields.get(descriptor);
+ final Object value = getField(descriptor);
if (value == null) {
return 0;
} else {
@@ -253,7 +298,7 @@
"getRepeatedField() can only be called on repeated fields.");
}
- final Object value = fields.get(descriptor);
+ final Object value = getField(descriptor);
if (value == null) {
throw new IndexOutOfBoundsException();
@@ -275,13 +320,13 @@
"getRepeatedField() can only be called on repeated fields.");
}
- final Object list = fields.get(descriptor);
+ final Object list = getField(descriptor);
if (list == null) {
throw new IndexOutOfBoundsException();
}
verifyType(descriptor.getLiteType(), value);
- ((List) list).set(index, value);
+ ((List<Object>) list).set(index, value);
}
/**
@@ -298,13 +343,13 @@
verifyType(descriptor.getLiteType(), value);
- final Object existingValue = fields.get(descriptor);
- List list;
+ final Object existingValue = getField(descriptor);
+ List<Object> list;
if (existingValue == null) {
- list = new ArrayList();
+ list = new ArrayList<Object>();
fields.put(descriptor, list);
} else {
- list = (List) existingValue;
+ list = (List<Object>) existingValue;
}
list.add(value);
@@ -338,7 +383,8 @@
break;
case MESSAGE:
// TODO(kenton): Caller must do type checking here, I guess.
- isValid = value instanceof MessageLite;
+ isValid =
+ (value instanceof MessageLite) || (value instanceof LazyField);
break;
}
@@ -392,8 +438,16 @@
}
}
} else {
- if (!((MessageLite) entry.getValue()).isInitialized()) {
- return false;
+ Object value = entry.getValue();
+ if (value instanceof MessageLite) {
+ if (!((MessageLite) value).isInitialized()) {
+ return false;
+ }
+ } else if (value instanceof LazyField) {
+ return true;
+ } else {
+ throw new IllegalArgumentException(
+ "Wrong object type used with protocol message reflection.");
}
}
}
@@ -416,7 +470,8 @@
}
/**
- * Like {@link #mergeFrom(Message)}, but merges from another {@link FieldSet}.
+ * Like {@link Message.Builder#mergeFrom(Message)}, but merges from another
+ * {@link FieldSet}.
*/
public void mergeFrom(final FieldSet<FieldDescriptorType> other) {
for (int i = 0; i < other.fields.getNumArrayEntries(); i++) {
@@ -428,14 +483,17 @@
}
}
- @SuppressWarnings("unchecked")
+ @SuppressWarnings({"unchecked", "rawtypes"})
private void mergeFromField(
final Map.Entry<FieldDescriptorType, Object> entry) {
final FieldDescriptorType descriptor = entry.getKey();
- final Object otherValue = entry.getValue();
+ Object otherValue = entry.getValue();
+ if (otherValue instanceof LazyField) {
+ otherValue = ((LazyField) otherValue).getValue();
+ }
if (descriptor.isRepeated()) {
- Object value = fields.get(descriptor);
+ Object value = getField(descriptor);
if (value == null) {
// Our list is empty, but we still need to make a defensive copy of
// the other list since we don't know if the other FieldSet is still
@@ -446,7 +504,7 @@
((List) value).addAll((List) otherValue);
}
} else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
- Object value = fields.get(descriptor);
+ Object value = getField(descriptor);
if (value == null) {
fields.put(descriptor, otherValue);
} else {
@@ -457,7 +515,6 @@
((MessageLite) value).toBuilder(), (MessageLite) otherValue)
.build());
}
-
} else {
fields.put(descriptor, otherValue);
}
@@ -646,7 +703,11 @@
}
}
} else {
- writeElement(output, type, number, value);
+ if (value instanceof LazyField) {
+ writeElement(output, type, number, ((LazyField) value).getValue());
+ } else {
+ writeElement(output, type, number, value);
+ }
}
}
@@ -686,12 +747,18 @@
private int getMessageSetSerializedSize(
final Map.Entry<FieldDescriptorType, Object> entry) {
final FieldDescriptorType descriptor = entry.getKey();
- if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE &&
- !descriptor.isRepeated() && !descriptor.isPacked()) {
- return CodedOutputStream.computeMessageSetExtensionSize(
- entry.getKey().getNumber(), (MessageLite) entry.getValue());
+ Object value = entry.getValue();
+ if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE
+ && !descriptor.isRepeated() && !descriptor.isPacked()) {
+ if (value instanceof LazyField) {
+ return CodedOutputStream.computeLazyFieldMessageSetExtensionSize(
+ entry.getKey().getNumber(), (LazyField) value);
+ } else {
+ return CodedOutputStream.computeMessageSetExtensionSize(
+ entry.getKey().getNumber(), (MessageLite) value);
+ }
} else {
- return computeFieldSize(descriptor, entry.getValue());
+ return computeFieldSize(descriptor, value);
}
}
@@ -741,7 +808,6 @@
case BOOL : return CodedOutputStream.computeBoolSizeNoTag ((Boolean )value);
case STRING : return CodedOutputStream.computeStringSizeNoTag ((String )value);
case GROUP : return CodedOutputStream.computeGroupSizeNoTag ((MessageLite)value);
- case MESSAGE : return CodedOutputStream.computeMessageSizeNoTag ((MessageLite)value);
case BYTES : return CodedOutputStream.computeBytesSizeNoTag ((ByteString )value);
case UINT32 : return CodedOutputStream.computeUInt32SizeNoTag ((Integer )value);
case SFIXED32: return CodedOutputStream.computeSFixed32SizeNoTag((Integer )value);
@@ -749,6 +815,13 @@
case SINT32 : return CodedOutputStream.computeSInt32SizeNoTag ((Integer )value);
case SINT64 : return CodedOutputStream.computeSInt64SizeNoTag ((Long )value);
+ case MESSAGE:
+ if (value instanceof LazyField) {
+ return CodedOutputStream.computeLazyFieldSizeNoTag((LazyField) value);
+ } else {
+ return CodedOutputStream.computeMessageSizeNoTag((MessageLite) value);
+ }
+
case ENUM:
return CodedOutputStream.computeEnumSizeNoTag(
((Internal.EnumLite) value).getNumber());
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessage.java
index b5eaded..0c15ca8 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -58,8 +58,6 @@
implements Serializable {
private static final long serialVersionUID = 1L;
- private final UnknownFieldSet unknownFields;
-
/**
* For testing. Allows a test to disable the optimization that avoids using
* field builders for nested messages until they are requested. By disabling
@@ -68,11 +66,14 @@
protected static boolean alwaysUseFieldBuilders = false;
protected GeneratedMessage() {
- this.unknownFields = UnknownFieldSet.getDefaultInstance();
}
protected GeneratedMessage(Builder<?> builder) {
- this.unknownFields = builder.getUnknownFields();
+ }
+
+ public Parser<? extends Message> getParserForType() {
+ throw new UnsupportedOperationException(
+ "This is supposed to be overridden by subclasses.");
}
/**
@@ -175,8 +176,28 @@
}
//@Override (Java 1.6 override semantics, but we must support 1.5)
- public final UnknownFieldSet getUnknownFields() {
- return unknownFields;
+ public UnknownFieldSet getUnknownFields() {
+ throw new UnsupportedOperationException(
+ "This is supposed to be overridden by subclasses.");
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ protected boolean parseUnknownField(
+ CodedInputStream input,
+ UnknownFieldSet.Builder unknownFields,
+ ExtensionRegistryLite extensionRegistry,
+ int tag) throws IOException {
+ return unknownFields.mergeFieldFrom(tag, input);
+ }
+
+ /**
+ * Used by parsing constructors in generated classes.
+ */
+ protected void makeExtensionsImmutable() {
+ // Noop for messages without extensions.
}
protected abstract Message.Builder newBuilderForType(BuilderParent parent);
@@ -319,6 +340,11 @@
}
//@Override (Java 1.6 override semantics, but we must support 1.5)
+ public Message.Builder getFieldBuilder(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).getBuilder(this);
+ }
+
+ //@Override (Java 1.6 override semantics, but we must support 1.5)
public boolean hasField(final FieldDescriptor field) {
return internalGetFieldAccessorTable().getField(field).has(this);
}
@@ -626,6 +652,25 @@
return super.isInitialized() && extensionsAreInitialized();
}
+ @Override
+ protected boolean parseUnknownField(
+ CodedInputStream input,
+ UnknownFieldSet.Builder unknownFields,
+ ExtensionRegistryLite extensionRegistry,
+ int tag) throws IOException {
+ return AbstractMessage.Builder.mergeFieldFrom(
+ input, unknownFields, extensionRegistry, getDescriptorForType(),
+ null, extensions, tag);
+ }
+
+ /**
+ * Used by parsing constructors in generated classes.
+ */
+ @Override
+ protected void makeExtensionsImmutable() {
+ extensions.makeImmutable();
+ }
+
/**
* Used by subclasses to serialize extensions. Extension ranges may be
* interleaved with field numbers, but we must write them in canonical
@@ -655,9 +700,21 @@
if (messageSetWireFormat && descriptor.getLiteJavaType() ==
WireFormat.JavaType.MESSAGE &&
!descriptor.isRepeated()) {
- output.writeMessageSetExtension(descriptor.getNumber(),
- (Message) next.getValue());
+ if (next instanceof LazyField.LazyEntry<?>) {
+ output.writeRawMessageSetExtension(descriptor.getNumber(),
+ ((LazyField.LazyEntry<?>) next).getField().toByteString());
+ } else {
+ output.writeMessageSetExtension(descriptor.getNumber(),
+ (Message) next.getValue());
+ }
} else {
+ // TODO(xiangl): Taken care of following code, it may cause
+ // problem when we use LazyField for normal fields/extensions.
+ // Due to the optional field can be duplicated at the end of
+ // serialized bytes, which will make the serialized size change
+ // after lazy field parsed. So when we use LazyField globally,
+ // we need to change the following write method to write cached
+ // bytes directly rather than write the parsed message.
FieldSet.writeField(descriptor, next.getValue(), output);
}
if (iter.hasNext()) {
@@ -974,7 +1031,8 @@
final ExtensionRegistryLite extensionRegistry,
final int tag) throws IOException {
return AbstractMessage.Builder.mergeFieldFrom(
- input, unknownFields, extensionRegistry, this, tag);
+ input, unknownFields, extensionRegistry, getDescriptorForType(),
+ this, null, tag);
}
// ---------------------------------------------------------------
@@ -1405,39 +1463,72 @@
final String[] camelCaseNames,
final Class<? extends GeneratedMessage> messageClass,
final Class<? extends Builder> builderClass) {
- this.descriptor = descriptor;
- fields = new FieldAccessor[descriptor.getFields().size()];
+ this(descriptor, camelCaseNames);
+ ensureFieldAccessorsInitialized(messageClass, builderClass);
+ }
- for (int i = 0; i < fields.length; i++) {
- final FieldDescriptor field = descriptor.getFields().get(i);
- if (field.isRepeated()) {
- if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
- fields[i] = new RepeatedMessageFieldAccessor(
- field, camelCaseNames[i], messageClass, builderClass);
- } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
- fields[i] = new RepeatedEnumFieldAccessor(
- field, camelCaseNames[i], messageClass, builderClass);
+ /**
+ * Construct a FieldAccessorTable for a particular message class without
+ * initializing FieldAccessors.
+ */
+ public FieldAccessorTable(
+ final Descriptor descriptor,
+ final String[] camelCaseNames) {
+ this.descriptor = descriptor;
+ this.camelCaseNames = camelCaseNames;
+ fields = new FieldAccessor[descriptor.getFields().size()];
+ initialized = false;
+ }
+
+ /**
+ * Ensures the field accessors are initialized. This method is thread-safe.
+ *
+ * @param messageClass The message type.
+ * @param builderClass The builder type.
+ * @return this
+ */
+ public FieldAccessorTable ensureFieldAccessorsInitialized(
+ Class<? extends GeneratedMessage> messageClass,
+ Class<? extends Builder> builderClass) {
+ if (initialized) { return this; }
+ synchronized (this) {
+ if (initialized) { return this; }
+ for (int i = 0; i < fields.length; i++) {
+ FieldDescriptor field = descriptor.getFields().get(i);
+ if (field.isRepeated()) {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ fields[i] = new RepeatedMessageFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+ fields[i] = new RepeatedEnumFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ } else {
+ fields[i] = new RepeatedFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ }
} else {
- fields[i] = new RepeatedFieldAccessor(
- field, camelCaseNames[i], messageClass, builderClass);
- }
- } else {
- if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
- fields[i] = new SingularMessageFieldAccessor(
- field, camelCaseNames[i], messageClass, builderClass);
- } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
- fields[i] = new SingularEnumFieldAccessor(
- field, camelCaseNames[i], messageClass, builderClass);
- } else {
- fields[i] = new SingularFieldAccessor(
- field, camelCaseNames[i], messageClass, builderClass);
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ fields[i] = new SingularMessageFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+ fields[i] = new SingularEnumFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ } else {
+ fields[i] = new SingularFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ }
}
}
+ initialized = true;
+ camelCaseNames = null;
+ return this;
}
}
private final Descriptor descriptor;
private final FieldAccessor[] fields;
+ private String[] camelCaseNames;
+ private volatile boolean initialized;
/** Get the FieldAccessor for a particular field. */
private FieldAccessor getField(final FieldDescriptor field) {
@@ -1472,6 +1563,7 @@
int getRepeatedCount(GeneratedMessage.Builder builder);
void clear(Builder builder);
Message.Builder newBuilder();
+ Message.Builder getBuilder(GeneratedMessage.Builder builder);
}
// ---------------------------------------------------------------
@@ -1551,6 +1643,10 @@
throw new UnsupportedOperationException(
"newBuilderForField() called on a non-Message type.");
}
+ public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
+ throw new UnsupportedOperationException(
+ "getFieldBuilder() called on a non-Message type.");
+ }
}
private static class RepeatedFieldAccessor implements FieldAccessor {
@@ -1573,8 +1669,6 @@
"get" + camelCaseName + "List");
getMethodBuilder = getMethodOrDie(builderClass,
"get" + camelCaseName + "List");
-
-
getRepeatedMethod =
getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
getRepeatedMethodBuilder =
@@ -1625,11 +1719,11 @@
}
public boolean has(final GeneratedMessage message) {
throw new UnsupportedOperationException(
- "hasField() called on a singular field.");
+ "hasField() called on a repeated field.");
}
public boolean has(GeneratedMessage.Builder builder) {
throw new UnsupportedOperationException(
- "hasField() called on a singular field.");
+ "hasField() called on a repeated field.");
}
public int getRepeatedCount(final GeneratedMessage message) {
return (Integer) invokeOrDie(getCountMethod, message);
@@ -1644,6 +1738,10 @@
throw new UnsupportedOperationException(
"newBuilderForField() called on a non-Message type.");
}
+ public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
+ throw new UnsupportedOperationException(
+ "getFieldBuilder() called on a non-Message type.");
+ }
}
// ---------------------------------------------------------------
@@ -1753,9 +1851,12 @@
super(descriptor, camelCaseName, messageClass, builderClass);
newBuilderMethod = getMethodOrDie(type, "newBuilder");
+ getBuilderMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Builder");
}
private final Method newBuilderMethod;
+ private final Method getBuilderMethodBuilder;
private Object coerceType(final Object value) {
if (type.isInstance(value)) {
@@ -1766,7 +1867,7 @@
// DynamicMessage -- we should accept it. In this case we can make
// a copy of the message.
return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
- .mergeFrom((Message) value).build();
+ .mergeFrom((Message) value).buildPartial();
}
}
@@ -1778,6 +1879,10 @@
public Message.Builder newBuilder() {
return (Message.Builder) invokeOrDie(newBuilderMethod, null);
}
+ @Override
+ public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
+ return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder);
+ }
}
private static final class RepeatedMessageFieldAccessor
@@ -1825,7 +1930,7 @@
/**
* Replaces this object in the output stream with a serialized form.
* Part of Java's serialization magic. Generated sub-classes must override
- * this method by calling <code>return super.writeReplace();</code>
+ * this method by calling {@code return super.writeReplace();}
* @return a SerializedForm of this message
*/
protected Object writeReplace() throws ObjectStreamException {
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index 1813e9b..437e341 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -55,6 +55,29 @@
protected GeneratedMessageLite(Builder builder) {
}
+ public Parser<? extends MessageLite> getParserForType() {
+ throw new UnsupportedOperationException(
+ "This is supposed to be overridden by subclasses.");
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ protected boolean parseUnknownField(
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry,
+ int tag) throws IOException {
+ return input.skipField(tag);
+ }
+
+ /**
+ * Used by parsing constructors in generated classes.
+ */
+ protected void makeExtensionsImmutable() {
+ // Noop for messages without extensions.
+ }
+
@SuppressWarnings("unchecked")
public abstract static class Builder<MessageType extends GeneratedMessageLite,
BuilderType extends Builder>
@@ -86,9 +109,9 @@
* @return {@code true} unless the tag is an end-group tag.
*/
protected boolean parseUnknownField(
- final CodedInputStream input,
- final ExtensionRegistryLite extensionRegistry,
- final int tag) throws IOException {
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry,
+ int tag) throws IOException {
return input.skipField(tag);
}
}
@@ -194,6 +217,31 @@
}
/**
+ * Called by subclasses to parse an unknown field or an extension.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ @Override
+ protected boolean parseUnknownField(
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry,
+ int tag) throws IOException {
+ return GeneratedMessageLite.parseUnknownField(
+ extensions,
+ getDefaultInstanceForType(),
+ input,
+ extensionRegistry,
+ tag);
+ }
+
+ /**
+ * Used by parsing constructors in generated classes.
+ */
+ @Override
+ protected void makeExtensionsImmutable() {
+ extensions.makeImmutable();
+ }
+
+ /**
* Used by subclasses to serialize extensions. Extension ranges may be
* interleaved with field numbers, but we must write them in canonical
* (sorted by field number) order. ExtensionWriter helps us write
@@ -400,115 +448,16 @@
*/
@Override
protected boolean parseUnknownField(
- final CodedInputStream input,
- final ExtensionRegistryLite extensionRegistry,
- final int tag) throws IOException {
- final int wireType = WireFormat.getTagWireType(tag);
- final int fieldNumber = WireFormat.getTagFieldNumber(tag);
-
- final GeneratedExtension<MessageType, ?> extension =
- extensionRegistry.findLiteExtensionByNumber(
- getDefaultInstanceForType(), fieldNumber);
-
- boolean unknown = false;
- boolean packed = false;
- if (extension == null) {
- unknown = true; // Unknown field.
- } else if (wireType == FieldSet.getWireFormatForFieldType(
- extension.descriptor.getLiteType(),
- false /* isPacked */)) {
- packed = false; // Normal, unpacked value.
- } else if (extension.descriptor.isRepeated &&
- extension.descriptor.type.isPackable() &&
- wireType == FieldSet.getWireFormatForFieldType(
- extension.descriptor.getLiteType(),
- true /* isPacked */)) {
- packed = true; // Packed value.
- } else {
- unknown = true; // Wrong wire type.
- }
-
- if (unknown) { // Unknown field or wrong wire type. Skip.
- return input.skipField(tag);
- }
-
- if (packed) {
- final int length = input.readRawVarint32();
- final int limit = input.pushLimit(length);
- if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
- while (input.getBytesUntilLimit() > 0) {
- final int rawValue = input.readEnum();
- final Object value =
- extension.descriptor.getEnumType().findValueByNumber(rawValue);
- if (value == null) {
- // If the number isn't recognized as a valid value for this
- // enum, drop it (don't even add it to unknownFields).
- return true;
- }
- ensureExtensionsIsMutable();
- extensions.addRepeatedField(extension.descriptor, value);
- }
- } else {
- while (input.getBytesUntilLimit() > 0) {
- final Object value =
- FieldSet.readPrimitiveField(input,
- extension.descriptor.getLiteType());
- ensureExtensionsIsMutable();
- extensions.addRepeatedField(extension.descriptor, value);
- }
- }
- input.popLimit(limit);
- } else {
- final Object value;
- switch (extension.descriptor.getLiteJavaType()) {
- case MESSAGE: {
- MessageLite.Builder subBuilder = null;
- if (!extension.descriptor.isRepeated()) {
- MessageLite existingValue =
- (MessageLite) extensions.getField(extension.descriptor);
- if (existingValue != null) {
- subBuilder = existingValue.toBuilder();
- }
- }
- if (subBuilder == null) {
- subBuilder = extension.messageDefaultInstance.newBuilderForType();
- }
- if (extension.descriptor.getLiteType() ==
- WireFormat.FieldType.GROUP) {
- input.readGroup(extension.getNumber(),
- subBuilder, extensionRegistry);
- } else {
- input.readMessage(subBuilder, extensionRegistry);
- }
- value = subBuilder.build();
- break;
- }
- case ENUM:
- final int rawValue = input.readEnum();
- value = extension.descriptor.getEnumType()
- .findValueByNumber(rawValue);
- // If the number isn't recognized as a valid value for this enum,
- // drop it.
- if (value == null) {
- return true;
- }
- break;
- default:
- value = FieldSet.readPrimitiveField(input,
- extension.descriptor.getLiteType());
- break;
- }
-
- if (extension.descriptor.isRepeated()) {
- ensureExtensionsIsMutable();
- extensions.addRepeatedField(extension.descriptor, value);
- } else {
- ensureExtensionsIsMutable();
- extensions.setField(extension.descriptor, value);
- }
- }
-
- return true;
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry,
+ int tag) throws IOException {
+ ensureExtensionsIsMutable();
+ return GeneratedMessageLite.parseUnknownField(
+ extensions,
+ getDefaultInstanceForType(),
+ input,
+ extensionRegistry,
+ tag);
}
protected final void mergeExtensionFields(final MessageType other) {
@@ -519,6 +468,123 @@
// -----------------------------------------------------------------
+ /**
+ * Parse an unknown field or an extension.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ private static <MessageType extends MessageLite>
+ boolean parseUnknownField(
+ FieldSet<ExtensionDescriptor> extensions,
+ MessageType defaultInstance,
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry,
+ int tag) throws IOException {
+ int wireType = WireFormat.getTagWireType(tag);
+ int fieldNumber = WireFormat.getTagFieldNumber(tag);
+
+ GeneratedExtension<MessageType, ?> extension =
+ extensionRegistry.findLiteExtensionByNumber(
+ defaultInstance, fieldNumber);
+
+ boolean unknown = false;
+ boolean packed = false;
+ if (extension == null) {
+ unknown = true; // Unknown field.
+ } else if (wireType == FieldSet.getWireFormatForFieldType(
+ extension.descriptor.getLiteType(),
+ false /* isPacked */)) {
+ packed = false; // Normal, unpacked value.
+ } else if (extension.descriptor.isRepeated &&
+ extension.descriptor.type.isPackable() &&
+ wireType == FieldSet.getWireFormatForFieldType(
+ extension.descriptor.getLiteType(),
+ true /* isPacked */)) {
+ packed = true; // Packed value.
+ } else {
+ unknown = true; // Wrong wire type.
+ }
+
+ if (unknown) { // Unknown field or wrong wire type. Skip.
+ return input.skipField(tag);
+ }
+
+ if (packed) {
+ int length = input.readRawVarint32();
+ int limit = input.pushLimit(length);
+ if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
+ while (input.getBytesUntilLimit() > 0) {
+ int rawValue = input.readEnum();
+ Object value =
+ extension.descriptor.getEnumType().findValueByNumber(rawValue);
+ if (value == null) {
+ // If the number isn't recognized as a valid value for this
+ // enum, drop it (don't even add it to unknownFields).
+ return true;
+ }
+ extensions.addRepeatedField(extension.descriptor, value);
+ }
+ } else {
+ while (input.getBytesUntilLimit() > 0) {
+ Object value =
+ FieldSet.readPrimitiveField(input,
+ extension.descriptor.getLiteType());
+ extensions.addRepeatedField(extension.descriptor, value);
+ }
+ }
+ input.popLimit(limit);
+ } else {
+ Object value;
+ switch (extension.descriptor.getLiteJavaType()) {
+ case MESSAGE: {
+ MessageLite.Builder subBuilder = null;
+ if (!extension.descriptor.isRepeated()) {
+ MessageLite existingValue =
+ (MessageLite) extensions.getField(extension.descriptor);
+ if (existingValue != null) {
+ subBuilder = existingValue.toBuilder();
+ }
+ }
+ if (subBuilder == null) {
+ subBuilder = extension.messageDefaultInstance.newBuilderForType();
+ }
+ if (extension.descriptor.getLiteType() ==
+ WireFormat.FieldType.GROUP) {
+ input.readGroup(extension.getNumber(),
+ subBuilder, extensionRegistry);
+ } else {
+ input.readMessage(subBuilder, extensionRegistry);
+ }
+ value = subBuilder.build();
+ break;
+ }
+ case ENUM:
+ int rawValue = input.readEnum();
+ value = extension.descriptor.getEnumType()
+ .findValueByNumber(rawValue);
+ // If the number isn't recognized as a valid value for this enum,
+ // drop it.
+ if (value == null) {
+ return true;
+ }
+ break;
+ default:
+ value = FieldSet.readPrimitiveField(input,
+ extension.descriptor.getLiteType());
+ break;
+ }
+
+ if (extension.descriptor.isRepeated()) {
+ extensions.addRepeatedField(extension.descriptor, value);
+ } else {
+ extensions.setField(extension.descriptor, value);
+ }
+ }
+
+ return true;
+ }
+
+ // -----------------------------------------------------------------
+
/** For use by generated code only. */
public static <ContainingType extends MessageLite, Type>
GeneratedExtension<ContainingType, Type>
@@ -722,7 +788,7 @@
/**
* Replaces this object in the output stream with a serialized form.
* Part of Java's serialization magic. Generated sub-classes must override
- * this method by calling <code>return super.writeReplace();</code>
+ * this method by calling {@code return super.writeReplace();}
* @return a SerializedForm of this message
*/
protected Object writeReplace() throws ObjectStreamException {
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/Internal.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/Internal.java
index 05eab57..81af258 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/Internal.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/Internal.java
@@ -103,85 +103,32 @@
* Helper called by generated code to determine if a byte array is a valid
* UTF-8 encoded string such that the original bytes can be converted to
* a String object and then back to a byte array round tripping the bytes
- * without loss.
- * <p>
- * This is inspired by UTF_8.java in sun.nio.cs.
+ * without loss. More precisely, returns {@code true} whenever:
+ * <pre> {@code
+ * Arrays.equals(byteString.toByteArray(),
+ * new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
+ * }</pre>
+ *
+ * <p>This method rejects "overlong" byte sequences, as well as
+ * 3-byte sequences that would map to a surrogate character, in
+ * accordance with the restricted definition of UTF-8 introduced in
+ * Unicode 3.1. Note that the UTF-8 decoder included in Oracle's
+ * JDK has been modified to also reject "overlong" byte sequences,
+ * but currently (2011) still accepts 3-byte surrogate character
+ * byte sequences.
+ *
+ * <p>See the Unicode Standard,</br>
+ * Table 3-6. <em>UTF-8 Bit Distribution</em>,</br>
+ * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
+ *
+ * <p>As of 2011-02, this method simply returns the result of {@link
+ * ByteString#isValidUtf8()}. Calling that method directly is preferred.
*
* @param byteString the string to check
* @return whether the byte array is round trippable
*/
public static boolean isValidUtf8(ByteString byteString) {
- int index = 0;
- int size = byteString.size();
- // To avoid the masking, we could change this to use bytes;
- // Then X > 0xC2 gets turned into X < -0xC2; X < 0x80
- // gets turned into X >= 0, etc.
-
- while (index < size) {
- int byte1 = byteString.byteAt(index++) & 0xFF;
- if (byte1 < 0x80) {
- // fast loop for single bytes
- continue;
-
- // we know from this point on that we have 2-4 byte forms
- } else if (byte1 < 0xC2 || byte1 > 0xF4) {
- // catch illegal first bytes: < C2 or > F4
- return false;
- }
- if (index >= size) {
- // fail if we run out of bytes
- return false;
- }
- int byte2 = byteString.byteAt(index++) & 0xFF;
- if (byte2 < 0x80 || byte2 > 0xBF) {
- // general trail-byte test
- return false;
- }
- if (byte1 <= 0xDF) {
- // two-byte form; general trail-byte test is sufficient
- continue;
- }
-
- // we know from this point on that we have 3 or 4 byte forms
- if (index >= size) {
- // fail if we run out of bytes
- return false;
- }
- int byte3 = byteString.byteAt(index++) & 0xFF;
- if (byte3 < 0x80 || byte3 > 0xBF) {
- // general trail-byte test
- return false;
- }
- if (byte1 <= 0xEF) {
- // three-byte form. Vastly more frequent than four-byte forms
- // The following has an extra test, but not worth restructuring
- if (byte1 == 0xE0 && byte2 < 0xA0 ||
- byte1 == 0xED && byte2 > 0x9F) {
- // check special cases of byte2
- return false;
- }
-
- } else {
- // four-byte form
-
- if (index >= size) {
- // fail if we run out of bytes
- return false;
- }
- int byte4 = byteString.byteAt(index++) & 0xFF;
- if (byte4 < 0x80 || byte4 > 0xBF) {
- // general trail-byte test
- return false;
- }
- // The following has an extra test, but not worth restructuring
- if (byte1 == 0xF0 && byte2 < 0x90 ||
- byte1 == 0xF4 && byte2 > 0x8F) {
- // check special cases of byte2
- return false;
- }
- }
- }
- return true;
+ return byteString.isValidUtf8();
}
/**
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
index 90f7ffb..72d7ff7 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -40,11 +40,32 @@
*/
public class InvalidProtocolBufferException extends IOException {
private static final long serialVersionUID = -1616151763072450476L;
+ private MessageLite unfinishedMessage = null;
public InvalidProtocolBufferException(final String description) {
super(description);
}
+ /**
+ * Attaches an unfinished message to the exception to support best-effort
+ * parsing in {@code Parser} interface.
+ *
+ * @return this
+ */
+ public InvalidProtocolBufferException setUnfinishedMessage(
+ MessageLite unfinishedMessage) {
+ this.unfinishedMessage = unfinishedMessage;
+ return this;
+ }
+
+ /**
+ * Returns the unfinished message attached to the exception, or null if
+ * no message is attached.
+ */
+ public MessageLite getUnfinishedMessage() {
+ return unfinishedMessage;
+ }
+
static InvalidProtocolBufferException truncatedMessage() {
return new InvalidProtocolBufferException(
"While parsing a protocol message, the input ended unexpectedly " +
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyField.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyField.java
new file mode 100644
index 0000000..df9425e
--- /dev/null
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyField.java
@@ -0,0 +1,216 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+/**
+ * LazyField encapsulates the logic of lazily parsing message fields. It stores
+ * the message in a ByteString initially and then parse it on-demand.
+ *
+ * LazyField is thread-compatible e.g. concurrent read are safe, however,
+ * synchronizations are needed under read/write situations.
+ *
+ * Now LazyField is only used to lazily load MessageSet.
+ * TODO(xiangl): Use LazyField to lazily load all messages.
+ *
+ * @author xiangl@google.com (Xiang Li)
+ */
+class LazyField {
+
+ final private MessageLite defaultInstance;
+ final private ExtensionRegistryLite extensionRegistry;
+
+ // Mutable because it is initialized lazily.
+ private ByteString bytes;
+ private volatile MessageLite value;
+ private volatile boolean isDirty = false;
+
+ public LazyField(MessageLite defaultInstance,
+ ExtensionRegistryLite extensionRegistry, ByteString bytes) {
+ this.defaultInstance = defaultInstance;
+ this.extensionRegistry = extensionRegistry;
+ this.bytes = bytes;
+ }
+
+ public MessageLite getValue() {
+ ensureInitialized();
+ return value;
+ }
+
+ /**
+ * LazyField is not thread-safe for write access. Synchronizations are needed
+ * under read/write situations.
+ */
+ public MessageLite setValue(MessageLite value) {
+ MessageLite originalValue = this.value;
+ this.value = value;
+ bytes = null;
+ isDirty = true;
+ return originalValue;
+ }
+
+ /**
+ * Due to the optional field can be duplicated at the end of serialized
+ * bytes, which will make the serialized size changed after LazyField
+ * parsed. Be careful when using this method.
+ */
+ public int getSerializedSize() {
+ if (isDirty) {
+ return value.getSerializedSize();
+ }
+ return bytes.size();
+ }
+
+ public ByteString toByteString() {
+ if (!isDirty) {
+ return bytes;
+ }
+ synchronized (this) {
+ if (!isDirty) {
+ return bytes;
+ }
+ bytes = value.toByteString();
+ isDirty = false;
+ return bytes;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ ensureInitialized();
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ ensureInitialized();
+ return value.equals(obj);
+ }
+
+ @Override
+ public String toString() {
+ ensureInitialized();
+ return value.toString();
+ }
+
+ private void ensureInitialized() {
+ if (value != null) {
+ return;
+ }
+ synchronized (this) {
+ if (value != null) {
+ return;
+ }
+ try {
+ if (bytes != null) {
+ value = defaultInstance.getParserForType()
+ .parseFrom(bytes, extensionRegistry);
+ }
+ } catch (IOException e) {
+ // TODO(xiangl): Refactory the API to support the exception thrown from
+ // lazily load messages.
+ }
+ }
+ }
+
+ // ====================================================
+
+ /**
+ * LazyEntry and LazyIterator are used to encapsulate the LazyField, when
+ * users iterate all fields from FieldSet.
+ */
+ static class LazyEntry<K> implements Entry<K, Object> {
+ private Entry<K, LazyField> entry;
+
+ private LazyEntry(Entry<K, LazyField> entry) {
+ this.entry = entry;
+ }
+
+ @Override
+ public K getKey() {
+ return entry.getKey();
+ }
+
+ @Override
+ public Object getValue() {
+ LazyField field = entry.getValue();
+ if (field == null) {
+ return null;
+ }
+ return field.getValue();
+ }
+
+ public LazyField getField() {
+ return entry.getValue();
+ }
+
+ @Override
+ public Object setValue(Object value) {
+ if (!(value instanceof MessageLite)) {
+ throw new IllegalArgumentException(
+ "LazyField now only used for MessageSet, "
+ + "and the value of MessageSet must be an instance of MessageLite");
+ }
+ return entry.getValue().setValue((MessageLite) value);
+ }
+ }
+
+ static class LazyIterator<K> implements Iterator<Entry<K, Object>> {
+ private Iterator<Entry<K, Object>> iterator;
+
+ public LazyIterator(Iterator<Entry<K, Object>> iterator) {
+ this.iterator = iterator;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Entry<K, Object> next() {
+ Entry<K, ?> entry = iterator.next();
+ if (entry.getValue() instanceof LazyField) {
+ return new LazyEntry<K>((Entry<K, LazyField>) entry);
+ }
+ return (Entry<K, Object>) entry;
+ }
+
+ @Override
+ public void remove() {
+ iterator.remove();
+ }
+ }
+}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringArrayList.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
index 1683a64..75c6a4b 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
@@ -33,8 +33,9 @@
import java.util.List;
import java.util.AbstractList;
import java.util.ArrayList;
-import java.util.RandomAccess;
import java.util.Collection;
+import java.util.Collections;
+import java.util.RandomAccess;
/**
* An implementation of {@link LazyStringList} that wraps an ArrayList. Each
@@ -72,6 +73,11 @@
list = new ArrayList<Object>();
}
+ public LazyStringArrayList(LazyStringList from) {
+ list = new ArrayList<Object>(from.size());
+ addAll(from);
+ }
+
public LazyStringArrayList(List<String> from) {
list = new ArrayList<Object>(from);
}
@@ -84,7 +90,7 @@
} else {
ByteString bs = (ByteString) o;
String s = bs.toStringUtf8();
- if (Internal.isValidUtf8(bs)) {
+ if (bs.isValidUtf8()) {
list.set(index, s);
}
return s;
@@ -109,8 +115,21 @@
}
@Override
+ public boolean addAll(Collection<? extends String> c) {
+ // The default implementation of AbstractCollection.addAll(Collection)
+ // delegates to add(Object). This implementation instead delegates to
+ // addAll(int, Collection), which makes a special case for Collections
+ // which are instances of LazyStringList.
+ return addAll(size(), c);
+ }
+
+ @Override
public boolean addAll(int index, Collection<? extends String> c) {
- boolean ret = list.addAll(index, c);
+ // When copying from another LazyStringList, directly copy the underlying
+ // elements rather than forcing each element to be decoded to a String.
+ Collection<?> collection = c instanceof LazyStringList
+ ? ((LazyStringList) c).getUnderlyingElements() : c;
+ boolean ret = list.addAll(index, collection);
modCount++;
return ret;
}
@@ -152,4 +171,9 @@
return ((ByteString) o).toStringUtf8();
}
}
+
+ @Override
+ public List<?> getUnderlyingElements() {
+ return Collections.unmodifiableList(list);
+ }
}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringList.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringList.java
index 97139ca..630932f 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringList.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/LazyStringList.java
@@ -33,7 +33,7 @@
import java.util.List;
/**
- * An interface extending List<String> that also provides access to the
+ * An interface extending {@code List<String>} that also provides access to the
* items of the list as UTF8-encoded ByteString objects. This is used by the
* protocol buffer implementation to support lazily converting bytes parsed
* over the wire to String objects until needed and also increases the
@@ -41,9 +41,9 @@
* ByteString is already cached.
* <p>
* This only adds additional methods that are required for the use in the
- * protocol buffer code in order to be able successfuly round trip byte arrays
+ * protocol buffer code in order to be able successfully round trip byte arrays
* through parsing and serialization without conversion to strings. It's not
- * attempting to support the functionality of say List<ByteString>, hence
+ * attempting to support the functionality of say {@code List<ByteString>}, hence
* why only these two very specific methods are added.
*
* @author jonp@google.com (Jon Perlow)
@@ -56,7 +56,7 @@
* @param index index of the element to return
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException if the index is out of range
- * (<tt>index < 0 || index >= size()</tt>)
+ * ({@code index < 0 || index >= size()})
*/
ByteString getByteString(int index);
@@ -69,4 +69,13 @@
* is not supported by this list
*/
void add(ByteString element);
+
+ /**
+ * Returns an unmodifiable List of the underlying elements, each of
+ * which is either a {@code String} or its equivalent UTF-8 encoded
+ * {@code ByteString}. It is an error for the caller to modify the returned
+ * List, and attempting to do so will result in an
+ * {@link UnsupportedOperationException}.
+ */
+ List<?> getUnderlyingElements();
}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/LiteralByteString.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/LiteralByteString.java
new file mode 100644
index 0000000..93c53dc
--- /dev/null
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/LiteralByteString.java
@@ -0,0 +1,349 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * This class implements a {@link com.google.protobuf.ByteString} backed by a
+ * single array of bytes, contiguous in memory. It supports substring by
+ * pointing to only a sub-range of the underlying byte array, meaning that a
+ * substring will reference the full byte-array of the string it's made from,
+ * exactly as with {@link String}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+class LiteralByteString extends ByteString {
+
+ protected final byte[] bytes;
+
+ /**
+ * Creates a {@code LiteralByteString} backed by the given array, without
+ * copying.
+ *
+ * @param bytes array to wrap
+ */
+ LiteralByteString(byte[] bytes) {
+ this.bytes = bytes;
+ }
+
+ @Override
+ public byte byteAt(int index) {
+ // Unlike most methods in this class, this one is a direct implementation
+ // ignoring the potential offset because we need to do range-checking in the
+ // substring case anyway.
+ return bytes[index];
+ }
+
+ @Override
+ public int size() {
+ return bytes.length;
+ }
+
+ // =================================================================
+ // ByteString -> substring
+
+ @Override
+ public ByteString substring(int beginIndex, int endIndex) {
+ if (beginIndex < 0) {
+ throw new IndexOutOfBoundsException(
+ "Beginning index: " + beginIndex + " < 0");
+ }
+ if (endIndex > size()) {
+ throw new IndexOutOfBoundsException("End index: " + endIndex + " > " +
+ size());
+ }
+ int substringLength = endIndex - beginIndex;
+ if (substringLength < 0) {
+ throw new IndexOutOfBoundsException(
+ "Beginning index larger than ending index: " + beginIndex + ", "
+ + endIndex);
+ }
+
+ ByteString result;
+ if (substringLength == 0) {
+ result = ByteString.EMPTY;
+ } else {
+ result = new BoundedByteString(bytes, getOffsetIntoBytes() + beginIndex,
+ substringLength);
+ }
+ return result;
+ }
+
+ // =================================================================
+ // ByteString -> byte[]
+
+ @Override
+ protected void copyToInternal(byte[] target, int sourceOffset,
+ int targetOffset, int numberToCopy) {
+ // Optimized form, not for subclasses, since we don't call
+ // getOffsetIntoBytes() or check the 'numberToCopy' parameter.
+ System.arraycopy(bytes, sourceOffset, target, targetOffset, numberToCopy);
+ }
+
+ @Override
+ public void copyTo(ByteBuffer target) {
+ target.put(bytes, getOffsetIntoBytes(), size()); // Copies bytes
+ }
+
+ @Override
+ public ByteBuffer asReadOnlyByteBuffer() {
+ ByteBuffer byteBuffer =
+ ByteBuffer.wrap(bytes, getOffsetIntoBytes(), size());
+ return byteBuffer.asReadOnlyBuffer();
+ }
+
+ @Override
+ public List<ByteBuffer> asReadOnlyByteBufferList() {
+ // Return the ByteBuffer generated by asReadOnlyByteBuffer() as a singleton
+ List<ByteBuffer> result = new ArrayList<ByteBuffer>(1);
+ result.add(asReadOnlyByteBuffer());
+ return result;
+ }
+
+ @Override
+ public void writeTo(OutputStream outputStream) throws IOException {
+ outputStream.write(toByteArray());
+ }
+
+ @Override
+ public String toString(String charsetName)
+ throws UnsupportedEncodingException {
+ return new String(bytes, getOffsetIntoBytes(), size(), charsetName);
+ }
+
+ // =================================================================
+ // UTF-8 decoding
+
+ @Override
+ public boolean isValidUtf8() {
+ int offset = getOffsetIntoBytes();
+ return Utf8.isValidUtf8(bytes, offset, offset + size());
+ }
+
+ @Override
+ protected int partialIsValidUtf8(int state, int offset, int length) {
+ int index = getOffsetIntoBytes() + offset;
+ return Utf8.partialIsValidUtf8(state, bytes, index, index + length);
+ }
+
+ // =================================================================
+ // equals() and hashCode()
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof ByteString)) {
+ return false;
+ }
+
+ if (size() != ((ByteString) other).size()) {
+ return false;
+ }
+ if (size() == 0) {
+ return true;
+ }
+
+ if (other instanceof LiteralByteString) {
+ return equalsRange((LiteralByteString) other, 0, size());
+ } else if (other instanceof RopeByteString) {
+ return other.equals(this);
+ } else {
+ throw new IllegalArgumentException(
+ "Has a new type of ByteString been created? Found "
+ + other.getClass());
+ }
+ }
+
+ /**
+ * Check equality of the substring of given length of this object starting at
+ * zero with another {@code LiteralByteString} substring starting at offset.
+ *
+ * @param other what to compare a substring in
+ * @param offset offset into other
+ * @param length number of bytes to compare
+ * @return true for equality of substrings, else false.
+ */
+ boolean equalsRange(LiteralByteString other, int offset, int length) {
+ if (length > other.size()) {
+ throw new IllegalArgumentException(
+ "Length too large: " + length + size());
+ }
+ if (offset + length > other.size()) {
+ throw new IllegalArgumentException(
+ "Ran off end of other: " + offset + ", " + length + ", " +
+ other.size());
+ }
+
+ byte[] thisBytes = bytes;
+ byte[] otherBytes = other.bytes;
+ int thisLimit = getOffsetIntoBytes() + length;
+ for (int thisIndex = getOffsetIntoBytes(), otherIndex =
+ other.getOffsetIntoBytes() + offset;
+ (thisIndex < thisLimit); ++thisIndex, ++otherIndex) {
+ if (thisBytes[thisIndex] != otherBytes[otherIndex]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Cached hash value. Intentionally accessed via a data race, which
+ * is safe because of the Java Memory Model's "no out-of-thin-air values"
+ * guarantees for ints.
+ */
+ private int hash = 0;
+
+ /**
+ * Compute the hashCode using the traditional algorithm from {@link
+ * ByteString}.
+ *
+ * @return hashCode value
+ */
+ @Override
+ public int hashCode() {
+ int h = hash;
+
+ if (h == 0) {
+ int size = size();
+ h = partialHash(size, 0, size);
+ if (h == 0) {
+ h = 1;
+ }
+ hash = h;
+ }
+ return h;
+ }
+
+ @Override
+ protected int peekCachedHashCode() {
+ return hash;
+ }
+
+ @Override
+ protected int partialHash(int h, int offset, int length) {
+ byte[] thisBytes = bytes;
+ for (int i = getOffsetIntoBytes() + offset, limit = i + length; i < limit;
+ i++) {
+ h = h * 31 + thisBytes[i];
+ }
+ return h;
+ }
+
+ // =================================================================
+ // Input stream
+
+ @Override
+ public InputStream newInput() {
+ return new ByteArrayInputStream(bytes, getOffsetIntoBytes(),
+ size()); // No copy
+ }
+
+ @Override
+ public CodedInputStream newCodedInput() {
+ // We trust CodedInputStream not to modify the bytes, or to give anyone
+ // else access to them.
+ return CodedInputStream
+ .newInstance(bytes, getOffsetIntoBytes(), size()); // No copy
+ }
+
+ // =================================================================
+ // ByteIterator
+
+ @Override
+ public ByteIterator iterator() {
+ return new LiteralByteIterator();
+ }
+
+ private class LiteralByteIterator implements ByteIterator {
+ private int position;
+ private final int limit;
+
+ private LiteralByteIterator() {
+ position = 0;
+ limit = size();
+ }
+
+ public boolean hasNext() {
+ return (position < limit);
+ }
+
+ public Byte next() {
+ // Boxing calls Byte.valueOf(byte), which does not instantiate.
+ return nextByte();
+ }
+
+ public byte nextByte() {
+ try {
+ return bytes[position++];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new NoSuchElementException(e.getMessage());
+ }
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ // =================================================================
+ // Internal methods
+
+ @Override
+ protected int getTreeDepth() {
+ return 0;
+ }
+
+ @Override
+ protected boolean isBalanced() {
+ return true;
+ }
+
+ /**
+ * Offset into {@code bytes[]} to use, non-zero for substrings.
+ *
+ * @return always 0 for this class
+ */
+ protected int getOffsetIntoBytes() {
+ return 0;
+ }
+}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/Message.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/Message.java
index 67c4148..2b88141 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/Message.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/Message.java
@@ -50,25 +50,28 @@
*/
public interface Message extends MessageLite, MessageOrBuilder {
+ // (From MessageLite, re-declared here only for return type covariance.)
+ Parser<? extends Message> getParserForType();
+
// -----------------------------------------------------------------
// Comparison and hashing
/**
* Compares the specified object with this message for equality. Returns
- * <tt>true</tt> if the given object is a message of the same type (as
+ * {@code true} if the given object is a message of the same type (as
* defined by {@code getDescriptorForType()}) and has identical values for
* all of its fields. Subclasses must implement this; inheriting
* {@code Object.equals()} is incorrect.
*
* @param other object to be compared for equality with this message
- * @return <tt>true</tt> if the specified object is equal to this message
+ * @return {@code true} if the specified object is equal to this message
*/
@Override
boolean equals(Object other);
/**
* Returns the hash code value for this message. The hash code of a message
- * should mix the message's type (object identity of the decsriptor) with its
+ * should mix the message's type (object identity of the descriptor) with its
* contents (known and unknown field values). Subclasses must implement this;
* inheriting {@code Object.hashCode()} is incorrect.
*
@@ -83,7 +86,8 @@
/**
* Converts the message to a string in protocol buffer text format. This is
- * just a trivial wrapper around {@link TextFormat#printToString(Message)}.
+ * just a trivial wrapper around {@link
+ * TextFormat#printToString(MessageOrBuilder)}.
*/
@Override
String toString();
@@ -145,6 +149,24 @@
Builder newBuilderForField(Descriptors.FieldDescriptor field);
/**
+ * Get a nested builder instance for the given field.
+ * <p>
+ * Normally, we hold a reference to the immutable message object for the
+ * message type field. Some implementations(the generated message builders),
+ * however, can also hold a reference to the builder object (a nested
+ * builder) for the field.
+ * <p>
+ * If the field is already backed up by a nested builder, the nested builder
+ * will be returned. Otherwise, a new field builder will be created and
+ * returned. The original message field (if exist) will be merged into the
+ * field builder, which will then be nested into its parent builder.
+ * <p>
+ * NOTE: implementations that do not support nested builders will throw
+ * <code>UnsupportedException</code>.
+ */
+ Builder getFieldBuilder(Descriptors.FieldDescriptor field);
+
+ /**
* Sets a field to the given value. The value must be of the correct type
* for this field, i.e. the same type that
* {@link Message#getField(Descriptors.FieldDescriptor)} would return.
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLite.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLite.java
index 31b8256..e5b9a47 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLite.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLite.java
@@ -79,6 +79,12 @@
*/
int getSerializedSize();
+
+ /**
+ * Gets the parser for a message of the same type as this message.
+ */
+ Parser<? extends MessageLite> getParserForType();
+
// -----------------------------------------------------------------
// Convenience methods.
@@ -144,11 +150,8 @@
Builder clear();
/**
- * Construct the final message. Once this is called, the Builder is no
- * longer valid, and calling any other method will result in undefined
- * behavior and may throw a NullPointerException. If you need to continue
- * working with the builder after calling {@code build()}, {@code clone()}
- * it first.
+ * Constructs the message based on the state of the Builder. Subsequent
+ * changes to the Builder will not affect the returned message.
* @throws UninitializedMessageException The message is missing one or more
* required fields (i.e. {@link #isInitialized()} returns false).
* Use {@link #buildPartial()} to bypass this check.
@@ -158,11 +161,7 @@
/**
* Like {@link #build()}, but does not throw an exception if the message
* is missing required fields. Instead, a partial message is returned.
- * Once this is called, the Builder is no longer valid, and calling any
- * will result in undefined behavior and may throw a NullPointerException.
- *
- * If you need to continue working with the builder after calling
- * {@code buildPartial()}, {@code clone()} it first.
+ * Subsequent changes to the Builder will not affect the returned message.
*/
MessageLite buildPartial();
@@ -174,7 +173,7 @@
/**
* Parses a message of this type from the input and merges it with this
- * message, as if using {@link Builder#mergeFrom(MessageLite)}.
+ * message.
*
* <p>Warning: This does not verify that all required fields are present in
* the input message. If you call {@link #build()} without setting all
@@ -184,11 +183,6 @@
* <ul>
* <li>Call {@link #isInitialized()} to verify that all required fields
* are set before building.
- * <li>Parse the message separately using one of the static
- * {@code parseFrom} methods, then use {@link #mergeFrom(MessageLite)}
- * to merge it with this one. {@code parseFrom} will throw an
- * {@link InvalidProtocolBufferException} (an {@code IOException})
- * if some required fields are missing.
* <li>Use {@code buildPartial()} to build, which ignores missing
* required fields.
* </ul>
@@ -225,7 +219,7 @@
/**
* Parse {@code data} as a message of this type and merge it with the
* message being built. This is just a small wrapper around
- * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+ * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
*
* @return this
*/
@@ -255,7 +249,7 @@
/**
* Parse {@code data} as a message of this type and merge it with the
* message being built. This is just a small wrapper around
- * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+ * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
*
* @return this
*/
@@ -266,7 +260,7 @@
/**
* Parse {@code data} as a message of this type and merge it with the
* message being built. This is just a small wrapper around
- * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+ * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
*
* @return this
*/
@@ -293,7 +287,7 @@
/**
* Parse a message of this type from {@code input} and merge it with the
* message being built. This is just a small wrapper around
- * {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
+ * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
*
* @return this
*/
@@ -308,9 +302,9 @@
* {@link MessageLite#writeDelimitedTo(OutputStream)} to write messages in
* this format.
*
- * @returns True if successful, or false if the stream is at EOF when the
- * method starts. Any other error (including reaching EOF during
- * parsing) will cause an exception to be thrown.
+ * @return True if successful, or false if the stream is at EOF when the
+ * method starts. Any other error (including reaching EOF during
+ * parsing) will cause an exception to be thrown.
*/
boolean mergeDelimitedFrom(InputStream input)
throws IOException;
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java
index 7cc72e9..05b2b16 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java
@@ -52,6 +52,8 @@
/**
* Returns true if all required fields in the message and all embedded
* messages are set, false otherwise.
+ *
+ * <p>See also: {@link MessageOrBuilder#getInitializationErrorString()}
*/
boolean isInitialized();
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageOrBuilder.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageOrBuilder.java
index 0132e7c..bf62d45 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageOrBuilder.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/MessageOrBuilder.java
@@ -30,6 +30,7 @@
package com.google.protobuf;
+import java.util.List;
import java.util.Map;
/**
@@ -45,6 +46,24 @@
Message getDefaultInstanceForType();
/**
+ * Returns a list of field paths (e.g. "foo.bar.baz") of required fields
+ * which are not set in this message. You should call
+ * {@link MessageLiteOrBuilder#isInitialized()} first to check if there
+ * are any missing fields, as that method is likely to be much faster
+ * than this one even when the message is fully-initialized.
+ */
+ List<String> findInitializationErrors();
+
+ /**
+ * Returns a comma-delimited list of required fields which are not set
+ * in this message object. You should call
+ * {@link MessageLiteOrBuilder#isInitialized()} first to check if there
+ * are any missing fields, as that method is likely to be much faster
+ * than this one even when the message is fully-initialized.
+ */
+ String getInitializationErrorString();
+
+ /**
* Get the message's type's descriptor. This differs from the
* {@code getDescriptor()} method of generated message classes in that
* this method is an abstract method of the {@code Message} interface
@@ -80,7 +99,7 @@
/**
* Obtains the value of the given field, or the default value if it is
* not set. For primitive fields, the boxed primitive value is returned.
- * For enum fields, the EnumValueDescriptor for the value is returend. For
+ * For enum fields, the EnumValueDescriptor for the value is returned. For
* embedded message fields, the sub-message is returned. For repeated
* fields, a java.util.List is returned.
*/
@@ -98,7 +117,7 @@
/**
* Gets an element of a repeated field. For primitive fields, the boxed
* primitive value is returned. For enum fields, the EnumValueDescriptor
- * for the value is returend. For embedded message fields, the sub-message
+ * for the value is returned. For embedded message fields, the sub-message
* is returned.
* @throws IllegalArgumentException The field is not a repeated field, or
* {@code field.getContainingType() != getDescriptorForType()}.
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/Parser.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/Parser.java
new file mode 100644
index 0000000..7d8e821
--- /dev/null
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/Parser.java
@@ -0,0 +1,259 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.io.InputStream;
+
+/**
+ * Abstract interface for parsing Protocol Messages.
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+public interface Parser<MessageType> {
+ /**
+ * Parses a message of {@code MessageType} from the input.
+ *
+ * <p>Note: The caller should call
+ * {@link CodedInputStream#checkLastTagWas(int)} after calling this to
+ * verify that the last tag seen was the appropriate end-group tag,
+ * or zero for EOF.
+ */
+ public MessageType parseFrom(CodedInputStream input)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(CodedInputStream)}, but also parses extensions.
+ * The extensions that you want to be able to parse must be registered in
+ * {@code extensionRegistry}. Extensions not in the registry will be treated
+ * as unknown fields.
+ */
+ public MessageType parseFrom(CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(CodedInputStream)}, but does not throw an
+ * exception if the message is missing required fields. Instead, a partial
+ * message is returned.
+ */
+ public MessageType parsePartialFrom(CodedInputStream input)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(CodedInputStream input, ExtensionRegistryLite)},
+ * but does not throw an exception if the message is missing required fields.
+ * Instead, a partial message is returned.
+ */
+ public MessageType parsePartialFrom(CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ // ---------------------------------------------------------------
+ // Convenience methods.
+
+ /**
+ * Parses {@code data} as a message of {@code MessageType}.
+ * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+ */
+ public MessageType parseFrom(ByteString data)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parses {@code data} as a message of {@code MessageType}.
+ * This is just a small wrapper around
+ * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+ */
+ public MessageType parseFrom(ByteString data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(ByteString)}, but does not throw an
+ * exception if the message is missing required fields. Instead, a partial
+ * message is returned.
+ */
+ public MessageType parsePartialFrom(ByteString data)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(ByteString, ExtensionRegistryLite)},
+ * but does not throw an exception if the message is missing required fields.
+ * Instead, a partial message is returned.
+ */
+ public MessageType parsePartialFrom(ByteString data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parses {@code data} as a message of {@code MessageType}.
+ * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+ */
+ public MessageType parseFrom(byte[] data, int off, int len)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parses {@code data} as a message of {@code MessageType}.
+ * This is just a small wrapper around
+ * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+ */
+ public MessageType parseFrom(byte[] data, int off, int len,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parses {@code data} as a message of {@code MessageType}.
+ * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+ */
+ public MessageType parseFrom(byte[] data)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parses {@code data} as a message of {@code MessageType}.
+ * This is just a small wrapper around
+ * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+ */
+ public MessageType parseFrom(byte[] data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(byte[], int, int)}, but does not throw an
+ * exception if the message is missing required fields. Instead, a partial
+ * message is returned.
+ */
+ public MessageType parsePartialFrom(byte[] data, int off, int len)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(ByteString, ExtensionRegistryLite)},
+ * but does not throw an exception if the message is missing required fields.
+ * Instead, a partial message is returned.
+ */
+ public MessageType parsePartialFrom(byte[] data, int off, int len,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(byte[])}, but does not throw an
+ * exception if the message is missing required fields. Instead, a partial
+ * message is returned.
+ */
+ public MessageType parsePartialFrom(byte[] data)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(byte[], ExtensionRegistryLite)},
+ * but does not throw an exception if the message is missing required fields.
+ * Instead, a partial message is returned.
+ */
+ public MessageType parsePartialFrom(byte[] data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parse a message of {@code MessageType} from {@code input}.
+ * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+ * Note that this method always reads the <i>entire</i> input (unless it
+ * throws an exception). If you want it to stop earlier, you will need to
+ * wrap your input in some wrapper stream that limits reading. Or, use
+ * {@link MessageLite#writeDelimitedTo(java.io.OutputStream)} to write your
+ * message and {@link #parseDelimitedFrom(InputStream)} to read it.
+ * <p>
+ * Despite usually reading the entire input, this does not close the stream.
+ */
+ public MessageType parseFrom(InputStream input)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parses a message of {@code MessageType} from {@code input}.
+ * This is just a small wrapper around
+ * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+ */
+ public MessageType parseFrom(InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(InputStream)}, but does not throw an
+ * exception if the message is missing required fields. Instead, a partial
+ * message is returned.
+ */
+ public MessageType parsePartialFrom(InputStream input)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(InputStream, ExtensionRegistryLite)},
+ * but does not throw an exception if the message is missing required fields.
+ * Instead, a partial message is returned.
+ */
+ public MessageType parsePartialFrom(InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(InputStream)}, but does not read util EOF.
+ * Instead, the size of message (encoded as a varint) is read first,
+ * then the message data. Use
+ * {@link MessageLite#writeDelimitedTo(java.io.OutputStream)} to write
+ * messages in this format.
+ *
+ * @return True if successful, or false if the stream is at EOF when the
+ * method starts. Any other error (including reaching EOF during
+ * parsing) will cause an exception to be thrown.
+ */
+ public MessageType parseDelimitedFrom(InputStream input)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseDelimitedFrom(InputStream)} but supporting extensions.
+ */
+ public MessageType parseDelimitedFrom(InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseDelimitedFrom(InputStream)}, but does not throw an
+ * exception if the message is missing required fields. Instead, a partial
+ * message is returned.
+ */
+ public MessageType parsePartialDelimitedFrom(InputStream input)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseDelimitedFrom(InputStream, ExtensionRegistryLite)},
+ * but does not throw an exception if the message is missing required fields.
+ * Instead, a partial message is returned.
+ */
+ public MessageType parsePartialDelimitedFrom(
+ InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
index 0024f79..65d9270 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
@@ -37,22 +37,22 @@
import java.util.List;
/**
- * <code>RepeatedFieldBuilder</code> implements a structure that a protocol
+ * {@code RepeatedFieldBuilder} implements a structure that a protocol
* message uses to hold a repeated field of other protocol messages. It supports
* the classical use case of adding immutable {@link Message}'s to the
* repeated field and is highly optimized around this (no extra memory
* allocations and sharing of immutable arrays).
* <br>
* It also supports the additional use case of adding a {@link Message.Builder}
- * to the repeated field and deferring conversion of that <code>Builder</code>
- * to an immutable <code>Message</code>. In this way, it's possible to maintain
- * a tree of <code>Builder</code>'s that acts as a fully read/write data
+ * to the repeated field and deferring conversion of that {@code Builder}
+ * to an immutable {@code Message}. In this way, it's possible to maintain
+ * a tree of {@code Builder}'s that acts as a fully read/write data
* structure.
* <br>
* Logically, one can think of a tree of builders as converting the entire tree
* to messages when build is called on the root or when any method is called
* that desires a Message instead of a Builder. In terms of the implementation,
- * the <code>SingleFieldBuilder</code> and <code>RepeatedFieldBuilder</code>
+ * the {@code SingleFieldBuilder} and {@code RepeatedFieldBuilder}
* classes cache messages that were created so that messages only need to be
* created when some change occured in its builder or a builder for one of its
* descendants.
@@ -192,7 +192,7 @@
/**
* Get the message at the specified index. If the message is currently stored
- * as a <code>Builder</code>, it is converted to a <code>Message</code> by
+ * as a {@code Builder}, it is converted to a {@code Message} by
* calling {@link Message.Builder#buildPartial} on it.
*
* @param index the index of the message to get
@@ -204,7 +204,7 @@
/**
* Get the message at the specified index. If the message is currently stored
- * as a <code>Builder</code>, it is converted to a <code>Message</code> by
+ * as a {@code Builder}, it is converted to a {@code Message} by
* calling {@link Message.Builder#buildPartial} on it.
*
* @param index the index of the message to get
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/RopeByteString.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/RopeByteString.java
new file mode 100644
index 0000000..8d44d11
--- /dev/null
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/RopeByteString.java
@@ -0,0 +1,945 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.io.ByteArrayInputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Class to represent {@code ByteStrings} formed by concatenation of other
+ * ByteStrings, without copying the data in the pieces. The concatenation is
+ * represented as a tree whose leaf nodes are each a {@link LiteralByteString}.
+ *
+ * <p>Most of the operation here is inspired by the now-famous paper <a
+ * href="http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol25/issue12/spe986.pdf">
+ * BAP95 </a> Ropes: an Alternative to Strings hans-j. boehm, russ atkinson and
+ * michael plass
+ *
+ * <p>The algorithms described in the paper have been implemented for character
+ * strings in {@link com.google.common.string.Rope} and in the c++ class {@code
+ * cord.cc}.
+ *
+ * <p>Fundamentally the Rope algorithm represents the collection of pieces as a
+ * binary tree. BAP95 uses a Fibonacci bound relating depth to a minimum
+ * sequence length, sequences that are too short relative to their depth cause a
+ * tree rebalance. More precisely, a tree of depth d is "balanced" in the
+ * terminology of BAP95 if its length is at least F(d+2), where F(n) is the
+ * n-the Fibonacci number. Thus for depths 0, 1, 2, 3, 4, 5,... we have minimum
+ * lengths 1, 2, 3, 5, 8, 13,...
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+class RopeByteString extends ByteString {
+
+ /**
+ * BAP95. Let Fn be the nth Fibonacci number. A {@link RopeByteString} of
+ * depth n is "balanced", i.e flat enough, if its length is at least Fn+2,
+ * e.g. a "balanced" {@link RopeByteString} of depth 1 must have length at
+ * least 2, of depth 4 must have length >= 8, etc.
+ *
+ * <p>There's nothing special about using the Fibonacci numbers for this, but
+ * they are a reasonable sequence for encapsulating the idea that we are OK
+ * with longer strings being encoded in deeper binary trees.
+ *
+ * <p>For 32-bit integers, this array has length 46.
+ */
+ private static final int[] minLengthByDepth;
+
+ static {
+ // Dynamically generate the list of Fibonacci numbers the first time this
+ // class is accessed.
+ List<Integer> numbers = new ArrayList<Integer>();
+
+ // we skip the first Fibonacci number (1). So instead of: 1 1 2 3 5 8 ...
+ // we have: 1 2 3 5 8 ...
+ int f1 = 1;
+ int f2 = 1;
+
+ // get all the values until we roll over.
+ while (f2 > 0) {
+ numbers.add(f2);
+ int temp = f1 + f2;
+ f1 = f2;
+ f2 = temp;
+ }
+
+ // we include this here so that we can index this array to [x + 1] in the
+ // loops below.
+ numbers.add(Integer.MAX_VALUE);
+ minLengthByDepth = new int[numbers.size()];
+ for (int i = 0; i < minLengthByDepth.length; i++) {
+ // unbox all the values
+ minLengthByDepth[i] = numbers.get(i);
+ }
+ }
+
+ private final int totalLength;
+ private final ByteString left;
+ private final ByteString right;
+ private final int leftLength;
+ private final int treeDepth;
+
+ /**
+ * Create a new RopeByteString, which can be thought of as a new tree node, by
+ * recording references to the two given strings.
+ *
+ * @param left string on the left of this node, should have {@code size() >
+ * 0}
+ * @param right string on the right of this node, should have {@code size() >
+ * 0}
+ */
+ private RopeByteString(ByteString left, ByteString right) {
+ this.left = left;
+ this.right = right;
+ leftLength = left.size();
+ totalLength = leftLength + right.size();
+ treeDepth = Math.max(left.getTreeDepth(), right.getTreeDepth()) + 1;
+ }
+
+ /**
+ * Concatenate the given strings while performing various optimizations to
+ * slow the growth rate of tree depth and tree node count. The result is
+ * either a {@link LiteralByteString} or a {@link RopeByteString}
+ * depending on which optimizations, if any, were applied.
+ *
+ * <p>Small pieces of length less than {@link
+ * ByteString#CONCATENATE_BY_COPY_SIZE} may be copied by value here, as in
+ * BAP95. Large pieces are referenced without copy.
+ *
+ * @param left string on the left
+ * @param right string on the right
+ * @return concatenation representing the same sequence as the given strings
+ */
+ static ByteString concatenate(ByteString left, ByteString right) {
+ ByteString result;
+ RopeByteString leftRope =
+ (left instanceof RopeByteString) ? (RopeByteString) left : null;
+ if (right.size() == 0) {
+ result = left;
+ } else if (left.size() == 0) {
+ result = right;
+ } else {
+ int newLength = left.size() + right.size();
+ if (newLength < ByteString.CONCATENATE_BY_COPY_SIZE) {
+ // Optimization from BAP95: For short (leaves in paper, but just short
+ // here) total length, do a copy of data to a new leaf.
+ result = concatenateBytes(left, right);
+ } else if (leftRope != null
+ && leftRope.right.size() + right.size() < CONCATENATE_BY_COPY_SIZE) {
+ // Optimization from BAP95: As an optimization of the case where the
+ // ByteString is constructed by repeated concatenate, recognize the case
+ // where a short string is concatenated to a left-hand node whose
+ // right-hand branch is short. In the paper this applies to leaves, but
+ // we just look at the length here. This has the advantage of shedding
+ // references to unneeded data when substrings have been taken.
+ //
+ // When we recognize this case, we do a copy of the data and create a
+ // new parent node so that the depth of the result is the same as the
+ // given left tree.
+ ByteString newRight = concatenateBytes(leftRope.right, right);
+ result = new RopeByteString(leftRope.left, newRight);
+ } else if (leftRope != null
+ && leftRope.left.getTreeDepth() > leftRope.right.getTreeDepth()
+ && leftRope.getTreeDepth() > right.getTreeDepth()) {
+ // Typically for concatenate-built strings the left-side is deeper than
+ // the right. This is our final attempt to concatenate without
+ // increasing the tree depth. We'll redo the the node on the RHS. This
+ // is yet another optimization for building the string by repeatedly
+ // concatenating on the right.
+ ByteString newRight = new RopeByteString(leftRope.right, right);
+ result = new RopeByteString(leftRope.left, newRight);
+ } else {
+ // Fine, we'll add a node and increase the tree depth--unless we
+ // rebalance ;^)
+ int newDepth = Math.max(left.getTreeDepth(), right.getTreeDepth()) + 1;
+ if (newLength >= minLengthByDepth[newDepth]) {
+ // The tree is shallow enough, so don't rebalance
+ result = new RopeByteString(left, right);
+ } else {
+ result = new Balancer().balance(left, right);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Concatenates two strings by copying data values. This is called in a few
+ * cases in order to reduce the growth of the number of tree nodes.
+ *
+ * @param left string on the left
+ * @param right string on the right
+ * @return string formed by copying data bytes
+ */
+ private static LiteralByteString concatenateBytes(ByteString left,
+ ByteString right) {
+ int leftSize = left.size();
+ int rightSize = right.size();
+ byte[] bytes = new byte[leftSize + rightSize];
+ left.copyTo(bytes, 0, 0, leftSize);
+ right.copyTo(bytes, 0, leftSize, rightSize);
+ return new LiteralByteString(bytes); // Constructor wraps bytes
+ }
+
+ /**
+ * Create a new RopeByteString for testing only while bypassing all the
+ * defenses of {@link #concatenate(ByteString, ByteString)}. This allows
+ * testing trees of specific structure. We are also able to insert empty
+ * leaves, though these are dis-allowed, so that we can make sure the
+ * implementation can withstand their presence.
+ *
+ * @param left string on the left of this node
+ * @param right string on the right of this node
+ * @return an unsafe instance for testing only
+ */
+ static RopeByteString newInstanceForTest(ByteString left, ByteString right) {
+ return new RopeByteString(left, right);
+ }
+
+ /**
+ * Gets the byte at the given index.
+ * Throws {@link ArrayIndexOutOfBoundsException} for backwards-compatibility
+ * reasons although it would more properly be {@link
+ * IndexOutOfBoundsException}.
+ *
+ * @param index index of byte
+ * @return the value
+ * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
+ */
+ @Override
+ public byte byteAt(int index) {
+ if (index < 0) {
+ throw new ArrayIndexOutOfBoundsException("Index < 0: " + index);
+ }
+ if (index > totalLength) {
+ throw new ArrayIndexOutOfBoundsException(
+ "Index > length: " + index + ", " + totalLength);
+ }
+
+ byte result;
+ // Find the relevant piece by recursive descent
+ if (index < leftLength) {
+ result = left.byteAt(index);
+ } else {
+ result = right.byteAt(index - leftLength);
+ }
+ return result;
+ }
+
+ @Override
+ public int size() {
+ return totalLength;
+ }
+
+ // =================================================================
+ // Pieces
+
+ @Override
+ protected int getTreeDepth() {
+ return treeDepth;
+ }
+
+ /**
+ * Determines if the tree is balanced according to BAP95, which means the tree
+ * is flat-enough with respect to the bounds. Note that this definition of
+ * balanced is one where sub-trees of balanced trees are not necessarily
+ * balanced.
+ *
+ * @return true if the tree is balanced
+ */
+ @Override
+ protected boolean isBalanced() {
+ return totalLength >= minLengthByDepth[treeDepth];
+ }
+
+ /**
+ * Takes a substring of this one. This involves recursive descent along the
+ * left and right edges of the substring, and referencing any wholly contained
+ * segments in between. Any leaf nodes entirely uninvolved in the substring
+ * will not be referenced by the substring.
+ *
+ * <p>Substrings of {@code length < 2} should result in at most a single
+ * recursive call chain, terminating at a leaf node. Thus the result will be a
+ * {@link LiteralByteString}. {@link #RopeByteString(ByteString,
+ * ByteString)}.
+ *
+ * @param beginIndex start at this index
+ * @param endIndex the last character is the one before this index
+ * @return substring leaf node or tree
+ */
+ @Override
+ public ByteString substring(int beginIndex, int endIndex) {
+ if (beginIndex < 0) {
+ throw new IndexOutOfBoundsException(
+ "Beginning index: " + beginIndex + " < 0");
+ }
+ if (endIndex > totalLength) {
+ throw new IndexOutOfBoundsException(
+ "End index: " + endIndex + " > " + totalLength);
+ }
+ int substringLength = endIndex - beginIndex;
+ if (substringLength < 0) {
+ throw new IndexOutOfBoundsException(
+ "Beginning index larger than ending index: " + beginIndex + ", "
+ + endIndex);
+ }
+
+ ByteString result;
+ if (substringLength == 0) {
+ // Empty substring
+ result = ByteString.EMPTY;
+ } else if (substringLength == totalLength) {
+ // The whole string
+ result = this;
+ } else {
+ // Proper substring
+ if (endIndex <= leftLength) {
+ // Substring on the left
+ result = left.substring(beginIndex, endIndex);
+ } else if (beginIndex >= leftLength) {
+ // Substring on the right
+ result = right
+ .substring(beginIndex - leftLength, endIndex - leftLength);
+ } else {
+ // Split substring
+ ByteString leftSub = left.substring(beginIndex);
+ ByteString rightSub = right.substring(0, endIndex - leftLength);
+ // Intentionally not rebalancing, since in many cases these two
+ // substrings will already be less deep than the top-level
+ // RopeByteString we're taking a substring of.
+ result = new RopeByteString(leftSub, rightSub);
+ }
+ }
+ return result;
+ }
+
+ // =================================================================
+ // ByteString -> byte[]
+
+ @Override
+ protected void copyToInternal(byte[] target, int sourceOffset,
+ int targetOffset, int numberToCopy) {
+ if (sourceOffset + numberToCopy <= leftLength) {
+ left.copyToInternal(target, sourceOffset, targetOffset, numberToCopy);
+ } else if (sourceOffset >= leftLength) {
+ right.copyToInternal(target, sourceOffset - leftLength, targetOffset,
+ numberToCopy);
+ } else {
+ int leftLength = this.leftLength - sourceOffset;
+ left.copyToInternal(target, sourceOffset, targetOffset, leftLength);
+ right.copyToInternal(target, 0, targetOffset + leftLength,
+ numberToCopy - leftLength);
+ }
+ }
+
+ @Override
+ public void copyTo(ByteBuffer target) {
+ left.copyTo(target);
+ right.copyTo(target);
+ }
+
+ @Override
+ public ByteBuffer asReadOnlyByteBuffer() {
+ ByteBuffer byteBuffer = ByteBuffer.wrap(toByteArray());
+ return byteBuffer.asReadOnlyBuffer();
+ }
+
+ @Override
+ public List<ByteBuffer> asReadOnlyByteBufferList() {
+ // Walk through the list of LiteralByteString's that make up this
+ // rope, and add each one as a read-only ByteBuffer.
+ List<ByteBuffer> result = new ArrayList<ByteBuffer>();
+ PieceIterator pieces = new PieceIterator(this);
+ while (pieces.hasNext()) {
+ LiteralByteString byteString = pieces.next();
+ result.add(byteString.asReadOnlyByteBuffer());
+ }
+ return result;
+ }
+
+ @Override
+ public void writeTo(OutputStream outputStream) throws IOException {
+ left.writeTo(outputStream);
+ right.writeTo(outputStream);
+ }
+
+ @Override
+ public String toString(String charsetName)
+ throws UnsupportedEncodingException {
+ return new String(toByteArray(), charsetName);
+ }
+
+ // =================================================================
+ // UTF-8 decoding
+
+ @Override
+ public boolean isValidUtf8() {
+ int leftPartial = left.partialIsValidUtf8(Utf8.COMPLETE, 0, leftLength);
+ int state = right.partialIsValidUtf8(leftPartial, 0, right.size());
+ return state == Utf8.COMPLETE;
+ }
+
+ @Override
+ protected int partialIsValidUtf8(int state, int offset, int length) {
+ int toIndex = offset + length;
+ if (toIndex <= leftLength) {
+ return left.partialIsValidUtf8(state, offset, length);
+ } else if (offset >= leftLength) {
+ return right.partialIsValidUtf8(state, offset - leftLength, length);
+ } else {
+ int leftLength = this.leftLength - offset;
+ int leftPartial = left.partialIsValidUtf8(state, offset, leftLength);
+ return right.partialIsValidUtf8(leftPartial, 0, length - leftLength);
+ }
+ }
+
+ // =================================================================
+ // equals() and hashCode()
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof ByteString)) {
+ return false;
+ }
+
+ ByteString otherByteString = (ByteString) other;
+ if (totalLength != otherByteString.size()) {
+ return false;
+ }
+ if (totalLength == 0) {
+ return true;
+ }
+
+ // You don't really want to be calling equals on long strings, but since
+ // we cache the hashCode, we effectively cache inequality. We use the cached
+ // hashCode if it's already computed. It's arguable we should compute the
+ // hashCode here, and if we're going to be testing a bunch of byteStrings,
+ // it might even make sense.
+ if (hash != 0) {
+ int cachedOtherHash = otherByteString.peekCachedHashCode();
+ if (cachedOtherHash != 0 && hash != cachedOtherHash) {
+ return false;
+ }
+ }
+
+ return equalsFragments(otherByteString);
+ }
+
+ /**
+ * Determines if this string is equal to another of the same length by
+ * iterating over the leaf nodes. On each step of the iteration, the
+ * overlapping segments of the leaves are compared.
+ *
+ * @param other string of the same length as this one
+ * @return true if the values of this string equals the value of the given
+ * one
+ */
+ private boolean equalsFragments(ByteString other) {
+ int thisOffset = 0;
+ Iterator<LiteralByteString> thisIter = new PieceIterator(this);
+ LiteralByteString thisString = thisIter.next();
+
+ int thatOffset = 0;
+ Iterator<LiteralByteString> thatIter = new PieceIterator(other);
+ LiteralByteString thatString = thatIter.next();
+
+ int pos = 0;
+ while (true) {
+ int thisRemaining = thisString.size() - thisOffset;
+ int thatRemaining = thatString.size() - thatOffset;
+ int bytesToCompare = Math.min(thisRemaining, thatRemaining);
+
+ // At least one of the offsets will be zero
+ boolean stillEqual = (thisOffset == 0)
+ ? thisString.equalsRange(thatString, thatOffset, bytesToCompare)
+ : thatString.equalsRange(thisString, thisOffset, bytesToCompare);
+ if (!stillEqual) {
+ return false;
+ }
+
+ pos += bytesToCompare;
+ if (pos >= totalLength) {
+ if (pos == totalLength) {
+ return true;
+ }
+ throw new IllegalStateException();
+ }
+ // We always get to the end of at least one of the pieces
+ if (bytesToCompare == thisRemaining) { // If reached end of this
+ thisOffset = 0;
+ thisString = thisIter.next();
+ } else {
+ thisOffset += bytesToCompare;
+ }
+ if (bytesToCompare == thatRemaining) { // If reached end of that
+ thatOffset = 0;
+ thatString = thatIter.next();
+ } else {
+ thatOffset += bytesToCompare;
+ }
+ }
+ }
+
+ /**
+ * Cached hash value. Intentionally accessed via a data race, which is safe
+ * because of the Java Memory Model's "no out-of-thin-air values" guarantees
+ * for ints.
+ */
+ private int hash = 0;
+
+ @Override
+ public int hashCode() {
+ int h = hash;
+
+ if (h == 0) {
+ h = totalLength;
+ h = partialHash(h, 0, totalLength);
+ if (h == 0) {
+ h = 1;
+ }
+ hash = h;
+ }
+ return h;
+ }
+
+ @Override
+ protected int peekCachedHashCode() {
+ return hash;
+ }
+
+ @Override
+ protected int partialHash(int h, int offset, int length) {
+ int toIndex = offset + length;
+ if (toIndex <= leftLength) {
+ return left.partialHash(h, offset, length);
+ } else if (offset >= leftLength) {
+ return right.partialHash(h, offset - leftLength, length);
+ } else {
+ int leftLength = this.leftLength - offset;
+ int leftPartial = left.partialHash(h, offset, leftLength);
+ return right.partialHash(leftPartial, 0, length - leftLength);
+ }
+ }
+
+ // =================================================================
+ // Input stream
+
+ @Override
+ public CodedInputStream newCodedInput() {
+ return CodedInputStream.newInstance(new RopeInputStream());
+ }
+
+ @Override
+ public InputStream newInput() {
+ return new RopeInputStream();
+ }
+
+ /**
+ * This class implements the balancing algorithm of BAP95. In the paper the
+ * authors use an array to keep track of pieces, while here we use a stack.
+ * The tree is balanced by traversing subtrees in left to right order, and the
+ * stack always contains the part of the string we've traversed so far.
+ *
+ * <p>One surprising aspect of the algorithm is the result of balancing is not
+ * necessarily balanced, though it is nearly balanced. For details, see
+ * BAP95.
+ */
+ private static class Balancer {
+ // Stack containing the part of the string, starting from the left, that
+ // we've already traversed. The final string should be the equivalent of
+ // concatenating the strings on the stack from bottom to top.
+ private final Deque<ByteString> prefixesStack =
+ new ArrayDeque<ByteString>(minLengthByDepth.length);
+
+ private ByteString balance(ByteString left, ByteString right) {
+ doBalance(left);
+ doBalance(right);
+
+ // Sweep stack to gather the result
+ ByteString partialString = prefixesStack.pop();
+ while (!prefixesStack.isEmpty()) {
+ ByteString newLeft = prefixesStack.pop();
+ partialString = new RopeByteString(newLeft, partialString);
+ }
+ // We should end up with a RopeByteString since at a minimum we will
+ // create one from concatenating left and right
+ return partialString;
+ }
+
+ private void doBalance(ByteString root) {
+ // BAP95: Insert balanced subtrees whole. This means the result might not
+ // be balanced, leading to repeated rebalancings on concatenate. However,
+ // these rebalancings are shallow due to ignoring balanced subtrees, and
+ // relatively few calls to insert() result.
+ if (root.isBalanced()) {
+ insert(root);
+ } else if (root instanceof RopeByteString) {
+ RopeByteString rbs = (RopeByteString) root;
+ doBalance(rbs.left);
+ doBalance(rbs.right);
+ } else {
+ throw new IllegalArgumentException(
+ "Has a new type of ByteString been created? Found " +
+ root.getClass());
+ }
+ }
+
+ /**
+ * Push a string on the balance stack (BAP95). BAP95 uses an array and
+ * calls the elements in the array 'bins'. We instead use a stack, so the
+ * 'bins' of lengths are represented by differences between the elements of
+ * minLengthByDepth.
+ *
+ * <p>If the length bin for our string, and all shorter length bins, are
+ * empty, we just push it on the stack. Otherwise, we need to start
+ * concatenating, putting the given string in the "middle" and continuing
+ * until we land in an empty length bin that matches the length of our
+ * concatenation.
+ *
+ * @param byteString string to place on the balance stack
+ */
+ private void insert(ByteString byteString) {
+ int depthBin = getDepthBinForLength(byteString.size());
+ int binEnd = minLengthByDepth[depthBin + 1];
+
+ // BAP95: Concatenate all trees occupying bins representing the length of
+ // our new piece or of shorter pieces, to the extent that is possible.
+ // The goal is to clear the bin which our piece belongs in, but that may
+ // not be entirely possible if there aren't enough longer bins occupied.
+ if (prefixesStack.isEmpty() || prefixesStack.peek().size() >= binEnd) {
+ prefixesStack.push(byteString);
+ } else {
+ int binStart = minLengthByDepth[depthBin];
+
+ // Concatenate the subtrees of shorter length
+ ByteString newTree = prefixesStack.pop();
+ while (!prefixesStack.isEmpty()
+ && prefixesStack.peek().size() < binStart) {
+ ByteString left = prefixesStack.pop();
+ newTree = new RopeByteString(left, newTree);
+ }
+
+ // Concatenate the given string
+ newTree = new RopeByteString(newTree, byteString);
+
+ // Continue concatenating until we land in an empty bin
+ while (!prefixesStack.isEmpty()) {
+ depthBin = getDepthBinForLength(newTree.size());
+ binEnd = minLengthByDepth[depthBin + 1];
+ if (prefixesStack.peek().size() < binEnd) {
+ ByteString left = prefixesStack.pop();
+ newTree = new RopeByteString(left, newTree);
+ } else {
+ break;
+ }
+ }
+ prefixesStack.push(newTree);
+ }
+ }
+
+ private int getDepthBinForLength(int length) {
+ int depth = Arrays.binarySearch(minLengthByDepth, length);
+ if (depth < 0) {
+ // It wasn't an exact match, so convert to the index of the containing
+ // fragment, which is one less even than the insertion point.
+ int insertionPoint = -(depth + 1);
+ depth = insertionPoint - 1;
+ }
+
+ return depth;
+ }
+ }
+
+ /**
+ * This class is a continuable tree traversal, which keeps the state
+ * information which would exist on the stack in a recursive traversal instead
+ * on a stack of "Bread Crumbs". The maximum depth of the stack in this
+ * iterator is the same as the depth of the tree being traversed.
+ *
+ * <p>This iterator is used to implement
+ * {@link RopeByteString#equalsFragments(ByteString)}.
+ */
+ private static class PieceIterator implements Iterator<LiteralByteString> {
+
+ private final Deque<RopeByteString> breadCrumbs =
+ new ArrayDeque<RopeByteString>(minLengthByDepth.length);
+ private LiteralByteString next;
+
+ private PieceIterator(ByteString root) {
+ next = getLeafByLeft(root);
+ }
+
+ private LiteralByteString getLeafByLeft(ByteString root) {
+ ByteString pos = root;
+ while (pos instanceof RopeByteString) {
+ RopeByteString rbs = (RopeByteString) pos;
+ breadCrumbs.push(rbs);
+ pos = rbs.left;
+ }
+ return (LiteralByteString) pos;
+ }
+
+ private LiteralByteString getNextNonEmptyLeaf() {
+ while (true) {
+ // Almost always, we go through this loop exactly once. However, if
+ // we discover an empty string in the rope, we toss it and try again.
+ if (breadCrumbs.isEmpty()) {
+ return null;
+ } else {
+ LiteralByteString result = getLeafByLeft(breadCrumbs.pop().right);
+ if (!result.isEmpty()) {
+ return result;
+ }
+ }
+ }
+ }
+
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ /**
+ * Returns the next item and advances one {@code LiteralByteString}.
+ *
+ * @return next non-empty LiteralByteString or {@code null}
+ */
+ public LiteralByteString next() {
+ if (next == null) {
+ throw new NoSuchElementException();
+ }
+ LiteralByteString result = next;
+ next = getNextNonEmptyLeaf();
+ return result;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ // =================================================================
+ // ByteIterator
+
+ @Override
+ public ByteIterator iterator() {
+ return new RopeByteIterator();
+ }
+
+ private class RopeByteIterator implements ByteString.ByteIterator {
+
+ private final PieceIterator pieces;
+ private ByteIterator bytes;
+ int bytesRemaining;
+
+ private RopeByteIterator() {
+ pieces = new PieceIterator(RopeByteString.this);
+ bytes = pieces.next().iterator();
+ bytesRemaining = size();
+ }
+
+ public boolean hasNext() {
+ return (bytesRemaining > 0);
+ }
+
+ public Byte next() {
+ return nextByte(); // Does not instantiate a Byte
+ }
+
+ public byte nextByte() {
+ if (!bytes.hasNext()) {
+ bytes = pieces.next().iterator();
+ }
+ --bytesRemaining;
+ return bytes.nextByte();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * This class is the {@link RopeByteString} equivalent for
+ * {@link ByteArrayInputStream}.
+ */
+ private class RopeInputStream extends InputStream {
+ // Iterates through the pieces of the rope
+ private PieceIterator pieceIterator;
+ // The current piece
+ private LiteralByteString currentPiece;
+ // The size of the current piece
+ private int currentPieceSize;
+ // The index of the next byte to read in the current piece
+ private int currentPieceIndex;
+ // The offset of the start of the current piece in the rope byte string
+ private int currentPieceOffsetInRope;
+ // Offset in the buffer at which user called mark();
+ private int mark;
+
+ public RopeInputStream() {
+ initialize();
+ }
+
+ @Override
+ public int read(byte b[], int offset, int length) {
+ if (b == null) {
+ throw new NullPointerException();
+ } else if (offset < 0 || length < 0 || length > b.length - offset) {
+ throw new IndexOutOfBoundsException();
+ }
+ return readSkipInternal(b, offset, length);
+ }
+
+ @Override
+ public long skip(long length) {
+ if (length < 0) {
+ throw new IndexOutOfBoundsException();
+ } else if (length > Integer.MAX_VALUE) {
+ length = Integer.MAX_VALUE;
+ }
+ return readSkipInternal(null, 0, (int) length);
+ }
+
+ /**
+ * Internal implementation of read and skip. If b != null, then read the
+ * next {@code length} bytes into the buffer {@code b} at
+ * offset {@code offset}. If b == null, then skip the next {@code length)
+ * bytes.
+ * <p>
+ * This method assumes that all error checking has already happened.
+ * <p>
+ * Returns the actual number of bytes read or skipped.
+ */
+ private int readSkipInternal(byte b[], int offset, int length) {
+ int bytesRemaining = length;
+ while (bytesRemaining > 0) {
+ advanceIfCurrentPieceFullyRead();
+ if (currentPiece == null) {
+ if (bytesRemaining == length) {
+ // We didn't manage to read anything
+ return -1;
+ }
+ break;
+ } else {
+ // Copy the bytes from this piece.
+ int currentPieceRemaining = currentPieceSize - currentPieceIndex;
+ int count = Math.min(currentPieceRemaining, bytesRemaining);
+ if (b != null) {
+ currentPiece.copyTo(b, currentPieceIndex, offset, count);
+ offset += count;
+ }
+ currentPieceIndex += count;
+ bytesRemaining -= count;
+ }
+ }
+ // Return the number of bytes read.
+ return length - bytesRemaining;
+ }
+
+ @Override
+ public int read() throws IOException {
+ advanceIfCurrentPieceFullyRead();
+ if (currentPiece == null) {
+ return -1;
+ } else {
+ return currentPiece.byteAt(currentPieceIndex++) & 0xFF;
+ }
+ }
+
+ @Override
+ public int available() throws IOException {
+ int bytesRead = currentPieceOffsetInRope + currentPieceIndex;
+ return RopeByteString.this.size() - bytesRead;
+ }
+
+ @Override
+ public boolean markSupported() {
+ return true;
+ }
+
+ @Override
+ public void mark(int readAheadLimit) {
+ // Set the mark to our position in the byte string
+ mark = currentPieceOffsetInRope + currentPieceIndex;
+ }
+
+ @Override
+ public synchronized void reset() {
+ // Just reinitialize and skip the specified number of bytes.
+ initialize();
+ readSkipInternal(null, 0, mark);
+ }
+
+ /** Common initialization code used by both the constructor and reset() */
+ private void initialize() {
+ pieceIterator = new PieceIterator(RopeByteString.this);
+ currentPiece = pieceIterator.next();
+ currentPieceSize = currentPiece.size();
+ currentPieceIndex = 0;
+ currentPieceOffsetInRope = 0;
+ }
+
+ /**
+ * Skips to the next piece if we have read all the data in the current
+ * piece. Sets currentPiece to null if we have reached the end of the
+ * input.
+ */
+ private void advanceIfCurrentPieceFullyRead() {
+ if (currentPiece != null && currentPieceIndex == currentPieceSize) {
+ // Generally, we can only go through this loop at most once, since
+ // empty strings can't end up in a rope. But better to test.
+ currentPieceOffsetInRope += currentPieceSize;
+ currentPieceIndex = 0;
+ if (pieceIterator.hasNext()) {
+ currentPiece = pieceIterator.next();
+ currentPieceSize = currentPiece.size();
+ } else {
+ currentPiece = null;
+ currentPieceSize = 0;
+ }
+ }
+ }
+ }
+}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/SingleFieldBuilder.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/SingleFieldBuilder.java
index d4475f6..4bfc9f3 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/SingleFieldBuilder.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/SingleFieldBuilder.java
@@ -31,21 +31,21 @@
package com.google.protobuf;
/**
- * <code>SingleFieldBuilder</code> implements a structure that a protocol
+ * {@code SingleFieldBuilder} implements a structure that a protocol
* message uses to hold a single field of another protocol message. It supports
* the classical use case of setting an immutable {@link Message} as the value
* of the field and is highly optimized around this.
* <br>
* It also supports the additional use case of setting a {@link Message.Builder}
- * as the field and deferring conversion of that <code>Builder</code>
- * to an immutable <code>Message</code>. In this way, it's possible to maintain
- * a tree of <code>Builder</code>'s that acts as a fully read/write data
+ * as the field and deferring conversion of that {@code Builder}
+ * to an immutable {@code Message}. In this way, it's possible to maintain
+ * a tree of {@code Builder}'s that acts as a fully read/write data
* structure.
* <br>
* Logically, one can think of a tree of builders as converting the entire tree
* to messages when build is called on the root or when any method is called
* that desires a Message instead of a Builder. In terms of the implementation,
- * the <code>SingleFieldBuilder</code> and <code>RepeatedFieldBuilder</code>
+ * the {@code SingleFieldBuilder} and {@code RepeatedFieldBuilder}
* classes cache messages that were created so that messages only need to be
* created when some change occured in its builder or a builder for one of its
* descendants.
@@ -99,7 +99,7 @@
/**
* Get the message for the field. If the message is currently stored
- * as a <code>Builder</code>, it is converted to a <code>Message</code> by
+ * as a {@code Builder}, it is converted to a {@code Message} by
* calling {@link Message.Builder#buildPartial} on it. If no message has
* been set, returns the default instance of the message.
*
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/SmallSortedMap.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/SmallSortedMap.java
index 1cf270f..c6cad6a 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/SmallSortedMap.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/SmallSortedMap.java
@@ -51,14 +51,14 @@
* remaining entries are stored in an overflow map. Iteration over the entries
* in the map should be done as follows:
*
- * <pre>
- * for (int i = 0; i < fieldMap.getNumArrayEntries(); i++) {
+ * <pre> {@code
+ * for (int i = 0; i < fieldMap.getNumArrayEntries(); i++) {
* process(fieldMap.getArrayEntryAt(i));
* }
- * for (Map.Entry<K, V> entry : fieldMap.getOverflowEntries()) {
+ * for (Map.Entry<K, V> entry : fieldMap.getOverflowEntries()) {
* process(entry);
* }
- * </pre>
+ * }</pre>
*
* The resulting iteration is in order of ascending field tag number. The
* object returned by {@link #entrySet()} adheres to the same contract but is
@@ -394,7 +394,7 @@
/**
* Entry implementation that implements Comparable in order to support
- * binary search witin the entry array. Also checks mutability in
+ * binary search within the entry array. Also checks mutability in
* {@link #setValue()}.
*/
private class Entry implements Map.Entry<K, V>, Comparable<Entry> {
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/TextFormat.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/TextFormat.java
index d5fbdab..ed46289 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/TextFormat.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/TextFormat.java
@@ -55,15 +55,18 @@
public final class TextFormat {
private TextFormat() {}
- private static final Printer DEFAULT_PRINTER = new Printer(false);
- private static final Printer SINGLE_LINE_PRINTER = new Printer(true);
+ private static final Printer DEFAULT_PRINTER = new Printer();
+ private static final Printer SINGLE_LINE_PRINTER =
+ (new Printer()).setSingleLineMode(true);
+ private static final Printer UNICODE_PRINTER =
+ (new Printer()).setEscapeNonAscii(false);
/**
* Outputs a textual representation of the Protocol Message supplied into
* the parameter output. (This representation is the new version of the
* classic "ProtocolPrinter" output from the original Protocol Buffer system)
*/
- public static void print(final Message message, final Appendable output)
+ public static void print(final MessageOrBuilder message, final Appendable output)
throws IOException {
DEFAULT_PRINTER.print(message, new TextGenerator(output));
}
@@ -79,7 +82,7 @@
* Generates a human readable form of this message, useful for debugging and
* other purposes, with no newline characters.
*/
- public static String shortDebugString(final Message message) {
+ public static String shortDebugString(final MessageOrBuilder message) {
try {
final StringBuilder sb = new StringBuilder();
SINGLE_LINE_PRINTER.print(message, new TextGenerator(sb));
@@ -109,7 +112,7 @@
* Like {@code print()}, but writes directly to a {@code String} and
* returns it.
*/
- public static String printToString(final Message message) {
+ public static String printToString(final MessageOrBuilder message) {
try {
final StringBuilder text = new StringBuilder();
print(message, text);
@@ -133,6 +136,34 @@
}
}
+ /**
+ * Same as {@code printToString()}, except that non-ASCII characters
+ * in string type fields are not escaped in backslash+octals.
+ */
+ public static String printToUnicodeString(final MessageOrBuilder message) {
+ try {
+ final StringBuilder text = new StringBuilder();
+ UNICODE_PRINTER.print(message, new TextGenerator(text));
+ return text.toString();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Same as {@code printToString()}, except that non-ASCII characters
+ * in string type fields are not escaped in backslash+octals.
+ */
+ public static String printToUnicodeString(final UnknownFieldSet fields) {
+ try {
+ final StringBuilder text = new StringBuilder();
+ UNICODE_PRINTER.printUnknownFields(fields, new TextGenerator(text));
+ return text.toString();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
public static void printField(final FieldDescriptor field,
final Object value,
final Appendable output)
@@ -216,13 +247,26 @@
/** Helper class for converting protobufs to text. */
private static final class Printer {
/** Whether to omit newlines from the output. */
- final boolean singleLineMode;
+ boolean singleLineMode = false;
- private Printer(final boolean singleLineMode) {
+ /** Whether to escape non ASCII characters with backslash and octal. */
+ boolean escapeNonAscii = true;
+
+ private Printer() {}
+
+ /** Setter of singleLineMode */
+ private Printer setSingleLineMode(boolean singleLineMode) {
this.singleLineMode = singleLineMode;
+ return this;
}
- private void print(final Message message, final TextGenerator generator)
+ /** Setter of escapeNonAscii */
+ private Printer setEscapeNonAscii(boolean escapeNonAscii) {
+ this.escapeNonAscii = escapeNonAscii;
+ return this;
+ }
+
+ private void print(final MessageOrBuilder message, final TextGenerator generator)
throws IOException {
for (Map.Entry<FieldDescriptor, Object> field
: message.getAllFields().entrySet()) {
@@ -339,7 +383,9 @@
case STRING:
generator.print("\"");
- generator.print(escapeText((String) value));
+ generator.print(escapeNonAscii ?
+ escapeText((String) value) :
+ (String) value);
generator.print("\"");
break;
@@ -541,7 +587,7 @@
private int previousLine = 0;
private int previousColumn = 0;
- // We use possesive quantifiers (*+ and ++) because otherwise the Java
+ // We use possessive quantifiers (*+ and ++) because otherwise the Java
// regex matcher has stack overflows on large inputs.
private static final Pattern WHITESPACE =
Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE);
@@ -864,7 +910,7 @@
public ParseException parseException(final String description) {
// Note: People generally prefer one-based line and column numbers.
return new ParseException(
- (line + 1) + ":" + (column + 1) + ": " + description);
+ line + 1, column + 1, description);
}
/**
@@ -875,7 +921,7 @@
final String description) {
// Note: People generally prefer one-based line and column numbers.
return new ParseException(
- (previousLine + 1) + ":" + (previousColumn + 1) + ": " + description);
+ previousLine + 1, previousColumn + 1, description);
}
/**
@@ -900,8 +946,45 @@
public static class ParseException extends IOException {
private static final long serialVersionUID = 3196188060225107702L;
+ private final int line;
+ private final int column;
+
+ /** Create a new instance, with -1 as the line and column numbers. */
public ParseException(final String message) {
- super(message);
+ this(-1, -1, message);
+ }
+
+ /**
+ * Create a new instance
+ *
+ * @param line the line number where the parse error occurred,
+ * using 1-offset.
+ * @param column the column number where the parser error occurred,
+ * using 1-offset.
+ */
+ public ParseException(final int line, final int column,
+ final String message) {
+ super(Integer.toString(line) + ":" + column + ": " + message);
+ this.line = line;
+ this.column = column;
+ }
+
+ /**
+ * Return the line where the parse exception occurred, or -1 when
+ * none is provided. The value is specified as 1-offset, so the first
+ * line is line 1.
+ */
+ public int getLine() {
+ return line;
+ }
+
+ /**
+ * Return the column where the parse exception occurred, or -1 when
+ * none is provided. The value is specified as 1-offset, so the first
+ * line is line 1.
+ */
+ public int getColumn() {
+ return column;
}
}
@@ -1073,7 +1156,7 @@
mergeField(tokenizer, extensionRegistry, subBuilder);
}
- value = subBuilder.build();
+ value = subBuilder.buildPartial();
} else {
tokenizer.consume(":");
@@ -1212,7 +1295,7 @@
*/
static ByteString unescapeBytes(final CharSequence charString)
throws InvalidEscapeSequenceException {
- // First convert the Java characater sequence to UTF-8 bytes.
+ // First convert the Java character sequence to UTF-8 bytes.
ByteString input = ByteString.copyFromUtf8(charString.toString());
// Then unescape certain byte sequences introduced by ASCII '\\'. The valid
// escapes can all be expressed with ASCII characters, so it is safe to
@@ -1349,7 +1432,7 @@
/**
* Parse a 32-bit signed integer from the text. Unlike the Java standard
* {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
- * and "0" to signify hexidecimal and octal numbers, respectively.
+ * and "0" to signify hexadecimal and octal numbers, respectively.
*/
static int parseInt32(final String text) throws NumberFormatException {
return (int) parseInteger(text, true, false);
@@ -1358,7 +1441,7 @@
/**
* Parse a 32-bit unsigned integer from the text. Unlike the Java standard
* {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
- * and "0" to signify hexidecimal and octal numbers, respectively. The
+ * and "0" to signify hexadecimal and octal numbers, respectively. The
* result is coerced to a (signed) {@code int} when returned since Java has
* no unsigned integer type.
*/
@@ -1369,7 +1452,7 @@
/**
* Parse a 64-bit signed integer from the text. Unlike the Java standard
* {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
- * and "0" to signify hexidecimal and octal numbers, respectively.
+ * and "0" to signify hexadecimal and octal numbers, respectively.
*/
static long parseInt64(final String text) throws NumberFormatException {
return parseInteger(text, true, true);
@@ -1378,7 +1461,7 @@
/**
* Parse a 64-bit unsigned integer from the text. Unlike the Java standard
* {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
- * and "0" to signify hexidecimal and octal numbers, respectively. The
+ * and "0" to signify hexadecimal and octal numbers, respectively. The
* result is coerced to a (signed) {@code long} when returned since Java has
* no unsigned long type.
*/
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/UnknownFieldSet.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
index 26a15d0..45e2e6e 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -46,7 +46,7 @@
* {@code UnknownFieldSet} is used to keep track of fields which were seen when
* parsing a protocol message but whose field numbers or types are unrecognized.
* This most frequently occurs when new fields are added to a message type
- * and then messages containing those feilds are read by old software that was
+ * and then messages containing those fields are read by old software that was
* compiled before the new types were added.
*
* <p>Every {@link Message} contains an {@code UnknownFieldSet} (and every
@@ -468,7 +468,7 @@
/**
* Parse a single field from {@code input} and merge it into this set.
* @param tag The field's tag number, which was already parsed.
- * @return {@code false} if the tag is an engroup tag.
+ * @return {@code false} if the tag is an end group tag.
*/
public boolean mergeFieldFrom(final int tag, final CodedInputStream input)
throws IOException {
@@ -950,4 +950,29 @@
}
}
}
+
+ /**
+ * Parser to implement MessageLite interface.
+ */
+ public static final class Parser extends AbstractParser<UnknownFieldSet> {
+ public UnknownFieldSet parsePartialFrom(
+ CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ Builder builder = newBuilder();
+ try {
+ builder.mergeFrom(input);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(builder.buildPartial());
+ } catch (IOException e) {
+ throw new InvalidProtocolBufferException(e.getMessage())
+ .setUnfinishedMessage(builder.buildPartial());
+ }
+ return builder.buildPartial();
+ }
+ }
+
+ private static final Parser PARSER = new Parser();
+ public final Parser getParserForType() {
+ return PARSER;
+ }
}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
index 83e5c79..f80f096 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
@@ -32,6 +32,7 @@
import java.util.AbstractList;
import java.util.RandomAccess;
+import java.util.List;
import java.util.ListIterator;
import java.util.Iterator;
@@ -143,4 +144,10 @@
}
};
}
+
+ @Override
+ public List<?> getUnderlyingElements() {
+ // The returned value is already unmodifiable.
+ return list.getUnderlyingElements();
+ }
}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/Utf8.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/Utf8.java
new file mode 100644
index 0000000..388f7fc
--- /dev/null
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/Utf8.java
@@ -0,0 +1,349 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+/**
+ * A set of low-level, high-performance static utility methods related
+ * to the UTF-8 character encoding. This class has no dependencies
+ * outside of the core JDK libraries.
+ *
+ * <p>There are several variants of UTF-8. The one implemented by
+ * this class is the restricted definition of UTF-8 introduced in
+ * Unicode 3.1, which mandates the rejection of "overlong" byte
+ * sequences as well as rejection of 3-byte surrogate codepoint byte
+ * sequences. Note that the UTF-8 decoder included in Oracle's JDK
+ * has been modified to also reject "overlong" byte sequences, but (as
+ * of 2011) still accepts 3-byte surrogate codepoint byte sequences.
+ *
+ * <p>The byte sequences considered valid by this class are exactly
+ * those that can be roundtrip converted to Strings and back to bytes
+ * using the UTF-8 charset, without loss: <pre> {@code
+ * Arrays.equals(bytes, new String(bytes, "UTF-8").getBytes("UTF-8"))
+ * }</pre>
+ *
+ * <p>See the Unicode Standard,</br>
+ * Table 3-6. <em>UTF-8 Bit Distribution</em>,</br>
+ * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
+ *
+ * <p>This class supports decoding of partial byte sequences, so that the
+ * bytes in a complete UTF-8 byte sequences can be stored in multiple
+ * segments. Methods typically return {@link #MALFORMED} if the partial
+ * byte sequence is definitely not well-formed, {@link #COMPLETE} if it is
+ * well-formed in the absence of additional input, or if the byte sequence
+ * apparently terminated in the middle of a character, an opaque integer
+ * "state" value containing enough information to decode the character when
+ * passed to a subsequent invocation of a partial decoding method.
+ *
+ * @author martinrb@google.com (Martin Buchholz)
+ */
+final class Utf8 {
+ private Utf8() {}
+
+ /**
+ * State value indicating that the byte sequence is well-formed and
+ * complete (no further bytes are needed to complete a character).
+ */
+ public static final int COMPLETE = 0;
+
+ /**
+ * State value indicating that the byte sequence is definitely not
+ * well-formed.
+ */
+ public static final int MALFORMED = -1;
+
+ // Other state values include the partial bytes of the incomplete
+ // character to be decoded in the simplest way: we pack the bytes
+ // into the state int in little-endian order. For example:
+ //
+ // int state = byte1 ^ (byte2 << 8) ^ (byte3 << 16);
+ //
+ // Such a state is unpacked thus (note the ~ operation for byte2 to
+ // undo byte1's sign-extension bits):
+ //
+ // int byte1 = (byte) state;
+ // int byte2 = (byte) ~(state >> 8);
+ // int byte3 = (byte) (state >> 16);
+ //
+ // We cannot store a zero byte in the state because it would be
+ // indistinguishable from the absence of a byte. But we don't need
+ // to, because partial bytes must always be negative. When building
+ // a state, we ensure that byte1 is negative and subsequent bytes
+ // are valid trailing bytes.
+
+ /**
+ * Returns {@code true} if the given byte array is a well-formed
+ * UTF-8 byte sequence.
+ *
+ * <p>This is a convenience method, equivalent to a call to {@code
+ * isValidUtf8(bytes, 0, bytes.length)}.
+ */
+ public static boolean isValidUtf8(byte[] bytes) {
+ return isValidUtf8(bytes, 0, bytes.length);
+ }
+
+ /**
+ * Returns {@code true} if the given byte array slice is a
+ * well-formed UTF-8 byte sequence. The range of bytes to be
+ * checked extends from index {@code index}, inclusive, to {@code
+ * limit}, exclusive.
+ *
+ * <p>This is a convenience method, equivalent to {@code
+ * partialIsValidUtf8(bytes, index, limit) == Utf8.COMPLETE}.
+ */
+ public static boolean isValidUtf8(byte[] bytes, int index, int limit) {
+ return partialIsValidUtf8(bytes, index, limit) == COMPLETE;
+ }
+
+ /**
+ * Tells whether the given byte array slice is a well-formed,
+ * malformed, or incomplete UTF-8 byte sequence. The range of bytes
+ * to be checked extends from index {@code index}, inclusive, to
+ * {@code limit}, exclusive.
+ *
+ * @param state either {@link Utf8#COMPLETE} (if this is the initial decoding
+ * operation) or the value returned from a call to a partial decoding method
+ * for the previous bytes
+ *
+ * @return {@link #MALFORMED} if the partial byte sequence is
+ * definitely not well-formed, {@link #COMPLETE} if it is well-formed
+ * (no additional input needed), or if the byte sequence is
+ * "incomplete", i.e. apparently terminated in the middle of a character,
+ * an opaque integer "state" value containing enough information to
+ * decode the character when passed to a subsequent invocation of a
+ * partial decoding method.
+ */
+ public static int partialIsValidUtf8(
+ int state, byte[] bytes, int index, int limit) {
+ if (state != COMPLETE) {
+ // The previous decoding operation was incomplete (or malformed).
+ // We look for a well-formed sequence consisting of bytes from
+ // the previous decoding operation (stored in state) together
+ // with bytes from the array slice.
+ //
+ // We expect such "straddler characters" to be rare.
+
+ if (index >= limit) { // No bytes? No progress.
+ return state;
+ }
+ int byte1 = (byte) state;
+ // byte1 is never ASCII.
+ if (byte1 < (byte) 0xE0) {
+ // two-byte form
+
+ // Simultaneously checks for illegal trailing-byte in
+ // leading position and overlong 2-byte form.
+ if (byte1 < (byte) 0xC2 ||
+ // byte2 trailing-byte test
+ bytes[index++] > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else if (byte1 < (byte) 0xF0) {
+ // three-byte form
+
+ // Get byte2 from saved state or array
+ int byte2 = (byte) ~(state >> 8);
+ if (byte2 == 0) {
+ byte2 = bytes[index++];
+ if (index >= limit) {
+ return incompleteStateFor(byte1, byte2);
+ }
+ }
+ if (byte2 > (byte) 0xBF ||
+ // overlong? 5 most significant bits must not all be zero
+ (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0) ||
+ // illegal surrogate codepoint?
+ (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0) ||
+ // byte3 trailing-byte test
+ bytes[index++] > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else {
+ // four-byte form
+
+ // Get byte2 and byte3 from saved state or array
+ int byte2 = (byte) ~(state >> 8);
+ int byte3 = 0;
+ if (byte2 == 0) {
+ byte2 = bytes[index++];
+ if (index >= limit) {
+ return incompleteStateFor(byte1, byte2);
+ }
+ } else {
+ byte3 = (byte) (state >> 16);
+ }
+ if (byte3 == 0) {
+ byte3 = bytes[index++];
+ if (index >= limit) {
+ return incompleteStateFor(byte1, byte2, byte3);
+ }
+ }
+
+ // If we were called with state == MALFORMED, then byte1 is 0xFF,
+ // which never occurs in well-formed UTF-8, and so we will return
+ // MALFORMED again below.
+
+ if (byte2 > (byte) 0xBF ||
+ // Check that 1 <= plane <= 16. Tricky optimized form of:
+ // if (byte1 > (byte) 0xF4 ||
+ // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+ // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+ (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0 ||
+ // byte3 trailing-byte test
+ byte3 > (byte) 0xBF ||
+ // byte4 trailing-byte test
+ bytes[index++] > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ }
+ }
+
+ return partialIsValidUtf8(bytes, index, limit);
+ }
+
+ /**
+ * Tells whether the given byte array slice is a well-formed,
+ * malformed, or incomplete UTF-8 byte sequence. The range of bytes
+ * to be checked extends from index {@code index}, inclusive, to
+ * {@code limit}, exclusive.
+ *
+ * <p>This is a convenience method, equivalent to a call to {@code
+ * partialIsValidUtf8(Utf8.COMPLETE, bytes, index, limit)}.
+ *
+ * @return {@link #MALFORMED} if the partial byte sequence is
+ * definitely not well-formed, {@link #COMPLETE} if it is well-formed
+ * (no additional input needed), or if the byte sequence is
+ * "incomplete", i.e. apparently terminated in the middle of a character,
+ * an opaque integer "state" value containing enough information to
+ * decode the character when passed to a subsequent invocation of a
+ * partial decoding method.
+ */
+ public static int partialIsValidUtf8(
+ byte[] bytes, int index, int limit) {
+ // Optimize for 100% ASCII.
+ // Hotspot loves small simple top-level loops like this.
+ while (index < limit && bytes[index] >= 0) {
+ index++;
+ }
+
+ return (index >= limit) ? COMPLETE :
+ partialIsValidUtf8NonAscii(bytes, index, limit);
+ }
+
+ private static int partialIsValidUtf8NonAscii(
+ byte[] bytes, int index, int limit) {
+ for (;;) {
+ int byte1, byte2;
+
+ // Optimize for interior runs of ASCII bytes.
+ do {
+ if (index >= limit) {
+ return COMPLETE;
+ }
+ } while ((byte1 = bytes[index++]) >= 0);
+
+ if (byte1 < (byte) 0xE0) {
+ // two-byte form
+
+ if (index >= limit) {
+ return byte1;
+ }
+
+ // Simultaneously checks for illegal trailing-byte in
+ // leading position and overlong 2-byte form.
+ if (byte1 < (byte) 0xC2 ||
+ bytes[index++] > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else if (byte1 < (byte) 0xF0) {
+ // three-byte form
+
+ if (index >= limit - 1) { // incomplete sequence
+ return incompleteStateFor(bytes, index, limit);
+ }
+ if ((byte2 = bytes[index++]) > (byte) 0xBF ||
+ // overlong? 5 most significant bits must not all be zero
+ (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0) ||
+ // check for illegal surrogate codepoints
+ (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0) ||
+ // byte3 trailing-byte test
+ bytes[index++] > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else {
+ // four-byte form
+
+ if (index >= limit - 2) { // incomplete sequence
+ return incompleteStateFor(bytes, index, limit);
+ }
+ if ((byte2 = bytes[index++]) > (byte) 0xBF ||
+ // Check that 1 <= plane <= 16. Tricky optimized form of:
+ // if (byte1 > (byte) 0xF4 ||
+ // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+ // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+ (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0 ||
+ // byte3 trailing-byte test
+ bytes[index++] > (byte) 0xBF ||
+ // byte4 trailing-byte test
+ bytes[index++] > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ }
+ }
+ }
+
+ private static int incompleteStateFor(int byte1) {
+ return (byte1 > (byte) 0xF4) ?
+ MALFORMED : byte1;
+ }
+
+ private static int incompleteStateFor(int byte1, int byte2) {
+ return (byte1 > (byte) 0xF4 ||
+ byte2 > (byte) 0xBF) ?
+ MALFORMED : byte1 ^ (byte2 << 8);
+ }
+
+ private static int incompleteStateFor(int byte1, int byte2, int byte3) {
+ return (byte1 > (byte) 0xF4 ||
+ byte2 > (byte) 0xBF ||
+ byte3 > (byte) 0xBF) ?
+ MALFORMED : byte1 ^ (byte2 << 8) ^ (byte3 << 16);
+ }
+
+ private static int incompleteStateFor(byte[] bytes, int index, int limit) {
+ int byte1 = bytes[index - 1];
+ switch (limit - index) {
+ case 0: return incompleteStateFor(byte1);
+ case 1: return incompleteStateFor(byte1, bytes[index]);
+ case 2: return incompleteStateFor(byte1, bytes[index], bytes[index + 1]);
+ default: throw new AssertionError();
+ }
+ }
+}
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/WireFormat.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/WireFormat.java
index a30f2a3..dd2d631 100644
--- a/third_party/protobuf/java/src/main/java/com/google/protobuf/WireFormat.java
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/WireFormat.java
@@ -146,7 +146,7 @@
public boolean isPackable() { return true; }
}
- // Field numbers for feilds in MessageSet wire format.
+ // Field numbers for fields in MessageSet wire format.
static final int MESSAGE_SET_ITEM = 1;
static final int MESSAGE_SET_TYPE_ID = 2;
static final int MESSAGE_SET_MESSAGE = 3;
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/AbstractMessageTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
index d53ce8d..3d05cb7 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
@@ -30,6 +30,7 @@
package com.google.protobuf;
+import com.google.protobuf.Descriptors.FieldDescriptor;
import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
import protobuf_unittest.UnittestProto;
import protobuf_unittest.UnittestProto.ForeignMessage;
@@ -167,6 +168,13 @@
wrappedBuilder.setUnknownFields(unknownFields);
return this;
}
+ @Override
+ public Message.Builder getFieldBuilder(FieldDescriptor field) {
+ return wrappedBuilder.getFieldBuilder(field);
+ }
+ }
+ public Parser<? extends Message> getParserForType() {
+ return wrappedMessage.getParserForType();
}
}
@@ -220,6 +228,34 @@
TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage);
}
+ public void testParsingUninitialized() throws Exception {
+ TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
+ builder.getOptionalMessageBuilder().setDummy2(10);
+ ByteString bytes = builder.buildPartial().toByteString();
+ Message.Builder abstractMessageBuilder =
+ new AbstractMessageWrapper.Builder(TestRequiredForeign.newBuilder());
+ // mergeFrom() should not throw initialization error.
+ abstractMessageBuilder.mergeFrom(bytes).buildPartial();
+ try {
+ abstractMessageBuilder.mergeFrom(bytes).build();
+ fail();
+ } catch (UninitializedMessageException ex) {
+ // pass
+ }
+
+ // test DynamicMessage directly.
+ Message.Builder dynamicMessageBuilder = DynamicMessage.newBuilder(
+ TestRequiredForeign.getDescriptor());
+ // mergeFrom() should not throw initialization error.
+ dynamicMessageBuilder.mergeFrom(bytes).buildPartial();
+ try {
+ dynamicMessageBuilder.mergeFrom(bytes).build();
+ fail();
+ } catch (UninitializedMessageException ex) {
+ // pass
+ }
+ }
+
public void testPackedSerialization() throws Exception {
Message abstractMessage =
new AbstractMessageWrapper(TestUtil.getPackedSet());
@@ -298,12 +334,16 @@
new AbstractMessageWrapper.Builder(builder);
assertFalse(abstractBuilder.isInitialized());
+ assertEquals("a, b, c", abstractBuilder.getInitializationErrorString());
builder.setA(1);
assertFalse(abstractBuilder.isInitialized());
+ assertEquals("b, c", abstractBuilder.getInitializationErrorString());
builder.setB(1);
assertFalse(abstractBuilder.isInitialized());
+ assertEquals("c", abstractBuilder.getInitializationErrorString());
builder.setC(1);
assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
}
public void testForeignIsInitialized() throws Exception {
@@ -312,18 +352,27 @@
new AbstractMessageWrapper.Builder(builder);
assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
assertFalse(abstractBuilder.isInitialized());
+ assertEquals(
+ "optional_message.a, optional_message.b, optional_message.c",
+ abstractBuilder.getInitializationErrorString());
builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
assertFalse(abstractBuilder.isInitialized());
+ assertEquals(
+ "repeated_message[0].a, repeated_message[0].b, repeated_message[0].c",
+ abstractBuilder.getInitializationErrorString());
builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
}
// -----------------------------------------------------------------
@@ -421,7 +470,7 @@
/**
- * Asserts that the given proto has symetric equals and hashCode methods.
+ * Asserts that the given proto has symmetric equals and hashCode methods.
*/
private void checkEqualsIsConsistent(Message message) {
// Object should be equal to itself.
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java
new file mode 100644
index 0000000..20fa2df
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java
@@ -0,0 +1,68 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * This class tests {@link BoundedByteString}, which extends {@link LiteralByteString},
+ * by inheriting the tests from {@link LiteralByteStringTest}. The only method which
+ * is strange enough that it needs to be overridden here is {@link #testToString()}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class BoundedByteStringTest extends LiteralByteStringTest {
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "BoundedByteString";
+ byte[] sourceBytes = ByteStringTest.getTestBytes(2341, 11337766L);
+ int from = 100;
+ int to = sourceBytes.length - 100;
+ stringUnderTest = ByteString.copyFrom(sourceBytes).substring(from, to);
+ referenceBytes = new byte[to - from];
+ System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from);
+ expectedHashCode = 727575887;
+ }
+
+ @Override
+ public void testToString() throws UnsupportedEncodingException {
+ String testString = "I love unicode \u1234\u5678 characters";
+ LiteralByteString unicode = new LiteralByteString(testString.getBytes(UTF_8));
+ ByteString chopped = unicode.substring(2, unicode.size() - 6);
+ assertEquals(classUnderTest + ".substring() must have the expected type",
+ classUnderTest, getActualClassName(chopped));
+
+ String roundTripString = chopped.toString(UTF_8);
+ assertEquals(classUnderTest + " unicode bytes must match",
+ testString.substring(2, testString.length() - 6), roundTripString);
+ }
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/ByteStringTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/ByteStringTest.java
new file mode 100644
index 0000000..7a1d682
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/ByteStringTest.java
@@ -0,0 +1,692 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import com.google.protobuf.ByteString.Output;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Random;
+
+/**
+ * Test methods with implementations in {@link ByteString}, plus do some top-level "integration"
+ * tests.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class ByteStringTest extends TestCase {
+
+ private static final String UTF_16 = "UTF-16";
+
+ static byte[] getTestBytes(int size, long seed) {
+ Random random = new Random(seed);
+ byte[] result = new byte[size];
+ random.nextBytes(result);
+ return result;
+ }
+
+ private byte[] getTestBytes(int size) {
+ return getTestBytes(size, 445566L);
+ }
+
+ private byte[] getTestBytes() {
+ return getTestBytes(1000);
+ }
+
+ // Compare the entire left array with a subset of the right array.
+ private boolean isArrayRange(byte[] left, byte[] right, int rightOffset, int length) {
+ boolean stillEqual = (left.length == length);
+ for (int i = 0; (stillEqual && i < length); ++i) {
+ stillEqual = (left[i] == right[rightOffset + i]);
+ }
+ return stillEqual;
+ }
+
+ // Returns true only if the given two arrays have identical contents.
+ private boolean isArray(byte[] left, byte[] right) {
+ return left.length == right.length && isArrayRange(left, right, 0, left.length);
+ }
+
+ public void testSubstring_BeginIndex() {
+ byte[] bytes = getTestBytes();
+ ByteString substring = ByteString.copyFrom(bytes).substring(500);
+ assertTrue("substring must contain the tail of the string",
+ isArrayRange(substring.toByteArray(), bytes, 500, bytes.length - 500));
+ }
+
+ public void testCopyFrom_BytesOffsetSize() {
+ byte[] bytes = getTestBytes();
+ ByteString byteString = ByteString.copyFrom(bytes, 500, 200);
+ assertTrue("copyFrom sub-range must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), bytes, 500, 200));
+ }
+
+ public void testCopyFrom_Bytes() {
+ byte[] bytes = getTestBytes();
+ ByteString byteString = ByteString.copyFrom(bytes);
+ assertTrue("copyFrom must contain the expected bytes",
+ isArray(byteString.toByteArray(), bytes));
+ }
+
+ public void testCopyFrom_ByteBufferSize() {
+ byte[] bytes = getTestBytes();
+ ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length);
+ byteBuffer.put(bytes);
+ byteBuffer.position(500);
+ ByteString byteString = ByteString.copyFrom(byteBuffer, 200);
+ assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), bytes, 500, 200));
+ }
+
+ public void testCopyFrom_ByteBuffer() {
+ byte[] bytes = getTestBytes();
+ ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length);
+ byteBuffer.put(bytes);
+ byteBuffer.position(500);
+ ByteString byteString = ByteString.copyFrom(byteBuffer);
+ assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), bytes, 500, bytes.length - 500));
+ }
+
+ public void testCopyFrom_StringEncoding() throws UnsupportedEncodingException {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString byteString = ByteString.copyFrom(testString, UTF_16);
+ byte[] testBytes = testString.getBytes(UTF_16);
+ assertTrue("copyFrom string must respect the charset",
+ isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+ }
+
+ public void testCopyFrom_Utf8() throws UnsupportedEncodingException {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString byteString = ByteString.copyFromUtf8(testString);
+ byte[] testBytes = testString.getBytes("UTF-8");
+ assertTrue("copyFromUtf8 string must respect the charset",
+ isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+ }
+
+ public void testCopyFrom_Iterable() {
+ byte[] testBytes = getTestBytes(77777, 113344L);
+ final List<ByteString> pieces = makeConcretePieces(testBytes);
+ // Call copyFrom() on a Collection
+ ByteString byteString = ByteString.copyFrom(pieces);
+ assertTrue("copyFrom a List must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+ // Call copyFrom on an iteration that's not a collection
+ ByteString byteStringAlt = ByteString.copyFrom(new Iterable<ByteString>() {
+ public Iterator<ByteString> iterator() {
+ return pieces.iterator();
+ }
+ });
+ assertEquals("copyFrom from an Iteration must contain the expected bytes",
+ byteString, byteStringAlt);
+ }
+
+ public void testCopyTo_TargetOffset() {
+ byte[] bytes = getTestBytes();
+ ByteString byteString = ByteString.copyFrom(bytes);
+ byte[] target = new byte[bytes.length + 1000];
+ byteString.copyTo(target, 400);
+ assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+ isArrayRange(bytes, target, 400, bytes.length));
+ }
+
+ public void testReadFrom_emptyStream() throws IOException {
+ ByteString byteString =
+ ByteString.readFrom(new ByteArrayInputStream(new byte[0]));
+ assertSame("reading an empty stream must result in the EMPTY constant "
+ + "byte string", ByteString.EMPTY, byteString);
+ }
+
+ public void testReadFrom_smallStream() throws IOException {
+ assertReadFrom(getTestBytes(10));
+ }
+
+ public void testReadFrom_mutating() throws IOException {
+ byte[] capturedArray = null;
+ EvilInputStream eis = new EvilInputStream();
+ ByteString byteString = ByteString.readFrom(eis);
+
+ capturedArray = eis.capturedArray;
+ byte[] originalValue = byteString.toByteArray();
+ for (int x = 0; x < capturedArray.length; ++x) {
+ capturedArray[x] = (byte) 0;
+ }
+
+ byte[] newValue = byteString.toByteArray();
+ assertTrue("copyFrom byteBuffer must not grant access to underlying array",
+ Arrays.equals(originalValue, newValue));
+ }
+
+ // Tests sizes that are near the rope copy-out threshold.
+ public void testReadFrom_mediumStream() throws IOException {
+ assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE - 1));
+ assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE));
+ assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE + 1));
+ assertReadFrom(getTestBytes(200));
+ }
+
+ // Tests sizes that are over multi-segment rope threshold.
+ public void testReadFrom_largeStream() throws IOException {
+ assertReadFrom(getTestBytes(0x100));
+ assertReadFrom(getTestBytes(0x101));
+ assertReadFrom(getTestBytes(0x110));
+ assertReadFrom(getTestBytes(0x1000));
+ assertReadFrom(getTestBytes(0x1001));
+ assertReadFrom(getTestBytes(0x1010));
+ assertReadFrom(getTestBytes(0x10000));
+ assertReadFrom(getTestBytes(0x10001));
+ assertReadFrom(getTestBytes(0x10010));
+ }
+
+ // Tests sizes that are near the read buffer size.
+ public void testReadFrom_byteBoundaries() throws IOException {
+ final int min = ByteString.MIN_READ_FROM_CHUNK_SIZE;
+ final int max = ByteString.MAX_READ_FROM_CHUNK_SIZE;
+
+ assertReadFrom(getTestBytes(min - 1));
+ assertReadFrom(getTestBytes(min));
+ assertReadFrom(getTestBytes(min + 1));
+
+ assertReadFrom(getTestBytes(min * 2 - 1));
+ assertReadFrom(getTestBytes(min * 2));
+ assertReadFrom(getTestBytes(min * 2 + 1));
+
+ assertReadFrom(getTestBytes(min * 4 - 1));
+ assertReadFrom(getTestBytes(min * 4));
+ assertReadFrom(getTestBytes(min * 4 + 1));
+
+ assertReadFrom(getTestBytes(min * 8 - 1));
+ assertReadFrom(getTestBytes(min * 8));
+ assertReadFrom(getTestBytes(min * 8 + 1));
+
+ assertReadFrom(getTestBytes(max - 1));
+ assertReadFrom(getTestBytes(max));
+ assertReadFrom(getTestBytes(max + 1));
+
+ assertReadFrom(getTestBytes(max * 2 - 1));
+ assertReadFrom(getTestBytes(max * 2));
+ assertReadFrom(getTestBytes(max * 2 + 1));
+ }
+
+ // Tests that IOExceptions propagate through ByteString.readFrom().
+ public void testReadFrom_IOExceptions() {
+ try {
+ ByteString.readFrom(new FailStream());
+ fail("readFrom must throw the underlying IOException");
+
+ } catch (IOException e) {
+ assertEquals("readFrom must throw the expected exception",
+ "synthetic failure", e.getMessage());
+ }
+ }
+
+ // Tests that ByteString.readFrom works with streams that don't
+ // always fill their buffers.
+ public void testReadFrom_reluctantStream() throws IOException {
+ final byte[] data = getTestBytes(0x1000);
+
+ ByteString byteString = ByteString.readFrom(new ReluctantStream(data));
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(byteString.toByteArray(), data));
+
+ // Same test as above, but with some specific chunk sizes.
+ assertReadFromReluctantStream(data, 100);
+ assertReadFromReluctantStream(data, 248);
+ assertReadFromReluctantStream(data, 249);
+ assertReadFromReluctantStream(data, 250);
+ assertReadFromReluctantStream(data, 251);
+ assertReadFromReluctantStream(data, 0x1000);
+ assertReadFromReluctantStream(data, 0x1001);
+ }
+
+ // Fails unless ByteString.readFrom reads the bytes correctly from a
+ // reluctant stream with the given chunkSize parameter.
+ private void assertReadFromReluctantStream(byte[] bytes, int chunkSize)
+ throws IOException {
+ ByteString b = ByteString.readFrom(new ReluctantStream(bytes), chunkSize);
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(b.toByteArray(), bytes));
+ }
+
+ // Tests that ByteString.readFrom works with streams that implement
+ // available().
+ public void testReadFrom_available() throws IOException {
+ final byte[] data = getTestBytes(0x1001);
+
+ ByteString byteString = ByteString.readFrom(new AvailableStream(data));
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(byteString.toByteArray(), data));
+ }
+
+ // Fails unless ByteString.readFrom reads the bytes correctly.
+ private void assertReadFrom(byte[] bytes) throws IOException {
+ ByteString byteString =
+ ByteString.readFrom(new ByteArrayInputStream(bytes));
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(byteString.toByteArray(), bytes));
+ }
+
+ // A stream that fails when read.
+ private static final class FailStream extends InputStream {
+ @Override public int read() throws IOException {
+ throw new IOException("synthetic failure");
+ }
+ }
+
+ // A stream that simulates blocking by only producing 250 characters
+ // per call to read(byte[]).
+ private static class ReluctantStream extends InputStream {
+ protected final byte[] data;
+ protected int pos = 0;
+
+ public ReluctantStream(byte[] data) {
+ this.data = data;
+ }
+
+ @Override public int read() {
+ if (pos == data.length) {
+ return -1;
+ } else {
+ return data[pos++];
+ }
+ }
+
+ @Override public int read(byte[] buf) {
+ return read(buf, 0, buf.length);
+ }
+
+ @Override public int read(byte[] buf, int offset, int size) {
+ if (pos == data.length) {
+ return -1;
+ }
+ int count = Math.min(Math.min(size, data.length - pos), 250);
+ System.arraycopy(data, pos, buf, offset, count);
+ pos += count;
+ return count;
+ }
+ }
+
+ // Same as above, but also implements available().
+ private static final class AvailableStream extends ReluctantStream {
+ public AvailableStream(byte[] data) {
+ super(data);
+ }
+
+ @Override public int available() {
+ return Math.min(250, data.length - pos);
+ }
+ }
+
+ // A stream which exposes the byte array passed into read(byte[], int, int).
+ private static class EvilInputStream extends InputStream {
+ public byte[] capturedArray = null;
+
+ @Override
+ public int read(byte[] buf, int off, int len) {
+ if (capturedArray != null) {
+ return -1;
+ } else {
+ capturedArray = buf;
+ for (int x = 0; x < len; ++x) {
+ buf[x] = (byte) x;
+ }
+ return len;
+ }
+ }
+
+ @Override
+ public int read() {
+ // Purposefully do nothing.
+ return -1;
+ }
+ }
+
+ // A stream which exposes the byte array passed into write(byte[], int, int).
+ private static class EvilOutputStream extends OutputStream {
+ public byte[] capturedArray = null;
+
+ @Override
+ public void write(byte[] buf, int off, int len) {
+ if (capturedArray == null) {
+ capturedArray = buf;
+ }
+ }
+
+ @Override
+ public void write(int ignored) {
+ // Purposefully do nothing.
+ }
+ }
+
+ public void testToStringUtf8() throws UnsupportedEncodingException {
+ String testString = "I love unicode \u1234\u5678 characters";
+ byte[] testBytes = testString.getBytes("UTF-8");
+ ByteString byteString = ByteString.copyFrom(testBytes);
+ assertEquals("copyToStringUtf8 must respect the charset",
+ testString, byteString.toStringUtf8());
+ }
+
+ public void testNewOutput_InitialCapacity() throws IOException {
+ byte[] bytes = getTestBytes();
+ ByteString.Output output = ByteString.newOutput(bytes.length + 100);
+ output.write(bytes);
+ ByteString byteString = output.toByteString();
+ assertTrue(
+ "String built from newOutput(int) must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+
+ // Test newOutput() using a variety of buffer sizes and a variety of (fixed)
+ // write sizes
+ public void testNewOutput_ArrayWrite() throws IOException {
+ byte[] bytes = getTestBytes();
+ int length = bytes.length;
+ int[] bufferSizes = {128, 256, length / 2, length - 1, length, length + 1,
+ 2 * length, 3 * length};
+ int[] writeSizes = {1, 4, 5, 7, 23, bytes.length};
+
+ for (int bufferSize : bufferSizes) {
+ for (int writeSize : writeSizes) {
+ // Test writing the entire output writeSize bytes at a time.
+ ByteString.Output output = ByteString.newOutput(bufferSize);
+ for (int i = 0; i < length; i += writeSize) {
+ output.write(bytes, i, Math.min(writeSize, length - i));
+ }
+ ByteString byteString = output.toByteString();
+ assertTrue("String built from newOutput() must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+ }
+ }
+
+ // Test newOutput() using a variety of buffer sizes, but writing all the
+ // characters using write(byte);
+ public void testNewOutput_WriteChar() throws IOException {
+ byte[] bytes = getTestBytes();
+ int length = bytes.length;
+ int[] bufferSizes = {0, 1, 128, 256, length / 2,
+ length - 1, length, length + 1,
+ 2 * length, 3 * length};
+ for (int bufferSize : bufferSizes) {
+ ByteString.Output output = ByteString.newOutput(bufferSize);
+ for (byte byteValue : bytes) {
+ output.write(byteValue);
+ }
+ ByteString byteString = output.toByteString();
+ assertTrue("String built from newOutput() must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+ }
+
+ // Test newOutput() in which we write the bytes using a variety of methods
+ // and sizes, and in which we repeatedly call toByteString() in the middle.
+ public void testNewOutput_Mixed() throws IOException {
+ Random rng = new Random(1);
+ byte[] bytes = getTestBytes();
+ int length = bytes.length;
+ int[] bufferSizes = {0, 1, 128, 256, length / 2,
+ length - 1, length, length + 1,
+ 2 * length, 3 * length};
+
+ for (int bufferSize : bufferSizes) {
+ // Test writing the entire output using a mixture of write sizes and
+ // methods;
+ ByteString.Output output = ByteString.newOutput(bufferSize);
+ int position = 0;
+ while (position < bytes.length) {
+ if (rng.nextBoolean()) {
+ int count = 1 + rng.nextInt(bytes.length - position);
+ output.write(bytes, position, count);
+ position += count;
+ } else {
+ output.write(bytes[position]);
+ position++;
+ }
+ assertEquals("size() returns the right value", position, output.size());
+ assertTrue("newOutput() substring must have correct bytes",
+ isArrayRange(output.toByteString().toByteArray(),
+ bytes, 0, position));
+ }
+ ByteString byteString = output.toByteString();
+ assertTrue("String built from newOutput() must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+ }
+
+ public void testNewOutputEmpty() throws IOException {
+ // Make sure newOutput() correctly builds empty byte strings
+ ByteString byteString = ByteString.newOutput().toByteString();
+ assertEquals(ByteString.EMPTY, byteString);
+ }
+
+ public void testNewOutput_Mutating() throws IOException {
+ Output os = ByteString.newOutput(5);
+ os.write(new byte[] {1, 2, 3, 4, 5});
+ EvilOutputStream eos = new EvilOutputStream();
+ os.writeTo(eos);
+ byte[] capturedArray = eos.capturedArray;
+ ByteString byteString = os.toByteString();
+ byte[] oldValue = byteString.toByteArray();
+ Arrays.fill(capturedArray, (byte) 0);
+ byte[] newValue = byteString.toByteArray();
+ assertTrue("Output must not provide access to the underlying byte array",
+ Arrays.equals(oldValue, newValue));
+ }
+
+ public void testNewCodedBuilder() throws IOException {
+ byte[] bytes = getTestBytes();
+ ByteString.CodedBuilder builder = ByteString.newCodedBuilder(bytes.length);
+ builder.getCodedOutput().writeRawBytes(bytes);
+ ByteString byteString = builder.build();
+ assertTrue("String built from newCodedBuilder() must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+
+ public void testSubstringParity() {
+ byte[] bigBytes = getTestBytes(2048 * 1024, 113344L);
+ int start = 512 * 1024 - 3333;
+ int end = 512 * 1024 + 7777;
+ ByteString concreteSubstring = ByteString.copyFrom(bigBytes).substring(start, end);
+ boolean ok = true;
+ for (int i = start; ok && i < end; ++i) {
+ ok = (bigBytes[i] == concreteSubstring.byteAt(i - start));
+ }
+ assertTrue("Concrete substring didn't capture the right bytes", ok);
+
+ ByteString literalString = ByteString.copyFrom(bigBytes, start, end - start);
+ assertTrue("Substring must be equal to literal string",
+ concreteSubstring.equals(literalString));
+ assertEquals("Substring must have same hashcode as literal string",
+ literalString.hashCode(), concreteSubstring.hashCode());
+ }
+
+ public void testCompositeSubstring() {
+ byte[] referenceBytes = getTestBytes(77748, 113344L);
+
+ List<ByteString> pieces = makeConcretePieces(referenceBytes);
+ ByteString listString = ByteString.copyFrom(pieces);
+
+ int from = 1000;
+ int to = 40000;
+ ByteString compositeSubstring = listString.substring(from, to);
+ byte[] substringBytes = compositeSubstring.toByteArray();
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < to - from; ++i) {
+ stillEqual = referenceBytes[from + i] == substringBytes[i];
+ }
+ assertTrue("Substring must return correct bytes", stillEqual);
+
+ stillEqual = true;
+ for (int i = 0; stillEqual && i < to - from; ++i) {
+ stillEqual = referenceBytes[from + i] == compositeSubstring.byteAt(i);
+ }
+ assertTrue("Substring must support byteAt() correctly", stillEqual);
+
+ ByteString literalSubstring = ByteString.copyFrom(referenceBytes, from, to - from);
+ assertTrue("Composite substring must equal a literal substring over the same bytes",
+ compositeSubstring.equals(literalSubstring));
+ assertTrue("Literal substring must equal a composite substring over the same bytes",
+ literalSubstring.equals(compositeSubstring));
+
+ assertEquals("We must get the same hashcodes for composite and literal substrings",
+ literalSubstring.hashCode(), compositeSubstring.hashCode());
+
+ assertFalse("We can't be equal to a proper substring",
+ compositeSubstring.equals(literalSubstring.substring(0, literalSubstring.size() - 1)));
+ }
+
+ public void testCopyFromList() {
+ byte[] referenceBytes = getTestBytes(77748, 113344L);
+ ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+ List<ByteString> pieces = makeConcretePieces(referenceBytes);
+ ByteString listString = ByteString.copyFrom(pieces);
+
+ assertTrue("Composite string must be equal to literal string",
+ listString.equals(literalString));
+ assertEquals("Composite string must have same hashcode as literal string",
+ literalString.hashCode(), listString.hashCode());
+ }
+
+ public void testConcat() {
+ byte[] referenceBytes = getTestBytes(77748, 113344L);
+ ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+ List<ByteString> pieces = makeConcretePieces(referenceBytes);
+
+ Iterator<ByteString> iter = pieces.iterator();
+ ByteString concatenatedString = iter.next();
+ while (iter.hasNext()) {
+ concatenatedString = concatenatedString.concat(iter.next());
+ }
+
+ assertTrue("Concatenated string must be equal to literal string",
+ concatenatedString.equals(literalString));
+ assertEquals("Concatenated string must have same hashcode as literal string",
+ literalString.hashCode(), concatenatedString.hashCode());
+ }
+
+ /**
+ * Test the Rope implementation can deal with Empty nodes, even though we
+ * guard against them. See also {@link LiteralByteStringTest#testConcat_empty()}.
+ */
+ public void testConcat_empty() {
+ byte[] referenceBytes = getTestBytes(7748, 113344L);
+ ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+ ByteString duo = RopeByteString.newInstanceForTest(literalString, literalString);
+ ByteString temp = RopeByteString.newInstanceForTest(
+ RopeByteString.newInstanceForTest(literalString, ByteString.EMPTY),
+ RopeByteString.newInstanceForTest(ByteString.EMPTY, literalString));
+ ByteString quintet = RopeByteString.newInstanceForTest(temp, ByteString.EMPTY);
+
+ assertTrue("String with concatenated nulls must equal simple concatenate",
+ duo.equals(quintet));
+ assertEquals("String with concatenated nulls have same hashcode as simple concatenate",
+ duo.hashCode(), quintet.hashCode());
+
+ ByteString.ByteIterator duoIter = duo.iterator();
+ ByteString.ByteIterator quintetIter = quintet.iterator();
+ boolean stillEqual = true;
+ while (stillEqual && quintetIter.hasNext()) {
+ stillEqual = (duoIter.nextByte() == quintetIter.nextByte());
+ }
+ assertTrue("We must get the same characters by iterating", stillEqual);
+ assertFalse("Iterator must be exhausted", duoIter.hasNext());
+ try {
+ duoIter.nextByte();
+ fail("Should have thrown an exception.");
+ } catch (NoSuchElementException e) {
+ // This is success
+ }
+ try {
+ quintetIter.nextByte();
+ fail("Should have thrown an exception.");
+ } catch (NoSuchElementException e) {
+ // This is success
+ }
+
+ // Test that even if we force empty strings in as rope leaves in this
+ // configuration, we always get a (possibly Bounded) LiteralByteString
+ // for a length 1 substring.
+ //
+ // It is possible, using the testing factory method to create deeply nested
+ // trees of empty leaves, to make a string that will fail this test.
+ for (int i = 1; i < duo.size(); ++i) {
+ assertTrue("Substrings of size() < 2 must not be RopeByteStrings",
+ duo.substring(i - 1, i) instanceof LiteralByteString);
+ }
+ for (int i = 1; i < quintet.size(); ++i) {
+ assertTrue("Substrings of size() < 2 must not be RopeByteStrings",
+ quintet.substring(i - 1, i) instanceof LiteralByteString);
+ }
+ }
+
+ public void testStartsWith() {
+ byte[] bytes = getTestBytes(1000, 1234L);
+ ByteString string = ByteString.copyFrom(bytes);
+ ByteString prefix = ByteString.copyFrom(bytes, 0, 500);
+ ByteString suffix = ByteString.copyFrom(bytes, 400, 600);
+ assertTrue(string.startsWith(ByteString.EMPTY));
+ assertTrue(string.startsWith(string));
+ assertTrue(string.startsWith(prefix));
+ assertFalse(string.startsWith(suffix));
+ assertFalse(prefix.startsWith(suffix));
+ assertFalse(suffix.startsWith(prefix));
+ assertFalse(ByteString.EMPTY.startsWith(prefix));
+ assertTrue(ByteString.EMPTY.startsWith(ByteString.EMPTY));
+ }
+
+ static List<ByteString> makeConcretePieces(byte[] referenceBytes) {
+ List<ByteString> pieces = new ArrayList<ByteString>();
+ // Starting length should be small enough that we'll do some concatenating by
+ // copying if we just concatenate all these pieces together.
+ for (int start = 0, length = 16; start < referenceBytes.length; start += length) {
+ length = (length << 1) - 1;
+ if (start + length > referenceBytes.length) {
+ length = referenceBytes.length - start;
+ }
+ pieces.add(ByteString.copyFrom(referenceBytes, start, length));
+ }
+ return pieces;
+ }
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
index 74476e3..8625502 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
@@ -30,8 +30,10 @@
package com.google.protobuf;
+import protobuf_unittest.UnittestProto.SparseEnumMessage;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestSparseEnum;
import junit.framework.TestCase;
@@ -302,17 +304,14 @@
}
/** Test writing a message containing a negative enum value. This used to
- * fail because the size was not properly computed as a sign-extended varint. */
+ * fail because the size was not properly computed as a sign-extended varint.
+ */
public void testWriteMessageWithNegativeEnumValue() throws Exception {
- protobuf_unittest.UnittestProto.SparseEnumMessage message =
- protobuf_unittest.UnittestProto.SparseEnumMessage.newBuilder()
- .setSparseEnum(protobuf_unittest.UnittestProto.TestSparseEnum.SPARSE_E)
- .build();
+ SparseEnumMessage message = SparseEnumMessage.newBuilder()
+ .setSparseEnum(TestSparseEnum.SPARSE_E) .build();
assertTrue(message.getSparseEnum().getNumber() < 0);
byte[] rawBytes = message.toByteArray();
- protobuf_unittest.UnittestProto.SparseEnumMessage message2 =
- protobuf_unittest.UnittestProto.SparseEnumMessage.parseFrom(rawBytes);
- assertEquals(protobuf_unittest.UnittestProto.TestSparseEnum.SPARSE_E,
- message2.getSparseEnum());
+ SparseEnumMessage message2 = SparseEnumMessage.parseFrom(rawBytes);
+ assertEquals(TestSparseEnum.SPARSE_E, message2.getSparseEnum());
}
}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/DescriptorsTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/DescriptorsTest.java
index 65d06e3..9c31091 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/DescriptorsTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -31,6 +31,8 @@
package com.google.protobuf;
import com.google.protobuf.DescriptorProtos.DescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumDescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto;
import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
import com.google.protobuf.Descriptors.DescriptorValidationException;
@@ -60,6 +62,7 @@
import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
/**
* Unit test for {@link Descriptors}.
@@ -426,7 +429,7 @@
UnittestEnormousDescriptor.getDescriptor()
.toProto().getSerializedSize() > 65536);
}
-
+
/**
* Tests that the DescriptorValidationException works as intended.
*/
@@ -445,7 +448,7 @@
.build())
.build();
try {
- Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
+ Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
new FileDescriptor[0]);
fail("DescriptorValidationException expected");
} catch (DescriptorValidationException e) {
@@ -457,4 +460,189 @@
assertTrue(e.getCause().getMessage().indexOf("invalid") != -1);
}
}
+
+ /**
+ * Tests the translate/crosslink for an example where a message field's name
+ * and type name are the same.
+ */
+ public void testDescriptorComplexCrosslink() throws Exception {
+ FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setType(FieldDescriptorProto.Type.TYPE_INT32)
+ .setName("foo")
+ .setNumber(1)
+ .build())
+ .build())
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Bar")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setTypeName("Foo")
+ .setName("Foo")
+ .setNumber(1)
+ .build())
+ .build())
+ .build();
+ // translate and crosslink
+ FileDescriptor file =
+ Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
+ new FileDescriptor[0]);
+ // verify resulting descriptors
+ assertNotNull(file);
+ List<Descriptor> msglist = file.getMessageTypes();
+ assertNotNull(msglist);
+ assertTrue(msglist.size() == 2);
+ boolean barFound = false;
+ for (Descriptor desc : msglist) {
+ if (desc.getName().equals("Bar")) {
+ barFound = true;
+ assertNotNull(desc.getFields());
+ List<FieldDescriptor> fieldlist = desc.getFields();
+ assertNotNull(fieldlist);
+ assertTrue(fieldlist.size() == 1);
+ assertTrue(fieldlist.get(0).getType() == FieldDescriptor.Type.MESSAGE);
+ assertTrue(fieldlist.get(0).getMessageType().getName().equals("Foo"));
+ }
+ }
+ assertTrue(barFound);
+ }
+
+ public void testInvalidPublicDependency() throws Exception {
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto") .build();
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("boo.proto")
+ .addDependency("foo.proto")
+ .addPublicDependency(1) // Error, should be 0.
+ .build();
+ FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto,
+ new FileDescriptor[0]);
+ try {
+ Descriptors.FileDescriptor.buildFrom(barProto,
+ new FileDescriptor[] {fooFile});
+ fail("DescriptorValidationException expected");
+ } catch (DescriptorValidationException e) {
+ assertTrue(
+ e.getMessage().indexOf("Invalid public dependency index.") != -1);
+ }
+ }
+
+ public void testHiddenDependency() throws Exception {
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("bar.proto")
+ .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
+ .build();
+ FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
+ .setName("forward.proto")
+ .addDependency("bar.proto")
+ .build();
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addDependency("forward.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setTypeName("Bar")
+ .setName("bar")
+ .setNumber(1)))
+ .build();
+ FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+ barProto, new FileDescriptor[0]);
+ FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
+ forwardProto, new FileDescriptor[] {barFile});
+
+ try {
+ Descriptors.FileDescriptor.buildFrom(
+ fooProto, new FileDescriptor[] {forwardFile});
+ fail("DescriptorValidationException expected");
+ } catch (DescriptorValidationException e) {
+ assertTrue(e.getMessage().indexOf("Bar") != -1);
+ assertTrue(e.getMessage().indexOf("is not defined") != -1);
+ }
+ }
+
+ public void testPublicDependency() throws Exception {
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("bar.proto")
+ .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
+ .build();
+ FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
+ .setName("forward.proto")
+ .addDependency("bar.proto")
+ .addPublicDependency(0)
+ .build();
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addDependency("forward.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setTypeName("Bar")
+ .setName("bar")
+ .setNumber(1)))
+ .build();
+ FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+ barProto, new FileDescriptor[0]);
+ FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
+ forwardProto, new FileDescriptor[]{barFile});
+ Descriptors.FileDescriptor.buildFrom(
+ fooProto, new FileDescriptor[] {forwardFile});
+ }
+
+ /**
+ * Tests the translate/crosslink for an example with a more complex namespace
+ * referencing.
+ */
+ public void testComplexNamespacePublicDependency() throws Exception {
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("bar.proto")
+ .setPackage("a.b.c.d.bar.shared")
+ .addEnumType(EnumDescriptorProto.newBuilder()
+ .setName("MyEnum")
+ .addValue(EnumValueDescriptorProto.newBuilder()
+ .setName("BLAH")
+ .setNumber(1)))
+ .build();
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addDependency("bar.proto")
+ .setPackage("a.b.c.d.foo.shared")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("MyMessage")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
+ .setTypeName("bar.shared.MyEnum")
+ .setName("MyField")
+ .setNumber(1)))
+ .build();
+ // translate and crosslink
+ FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(
+ fooProto, new FileDescriptor[0]);
+ FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+ barProto, new FileDescriptor[]{fooFile});
+ // verify resulting descriptors
+ assertNotNull(barFile);
+ List<Descriptor> msglist = barFile.getMessageTypes();
+ assertNotNull(msglist);
+ assertTrue(msglist.size() == 1);
+ Descriptor desc = msglist.get(0);
+ if (desc.getName().equals("MyMessage")) {
+ assertNotNull(desc.getFields());
+ List<FieldDescriptor> fieldlist = desc.getFields();
+ assertNotNull(fieldlist);
+ assertTrue(fieldlist.size() == 1);
+ FieldDescriptor field = fieldlist.get(0);
+ assertTrue(field.getType() == FieldDescriptor.Type.ENUM);
+ assertTrue(field.getEnumType().getName().equals("MyEnum"));
+ assertTrue(field.getEnumType().getFile().getName().equals("bar.proto"));
+ assertTrue(field.getEnumType().getFile().getPackage().equals(
+ "a.b.c.d.bar.shared"));
+ }
+ }
}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/DynamicMessageTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
index aabccda..990e8ca 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
@@ -30,8 +30,9 @@
package com.google.protobuf;
-import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
import protobuf_unittest.UnittestProto.TestPackedTypes;
import junit.framework.TestCase;
@@ -61,28 +62,44 @@
reflectionTester.assertAllFieldsSetViaReflection(message);
}
- public void testDoubleBuildError() throws Exception {
+ public void testSettersAfterBuild() throws Exception {
Message.Builder builder =
DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ Message firstMessage = builder.build();
+ // double build()
builder.build();
- try {
- builder.build();
- fail("Should have thrown exception.");
- } catch (IllegalStateException e) {
- // Success.
- }
+ // clear() after build()
+ builder.clear();
+ // setters after build()
+ reflectionTester.setAllFieldsViaReflection(builder);
+ Message message = builder.build();
+ reflectionTester.assertAllFieldsSetViaReflection(message);
+ // repeated setters after build()
+ reflectionTester.modifyRepeatedFieldsViaReflection(builder);
+ message = builder.build();
+ reflectionTester.assertRepeatedFieldsModifiedViaReflection(message);
+ // firstMessage shouldn't have been modified.
+ reflectionTester.assertClearViaReflection(firstMessage);
}
- public void testClearAfterBuildError() throws Exception {
+ public void testUnknownFields() throws Exception {
Message.Builder builder =
- DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
- builder.build();
- try {
- builder.clear();
- fail("Should have thrown exception.");
- } catch (IllegalStateException e) {
- // Success.
- }
+ DynamicMessage.newBuilder(TestEmptyMessage.getDescriptor());
+ builder.setUnknownFields(UnknownFieldSet.newBuilder()
+ .addField(1, UnknownFieldSet.Field.newBuilder().addVarint(1).build())
+ .addField(2, UnknownFieldSet.Field.newBuilder().addFixed32(1).build())
+ .build());
+ Message message = builder.build();
+ assertEquals(2, message.getUnknownFields().asMap().size());
+ // clone() with unknown fields
+ Message.Builder newBuilder = builder.clone();
+ assertEquals(2, newBuilder.getUnknownFields().asMap().size());
+ // clear() with unknown fields
+ newBuilder.clear();
+ assertTrue(newBuilder.getUnknownFields().asMap().isEmpty());
+ // serialize/parse with unknown fields
+ newBuilder.mergeFrom(message.toByteString());
+ assertEquals(2, newBuilder.getUnknownFields().asMap().size());
}
public void testDynamicMessageSettersRejectNull() throws Exception {
@@ -167,6 +184,23 @@
Message message2 =
DynamicMessage.parseFrom(TestAllTypes.getDescriptor(), rawBytes);
reflectionTester.assertAllFieldsSetViaReflection(message2);
+
+ // Test Parser interface.
+ Message message3 = message2.getParserForType().parseFrom(rawBytes);
+ reflectionTester.assertAllFieldsSetViaReflection(message3);
+ }
+
+ public void testDynamicMessageExtensionParsing() throws Exception {
+ ByteString rawBytes = TestUtil.getAllExtensionsSet().toByteString();
+ Message message = DynamicMessage.parseFrom(
+ TestAllExtensions.getDescriptor(), rawBytes,
+ TestUtil.getExtensionRegistry());
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
+
+ // Test Parser interface.
+ Message message2 = message.getParserForType().parseFrom(
+ rawBytes, TestUtil.getExtensionRegistry());
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(message2);
}
public void testDynamicMessagePackedSerialization() throws Exception {
@@ -194,6 +228,10 @@
Message message2 =
DynamicMessage.parseFrom(TestPackedTypes.getDescriptor(), rawBytes);
packedReflectionTester.assertPackedFieldsSetViaReflection(message2);
+
+ // Test Parser interface.
+ Message message3 = message2.getParserForType().parseFrom(rawBytes);
+ packedReflectionTester.assertPackedFieldsSetViaReflection(message3);
}
public void testDynamicMessageCopy() throws Exception {
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index acb2235..bf9db75 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -30,6 +30,8 @@
package com.google.protobuf;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
import com.google.protobuf.test.UnittestImport;
import protobuf_unittest.EnumWithNoOuter;
@@ -53,6 +55,7 @@
import protobuf_unittest.UnittestProto.ForeignMessageOrBuilder;
import protobuf_unittest.UnittestProto.TestAllExtensions;
import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
import protobuf_unittest.UnittestProto.TestPackedTypes;
@@ -180,6 +183,33 @@
assertIsUnmodifiable(value.getRepeatedFloatList());
}
+ public void testParsedMessagesAreImmutable() throws Exception {
+ TestAllTypes value = TestAllTypes.PARSER.parseFrom(
+ TestUtil.getAllSet().toByteString());
+ assertIsUnmodifiable(value.getRepeatedInt32List());
+ assertIsUnmodifiable(value.getRepeatedInt64List());
+ assertIsUnmodifiable(value.getRepeatedUint32List());
+ assertIsUnmodifiable(value.getRepeatedUint64List());
+ assertIsUnmodifiable(value.getRepeatedSint32List());
+ assertIsUnmodifiable(value.getRepeatedSint64List());
+ assertIsUnmodifiable(value.getRepeatedFixed32List());
+ assertIsUnmodifiable(value.getRepeatedFixed64List());
+ assertIsUnmodifiable(value.getRepeatedSfixed32List());
+ assertIsUnmodifiable(value.getRepeatedSfixed64List());
+ assertIsUnmodifiable(value.getRepeatedFloatList());
+ assertIsUnmodifiable(value.getRepeatedDoubleList());
+ assertIsUnmodifiable(value.getRepeatedBoolList());
+ assertIsUnmodifiable(value.getRepeatedStringList());
+ assertIsUnmodifiable(value.getRepeatedBytesList());
+ assertIsUnmodifiable(value.getRepeatedGroupList());
+ assertIsUnmodifiable(value.getRepeatedNestedMessageList());
+ assertIsUnmodifiable(value.getRepeatedForeignMessageList());
+ assertIsUnmodifiable(value.getRepeatedImportMessageList());
+ assertIsUnmodifiable(value.getRepeatedNestedEnumList());
+ assertIsUnmodifiable(value.getRepeatedForeignEnumList());
+ assertIsUnmodifiable(value.getRepeatedImportEnumList());
+ }
+
private void assertIsUnmodifiable(List<?> list) {
if (list == Collections.emptyList()) {
// OKAY -- Need to check this b/c EmptyList allows you to call clear.
@@ -881,7 +911,7 @@
builder.setOptionalNestedMessage(nestedMessage1);
assertEquals(3, mockParent.getInvalidationCount());
- // primitive repated
+ // primitive repeated
builder.buildPartial();
builder.addRepeatedInt32(2);
builder.addRepeatedInt32(3);
@@ -977,4 +1007,140 @@
assertSame(b1, messageOrBuilderList.get(1));
assertSame(m2, messageOrBuilderList.get(2));
}
+
+ public void testGetFieldBuilder() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+
+ FieldDescriptor fieldDescriptor =
+ descriptor.findFieldByName("optional_nested_message");
+ FieldDescriptor foreignFieldDescriptor =
+ descriptor.findFieldByName("optional_foreign_message");
+ FieldDescriptor importFieldDescriptor =
+ descriptor.findFieldByName("optional_import_message");
+
+ // Mutate the message with new field builder
+ // Mutate nested message
+ TestAllTypes.Builder builder1 = TestAllTypes.newBuilder();
+ Message.Builder fieldBuilder1 = builder1.newBuilderForField(fieldDescriptor)
+ .mergeFrom((Message) builder1.getField(fieldDescriptor));
+ FieldDescriptor subFieldDescriptor1 =
+ fieldBuilder1.getDescriptorForType().findFieldByName("bb");
+ fieldBuilder1.setField(subFieldDescriptor1, 1);
+ builder1.setField(fieldDescriptor, fieldBuilder1.build());
+
+ // Mutate foreign message
+ Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField(
+ foreignFieldDescriptor)
+ .mergeFrom((Message) builder1.getField(foreignFieldDescriptor));
+ FieldDescriptor subForeignFieldDescriptor1 =
+ foreignFieldBuilder1.getDescriptorForType().findFieldByName("c");
+ foreignFieldBuilder1.setField(subForeignFieldDescriptor1, 2);
+ builder1.setField(foreignFieldDescriptor, foreignFieldBuilder1.build());
+
+ // Mutate import message
+ Message.Builder importFieldBuilder1 = builder1.newBuilderForField(
+ importFieldDescriptor)
+ .mergeFrom((Message) builder1.getField(importFieldDescriptor));
+ FieldDescriptor subImportFieldDescriptor1 =
+ importFieldBuilder1.getDescriptorForType().findFieldByName("d");
+ importFieldBuilder1.setField(subImportFieldDescriptor1, 3);
+ builder1.setField(importFieldDescriptor, importFieldBuilder1.build());
+
+ Message newMessage1 = builder1.build();
+
+ // Mutate the message with existing field builder
+ // Mutate nested message
+ TestAllTypes.Builder builder2 = TestAllTypes.newBuilder();
+ Message.Builder fieldBuilder2 = builder2.getFieldBuilder(fieldDescriptor);
+ FieldDescriptor subFieldDescriptor2 =
+ fieldBuilder2.getDescriptorForType().findFieldByName("bb");
+ fieldBuilder2.setField(subFieldDescriptor2, 1);
+ builder2.setField(fieldDescriptor, fieldBuilder2.build());
+
+ // Mutate foreign message
+ Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField(
+ foreignFieldDescriptor)
+ .mergeFrom((Message) builder2.getField(foreignFieldDescriptor));
+ FieldDescriptor subForeignFieldDescriptor2 =
+ foreignFieldBuilder2.getDescriptorForType().findFieldByName("c");
+ foreignFieldBuilder2.setField(subForeignFieldDescriptor2, 2);
+ builder2.setField(foreignFieldDescriptor, foreignFieldBuilder2.build());
+
+ // Mutate import message
+ Message.Builder importFieldBuilder2 = builder2.newBuilderForField(
+ importFieldDescriptor)
+ .mergeFrom((Message) builder2.getField(importFieldDescriptor));
+ FieldDescriptor subImportFieldDescriptor2 =
+ importFieldBuilder2.getDescriptorForType().findFieldByName("d");
+ importFieldBuilder2.setField(subImportFieldDescriptor2, 3);
+ builder2.setField(importFieldDescriptor, importFieldBuilder2.build());
+
+ Message newMessage2 = builder2.build();
+
+ // These two messages should be equal.
+ assertEquals(newMessage1, newMessage2);
+ }
+
+ public void testGetFieldBuilderWithInitializedValue() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor fieldDescriptor =
+ descriptor.findFieldByName("optional_nested_message");
+
+ // Before setting field, builder is initialized by default value.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ NestedMessage.Builder fieldBuilder =
+ (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
+ assertEquals(0, fieldBuilder.getBb());
+
+ // Setting field value with new field builder instance.
+ builder = TestAllTypes.newBuilder();
+ NestedMessage.Builder newFieldBuilder =
+ builder.getOptionalNestedMessageBuilder();
+ newFieldBuilder.setBb(2);
+ // Then get the field builder instance by getFieldBuilder().
+ fieldBuilder =
+ (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
+ // It should contain new value.
+ assertEquals(2, fieldBuilder.getBb());
+ // These two builder should be equal.
+ assertSame(fieldBuilder, newFieldBuilder);
+ }
+
+ public void testGetFieldBuilderNotSupportedException() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ builder.getFieldBuilder(descriptor.findFieldByName("optional_int32"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(
+ descriptor.findFieldByName("optional_nested_enum"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(descriptor.findFieldByName("repeated_int32"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(
+ descriptor.findFieldByName("repeated_nested_enum"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(
+ descriptor.findFieldByName("repeated_nested_message"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ }
}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/IsValidUtf8Test.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/IsValidUtf8Test.java
new file mode 100644
index 0000000..b204b60
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/IsValidUtf8Test.java
@@ -0,0 +1,180 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import com.google.protobuf.IsValidUtf8TestUtil.Shard;
+
+import junit.framework.TestCase;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Tests cases for {@link ByteString#isValidUtf8()}. This includes three
+ * brute force tests that actually test every permutation of one byte, two byte,
+ * and three byte sequences to ensure that the method produces the right result
+ * for every possible byte encoding where "right" means it's consistent with
+ * java's UTF-8 string encoding/decoding such that the method returns true for
+ * any sequence that will round trip when converted to a String and then back to
+ * bytes and will return false for any sequence that will not round trip.
+ * See also {@link IsValidUtf8FourByteTest}. It also includes some
+ * other more targeted tests.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ * @author martinrb@google.com (Martin Buchholz)
+ */
+public class IsValidUtf8Test extends TestCase {
+
+ /**
+ * Tests that round tripping of all two byte permutations work.
+ */
+ public void testIsValidUtf8_1Byte() throws UnsupportedEncodingException {
+ IsValidUtf8TestUtil.testBytes(1,
+ IsValidUtf8TestUtil.EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT);
+ }
+
+ /**
+ * Tests that round tripping of all two byte permutations work.
+ */
+ public void testIsValidUtf8_2Bytes() throws UnsupportedEncodingException {
+ IsValidUtf8TestUtil.testBytes(2,
+ IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT);
+ }
+
+ /**
+ * Tests that round tripping of all three byte permutations work.
+ */
+ public void testIsValidUtf8_3Bytes() throws UnsupportedEncodingException {
+ IsValidUtf8TestUtil.testBytes(3,
+ IsValidUtf8TestUtil.EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT);
+ }
+
+ /**
+ * Tests that round tripping of a sample of four byte permutations work.
+ * All permutations are prohibitively expensive to test for automated runs;
+ * {@link IsValidUtf8FourByteTest} is used for full coverage. This method
+ * tests specific four-byte cases.
+ */
+ public void testIsValidUtf8_4BytesSamples()
+ throws UnsupportedEncodingException {
+ // Valid 4 byte.
+ assertValidUtf8(0xF0, 0xA4, 0xAD, 0xA2);
+
+ // Bad trailing bytes
+ assertInvalidUtf8(0xF0, 0xA4, 0xAD, 0x7F);
+ assertInvalidUtf8(0xF0, 0xA4, 0xAD, 0xC0);
+
+ // Special cases for byte2
+ assertInvalidUtf8(0xF0, 0x8F, 0xAD, 0xA2);
+ assertInvalidUtf8(0xF4, 0x90, 0xAD, 0xA2);
+ }
+
+ /**
+ * Tests some hard-coded test cases.
+ */
+ public void testSomeSequences() {
+ // Empty
+ assertTrue(asBytes("").isValidUtf8());
+
+ // One-byte characters, including control characters
+ assertTrue(asBytes("\u0000abc\u007f").isValidUtf8());
+
+ // Two-byte characters
+ assertTrue(asBytes("\u00a2\u00a2").isValidUtf8());
+
+ // Three-byte characters
+ assertTrue(asBytes("\u020ac\u020ac").isValidUtf8());
+
+ // Four-byte characters
+ assertTrue(asBytes("\u024B62\u024B62").isValidUtf8());
+
+ // Mixed string
+ assertTrue(
+ asBytes("a\u020ac\u00a2b\\u024B62u020acc\u00a2de\u024B62")
+ .isValidUtf8());
+
+ // Not a valid string
+ assertInvalidUtf8(-1, 0, -1, 0);
+ }
+
+ private byte[] toByteArray(int... bytes) {
+ byte[] realBytes = new byte[bytes.length];
+ for (int i = 0; i < bytes.length; i++) {
+ realBytes[i] = (byte) bytes[i];
+ }
+ return realBytes;
+ }
+
+ private ByteString toByteString(int... bytes) {
+ return ByteString.copyFrom(toByteArray(bytes));
+ }
+
+ private void assertValidUtf8(int[] bytes, boolean not) {
+ byte[] realBytes = toByteArray(bytes);
+ assertTrue(not ^ Utf8.isValidUtf8(realBytes));
+ assertTrue(not ^ Utf8.isValidUtf8(realBytes, 0, bytes.length));
+ ByteString lit = ByteString.copyFrom(realBytes);
+ ByteString sub = lit.substring(0, bytes.length);
+ assertTrue(not ^ lit.isValidUtf8());
+ assertTrue(not ^ sub.isValidUtf8());
+ ByteString[] ropes = {
+ RopeByteString.newInstanceForTest(ByteString.EMPTY, lit),
+ RopeByteString.newInstanceForTest(ByteString.EMPTY, sub),
+ RopeByteString.newInstanceForTest(lit, ByteString.EMPTY),
+ RopeByteString.newInstanceForTest(sub, ByteString.EMPTY),
+ RopeByteString.newInstanceForTest(sub, lit)
+ };
+ for (ByteString rope : ropes) {
+ assertTrue(not ^ rope.isValidUtf8());
+ }
+ }
+
+ private void assertValidUtf8(int... bytes) {
+ assertValidUtf8(bytes, false);
+ }
+
+ private void assertInvalidUtf8(int... bytes) {
+ assertValidUtf8(bytes, true);
+ }
+
+ private static ByteString asBytes(String s) {
+ return ByteString.copyFromUtf8(s);
+ }
+
+ public void testShardsHaveExpectedRoundTrippables() {
+ // A sanity check.
+ int actual = 0;
+ for (Shard shard : IsValidUtf8TestUtil.FOUR_BYTE_SHARDS) {
+ actual += shard.expected;
+ }
+ assertEquals(IsValidUtf8TestUtil.EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT,
+ actual);
+ }
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java
new file mode 100644
index 0000000..4cb3d5b
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java
@@ -0,0 +1,421 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import static junit.framework.Assert.*;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.logging.Logger;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.Charset;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+
+/**
+ * Shared testing code for {@link IsValidUtf8Test} and
+ * {@link IsValidUtf8FourByteTest}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ * @author martinrb@google.com (Martin Buchholz)
+ */
+class IsValidUtf8TestUtil {
+ private static Logger logger = Logger.getLogger(
+ IsValidUtf8TestUtil.class.getName());
+
+ // 128 - [chars 0x0000 to 0x007f]
+ static long ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x007f - 0x0000 + 1;
+
+ // 128
+ static long EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT =
+ ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+ // 1920 [chars 0x0080 to 0x07FF]
+ static long TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x07FF - 0x0080 + 1;
+
+ // 18,304
+ static long EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT =
+ // Both bytes are one byte characters
+ (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 2) +
+ // The possible number of two byte characters
+ TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+ // 2048
+ static long THREE_BYTE_SURROGATES = 2 * 1024;
+
+ // 61,440 [chars 0x0800 to 0xFFFF, minus surrogates]
+ static long THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS =
+ 0xFFFF - 0x0800 + 1 - THREE_BYTE_SURROGATES;
+
+ // 2,650,112
+ static long EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT =
+ // All one byte characters
+ (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 3) +
+ // One two byte character and a one byte character
+ 2 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS *
+ ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+ // Three byte characters
+ THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+ // 1,048,576 [chars 0x10000L to 0x10FFFF]
+ static long FOUR_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x10FFFF - 0x10000L + 1;
+
+ // 289,571,839
+ static long EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT =
+ // All one byte characters
+ (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 4) +
+ // One and three byte characters
+ 2 * THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS *
+ ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+ // Two two byte characters
+ TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+ // Permutations of one and two byte characters
+ 3 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS *
+ ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS *
+ ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+ // Four byte characters
+ FOUR_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+ static class Shard {
+ final long index;
+ final long start;
+ final long lim;
+ final long expected;
+
+
+ public Shard(long index, long start, long lim, long expected) {
+ assertTrue(start < lim);
+ this.index = index;
+ this.start = start;
+ this.lim = lim;
+ this.expected = expected;
+ }
+ }
+
+ static final long[] FOUR_BYTE_SHARDS_EXPECTED_ROUNTRIPPABLES =
+ generateFourByteShardsExpectedRunnables();
+
+ private static long[] generateFourByteShardsExpectedRunnables() {
+ long[] expected = new long[128];
+
+ // 0-63 are all 5300224
+ for (int i = 0; i <= 63; i++) {
+ expected[i] = 5300224;
+ }
+
+ // 97-111 are all 2342912
+ for (int i = 97; i <= 111; i++) {
+ expected[i] = 2342912;
+ }
+
+ // 113-117 are all 1048576
+ for (int i = 113; i <= 117; i++) {
+ expected[i] = 1048576;
+ }
+
+ // One offs
+ expected[112] = 786432;
+ expected[118] = 786432;
+ expected[119] = 1048576;
+ expected[120] = 458752;
+ expected[121] = 524288;
+ expected[122] = 65536;
+
+ // Anything not assigned was the default 0.
+ return expected;
+ }
+
+ static final List<Shard> FOUR_BYTE_SHARDS = generateFourByteShards(
+ 128, FOUR_BYTE_SHARDS_EXPECTED_ROUNTRIPPABLES);
+
+
+ private static List<Shard> generateFourByteShards(
+ int numShards, long[] expected) {
+ assertEquals(numShards, expected.length);
+ List<Shard> shards = new ArrayList<Shard>(numShards);
+ long LIM = 1L << 32;
+ long increment = LIM / numShards;
+ assertTrue(LIM % numShards == 0);
+ for (int i = 0; i < numShards; i++) {
+ shards.add(new Shard(i,
+ increment * i,
+ increment * (i + 1),
+ expected[i]));
+ }
+ return shards;
+ }
+
+ /**
+ * Helper to run the loop to test all the permutations for the number of bytes
+ * specified.
+ *
+ * @param numBytes the number of bytes in the byte array
+ * @param expectedCount the expected number of roundtrippable permutations
+ */
+ static void testBytes(int numBytes, long expectedCount)
+ throws UnsupportedEncodingException {
+ testBytes(numBytes, expectedCount, 0, -1);
+ }
+
+ /**
+ * Helper to run the loop to test all the permutations for the number of bytes
+ * specified. This overload is useful for debugging to get the loop to start
+ * at a certain character.
+ *
+ * @param numBytes the number of bytes in the byte array
+ * @param expectedCount the expected number of roundtrippable permutations
+ * @param start the starting bytes encoded as a long as big-endian
+ * @param lim the limit of bytes to process encoded as a long as big-endian,
+ * or -1 to mean the max limit for numBytes
+ */
+ static void testBytes(int numBytes, long expectedCount, long start, long lim)
+ throws UnsupportedEncodingException {
+ Random rnd = new Random();
+ byte[] bytes = new byte[numBytes];
+
+ if (lim == -1) {
+ lim = 1L << (numBytes * 8);
+ }
+ long count = 0;
+ long countRoundTripped = 0;
+ for (long byteChar = start; byteChar < lim; byteChar++) {
+ long tmpByteChar = byteChar;
+ for (int i = 0; i < numBytes; i++) {
+ bytes[bytes.length - i - 1] = (byte) tmpByteChar;
+ tmpByteChar = tmpByteChar >> 8;
+ }
+ ByteString bs = ByteString.copyFrom(bytes);
+ boolean isRoundTrippable = bs.isValidUtf8();
+ String s = new String(bytes, "UTF-8");
+ byte[] bytesReencoded = s.getBytes("UTF-8");
+ boolean bytesEqual = Arrays.equals(bytes, bytesReencoded);
+
+ if (bytesEqual != isRoundTrippable) {
+ outputFailure(byteChar, bytes, bytesReencoded);
+ }
+
+ // Check agreement with static Utf8 methods.
+ assertEquals(isRoundTrippable, Utf8.isValidUtf8(bytes));
+ assertEquals(isRoundTrippable, Utf8.isValidUtf8(bytes, 0, numBytes));
+
+ // Test partial sequences.
+ // Partition numBytes into three segments (not necessarily non-empty).
+ int i = rnd.nextInt(numBytes);
+ int j = rnd.nextInt(numBytes);
+ if (j < i) {
+ int tmp = i; i = j; j = tmp;
+ }
+ int state1 = Utf8.partialIsValidUtf8(Utf8.COMPLETE, bytes, 0, i);
+ int state2 = Utf8.partialIsValidUtf8(state1, bytes, i, j);
+ int state3 = Utf8.partialIsValidUtf8(state2, bytes, j, numBytes);
+ if (isRoundTrippable != (state3 == Utf8.COMPLETE)) {
+ System.out.printf("state=%04x %04x %04x i=%d j=%d%n",
+ state1, state2, state3, i, j);
+ outputFailure(byteChar, bytes, bytesReencoded);
+ }
+ assertEquals(isRoundTrippable, (state3 == Utf8.COMPLETE));
+
+ // Test ropes built out of small partial sequences
+ ByteString rope = RopeByteString.newInstanceForTest(
+ bs.substring(0, i),
+ RopeByteString.newInstanceForTest(
+ bs.substring(i, j),
+ bs.substring(j, numBytes)));
+ assertSame(RopeByteString.class, rope.getClass());
+
+ ByteString[] byteStrings = { bs, bs.substring(0, numBytes), rope };
+ for (ByteString x : byteStrings) {
+ assertEquals(isRoundTrippable,
+ x.isValidUtf8());
+ assertEquals(state3,
+ x.partialIsValidUtf8(Utf8.COMPLETE, 0, numBytes));
+
+ assertEquals(state1,
+ x.partialIsValidUtf8(Utf8.COMPLETE, 0, i));
+ assertEquals(state1,
+ x.substring(0, i).partialIsValidUtf8(Utf8.COMPLETE, 0, i));
+ assertEquals(state2,
+ x.partialIsValidUtf8(state1, i, j - i));
+ assertEquals(state2,
+ x.substring(i, j).partialIsValidUtf8(state1, 0, j - i));
+ assertEquals(state3,
+ x.partialIsValidUtf8(state2, j, numBytes - j));
+ assertEquals(state3,
+ x.substring(j, numBytes)
+ .partialIsValidUtf8(state2, 0, numBytes - j));
+ }
+
+ // ByteString reduplication should not affect its UTF-8 validity.
+ ByteString ropeADope =
+ RopeByteString.newInstanceForTest(bs, bs.substring(0, numBytes));
+ assertEquals(isRoundTrippable, ropeADope.isValidUtf8());
+
+ if (isRoundTrippable) {
+ countRoundTripped++;
+ }
+ count++;
+ if (byteChar != 0 && byteChar % 1000000L == 0) {
+ logger.info("Processed " + (byteChar / 1000000L) +
+ " million characters");
+ }
+ }
+ logger.info("Round tripped " + countRoundTripped + " of " + count);
+ assertEquals(expectedCount, countRoundTripped);
+ }
+
+ /**
+ * Variation of {@link #testBytes} that does less allocation using the
+ * low-level encoders/decoders directly. Checked in because it's useful for
+ * debugging when trying to process bytes faster, but since it doesn't use the
+ * actual String class, it's possible for incompatibilities to develop
+ * (although unlikely).
+ *
+ * @param numBytes the number of bytes in the byte array
+ * @param expectedCount the expected number of roundtrippable permutations
+ * @param start the starting bytes encoded as a long as big-endian
+ * @param lim the limit of bytes to process encoded as a long as big-endian,
+ * or -1 to mean the max limit for numBytes
+ */
+ void testBytesUsingByteBuffers(
+ int numBytes, long expectedCount, long start, long lim)
+ throws UnsupportedEncodingException {
+ CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder()
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE);
+ CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder()
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE);
+ byte[] bytes = new byte[numBytes];
+ int maxChars = (int) (decoder.maxCharsPerByte() * numBytes) + 1;
+ char[] charsDecoded =
+ new char[(int) (decoder.maxCharsPerByte() * numBytes) + 1];
+ int maxBytes = (int) (encoder.maxBytesPerChar() * maxChars) + 1;
+ byte[] bytesReencoded = new byte[maxBytes];
+
+ ByteBuffer bb = ByteBuffer.wrap(bytes);
+ CharBuffer cb = CharBuffer.wrap(charsDecoded);
+ ByteBuffer bbReencoded = ByteBuffer.wrap(bytesReencoded);
+ if (lim == -1) {
+ lim = 1L << (numBytes * 8);
+ }
+ long count = 0;
+ long countRoundTripped = 0;
+ for (long byteChar = start; byteChar < lim; byteChar++) {
+ bb.rewind();
+ bb.limit(bytes.length);
+ cb.rewind();
+ cb.limit(charsDecoded.length);
+ bbReencoded.rewind();
+ bbReencoded.limit(bytesReencoded.length);
+ encoder.reset();
+ decoder.reset();
+ long tmpByteChar = byteChar;
+ for (int i = 0; i < bytes.length; i++) {
+ bytes[bytes.length - i - 1] = (byte) tmpByteChar;
+ tmpByteChar = tmpByteChar >> 8;
+ }
+ boolean isRoundTrippable = ByteString.copyFrom(bytes).isValidUtf8();
+ CoderResult result = decoder.decode(bb, cb, true);
+ assertFalse(result.isError());
+ result = decoder.flush(cb);
+ assertFalse(result.isError());
+
+ int charLen = cb.position();
+ cb.rewind();
+ cb.limit(charLen);
+ result = encoder.encode(cb, bbReencoded, true);
+ assertFalse(result.isError());
+ result = encoder.flush(bbReencoded);
+ assertFalse(result.isError());
+
+ boolean bytesEqual = true;
+ int bytesLen = bbReencoded.position();
+ if (bytesLen != numBytes) {
+ bytesEqual = false;
+ } else {
+ for (int i = 0; i < numBytes; i++) {
+ if (bytes[i] != bytesReencoded[i]) {
+ bytesEqual = false;
+ break;
+ }
+ }
+ }
+ if (bytesEqual != isRoundTrippable) {
+ outputFailure(byteChar, bytes, bytesReencoded, bytesLen);
+ }
+
+ count++;
+ if (isRoundTrippable) {
+ countRoundTripped++;
+ }
+ if (byteChar != 0 && byteChar % 1000000 == 0) {
+ logger.info("Processed " + (byteChar / 1000000) +
+ " million characters");
+ }
+ }
+ logger.info("Round tripped " + countRoundTripped + " of " + count);
+ assertEquals(expectedCount, countRoundTripped);
+ }
+
+ private static void outputFailure(long byteChar, byte[] bytes, byte[] after) {
+ outputFailure(byteChar, bytes, after, after.length);
+ }
+
+ private static void outputFailure(long byteChar, byte[] bytes, byte[] after,
+ int len) {
+ fail("Failure: (" + Long.toHexString(byteChar) + ") " +
+ toHexString(bytes) + " => " + toHexString(after, len));
+ }
+
+ private static String toHexString(byte[] b) {
+ return toHexString(b, b.length);
+ }
+
+ private static String toHexString(byte[] b, int len) {
+ StringBuilder s = new StringBuilder();
+ s.append("\"");
+ for (int i = 0; i < len; i++) {
+ if (i > 0) {
+ s.append(" ");
+ }
+ s.append(String.format("%02x", b[i] & 0xFF));
+ }
+ s.append("\"");
+ return s.toString();
+ }
+
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
index 4dcdc74..d500595 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
@@ -32,6 +32,9 @@
import junit.framework.TestCase;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Tests for {@link LazyStringArrayList}.
*
@@ -115,4 +118,45 @@
assertSame(aPrimeByteString, list.getByteString(0));
assertSame(bPrimeByteString, list.getByteString(1));
}
+
+ public void testCopyConstructorCopiesByReference() {
+ LazyStringArrayList list1 = new LazyStringArrayList();
+ list1.add(STRING_A);
+ list1.add(BYTE_STRING_B);
+ list1.add(BYTE_STRING_C);
+
+ LazyStringArrayList list2 = new LazyStringArrayList(list1);
+ assertEquals(3, list2.size());
+ assertSame(STRING_A, list2.get(0));
+ assertSame(BYTE_STRING_B, list2.getByteString(1));
+ assertSame(BYTE_STRING_C, list2.getByteString(2));
+ }
+
+ public void testListCopyConstructor() {
+ List<String> list1 = new ArrayList<String>();
+ list1.add(STRING_A);
+ list1.add(STRING_B);
+ list1.add(STRING_C);
+
+ LazyStringArrayList list2 = new LazyStringArrayList(list1);
+ assertEquals(3, list2.size());
+ assertSame(STRING_A, list2.get(0));
+ assertSame(STRING_B, list2.get(1));
+ assertSame(STRING_C, list2.get(2));
+ }
+
+ public void testAddAllCopiesByReferenceIfPossible() {
+ LazyStringArrayList list1 = new LazyStringArrayList();
+ list1.add(STRING_A);
+ list1.add(BYTE_STRING_B);
+ list1.add(BYTE_STRING_C);
+
+ LazyStringArrayList list2 = new LazyStringArrayList();
+ list2.addAll(list1);
+
+ assertEquals(3, list2.size());
+ assertSame(STRING_A, list2.get(0));
+ assertSame(BYTE_STRING_B, list2.getByteString(1));
+ assertSame(BYTE_STRING_C, list2.getByteString(2));
+ }
}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
index e6870b5..fe9599e 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
@@ -50,6 +50,19 @@
114, 4, -1, 0, -1, 0, -30, 2, 4, -1,
0, -1, 0, -30, 2, 4, -1, 0, -1, 0, });
+ private ByteString encodedTestAllTypes;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.encodedTestAllTypes = UnittestProto.TestAllTypes.newBuilder()
+ .setOptionalString("foo")
+ .addRepeatedString("bar")
+ .addRepeatedString("baz")
+ .build()
+ .toByteString();
+ }
+
/**
* Tests that an invalid UTF8 string will roundtrip through a parse
* and serialization.
@@ -112,4 +125,19 @@
assertSame(bPrime, proto.getRepeatedString(0));
assertSame(cPrime, proto.getRepeatedString(1));
}
+
+ public void testNoStringCachingIfOnlyBytesAccessed() throws Exception {
+ UnittestProto.TestAllTypes proto =
+ UnittestProto.TestAllTypes.parseFrom(encodedTestAllTypes);
+ ByteString optional = proto.getOptionalStringBytes();
+ assertSame(optional, proto.getOptionalStringBytes());
+ assertSame(optional, proto.toBuilder().getOptionalStringBytes());
+
+ ByteString repeated0 = proto.getRepeatedStringBytes(0);
+ ByteString repeated1 = proto.getRepeatedStringBytes(1);
+ assertSame(repeated0, proto.getRepeatedStringBytes(0));
+ assertSame(repeated1, proto.getRepeatedStringBytes(1));
+ assertSame(repeated0, proto.toBuilder().getRepeatedStringBytes(0));
+ assertSame(repeated1, proto.toBuilder().getRepeatedStringBytes(1));
+ }
}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
new file mode 100644
index 0000000..deee1ee
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
@@ -0,0 +1,396 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Test {@link LiteralByteString} by setting up a reference string in {@link #setUp()}.
+ * This class is designed to be extended for testing extensions of {@link LiteralByteString}
+ * such as {@link BoundedByteString}, see {@link BoundedByteStringTest}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class LiteralByteStringTest extends TestCase {
+ protected static final String UTF_8 = "UTF-8";
+
+ protected String classUnderTest;
+ protected byte[] referenceBytes;
+ protected ByteString stringUnderTest;
+ protected int expectedHashCode;
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "LiteralByteString";
+ referenceBytes = ByteStringTest.getTestBytes(1234, 11337766L);
+ stringUnderTest = ByteString.copyFrom(referenceBytes);
+ expectedHashCode = 331161852;
+ }
+
+ public void testExpectedType() {
+ String actualClassName = getActualClassName(stringUnderTest);
+ assertEquals(classUnderTest + " should match type exactly", classUnderTest, actualClassName);
+ }
+
+ protected String getActualClassName(Object object) {
+ String actualClassName = object.getClass().getName();
+ actualClassName = actualClassName.substring(actualClassName.lastIndexOf('.') + 1);
+ return actualClassName;
+ }
+
+ public void testByteAt() {
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
+ stillEqual = (referenceBytes[i] == stringUnderTest.byteAt(i));
+ }
+ assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
+ }
+
+ public void testByteIterator() {
+ boolean stillEqual = true;
+ ByteString.ByteIterator iter = stringUnderTest.iterator();
+ for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
+ stillEqual = (iter.hasNext() && referenceBytes[i] == iter.nextByte());
+ }
+ assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
+ assertFalse(classUnderTest + " must have exhausted the itertor", iter.hasNext());
+
+ try {
+ iter.nextByte();
+ fail("Should have thrown an exception.");
+ } catch (NoSuchElementException e) {
+ // This is success
+ }
+ }
+
+ public void testByteIterable() {
+ boolean stillEqual = true;
+ int j = 0;
+ for (byte quantum : stringUnderTest) {
+ stillEqual = (referenceBytes[j] == quantum);
+ ++j;
+ }
+ assertTrue(classUnderTest + " must capture the right bytes as Bytes", stillEqual);
+ assertEquals(classUnderTest + " iterable character count", referenceBytes.length, j);
+ }
+
+ public void testSize() {
+ assertEquals(classUnderTest + " must have the expected size", referenceBytes.length,
+ stringUnderTest.size());
+ }
+
+ public void testGetTreeDepth() {
+ assertEquals(classUnderTest + " must have depth 0", 0, stringUnderTest.getTreeDepth());
+ }
+
+ public void testIsBalanced() {
+ assertTrue(classUnderTest + " is technically balanced", stringUnderTest.isBalanced());
+ }
+
+ public void testCopyTo_ByteArrayOffsetLength() {
+ int destinationOffset = 50;
+ int length = 100;
+ byte[] destination = new byte[destinationOffset + length];
+ int sourceOffset = 213;
+ stringUnderTest.copyTo(destination, sourceOffset, destinationOffset, length);
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < length; ++i) {
+ stillEqual = referenceBytes[i + sourceOffset] == destination[i + destinationOffset];
+ }
+ assertTrue(classUnderTest + ".copyTo(4 arg) must give the expected bytes", stillEqual);
+ }
+
+ public void testCopyTo_ByteArrayOffsetLengthErrors() {
+ int destinationOffset = 50;
+ int length = 100;
+ byte[] destination = new byte[destinationOffset + length];
+
+ try {
+ // Copy one too many bytes
+ stringUnderTest.copyTo(destination, stringUnderTest.size() + 1 - length,
+ destinationOffset, length);
+ fail("Should have thrown an exception when copying too many bytes of a "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative sourceOffset
+ stringUnderTest.copyTo(destination, -1, destinationOffset, length);
+ fail("Should have thrown an exception when given a negative sourceOffset in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative destinationOffset
+ stringUnderTest.copyTo(destination, 0, -1, length);
+ fail("Should have thrown an exception when given a negative destinationOffset in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative size
+ stringUnderTest.copyTo(destination, 0, 0, -1);
+ fail("Should have thrown an exception when given a negative size in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal too-large sourceOffset
+ stringUnderTest.copyTo(destination, 2 * stringUnderTest.size(), 0, length);
+ fail("Should have thrown an exception when the destinationOffset is too large in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal too-large destinationOffset
+ stringUnderTest.copyTo(destination, 0, 2 * destination.length, length);
+ fail("Should have thrown an exception when the destinationOffset is too large in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+ }
+
+ public void testCopyTo_ByteBuffer() {
+ ByteBuffer myBuffer = ByteBuffer.allocate(referenceBytes.length);
+ stringUnderTest.copyTo(myBuffer);
+ assertTrue(classUnderTest + ".copyTo(ByteBuffer) must give back the same bytes",
+ Arrays.equals(referenceBytes, myBuffer.array()));
+ }
+
+ public void testAsReadOnlyByteBuffer() {
+ ByteBuffer byteBuffer = stringUnderTest.asReadOnlyByteBuffer();
+ byte[] roundTripBytes = new byte[referenceBytes.length];
+ assertTrue(byteBuffer.remaining() == referenceBytes.length);
+ assertTrue(byteBuffer.isReadOnly());
+ byteBuffer.get(roundTripBytes);
+ assertTrue(classUnderTest + ".asReadOnlyByteBuffer() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testAsReadOnlyByteBufferList() {
+ List<ByteBuffer> byteBuffers = stringUnderTest.asReadOnlyByteBufferList();
+ int bytesSeen = 0;
+ byte[] roundTripBytes = new byte[referenceBytes.length];
+ for (ByteBuffer byteBuffer : byteBuffers) {
+ int thisLength = byteBuffer.remaining();
+ assertTrue(byteBuffer.isReadOnly());
+ assertTrue(bytesSeen + thisLength <= referenceBytes.length);
+ byteBuffer.get(roundTripBytes, bytesSeen, thisLength);
+ bytesSeen += thisLength;
+ }
+ assertTrue(bytesSeen == referenceBytes.length);
+ assertTrue(classUnderTest + ".asReadOnlyByteBufferTest() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testToByteArray() {
+ byte[] roundTripBytes = stringUnderTest.toByteArray();
+ assertTrue(classUnderTest + ".toByteArray() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testWriteTo() throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ stringUnderTest.writeTo(bos);
+ byte[] roundTripBytes = bos.toByteArray();
+ assertTrue(classUnderTest + ".writeTo() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testWriteTo_mutating() throws IOException {
+ OutputStream os = new OutputStream() {
+ @Override
+ public void write(byte[] b, int off, int len) {
+ for (int x = 0; x < len; ++x) {
+ b[off + x] = (byte) 0;
+ }
+ }
+
+ @Override
+ public void write(int b) {
+ // Purposefully left blank.
+ }
+ };
+
+ stringUnderTest.writeTo(os);
+ byte[] newBytes = stringUnderTest.toByteArray();
+ assertTrue(classUnderTest + ".writeTo() must not grant access to underlying array",
+ Arrays.equals(referenceBytes, newBytes));
+ }
+
+ public void testNewOutput() throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ByteString.Output output = ByteString.newOutput();
+ stringUnderTest.writeTo(output);
+ assertEquals("Output Size returns correct result",
+ output.size(), stringUnderTest.size());
+ output.writeTo(bos);
+ assertTrue("Output.writeTo() must give back the same bytes",
+ Arrays.equals(referenceBytes, bos.toByteArray()));
+
+ // write the output stream to itself! This should cause it to double
+ output.writeTo(output);
+ assertEquals("Writing an output stream to itself is successful",
+ stringUnderTest.concat(stringUnderTest), output.toByteString());
+
+ output.reset();
+ assertEquals("Output.reset() resets the output", 0, output.size());
+ assertEquals("Output.reset() resets the output",
+ ByteString.EMPTY, output.toByteString());
+
+ }
+
+ public void testToString() throws UnsupportedEncodingException {
+ String testString = "I love unicode \u1234\u5678 characters";
+ LiteralByteString unicode = new LiteralByteString(testString.getBytes(UTF_8));
+ String roundTripString = unicode.toString(UTF_8);
+ assertEquals(classUnderTest + " unicode must match", testString, roundTripString);
+ }
+
+ public void testEquals() {
+ assertEquals(classUnderTest + " must not equal null", false, stringUnderTest.equals(null));
+ assertEquals(classUnderTest + " must equal self", stringUnderTest, stringUnderTest);
+ assertFalse(classUnderTest + " must not equal the empty string",
+ stringUnderTest.equals(ByteString.EMPTY));
+ assertEquals(classUnderTest + " empty strings must be equal",
+ new LiteralByteString(new byte[]{}), stringUnderTest.substring(55, 55));
+ assertEquals(classUnderTest + " must equal another string with the same value",
+ stringUnderTest, new LiteralByteString(referenceBytes));
+
+ byte[] mungedBytes = new byte[referenceBytes.length];
+ System.arraycopy(referenceBytes, 0, mungedBytes, 0, referenceBytes.length);
+ mungedBytes[mungedBytes.length - 5] ^= 0xFF;
+ assertFalse(classUnderTest + " must not equal every string with the same length",
+ stringUnderTest.equals(new LiteralByteString(mungedBytes)));
+ }
+
+ public void testHashCode() {
+ int hash = stringUnderTest.hashCode();
+ assertEquals(classUnderTest + " must have expected hashCode", expectedHashCode, hash);
+ }
+
+ public void testPeekCachedHashCode() {
+ assertEquals(classUnderTest + ".peekCachedHashCode() should return zero at first", 0,
+ stringUnderTest.peekCachedHashCode());
+ stringUnderTest.hashCode();
+ assertEquals(classUnderTest + ".peekCachedHashCode should return zero at first",
+ expectedHashCode, stringUnderTest.peekCachedHashCode());
+ }
+
+ public void testPartialHash() {
+ // partialHash() is more strenuously tested elsewhere by testing hashes of substrings.
+ // This test would fail if the expected hash were 1. It's not.
+ int hash = stringUnderTest.partialHash(stringUnderTest.size(), 0, stringUnderTest.size());
+ assertEquals(classUnderTest + ".partialHash() must yield expected hashCode",
+ expectedHashCode, hash);
+ }
+
+ public void testNewInput() throws IOException {
+ InputStream input = stringUnderTest.newInput();
+ assertEquals("InputStream.available() returns correct value",
+ stringUnderTest.size(), input.available());
+ boolean stillEqual = true;
+ for (byte referenceByte : referenceBytes) {
+ int expectedInt = (referenceByte & 0xFF);
+ stillEqual = (expectedInt == input.read());
+ }
+ assertEquals("InputStream.available() returns correct value",
+ 0, input.available());
+ assertTrue(classUnderTest + " must give the same bytes from the InputStream", stillEqual);
+ assertEquals(classUnderTest + " InputStream must now be exhausted", -1, input.read());
+ }
+
+ public void testNewInput_skip() throws IOException {
+ InputStream input = stringUnderTest.newInput();
+ int stringSize = stringUnderTest.size();
+ int nearEndIndex = stringSize * 2 / 3;
+ long skipped1 = input.skip(nearEndIndex);
+ assertEquals("InputStream.skip()", skipped1, nearEndIndex);
+ assertEquals("InputStream.available()",
+ stringSize - skipped1, input.available());
+ assertTrue("InputStream.mark() is available", input.markSupported());
+ input.mark(0);
+ assertEquals("InputStream.skip(), read()",
+ stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
+ assertEquals("InputStream.available()",
+ stringSize - skipped1 - 1, input.available());
+ long skipped2 = input.skip(stringSize);
+ assertEquals("InputStream.skip() incomplete",
+ skipped2, stringSize - skipped1 - 1);
+ assertEquals("InputStream.skip(), no more input", 0, input.available());
+ assertEquals("InputStream.skip(), no more input", -1, input.read());
+ input.reset();
+ assertEquals("InputStream.reset() succeded",
+ stringSize - skipped1, input.available());
+ assertEquals("InputStream.reset(), read()",
+ stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
+ }
+
+ public void testNewCodedInput() throws IOException {
+ CodedInputStream cis = stringUnderTest.newCodedInput();
+ byte[] roundTripBytes = cis.readRawBytes(referenceBytes.length);
+ assertTrue(classUnderTest + " must give the same bytes back from the CodedInputStream",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ assertTrue(classUnderTest + " CodedInputStream must now be exhausted", cis.isAtEnd());
+ }
+
+ /**
+ * Make sure we keep things simple when concatenating with empty. See also
+ * {@link ByteStringTest#testConcat_empty()}.
+ */
+ public void testConcat_empty() {
+ assertSame(classUnderTest + " concatenated with empty must give " + classUnderTest,
+ stringUnderTest.concat(ByteString.EMPTY), stringUnderTest);
+ assertSame("empty concatenated with " + classUnderTest + " must give " + classUnderTest,
+ ByteString.EMPTY.concat(stringUnderTest), stringUnderTest);
+ }
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/MessageTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/MessageTest.java
index c2f47eb..747fed7 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/MessageTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/MessageTest.java
@@ -38,6 +38,8 @@
import junit.framework.TestCase;
+import java.util.List;
+
/**
* Misc. unit tests for message operations that apply to both generated
* and dynamic messages.
@@ -310,4 +312,42 @@
assertEquals("Message missing required fields: a, b, c", e.getMessage());
}
}
+
+ /** Test reading unset repeated message from DynamicMessage. */
+ public void testDynamicRepeatedMessageNull() throws Exception {
+ Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+ DynamicMessage result =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
+ .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
+ .build();
+
+ assertTrue(result.getField(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")) instanceof List<?>);
+ assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")), 0);
+ }
+
+ /** Test reading repeated message from DynamicMessage. */
+ public void testDynamicRepeatedMessageNotNull() throws Exception {
+
+ TestAllTypes REPEATED_NESTED =
+ TestAllTypes.newBuilder()
+ .setOptionalInt32(1)
+ .setOptionalString("foo")
+ .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
+ .addRepeatedString("bar")
+ .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
+ .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
+ .build();
+ Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+ DynamicMessage result =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
+ .mergeFrom(DynamicMessage.newBuilder(REPEATED_NESTED).build())
+ .build();
+
+ assertTrue(result.getField(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")) instanceof List<?>);
+ assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")), 2);
+ }
}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/ParserTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/ParserTest.java
new file mode 100644
index 0000000..396902c
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/ParserTest.java
@@ -0,0 +1,375 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+import com.google.protobuf.UnittestLite.TestParsingMergeLite;
+import com.google.protobuf.UnittestLite;
+import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestParsingMerge;
+import protobuf_unittest.UnittestProto;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Unit test for {@link Parser}.
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+public class ParserTest extends TestCase {
+ public void testGeneratedMessageParserSingleton() throws Exception {
+ for (int i = 0; i < 10; i++) {
+ assertEquals(TestAllTypes.PARSER,
+ TestUtil.getAllSet().getParserForType());
+ }
+ }
+
+ private void assertRoundTripEquals(MessageLite message,
+ ExtensionRegistryLite registry)
+ throws Exception {
+ final byte[] data = message.toByteArray();
+ final int offset = 20;
+ final int length = data.length;
+ final int padding = 30;
+ Parser<? extends MessageLite> parser = message.getParserForType();
+ assertMessageEquals(message, parser.parseFrom(data, registry));
+ assertMessageEquals(message, parser.parseFrom(
+ generatePaddingArray(data, offset, padding),
+ offset, length, registry));
+ assertMessageEquals(message, parser.parseFrom(
+ message.toByteString(), registry));
+ assertMessageEquals(message, parser.parseFrom(
+ new ByteArrayInputStream(data), registry));
+ assertMessageEquals(message, parser.parseFrom(
+ CodedInputStream.newInstance(data), registry));
+ }
+
+ private void assertRoundTripEquals(MessageLite message) throws Exception {
+ final byte[] data = message.toByteArray();
+ final int offset = 20;
+ final int length = data.length;
+ final int padding = 30;
+ Parser<? extends MessageLite> parser = message.getParserForType();
+ assertMessageEquals(message, parser.parseFrom(data));
+ assertMessageEquals(message, parser.parseFrom(
+ generatePaddingArray(data, offset, padding),
+ offset, length));
+ assertMessageEquals(message, parser.parseFrom(message.toByteString()));
+ assertMessageEquals(message, parser.parseFrom(
+ new ByteArrayInputStream(data)));
+ assertMessageEquals(message, parser.parseFrom(
+ CodedInputStream.newInstance(data)));
+ }
+
+ private void assertMessageEquals(MessageLite expected, MessageLite actual)
+ throws Exception {
+ if (expected instanceof Message) {
+ assertEquals(expected, actual);
+ } else {
+ assertEquals(expected.toByteString(), actual.toByteString());
+ }
+ }
+
+ private byte[] generatePaddingArray(byte[] data, int offset, int padding) {
+ byte[] result = new byte[offset + data.length + padding];
+ System.arraycopy(data, 0, result, offset, data.length);
+ return result;
+ }
+
+ public void testNormalMessage() throws Exception {
+ assertRoundTripEquals(TestUtil.getAllSet());
+ }
+
+ public void testParsePartial() throws Exception {
+ Parser<TestRequired> parser = TestRequired.PARSER;
+ final String errorString =
+ "Should throw exceptions when the parsed message isn't initialized.";
+
+ // TestRequired.b and TestRequired.c are not set.
+ TestRequired partialMessage = TestRequired.newBuilder()
+ .setA(1).buildPartial();
+
+ // parsePartialFrom should pass.
+ byte[] data = partialMessage.toByteArray();
+ assertEquals(partialMessage, parser.parsePartialFrom(data));
+ assertEquals(partialMessage, parser.parsePartialFrom(
+ partialMessage.toByteString()));
+ assertEquals(partialMessage, parser.parsePartialFrom(
+ new ByteArrayInputStream(data)));
+ assertEquals(partialMessage, parser.parsePartialFrom(
+ CodedInputStream.newInstance(data)));
+
+ // parseFrom(ByteArray)
+ try {
+ parser.parseFrom(partialMessage.toByteArray());
+ fail(errorString);
+ } catch (InvalidProtocolBufferException e) {
+ // pass.
+ }
+
+ // parseFrom(ByteString)
+ try {
+ parser.parseFrom(partialMessage.toByteString());
+ fail(errorString);
+ } catch (InvalidProtocolBufferException e) {
+ // pass.
+ }
+
+ // parseFrom(InputStream)
+ try {
+ parser.parseFrom(new ByteArrayInputStream(partialMessage.toByteArray()));
+ fail(errorString);
+ } catch (IOException e) {
+ // pass.
+ }
+
+ // parseFrom(CodedInputStream)
+ try {
+ parser.parseFrom(CodedInputStream.newInstance(
+ partialMessage.toByteArray()));
+ fail(errorString);
+ } catch (IOException e) {
+ // pass.
+ }
+ }
+
+ public void testParseExtensions() throws Exception {
+ assertRoundTripEquals(TestUtil.getAllExtensionsSet(),
+ TestUtil.getExtensionRegistry());
+ assertRoundTripEquals(TestUtil.getAllLiteExtensionsSet(),
+ TestUtil.getExtensionRegistryLite());
+ }
+
+ public void testParsePacked() throws Exception {
+ assertRoundTripEquals(TestUtil.getPackedSet());
+ assertRoundTripEquals(TestUtil.getPackedExtensionsSet(),
+ TestUtil.getExtensionRegistry());
+ assertRoundTripEquals(TestUtil.getLitePackedExtensionsSet(),
+ TestUtil.getExtensionRegistryLite());
+ }
+
+ public void testParseDelimitedTo() throws Exception {
+ // Write normal Message.
+ TestAllTypes normalMessage = TestUtil.getAllSet();
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ normalMessage.writeDelimitedTo(output);
+
+ // Write MessageLite with packed extension fields.
+ TestPackedExtensionsLite packedMessage =
+ TestUtil.getLitePackedExtensionsSet();
+ packedMessage.writeDelimitedTo(output);
+
+ InputStream input = new ByteArrayInputStream(output.toByteArray());
+ assertMessageEquals(
+ normalMessage,
+ normalMessage.getParserForType().parseDelimitedFrom(input));
+ assertMessageEquals(
+ packedMessage,
+ packedMessage.getParserForType().parseDelimitedFrom(
+ input, TestUtil.getExtensionRegistryLite()));
+ }
+
+ public void testParseUnknownFields() throws Exception {
+ // All fields will be treated as unknown fields in emptyMessage.
+ TestEmptyMessage emptyMessage = TestEmptyMessage.PARSER.parseFrom(
+ TestUtil.getAllSet().toByteString());
+ assertEquals(
+ TestUtil.getAllSet().toByteString(),
+ emptyMessage.toByteString());
+ }
+
+ public void testOptimizeForSize() throws Exception {
+ TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
+ builder.setI(12).setMsg(ForeignMessage.newBuilder().setC(34).build());
+ builder.setExtension(TestOptimizedForSize.testExtension, 56);
+ builder.setExtension(TestOptimizedForSize.testExtension2,
+ TestRequiredOptimizedForSize.newBuilder().setX(78).build());
+
+ TestOptimizedForSize message = builder.build();
+ ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ UnittestOptimizeFor.registerAllExtensions(registry);
+
+ assertRoundTripEquals(message, registry);
+ }
+
+ /** Helper method for {@link #testParsingMerge()}.*/
+ private void assertMessageMerged(TestAllTypes allTypes)
+ throws Exception {
+ assertEquals(3, allTypes.getOptionalInt32());
+ assertEquals(2, allTypes.getOptionalInt64());
+ assertEquals("hello", allTypes.getOptionalString());
+ }
+
+ /** Helper method for {@link #testParsingMergeLite()}.*/
+ private void assertMessageMerged(TestAllTypesLite allTypes)
+ throws Exception {
+ assertEquals(3, allTypes.getOptionalInt32());
+ assertEquals(2, allTypes.getOptionalInt64());
+ assertEquals("hello", allTypes.getOptionalString());
+ }
+
+ public void testParsingMerge() throws Exception {
+ // Build messages.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestAllTypes msg1 = builder.setOptionalInt32(1).build();
+ builder.clear();
+ TestAllTypes msg2 = builder.setOptionalInt64(2).build();
+ builder.clear();
+ TestAllTypes msg3 = builder.setOptionalInt32(3)
+ .setOptionalString("hello").build();
+
+ // Build groups.
+ TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG1 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg1).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG2 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg2).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG3 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg3).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG1 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg1).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG2 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg2).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG3 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg3).build();
+
+ // Assign and serialize RepeatedFieldsGenerator.
+ ByteString data = TestParsingMerge.RepeatedFieldsGenerator.newBuilder()
+ .addField1(msg1).addField1(msg2).addField1(msg3)
+ .addField2(msg1).addField2(msg2).addField2(msg3)
+ .addField3(msg1).addField3(msg2).addField3(msg3)
+ .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
+ .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
+ .addExt1(msg1).addExt1(msg2).addExt1(msg3)
+ .addExt2(msg1).addExt2(msg2).addExt2(msg3)
+ .build().toByteString();
+
+ // Parse TestParsingMerge.
+ ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ UnittestProto.registerAllExtensions(registry);
+ TestParsingMerge parsingMerge =
+ TestParsingMerge.PARSER.parseFrom(data, registry);
+
+ // Required and optional fields should be merged.
+ assertMessageMerged(parsingMerge.getRequiredAllTypes());
+ assertMessageMerged(parsingMerge.getOptionalAllTypes());
+ assertMessageMerged(
+ parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
+ assertMessageMerged(parsingMerge.getExtension(
+ TestParsingMerge.optionalExt));
+
+ // Repeated fields should not be merged.
+ assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
+ assertEquals(3, parsingMerge.getRepeatedGroupCount());
+ assertEquals(3, parsingMerge.getExtensionCount(
+ TestParsingMerge.repeatedExt));
+ }
+
+ public void testParsingMergeLite() throws Exception {
+ // Build messages.
+ TestAllTypesLite.Builder builder =
+ TestAllTypesLite.newBuilder();
+ TestAllTypesLite msg1 = builder.setOptionalInt32(1).build();
+ builder.clear();
+ TestAllTypesLite msg2 = builder.setOptionalInt64(2).build();
+ builder.clear();
+ TestAllTypesLite msg3 = builder.setOptionalInt32(3)
+ .setOptionalString("hello").build();
+
+ // Build groups.
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG1 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg1).build();
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG2 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg2).build();
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG3 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg3).build();
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG1 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg1).build();
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG2 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg2).build();
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG3 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg3).build();
+
+ // Assign and serialize RepeatedFieldsGenerator.
+ ByteString data = TestParsingMergeLite.RepeatedFieldsGenerator.newBuilder()
+ .addField1(msg1).addField1(msg2).addField1(msg3)
+ .addField2(msg1).addField2(msg2).addField2(msg3)
+ .addField3(msg1).addField3(msg2).addField3(msg3)
+ .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
+ .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
+ .addExt1(msg1).addExt1(msg2).addExt1(msg3)
+ .addExt2(msg1).addExt2(msg2).addExt2(msg3)
+ .build().toByteString();
+
+ // Parse TestParsingMergeLite.
+ ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ UnittestLite.registerAllExtensions(registry);
+ TestParsingMergeLite parsingMerge =
+ TestParsingMergeLite.PARSER.parseFrom(data, registry);
+
+ // Required and optional fields should be merged.
+ assertMessageMerged(parsingMerge.getRequiredAllTypes());
+ assertMessageMerged(parsingMerge.getOptionalAllTypes());
+ assertMessageMerged(
+ parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
+ assertMessageMerged(parsingMerge.getExtension(
+ TestParsingMergeLite.optionalExt));
+
+ // Repeated fields should not be merged.
+ assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
+ assertEquals(3, parsingMerge.getRepeatedGroupCount());
+ assertEquals(3, parsingMerge.getExtensionCount(
+ TestParsingMergeLite.repeatedExt));
+ }
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java
new file mode 100644
index 0000000..06707a2
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java
@@ -0,0 +1,97 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Iterator;
+
+/**
+ * This class tests {@link RopeByteString#substring(int, int)} by inheriting the tests from
+ * {@link LiteralByteStringTest}. Only a couple of methods are overridden.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class RopeByteStringSubstringTest extends LiteralByteStringTest {
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "RopeByteString";
+ byte[] sourceBytes = ByteStringTest.getTestBytes(22341, 22337766L);
+ Iterator<ByteString> iter = ByteStringTest.makeConcretePieces(sourceBytes).iterator();
+ ByteString sourceString = iter.next();
+ while (iter.hasNext()) {
+ sourceString = sourceString.concat(iter.next());
+ }
+
+ int from = 1130;
+ int to = sourceBytes.length - 5555;
+ stringUnderTest = sourceString.substring(from, to);
+ referenceBytes = new byte[to - from];
+ System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from);
+ expectedHashCode = -1259260680;
+ }
+
+ @Override
+ public void testGetTreeDepth() {
+ assertEquals(classUnderTest + " must have the expected tree depth",
+ 3, stringUnderTest.getTreeDepth());
+ }
+
+ @Override
+ public void testToString() throws UnsupportedEncodingException {
+ String sourceString = "I love unicode \u1234\u5678 characters";
+ ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+ int copies = 250;
+
+ // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+ StringBuilder builder = new StringBuilder(copies * sourceString.length());
+ ByteString unicode = ByteString.EMPTY;
+ for (int i = 0; i < copies; ++i) {
+ builder.append(sourceString);
+ unicode = RopeByteString.concatenate(unicode, sourceByteString);
+ }
+ String testString = builder.toString();
+
+ // Do the substring part
+ testString = testString.substring(2, testString.length() - 6);
+ unicode = unicode.substring(2, unicode.size() - 6);
+
+ assertEquals(classUnderTest + " from string must have the expected type",
+ classUnderTest, getActualClassName(unicode));
+ String roundTripString = unicode.toString(UTF_8);
+ assertEquals(classUnderTest + " unicode bytes must match",
+ testString, roundTripString);
+ ByteString flatString = ByteString.copyFromUtf8(testString);
+ assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+ assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+ flatString.hashCode(), unicode.hashCode());
+ }
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/RopeByteStringTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
new file mode 100644
index 0000000..15f660d
--- /dev/null
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
@@ -0,0 +1,115 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * This class tests {@link RopeByteString} by inheriting the tests from
+ * {@link LiteralByteStringTest}. Only a couple of methods are overridden.
+ *
+ * <p>A full test of the result of {@link RopeByteString#substring(int, int)} is found in the
+ * separate class {@link RopeByteStringSubstringTest}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class RopeByteStringTest extends LiteralByteStringTest {
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "RopeByteString";
+ referenceBytes = ByteStringTest.getTestBytes(22341, 22337766L);
+ Iterator<ByteString> iter = ByteStringTest.makeConcretePieces(referenceBytes).iterator();
+ stringUnderTest = iter.next();
+ while (iter.hasNext()) {
+ stringUnderTest = stringUnderTest.concat(iter.next());
+ }
+ expectedHashCode = -1214197238;
+ }
+
+ @Override
+ public void testGetTreeDepth() {
+ assertEquals(classUnderTest + " must have the expected tree depth",
+ 4, stringUnderTest.getTreeDepth());
+ }
+
+ public void testBalance() {
+ int numberOfPieces = 10000;
+ int pieceSize = 64;
+ byte[] testBytes = ByteStringTest.getTestBytes(numberOfPieces * pieceSize, 113377L);
+
+ // Build up a big ByteString from smaller pieces to force a rebalance
+ ByteString concatenated = ByteString.EMPTY;
+ for (int i = 0; i < numberOfPieces; ++i) {
+ concatenated = concatenated.concat(ByteString.copyFrom(testBytes, i * pieceSize, pieceSize));
+ }
+
+ assertEquals(classUnderTest + " from string must have the expected type",
+ classUnderTest, getActualClassName(concatenated));
+ assertTrue(classUnderTest + " underlying bytes must match after balancing",
+ Arrays.equals(testBytes, concatenated.toByteArray()));
+ ByteString testString = ByteString.copyFrom(testBytes);
+ assertTrue(classUnderTest + " balanced string must equal flat string",
+ concatenated.equals(testString));
+ assertTrue(classUnderTest + " flat string must equal balanced string",
+ testString.equals(concatenated));
+ assertEquals(classUnderTest + " balanced string must have same hash code as flat string",
+ testString.hashCode(), concatenated.hashCode());
+ }
+
+ @Override
+ public void testToString() throws UnsupportedEncodingException {
+ String sourceString = "I love unicode \u1234\u5678 characters";
+ ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+ int copies = 250;
+
+ // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+ StringBuilder builder = new StringBuilder(copies * sourceString.length());
+ ByteString unicode = ByteString.EMPTY;
+ for (int i = 0; i < copies; ++i) {
+ builder.append(sourceString);
+ unicode = RopeByteString.concatenate(unicode, sourceByteString);
+ }
+ String testString = builder.toString();
+
+ assertEquals(classUnderTest + " from string must have the expected type",
+ classUnderTest, getActualClassName(unicode));
+ String roundTripString = unicode.toString(UTF_8);
+ assertEquals(classUnderTest + " unicode bytes must match",
+ testString, roundTripString);
+ ByteString flatString = ByteString.copyFromUtf8(testString);
+ assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+ assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+ flatString.hashCode(), unicode.hashCode());
+ }
+}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java
index 6feec4e..382acf0 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java
@@ -35,7 +35,7 @@
/**
* Tests that proto2 api generation doesn't cause compile errors when
* compiling protocol buffers that have names that would otherwise conflict
- * if not fully qualified (like @Deprecated and @Override).
+ * if not fully qualified (like @Deprecated and @Override).
*
* @author jonp@google.com (Jon Perlow)
*/
@@ -45,5 +45,19 @@
// If this compiles, it means the generation was correct.
TestBadIdentifiersProto.Deprecated.newBuilder();
TestBadIdentifiersProto.Override.newBuilder();
- }
+ }
+
+ public void testGetDescriptor() {
+ Descriptors.FileDescriptor fileDescriptor =
+ TestBadIdentifiersProto.getDescriptor();
+ String descriptorField = TestBadIdentifiersProto.Descriptor
+ .getDefaultInstance().getDescriptor();
+ Descriptors.Descriptor protoDescriptor = TestBadIdentifiersProto.Descriptor
+ .getDefaultInstance().getDescriptorForType();
+ String nestedDescriptorField = TestBadIdentifiersProto.Descriptor
+ .NestedDescriptor.getDefaultInstance().getDescriptor();
+ Descriptors.Descriptor nestedProtoDescriptor = TestBadIdentifiersProto
+ .Descriptor.NestedDescriptor.getDefaultInstance()
+ .getDescriptorForType();
+ }
}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/TestUtil.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/TestUtil.java
index 9109f41..76f5c60 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/TestUtil.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/TestUtil.java
@@ -72,14 +72,16 @@
import static protobuf_unittest.UnittestProto.optionalStringExtension;
import static protobuf_unittest.UnittestProto.optionalBytesExtension;
import static protobuf_unittest.UnittestProto.optionalGroupExtension;
-import static protobuf_unittest.UnittestProto.optionalNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalCordExtension;
+import static protobuf_unittest.UnittestProto.optionalForeignEnumExtension;
import static protobuf_unittest.UnittestProto.optionalForeignMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalImportEnumExtension;
import static protobuf_unittest.UnittestProto.optionalImportMessageExtension;
import static protobuf_unittest.UnittestProto.optionalNestedEnumExtension;
-import static protobuf_unittest.UnittestProto.optionalForeignEnumExtension;
-import static protobuf_unittest.UnittestProto.optionalImportEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalPublicImportMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalLazyMessageExtension;
import static protobuf_unittest.UnittestProto.optionalStringPieceExtension;
-import static protobuf_unittest.UnittestProto.optionalCordExtension;
import static protobuf_unittest.UnittestProto.repeatedInt32Extension;
import static protobuf_unittest.UnittestProto.repeatedInt64Extension;
@@ -100,6 +102,7 @@
import static protobuf_unittest.UnittestProto.repeatedNestedMessageExtension;
import static protobuf_unittest.UnittestProto.repeatedForeignMessageExtension;
import static protobuf_unittest.UnittestProto.repeatedImportMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedLazyMessageExtension;
import static protobuf_unittest.UnittestProto.repeatedNestedEnumExtension;
import static protobuf_unittest.UnittestProto.repeatedForeignEnumExtension;
import static protobuf_unittest.UnittestProto.repeatedImportEnumExtension;
@@ -162,11 +165,13 @@
import static com.google.protobuf.UnittestLite.optionalBytesExtensionLite;
import static com.google.protobuf.UnittestLite.optionalGroupExtensionLite;
import static com.google.protobuf.UnittestLite.optionalNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite;
import static com.google.protobuf.UnittestLite.optionalForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite;
import static com.google.protobuf.UnittestLite.optionalImportMessageExtensionLite;
import static com.google.protobuf.UnittestLite.optionalNestedEnumExtensionLite;
-import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite;
-import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalPublicImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalLazyMessageExtensionLite;
import static com.google.protobuf.UnittestLite.optionalStringPieceExtensionLite;
import static com.google.protobuf.UnittestLite.optionalCordExtensionLite;
@@ -189,6 +194,7 @@
import static com.google.protobuf.UnittestLite.repeatedNestedMessageExtensionLite;
import static com.google.protobuf.UnittestLite.repeatedForeignMessageExtensionLite;
import static com.google.protobuf.UnittestLite.repeatedImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedLazyMessageExtensionLite;
import static com.google.protobuf.UnittestLite.repeatedNestedEnumExtensionLite;
import static com.google.protobuf.UnittestLite.repeatedForeignEnumExtensionLite;
import static com.google.protobuf.UnittestLite.repeatedImportEnumExtensionLite;
@@ -222,8 +228,9 @@
import protobuf_unittest.UnittestProto.TestUnpackedTypes;
import protobuf_unittest.UnittestProto.ForeignMessage;
import protobuf_unittest.UnittestProto.ForeignEnum;
-import com.google.protobuf.test.UnittestImport.ImportMessage;
import com.google.protobuf.test.UnittestImport.ImportEnum;
+import com.google.protobuf.test.UnittestImport.ImportMessage;
+import com.google.protobuf.test.UnittestImportPublic.PublicImportMessage;
import com.google.protobuf.UnittestLite.TestAllTypesLite;
import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
@@ -231,8 +238,9 @@
import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
import com.google.protobuf.UnittestLite.ForeignMessageLite;
import com.google.protobuf.UnittestLite.ForeignEnumLite;
-import com.google.protobuf.UnittestImportLite.ImportMessageLite;
import com.google.protobuf.UnittestImportLite.ImportEnumLite;
+import com.google.protobuf.UnittestImportLite.ImportMessageLite;
+import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
import junit.framework.Assert;
@@ -242,7 +250,7 @@
/**
* Contains methods for setting all fields of {@code TestAllTypes} to
- * some vaules as well as checking that all the fields are set to those values.
+ * some values as well as checking that all the fields are set to those values.
* These are useful for testing various protocol message features, e.g.
* set all fields of a message, serialize it, parse it, and check that all
* fields are set.
@@ -275,6 +283,16 @@
}
/**
+ * Get a {@code TestAllTypes.Builder} with all fields set as they would be by
+ * {@link #setAllFields(TestAllTypes.Builder)}.
+ */
+ public static TestAllTypes.Builder getAllSetBuilder() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ setAllFields(builder);
+ return builder;
+ }
+
+ /**
* Get a {@code TestAllExtensions} with all fields set as they would be by
* {@link #setAllExtensions(TestAllExtensions.Builder)}.
*/
@@ -344,6 +362,10 @@
ForeignMessage.newBuilder().setC(119).build());
message.setOptionalImportMessage(
ImportMessage.newBuilder().setD(120).build());
+ message.setOptionalPublicImportMessage(
+ PublicImportMessage.newBuilder().setE(126).build());
+ message.setOptionalLazyMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(127).build());
message.setOptionalNestedEnum (TestAllTypes.NestedEnum.BAZ);
message.setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ);
@@ -378,6 +400,8 @@
ForeignMessage.newBuilder().setC(219).build());
message.addRepeatedImportMessage(
ImportMessage.newBuilder().setD(220).build());
+ message.addRepeatedLazyMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(227).build());
message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAR);
message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAR);
@@ -411,6 +435,8 @@
ForeignMessage.newBuilder().setC(319).build());
message.addRepeatedImportMessage(
ImportMessage.newBuilder().setD(320).build());
+ message.addRepeatedLazyMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(327).build());
message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAZ);
message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAZ);
@@ -476,6 +502,8 @@
ForeignMessage.newBuilder().setC(519).build());
message.setRepeatedImportMessage(1,
ImportMessage.newBuilder().setD(520).build());
+ message.setRepeatedLazyMessage(1,
+ TestAllTypes.NestedMessage.newBuilder().setBb(527).build());
message.setRepeatedNestedEnum (1, TestAllTypes.NestedEnum.FOO);
message.setRepeatedForeignEnum(1, ForeignEnum.FOREIGN_FOO);
@@ -541,10 +569,12 @@
Assert.assertEquals("115", message.getOptionalString ());
Assert.assertEquals(toBytes("116"), message.getOptionalBytes());
- Assert.assertEquals(117, message.getOptionalGroup ().getA());
- Assert.assertEquals(118, message.getOptionalNestedMessage ().getBb());
- Assert.assertEquals(119, message.getOptionalForeignMessage().getC());
- Assert.assertEquals(120, message.getOptionalImportMessage ().getD());
+ Assert.assertEquals(117, message.getOptionalGroup ().getA());
+ Assert.assertEquals(118, message.getOptionalNestedMessage ().getBb());
+ Assert.assertEquals(119, message.getOptionalForeignMessage ().getC());
+ Assert.assertEquals(120, message.getOptionalImportMessage ().getD());
+ Assert.assertEquals(126, message.getOptionalPublicImportMessage().getE());
+ Assert.assertEquals(127, message.getOptionalLazyMessage ().getBb());
Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getOptionalNestedEnum());
Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getOptionalForeignEnum());
@@ -575,6 +605,7 @@
Assert.assertEquals(2, message.getRepeatedNestedMessageCount ());
Assert.assertEquals(2, message.getRepeatedForeignMessageCount());
Assert.assertEquals(2, message.getRepeatedImportMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedLazyMessageCount ());
Assert.assertEquals(2, message.getRepeatedNestedEnumCount ());
Assert.assertEquals(2, message.getRepeatedForeignEnumCount ());
Assert.assertEquals(2, message.getRepeatedImportEnumCount ());
@@ -602,6 +633,7 @@
Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb());
Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC());
Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD());
+ Assert.assertEquals(227, message.getRepeatedLazyMessage (0).getBb());
Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0));
Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0));
@@ -630,6 +662,7 @@
Assert.assertEquals(318, message.getRepeatedNestedMessage (1).getBb());
Assert.assertEquals(319, message.getRepeatedForeignMessage(1).getC());
Assert.assertEquals(320, message.getRepeatedImportMessage (1).getD());
+ Assert.assertEquals(327, message.getRepeatedLazyMessage (1).getBb());
Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getRepeatedNestedEnum (1));
Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getRepeatedForeignEnum(1));
@@ -741,15 +774,19 @@
Assert.assertEquals(ByteString.EMPTY, message.getOptionalBytes());
// Embedded messages should also be clear.
- Assert.assertFalse(message.getOptionalGroup ().hasA());
- Assert.assertFalse(message.getOptionalNestedMessage ().hasBb());
- Assert.assertFalse(message.getOptionalForeignMessage().hasC());
- Assert.assertFalse(message.getOptionalImportMessage ().hasD());
+ Assert.assertFalse(message.getOptionalGroup ().hasA());
+ Assert.assertFalse(message.getOptionalNestedMessage ().hasBb());
+ Assert.assertFalse(message.getOptionalForeignMessage ().hasC());
+ Assert.assertFalse(message.getOptionalImportMessage ().hasD());
+ Assert.assertFalse(message.getOptionalPublicImportMessage().hasE());
+ Assert.assertFalse(message.getOptionalLazyMessage ().hasBb());
- Assert.assertEquals(0, message.getOptionalGroup ().getA());
- Assert.assertEquals(0, message.getOptionalNestedMessage ().getBb());
- Assert.assertEquals(0, message.getOptionalForeignMessage().getC());
- Assert.assertEquals(0, message.getOptionalImportMessage ().getD());
+ Assert.assertEquals(0, message.getOptionalGroup ().getA());
+ Assert.assertEquals(0, message.getOptionalNestedMessage ().getBb());
+ Assert.assertEquals(0, message.getOptionalForeignMessage ().getC());
+ Assert.assertEquals(0, message.getOptionalImportMessage ().getD());
+ Assert.assertEquals(0, message.getOptionalPublicImportMessage().getE());
+ Assert.assertEquals(0, message.getOptionalLazyMessage ().getBb());
// Enums without defaults are set to the first value in the enum.
Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getOptionalNestedEnum ());
@@ -780,6 +817,7 @@
Assert.assertEquals(0, message.getRepeatedNestedMessageCount ());
Assert.assertEquals(0, message.getRepeatedForeignMessageCount());
Assert.assertEquals(0, message.getRepeatedImportMessageCount ());
+ Assert.assertEquals(0, message.getRepeatedLazyMessageCount ());
Assert.assertEquals(0, message.getRepeatedNestedEnumCount ());
Assert.assertEquals(0, message.getRepeatedForeignEnumCount ());
Assert.assertEquals(0, message.getRepeatedImportEnumCount ());
@@ -868,6 +906,7 @@
Assert.assertEquals(2, message.getRepeatedNestedMessageCount ());
Assert.assertEquals(2, message.getRepeatedForeignMessageCount());
Assert.assertEquals(2, message.getRepeatedImportMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedLazyMessageCount ());
Assert.assertEquals(2, message.getRepeatedNestedEnumCount ());
Assert.assertEquals(2, message.getRepeatedForeignEnumCount ());
Assert.assertEquals(2, message.getRepeatedImportEnumCount ());
@@ -895,6 +934,7 @@
Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb());
Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC());
Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD());
+ Assert.assertEquals(227, message.getRepeatedLazyMessage (0).getBb());
Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0));
Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0));
@@ -924,6 +964,7 @@
Assert.assertEquals(518, message.getRepeatedNestedMessage (1).getBb());
Assert.assertEquals(519, message.getRepeatedForeignMessage(1).getC());
Assert.assertEquals(520, message.getRepeatedImportMessage (1).getD());
+ Assert.assertEquals(527, message.getRepeatedLazyMessage (1).getBb());
Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getRepeatedNestedEnum (1));
Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getRepeatedForeignEnum(1));
@@ -1210,6 +1251,10 @@
ForeignMessage.newBuilder().setC(119).build());
message.setExtension(optionalImportMessageExtension,
ImportMessage.newBuilder().setD(120).build());
+ message.setExtension(optionalPublicImportMessageExtension,
+ PublicImportMessage.newBuilder().setE(126).build());
+ message.setExtension(optionalLazyMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(127).build());
message.setExtension(optionalNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
message.setExtension(optionalForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
@@ -1244,6 +1289,8 @@
ForeignMessage.newBuilder().setC(219).build());
message.addExtension(repeatedImportMessageExtension,
ImportMessage.newBuilder().setD(220).build());
+ message.addExtension(repeatedLazyMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(227).build());
message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAR);
message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAR);
@@ -1277,6 +1324,8 @@
ForeignMessage.newBuilder().setC(319).build());
message.addExtension(repeatedImportMessageExtension,
ImportMessage.newBuilder().setD(320).build());
+ message.addExtension(repeatedLazyMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(327).build());
message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
@@ -1343,6 +1392,8 @@
ForeignMessage.newBuilder().setC(519).build());
message.setExtension(repeatedImportMessageExtension, 1,
ImportMessage.newBuilder().setD(520).build());
+ message.setExtension(repeatedLazyMessageExtension, 1,
+ TestAllTypes.NestedMessage.newBuilder().setBb(527).build());
message.setExtension(repeatedNestedEnumExtension , 1, TestAllTypes.NestedEnum.FOO);
message.setExtension(repeatedForeignEnumExtension, 1, ForeignEnum.FOREIGN_FOO);
@@ -1409,10 +1460,12 @@
assertEqualsExactType("115", message.getExtension(optionalStringExtension ));
assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtension));
- assertEqualsExactType(117, message.getExtension(optionalGroupExtension ).getA());
- assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtension ).getBb());
- assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtension).getC());
- assertEqualsExactType(120, message.getExtension(optionalImportMessageExtension ).getD());
+ assertEqualsExactType(117, message.getExtension(optionalGroupExtension ).getA());
+ assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtension ).getBb());
+ assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtension ).getC());
+ assertEqualsExactType(120, message.getExtension(optionalImportMessageExtension ).getD());
+ assertEqualsExactType(126, message.getExtension(optionalPublicImportMessageExtension).getE());
+ assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtension ).getBb());
assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
message.getExtension(optionalNestedEnumExtension));
@@ -1446,6 +1499,7 @@
Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension ));
Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension ));
Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension ));
Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension ));
@@ -1473,6 +1527,7 @@
assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
+ assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension , 0).getBb());
assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
message.getExtension(repeatedNestedEnumExtension, 0));
@@ -1504,6 +1559,7 @@
assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtension, 1).getC());
assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtension , 1).getD());
+ assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtension , 1).getBb());
assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
message.getExtension(repeatedNestedEnumExtension, 1));
@@ -1664,6 +1720,7 @@
Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtension ));
Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtension));
Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtension ));
Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtension ));
Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtension ));
Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtension ));
@@ -1692,6 +1749,7 @@
Assert.assertEquals(0, message.getExtension(repeatedNestedMessageExtension ).size());
Assert.assertEquals(0, message.getExtension(repeatedForeignMessageExtension).size());
Assert.assertEquals(0, message.getExtension(repeatedImportMessageExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedLazyMessageExtension ).size());
Assert.assertEquals(0, message.getExtension(repeatedNestedEnumExtension ).size());
Assert.assertEquals(0, message.getExtension(repeatedForeignEnumExtension ).size());
Assert.assertEquals(0, message.getExtension(repeatedImportEnumExtension ).size());
@@ -1783,6 +1841,7 @@
Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension ));
Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension ));
Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension ));
Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension ));
@@ -1810,6 +1869,7 @@
assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
+ assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension , 0).getBb());
assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
message.getExtension(repeatedNestedEnumExtension, 0));
@@ -1842,6 +1902,7 @@
assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtension, 1).getC());
assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtension , 1).getD());
+ assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtension , 1).getBb());
assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
message.getExtension(repeatedNestedEnumExtension, 1));
@@ -1965,6 +2026,10 @@
ForeignMessageLite.newBuilder().setC(119).build());
message.setExtension(optionalImportMessageExtensionLite,
ImportMessageLite.newBuilder().setD(120).build());
+ message.setExtension(optionalPublicImportMessageExtensionLite,
+ PublicImportMessageLite.newBuilder().setE(126).build());
+ message.setExtension(optionalLazyMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build());
message.setExtension(optionalNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
message.setExtension(optionalForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
@@ -1999,6 +2064,8 @@
ForeignMessageLite.newBuilder().setC(219).build());
message.addExtension(repeatedImportMessageExtensionLite,
ImportMessageLite.newBuilder().setD(220).build());
+ message.addExtension(repeatedLazyMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build());
message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAR);
message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
@@ -2032,6 +2099,8 @@
ForeignMessageLite.newBuilder().setC(319).build());
message.addExtension(repeatedImportMessageExtensionLite,
ImportMessageLite.newBuilder().setD(320).build());
+ message.addExtension(repeatedLazyMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build());
message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
@@ -2098,6 +2167,8 @@
ForeignMessageLite.newBuilder().setC(519).build());
message.setExtension(repeatedImportMessageExtensionLite, 1,
ImportMessageLite.newBuilder().setD(520).build());
+ message.setExtension(repeatedLazyMessageExtensionLite, 1,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(527).build());
message.setExtension(repeatedNestedEnumExtensionLite , 1, TestAllTypesLite.NestedEnum.FOO);
message.setExtension(repeatedForeignEnumExtensionLite, 1, ForeignEnumLite.FOREIGN_LITE_FOO);
@@ -2168,6 +2239,9 @@
assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtensionLite ).getBb());
assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtensionLite).getC());
assertEqualsExactType(120, message.getExtension(optionalImportMessageExtensionLite ).getD());
+ assertEqualsExactType(126, message.getExtension(
+ optionalPublicImportMessageExtensionLite).getE());
+ assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtensionLite).getBb());
assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ,
message.getExtension(optionalNestedEnumExtensionLite));
@@ -2201,6 +2275,7 @@
Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite));
Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite ));
Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite ));
Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite ));
Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite ));
@@ -2228,6 +2303,7 @@
assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb());
assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC());
assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD());
+ assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite ,0).getBb());
assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
message.getExtension(repeatedNestedEnumExtensionLite, 0));
@@ -2259,6 +2335,7 @@
assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb());
assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtensionLite,1).getC());
assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtensionLite ,1).getD());
+ assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtensionLite ,1).getBb());
assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ,
message.getExtension(repeatedNestedEnumExtensionLite, 1));
@@ -2348,10 +2425,12 @@
Assert.assertFalse(message.hasExtension(optionalStringExtensionLite ));
Assert.assertFalse(message.hasExtension(optionalBytesExtensionLite ));
- Assert.assertFalse(message.hasExtension(optionalGroupExtensionLite ));
- Assert.assertFalse(message.hasExtension(optionalNestedMessageExtensionLite ));
- Assert.assertFalse(message.hasExtension(optionalForeignMessageExtensionLite));
- Assert.assertFalse(message.hasExtension(optionalImportMessageExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalGroupExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalNestedMessageExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalForeignMessageExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalImportMessageExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalPublicImportMessageExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalLazyMessageExtensionLite ));
Assert.assertFalse(message.hasExtension(optionalNestedEnumExtensionLite ));
Assert.assertFalse(message.hasExtension(optionalForeignEnumExtensionLite));
@@ -2378,15 +2457,20 @@
assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtensionLite));
// Embedded messages should also be clear.
- Assert.assertFalse(message.getExtension(optionalGroupExtensionLite ).hasA());
- Assert.assertFalse(message.getExtension(optionalNestedMessageExtensionLite ).hasBb());
- Assert.assertFalse(message.getExtension(optionalForeignMessageExtensionLite).hasC());
- Assert.assertFalse(message.getExtension(optionalImportMessageExtensionLite ).hasD());
+ Assert.assertFalse(message.getExtension(optionalGroupExtensionLite ).hasA());
+ Assert.assertFalse(message.getExtension(optionalNestedMessageExtensionLite ).hasBb());
+ Assert.assertFalse(message.getExtension(optionalForeignMessageExtensionLite ).hasC());
+ Assert.assertFalse(message.getExtension(optionalImportMessageExtensionLite ).hasD());
+ Assert.assertFalse(message.getExtension(optionalPublicImportMessageExtensionLite).hasE());
+ Assert.assertFalse(message.getExtension(optionalLazyMessageExtensionLite ).hasBb());
assertEqualsExactType(0, message.getExtension(optionalGroupExtensionLite ).getA());
assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtensionLite ).getBb());
assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtensionLite).getC());
assertEqualsExactType(0, message.getExtension(optionalImportMessageExtensionLite ).getD());
+ assertEqualsExactType(0, message.getExtension(
+ optionalPublicImportMessageExtensionLite).getE());
+ assertEqualsExactType(0, message.getExtension(optionalLazyMessageExtensionLite ).getBb());
// Enums without defaults are set to the first value in the enum.
assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
@@ -2420,6 +2504,7 @@
Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtensionLite));
Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtensionLite ));
Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtensionLite ));
Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtensionLite ));
Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtensionLite ));
@@ -2511,6 +2596,7 @@
Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite));
Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite ));
Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite ));
Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite ));
Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite ));
@@ -2538,6 +2624,7 @@
assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb());
assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC());
assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD());
+ assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite ,0).getBb());
assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
message.getExtension(repeatedNestedEnumExtensionLite, 0));
@@ -2570,6 +2657,7 @@
assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb());
assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtensionLite,1).getC());
assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtensionLite ,1).getD());
+ assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtensionLite ,1).getBb());
assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
message.getExtension(repeatedNestedEnumExtensionLite, 1));
@@ -2674,18 +2762,21 @@
private final Descriptors.FileDescriptor file;
private final Descriptors.FileDescriptor importFile;
+ private final Descriptors.FileDescriptor publicImportFile;
private final Descriptors.Descriptor optionalGroup;
private final Descriptors.Descriptor repeatedGroup;
private final Descriptors.Descriptor nestedMessage;
private final Descriptors.Descriptor foreignMessage;
private final Descriptors.Descriptor importMessage;
+ private final Descriptors.Descriptor publicImportMessage;
private final Descriptors.FieldDescriptor groupA;
private final Descriptors.FieldDescriptor repeatedGroupA;
private final Descriptors.FieldDescriptor nestedB;
private final Descriptors.FieldDescriptor foreignC;
private final Descriptors.FieldDescriptor importD;
+ private final Descriptors.FieldDescriptor importE;
private final Descriptors.EnumDescriptor nestedEnum;
private final Descriptors.EnumDescriptor foreignEnum;
@@ -2722,6 +2813,7 @@
this.file = baseDescriptor.getFile();
Assert.assertEquals(1, file.getDependencies().size());
this.importFile = file.getDependencies().get(0);
+ this.publicImportFile = importFile.getDependencies().get(0);
Descriptors.Descriptor testAllTypes;
if (baseDescriptor.getName() == "TestAllTypes") {
@@ -2748,6 +2840,8 @@
this.nestedMessage = testAllTypes.findNestedTypeByName("NestedMessage");
this.foreignMessage = file.findMessageTypeByName("ForeignMessage");
this.importMessage = importFile.findMessageTypeByName("ImportMessage");
+ this.publicImportMessage = publicImportFile.findMessageTypeByName(
+ "PublicImportMessage");
this.nestedEnum = testAllTypes.findEnumTypeByName("NestedEnum");
this.foreignEnum = file.findEnumTypeByName("ForeignEnum");
@@ -2765,6 +2859,7 @@
this.nestedB = nestedMessage .findFieldByName("bb");
this.foreignC = foreignMessage.findFieldByName("c");
this.importD = importMessage .findFieldByName("d");
+ this.importE = publicImportMessage.findFieldByName("e");
this.nestedFoo = nestedEnum.findValueByName("FOO");
this.nestedBar = nestedEnum.findValueByName("BAR");
this.nestedBaz = nestedEnum.findValueByName("BAZ");
@@ -2783,6 +2878,7 @@
Assert.assertNotNull(nestedB );
Assert.assertNotNull(foreignC );
Assert.assertNotNull(importD );
+ Assert.assertNotNull(importE );
Assert.assertNotNull(nestedFoo );
Assert.assertNotNull(nestedBar );
Assert.assertNotNull(nestedBaz );
@@ -2863,6 +2959,12 @@
message.setField(f("optional_import_message"),
newBuilderForField(message, f("optional_import_message"))
.setField(importD, 120).build());
+ message.setField(f("optional_public_import_message"),
+ newBuilderForField(message, f("optional_public_import_message"))
+ .setField(importE, 126).build());
+ message.setField(f("optional_lazy_message"),
+ newBuilderForField(message, f("optional_lazy_message"))
+ .setField(nestedB, 127).build());
message.setField(f("optional_nested_enum" ), nestedBaz);
message.setField(f("optional_foreign_enum"), foreignBaz);
@@ -2901,6 +3003,9 @@
message.addRepeatedField(f("repeated_import_message"),
newBuilderForField(message, f("repeated_import_message"))
.setField(importD, 220).build());
+ message.addRepeatedField(f("repeated_lazy_message"),
+ newBuilderForField(message, f("repeated_lazy_message"))
+ .setField(nestedB, 227).build());
message.addRepeatedField(f("repeated_nested_enum" ), nestedBar);
message.addRepeatedField(f("repeated_foreign_enum"), foreignBar);
@@ -2938,6 +3043,9 @@
message.addRepeatedField(f("repeated_import_message"),
newBuilderForField(message, f("repeated_import_message"))
.setField(importD, 320).build());
+ message.addRepeatedField(f("repeated_lazy_message"),
+ newBuilderForField(message, f("repeated_lazy_message"))
+ .setField(nestedB, 327).build());
message.addRepeatedField(f("repeated_nested_enum" ), nestedBaz);
message.addRepeatedField(f("repeated_foreign_enum"), foreignBaz);
@@ -3008,6 +3116,9 @@
message.setRepeatedField(f("repeated_import_message"), 1,
newBuilderForField(message, f("repeated_import_message"))
.setField(importD, 520).build());
+ message.setRepeatedField(f("repeated_lazy_message"), 1,
+ newBuilderForField(message, f("repeated_lazy_message"))
+ .setField(nestedB, 527).build());
message.setRepeatedField(f("repeated_nested_enum" ), 1, nestedFoo);
message.setRepeatedField(f("repeated_foreign_enum"), 1, foreignFoo);
@@ -3092,6 +3203,12 @@
Assert.assertEquals(120,
((Message)message.getField(f("optional_import_message")))
.getField(importD));
+ Assert.assertEquals(126,
+ ((Message)message.getField(f("optional_public_import_message")))
+ .getField(importE));
+ Assert.assertEquals(127,
+ ((Message)message.getField(f("optional_lazy_message")))
+ .getField(nestedB));
Assert.assertEquals( nestedBaz, message.getField(f("optional_nested_enum" )));
Assert.assertEquals(foreignBaz, message.getField(f("optional_foreign_enum")));
@@ -3122,6 +3239,7 @@
Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" )));
Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message")));
Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message" )));
Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum" )));
Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum" )));
Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum" )));
@@ -3157,6 +3275,9 @@
Assert.assertEquals(220,
((Message)message.getRepeatedField(f("repeated_import_message"), 0))
.getField(importD));
+ Assert.assertEquals(227,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0))
+ .getField(nestedB));
Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0));
Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0));
@@ -3193,6 +3314,9 @@
Assert.assertEquals(320,
((Message)message.getRepeatedField(f("repeated_import_message"), 1))
.getField(importD));
+ Assert.assertEquals(327,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1))
+ .getField(nestedB));
Assert.assertEquals( nestedBaz, message.getRepeatedField(f("repeated_nested_enum" ),1));
Assert.assertEquals(foreignBaz, message.getRepeatedField(f("repeated_foreign_enum"),1));
@@ -3316,6 +3440,12 @@
Assert.assertFalse(
((Message)message.getField(f("optional_import_message")))
.hasField(importD));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_public_import_message")))
+ .hasField(importE));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_lazy_message")))
+ .hasField(nestedB));
Assert.assertEquals(0,
((Message)message.getField(f("optionalgroup"))).getField(groupA));
@@ -3328,6 +3458,12 @@
Assert.assertEquals(0,
((Message)message.getField(f("optional_import_message")))
.getField(importD));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_public_import_message")))
+ .getField(importE));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_lazy_message")))
+ .getField(nestedB));
// Enums without defaults are set to the first value in the enum.
Assert.assertEquals( nestedFoo, message.getField(f("optional_nested_enum" )));
@@ -3358,6 +3494,7 @@
Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_message" )));
Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_message")));
Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_message" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_lazy_message" )));
Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_enum" )));
Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_enum" )));
Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_enum" )));
@@ -3442,6 +3579,7 @@
Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" )));
Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message")));
Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message" )));
Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum" )));
Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum" )));
Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum" )));
@@ -3477,6 +3615,9 @@
Assert.assertEquals(220,
((Message)message.getRepeatedField(f("repeated_import_message"), 0))
.getField(importD));
+ Assert.assertEquals(227,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0))
+ .getField(nestedB));
Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0));
Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0));
@@ -3513,6 +3654,9 @@
Assert.assertEquals(520,
((Message)message.getRepeatedField(f("repeated_import_message"), 1))
.getField(importD));
+ Assert.assertEquals(527,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1))
+ .getField(nestedB));
Assert.assertEquals( nestedFoo, message.getRepeatedField(f("repeated_nested_enum" ),1));
Assert.assertEquals(foreignFoo, message.getRepeatedField(f("repeated_foreign_enum"),1));
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/TextFormatTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/TextFormatTest.java
index 47690d1..5323d70 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -121,6 +121,18 @@
assertEquals(allFieldsSetText, javaText);
}
+ /** Print TestAllTypes as Builder and compare with golden file. */
+ public void testPrintMessageBuilder() throws Exception {
+ String javaText = TextFormat.printToString(TestUtil.getAllSetBuilder());
+
+ // Java likes to add a trailing ".0" to floats and doubles. C printf
+ // (with %g format) does not. Our golden files are used for both
+ // C++ and Java TextFormat classes, so we need to conform.
+ javaText = javaText.replace(".0\n", "\n");
+
+ assertEquals(allFieldsSetText, javaText);
+ }
+
/** Print TestAllExtensions and compare with golden file. */
public void testPrintExtensions() throws Exception {
String javaText = TextFormat.printToString(TestUtil.getAllExtensionsSet());
@@ -749,4 +761,26 @@
+ " 0xabcdef1234567890",
TextFormat.shortDebugString(makeUnknownFieldSet()));
}
+
+ public void testPrintToUnicodeString() {
+ assertEquals(
+ "optional_string: \"abc\u3042efg\"\n" +
+ "optional_bytes: \"\\343\\201\\202\"\n" +
+ "repeated_string: \"\u3093XYZ\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("abc\u3042efg")
+ .setOptionalBytes(bytes(0xe3, 0x81, 0x82))
+ .addRepeatedString("\u3093XYZ")
+ .build()));
+ }
+
+ public void testPrintToUnicodeString_unknown() {
+ assertEquals(
+ "1: \"\\343\\201\\202\"\n",
+ TextFormat.printToUnicodeString(UnknownFieldSet.newBuilder()
+ .addField(1,
+ UnknownFieldSet.Field.newBuilder()
+ .addLengthDelimited(bytes(0xe3, 0x81, 0x82)).build())
+ .build()));
+ }
}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/WireFormatTest.java b/third_party/protobuf/java/src/test/java/com/google/protobuf/WireFormatTest.java
index 5ea1dd6..94f6213 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/WireFormatTest.java
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/WireFormatTest.java
@@ -34,6 +34,7 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.util.List;
import protobuf_unittest.UnittestProto;
import protobuf_unittest.UnittestProto.TestAllExtensions;
@@ -328,7 +329,17 @@
private static final int TYPE_ID_2 =
TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber();
- public void testSerializeMessageSet() throws Exception {
+ public void testSerializeMessageSetEagerly() throws Exception {
+ testSerializeMessageSetWithFlag(true);
+ }
+
+ public void testSerializeMessageSetNotEagerly() throws Exception {
+ testSerializeMessageSetWithFlag(false);
+ }
+
+ private void testSerializeMessageSetWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
// Set up a TestMessageSet with two known messages and an unknown one.
TestMessageSet messageSet =
TestMessageSet.newBuilder()
@@ -372,7 +383,17 @@
assertEquals("bar", raw.getItem(2).getMessage().toStringUtf8());
}
- public void testParseMessageSet() throws Exception {
+ public void testParseMessageSetEagerly() throws Exception {
+ testParseMessageSetWithFlag(true);
+ }
+
+ public void testParseMessageSetNotEagerly()throws Exception {
+ testParseMessageSetWithFlag(false);
+ }
+
+ private void testParseMessageSetWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
@@ -424,4 +445,136 @@
assertEquals(1, field.getLengthDelimitedList().size());
assertEquals("bar", field.getLengthDelimitedList().get(0).toStringUtf8());
}
+
+ public void testParseMessageSetExtensionEagerly() throws Exception {
+ testParseMessageSetExtensionWithFlag(true);
+ }
+
+ public void testParseMessageSetExtensionNotEagerly() throws Exception {
+ testParseMessageSetExtensionWithFlag(false);
+ }
+
+ private void testParseMessageSetExtensionWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+ // Set up a RawMessageSet with a known messages.
+ int TYPE_ID_1 =
+ TestMessageSetExtension1
+ .getDescriptor().getExtensions().get(0).getNumber();
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_1)
+ .setMessage(
+ TestMessageSetExtension1.newBuilder()
+ .setI(123)
+ .build().toByteString())
+ .build())
+ .build();
+
+ ByteString data = raw.toByteString();
+
+ // Parse as a TestMessageSet and check the contents.
+ TestMessageSet messageSet =
+ TestMessageSet.parseFrom(data, extensionRegistry);
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ }
+
+ public void testMergeLazyMessageSetExtensionEagerly() throws Exception {
+ testMergeLazyMessageSetExtensionWithFlag(true);
+ }
+
+ public void testMergeLazyMessageSetExtensionNotEagerly() throws Exception {
+ testMergeLazyMessageSetExtensionWithFlag(false);
+ }
+
+ private void testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+ // Set up a RawMessageSet with a known messages.
+ int TYPE_ID_1 =
+ TestMessageSetExtension1
+ .getDescriptor().getExtensions().get(0).getNumber();
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_1)
+ .setMessage(
+ TestMessageSetExtension1.newBuilder()
+ .setI(123)
+ .build().toByteString())
+ .build())
+ .build();
+
+ ByteString data = raw.toByteString();
+
+ // Parse as a TestMessageSet and store value into lazy field
+ TestMessageSet messageSet =
+ TestMessageSet.parseFrom(data, extensionRegistry);
+ // Merge lazy field check the contents.
+ messageSet =
+ messageSet.toBuilder().mergeFrom(data, extensionRegistry).build();
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ }
+
+ public void testMergeMessageSetExtensionEagerly() throws Exception {
+ testMergeMessageSetExtensionWithFlag(true);
+ }
+
+ public void testMergeMessageSetExtensionNotEagerly() throws Exception {
+ testMergeMessageSetExtensionWithFlag(false);
+ }
+
+ private void testMergeMessageSetExtensionWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+ // Set up a RawMessageSet with a known messages.
+ int TYPE_ID_1 =
+ TestMessageSetExtension1
+ .getDescriptor().getExtensions().get(0).getNumber();
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_1)
+ .setMessage(
+ TestMessageSetExtension1.newBuilder()
+ .setI(123)
+ .build().toByteString())
+ .build())
+ .build();
+
+ // Serialize RawMessageSet unnormally (message value before type id)
+ ByteString.CodedBuilder out = ByteString.newCodedBuilder(
+ raw.getSerializedSize());
+ CodedOutputStream output = out.getCodedOutput();
+ List<RawMessageSet.Item> items = raw.getItemList();
+ for (int i = 0; i < items.size(); i++) {
+ RawMessageSet.Item item = items.get(i);
+ output.writeTag(1, WireFormat.WIRETYPE_START_GROUP);
+ output.writeBytes(3, item.getMessage());
+ output.writeInt32(2, item.getTypeId());
+ output.writeTag(1, WireFormat.WIRETYPE_END_GROUP);
+ }
+ ByteString data = out.build();
+
+ // Merge bytes into TestMessageSet and check the contents.
+ TestMessageSet messageSet =
+ TestMessageSet.newBuilder().mergeFrom(data, extensionRegistry).build();
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ }
}
diff --git a/third_party/protobuf/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto b/third_party/protobuf/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
index 9610e9d..6e67d97 100644
--- a/third_party/protobuf/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
+++ b/third_party/protobuf/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
@@ -46,6 +46,23 @@
message TestMessage {
}
+message Descriptor {
+ option no_standard_descriptor_accessor = true;
+ optional string descriptor = 1;
+ message NestedDescriptor {
+ option no_standard_descriptor_accessor = true;
+ optional string descriptor = 1;
+ }
+ optional NestedDescriptor nested_descriptor = 2;
+}
+
+message Parser {
+ enum ParserEnum {
+ PARSER = 1;
+ }
+ optional ParserEnum parser = 1;
+}
+
message Deprecated {
enum TestEnum {
FOO = 1;
@@ -62,6 +79,7 @@
message Object {
optional int32 object = 1;
+ optional string string_object = 2;
}
message String {
diff --git a/third_party/protobuf/protobuf.gyp b/third_party/protobuf/protobuf.gyp
index df0f6e5..44bcdd6 100644
--- a/third_party/protobuf/protobuf.gyp
+++ b/third_party/protobuf/protobuf.gyp
@@ -22,6 +22,7 @@
4244, # implicit conversion, possible loss of data
4355, # 'this' used in base member initializer list
4267, # size_t to int truncation
+ 4291, # no matching operator delete for a placement new
],
'defines!': [
'WIN32_LEAN_AND_MEAN', # Protobuf defines this itself.
@@ -161,6 +162,7 @@
'src/google/protobuf/descriptor.pb.h',
'src/google/protobuf/descriptor_database.h',
'src/google/protobuf/dynamic_message.h',
+ 'src/google/protobuf/generated_enum_reflection.h',
'src/google/protobuf/generated_message_reflection.h',
'src/google/protobuf/message.h',
'src/google/protobuf/reflection_ops.h',
@@ -174,17 +176,27 @@
'src/google/protobuf/compiler/code_generator.h',
'src/google/protobuf/compiler/command_line_interface.h',
'src/google/protobuf/compiler/importer.h',
+ 'src/google/protobuf/compiler/java/java_doc_comment.cc',
+ 'src/google/protobuf/compiler/java/java_doc_comment.h',
'src/google/protobuf/compiler/parser.h',
'src/google/protobuf/stubs/strutil.cc',
'src/google/protobuf/stubs/strutil.h',
'src/google/protobuf/stubs/substitute.cc',
'src/google/protobuf/stubs/substitute.h',
+ 'src/google/protobuf/stubs/stl_util.h',
+ 'src/google/protobuf/stubs/stringprintf.cc',
+ 'src/google/protobuf/stubs/stringprintf.h',
'src/google/protobuf/stubs/structurally_valid.cc',
+ 'src/google/protobuf/stubs/template_util.h',
+ 'src/google/protobuf/stubs/type_traits.h',
+
'src/google/protobuf/descriptor.cc',
'src/google/protobuf/descriptor.pb.cc',
'src/google/protobuf/descriptor_database.cc',
'src/google/protobuf/dynamic_message.cc',
+ 'src/google/protobuf/extension_set.cc',
+ 'src/google/protobuf/extension_set.h',
'src/google/protobuf/extension_set_heavy.cc',
'src/google/protobuf/generated_message_reflection.cc',
'src/google/protobuf/message.cc',
@@ -314,7 +326,10 @@
'files': [
'python/google/protobuf/__init__.py',
'python/google/protobuf/descriptor.py',
+ 'python/google/protobuf/descriptor_database.py',
+ 'python/google/protobuf/descriptor_pool.py',
'python/google/protobuf/message.py',
+ 'python/google/protobuf/message_factory.py',
'python/google/protobuf/reflection.py',
'python/google/protobuf/service.py',
'python/google/protobuf/service_reflection.py',
@@ -340,6 +355,7 @@
'python/google/protobuf/internal/cpp_message.py',
'python/google/protobuf/internal/decoder.py',
'python/google/protobuf/internal/encoder.py',
+ 'python/google/protobuf/internal/enum_type_wrapper.py',
'python/google/protobuf/internal/generator_test.py',
'python/google/protobuf/internal/message_listener.py',
'python/google/protobuf/internal/python_message.py',
diff --git a/third_party/protobuf/protobuf_full_do_not_use.host.darwin-arm.mk b/third_party/protobuf/protobuf_full_do_not_use.host.darwin-arm.mk
index f29686a..bed5990 100644
--- a/third_party/protobuf/protobuf_full_do_not_use.host.darwin-arm.mk
+++ b/third_party/protobuf/protobuf_full_do_not_use.host.darwin-arm.mk
@@ -24,13 +24,16 @@
GYP_COPIED_SOURCE_ORIGIN_DIRS :=
LOCAL_SRC_FILES := \
+ third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc \
third_party/protobuf/src/google/protobuf/stubs/strutil.cc \
third_party/protobuf/src/google/protobuf/stubs/substitute.cc \
+ third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc \
third_party/protobuf/src/google/protobuf/stubs/structurally_valid.cc \
third_party/protobuf/src/google/protobuf/descriptor.cc \
third_party/protobuf/src/google/protobuf/descriptor.pb.cc \
third_party/protobuf/src/google/protobuf/descriptor_database.cc \
third_party/protobuf/src/google/protobuf/dynamic_message.cc \
+ third_party/protobuf/src/google/protobuf/extension_set.cc \
third_party/protobuf/src/google/protobuf/extension_set_heavy.cc \
third_party/protobuf/src/google/protobuf/generated_message_reflection.cc \
third_party/protobuf/src/google/protobuf/message.cc \
@@ -48,7 +51,6 @@
third_party/protobuf/src/google/protobuf/unknown_field_set.cc \
third_party/protobuf/src/google/protobuf/stubs/common.cc \
third_party/protobuf/src/google/protobuf/stubs/once.cc \
- third_party/protobuf/src/google/protobuf/extension_set.cc \
third_party/protobuf/src/google/protobuf/generated_message_util.cc \
third_party/protobuf/src/google/protobuf/message_lite.cc \
third_party/protobuf/src/google/protobuf/repeated_field.cc \
diff --git a/third_party/protobuf/protobuf_full_do_not_use.host.darwin-mips.mk b/third_party/protobuf/protobuf_full_do_not_use.host.darwin-mips.mk
index 1ef7fc0..6614ab9 100644
--- a/third_party/protobuf/protobuf_full_do_not_use.host.darwin-mips.mk
+++ b/third_party/protobuf/protobuf_full_do_not_use.host.darwin-mips.mk
@@ -24,13 +24,16 @@
GYP_COPIED_SOURCE_ORIGIN_DIRS :=
LOCAL_SRC_FILES := \
+ third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc \
third_party/protobuf/src/google/protobuf/stubs/strutil.cc \
third_party/protobuf/src/google/protobuf/stubs/substitute.cc \
+ third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc \
third_party/protobuf/src/google/protobuf/stubs/structurally_valid.cc \
third_party/protobuf/src/google/protobuf/descriptor.cc \
third_party/protobuf/src/google/protobuf/descriptor.pb.cc \
third_party/protobuf/src/google/protobuf/descriptor_database.cc \
third_party/protobuf/src/google/protobuf/dynamic_message.cc \
+ third_party/protobuf/src/google/protobuf/extension_set.cc \
third_party/protobuf/src/google/protobuf/extension_set_heavy.cc \
third_party/protobuf/src/google/protobuf/generated_message_reflection.cc \
third_party/protobuf/src/google/protobuf/message.cc \
@@ -48,7 +51,6 @@
third_party/protobuf/src/google/protobuf/unknown_field_set.cc \
third_party/protobuf/src/google/protobuf/stubs/common.cc \
third_party/protobuf/src/google/protobuf/stubs/once.cc \
- third_party/protobuf/src/google/protobuf/extension_set.cc \
third_party/protobuf/src/google/protobuf/generated_message_util.cc \
third_party/protobuf/src/google/protobuf/message_lite.cc \
third_party/protobuf/src/google/protobuf/repeated_field.cc \
diff --git a/third_party/protobuf/protobuf_full_do_not_use.host.darwin-x86.mk b/third_party/protobuf/protobuf_full_do_not_use.host.darwin-x86.mk
index c542ad0..9285232 100644
--- a/third_party/protobuf/protobuf_full_do_not_use.host.darwin-x86.mk
+++ b/third_party/protobuf/protobuf_full_do_not_use.host.darwin-x86.mk
@@ -24,13 +24,16 @@
GYP_COPIED_SOURCE_ORIGIN_DIRS :=
LOCAL_SRC_FILES := \
+ third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc \
third_party/protobuf/src/google/protobuf/stubs/strutil.cc \
third_party/protobuf/src/google/protobuf/stubs/substitute.cc \
+ third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc \
third_party/protobuf/src/google/protobuf/stubs/structurally_valid.cc \
third_party/protobuf/src/google/protobuf/descriptor.cc \
third_party/protobuf/src/google/protobuf/descriptor.pb.cc \
third_party/protobuf/src/google/protobuf/descriptor_database.cc \
third_party/protobuf/src/google/protobuf/dynamic_message.cc \
+ third_party/protobuf/src/google/protobuf/extension_set.cc \
third_party/protobuf/src/google/protobuf/extension_set_heavy.cc \
third_party/protobuf/src/google/protobuf/generated_message_reflection.cc \
third_party/protobuf/src/google/protobuf/message.cc \
@@ -48,7 +51,6 @@
third_party/protobuf/src/google/protobuf/unknown_field_set.cc \
third_party/protobuf/src/google/protobuf/stubs/common.cc \
third_party/protobuf/src/google/protobuf/stubs/once.cc \
- third_party/protobuf/src/google/protobuf/extension_set.cc \
third_party/protobuf/src/google/protobuf/generated_message_util.cc \
third_party/protobuf/src/google/protobuf/message_lite.cc \
third_party/protobuf/src/google/protobuf/repeated_field.cc \
diff --git a/third_party/protobuf/protobuf_full_do_not_use.host.linux-arm.mk b/third_party/protobuf/protobuf_full_do_not_use.host.linux-arm.mk
index 4fa32d2..0f0b8b4 100644
--- a/third_party/protobuf/protobuf_full_do_not_use.host.linux-arm.mk
+++ b/third_party/protobuf/protobuf_full_do_not_use.host.linux-arm.mk
@@ -24,13 +24,16 @@
GYP_COPIED_SOURCE_ORIGIN_DIRS :=
LOCAL_SRC_FILES := \
+ third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc \
third_party/protobuf/src/google/protobuf/stubs/strutil.cc \
third_party/protobuf/src/google/protobuf/stubs/substitute.cc \
+ third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc \
third_party/protobuf/src/google/protobuf/stubs/structurally_valid.cc \
third_party/protobuf/src/google/protobuf/descriptor.cc \
third_party/protobuf/src/google/protobuf/descriptor.pb.cc \
third_party/protobuf/src/google/protobuf/descriptor_database.cc \
third_party/protobuf/src/google/protobuf/dynamic_message.cc \
+ third_party/protobuf/src/google/protobuf/extension_set.cc \
third_party/protobuf/src/google/protobuf/extension_set_heavy.cc \
third_party/protobuf/src/google/protobuf/generated_message_reflection.cc \
third_party/protobuf/src/google/protobuf/message.cc \
@@ -48,7 +51,6 @@
third_party/protobuf/src/google/protobuf/unknown_field_set.cc \
third_party/protobuf/src/google/protobuf/stubs/common.cc \
third_party/protobuf/src/google/protobuf/stubs/once.cc \
- third_party/protobuf/src/google/protobuf/extension_set.cc \
third_party/protobuf/src/google/protobuf/generated_message_util.cc \
third_party/protobuf/src/google/protobuf/message_lite.cc \
third_party/protobuf/src/google/protobuf/repeated_field.cc \
diff --git a/third_party/protobuf/protobuf_full_do_not_use.host.linux-mips.mk b/third_party/protobuf/protobuf_full_do_not_use.host.linux-mips.mk
index c8047bb..dcc523d 100644
--- a/third_party/protobuf/protobuf_full_do_not_use.host.linux-mips.mk
+++ b/third_party/protobuf/protobuf_full_do_not_use.host.linux-mips.mk
@@ -24,13 +24,16 @@
GYP_COPIED_SOURCE_ORIGIN_DIRS :=
LOCAL_SRC_FILES := \
+ third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc \
third_party/protobuf/src/google/protobuf/stubs/strutil.cc \
third_party/protobuf/src/google/protobuf/stubs/substitute.cc \
+ third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc \
third_party/protobuf/src/google/protobuf/stubs/structurally_valid.cc \
third_party/protobuf/src/google/protobuf/descriptor.cc \
third_party/protobuf/src/google/protobuf/descriptor.pb.cc \
third_party/protobuf/src/google/protobuf/descriptor_database.cc \
third_party/protobuf/src/google/protobuf/dynamic_message.cc \
+ third_party/protobuf/src/google/protobuf/extension_set.cc \
third_party/protobuf/src/google/protobuf/extension_set_heavy.cc \
third_party/protobuf/src/google/protobuf/generated_message_reflection.cc \
third_party/protobuf/src/google/protobuf/message.cc \
@@ -48,7 +51,6 @@
third_party/protobuf/src/google/protobuf/unknown_field_set.cc \
third_party/protobuf/src/google/protobuf/stubs/common.cc \
third_party/protobuf/src/google/protobuf/stubs/once.cc \
- third_party/protobuf/src/google/protobuf/extension_set.cc \
third_party/protobuf/src/google/protobuf/generated_message_util.cc \
third_party/protobuf/src/google/protobuf/message_lite.cc \
third_party/protobuf/src/google/protobuf/repeated_field.cc \
diff --git a/third_party/protobuf/protobuf_full_do_not_use.host.linux-x86.mk b/third_party/protobuf/protobuf_full_do_not_use.host.linux-x86.mk
index 1562026..6edfc29 100644
--- a/third_party/protobuf/protobuf_full_do_not_use.host.linux-x86.mk
+++ b/third_party/protobuf/protobuf_full_do_not_use.host.linux-x86.mk
@@ -24,13 +24,16 @@
GYP_COPIED_SOURCE_ORIGIN_DIRS :=
LOCAL_SRC_FILES := \
+ third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc \
third_party/protobuf/src/google/protobuf/stubs/strutil.cc \
third_party/protobuf/src/google/protobuf/stubs/substitute.cc \
+ third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc \
third_party/protobuf/src/google/protobuf/stubs/structurally_valid.cc \
third_party/protobuf/src/google/protobuf/descriptor.cc \
third_party/protobuf/src/google/protobuf/descriptor.pb.cc \
third_party/protobuf/src/google/protobuf/descriptor_database.cc \
third_party/protobuf/src/google/protobuf/dynamic_message.cc \
+ third_party/protobuf/src/google/protobuf/extension_set.cc \
third_party/protobuf/src/google/protobuf/extension_set_heavy.cc \
third_party/protobuf/src/google/protobuf/generated_message_reflection.cc \
third_party/protobuf/src/google/protobuf/message.cc \
@@ -48,7 +51,6 @@
third_party/protobuf/src/google/protobuf/unknown_field_set.cc \
third_party/protobuf/src/google/protobuf/stubs/common.cc \
third_party/protobuf/src/google/protobuf/stubs/once.cc \
- third_party/protobuf/src/google/protobuf/extension_set.cc \
third_party/protobuf/src/google/protobuf/generated_message_util.cc \
third_party/protobuf/src/google/protobuf/message_lite.cc \
third_party/protobuf/src/google/protobuf/repeated_field.cc \
diff --git a/third_party/protobuf/python/google/protobuf/descriptor.py b/third_party/protobuf/python/google/protobuf/descriptor.py
index cf609be..eb13eda 100755
--- a/third_party/protobuf/python/google/protobuf/descriptor.py
+++ b/third_party/protobuf/python/google/protobuf/descriptor.py
@@ -39,13 +39,20 @@
if api_implementation.Type() == 'cpp':
- from google.protobuf.internal import cpp_message
+ if api_implementation.Version() == 2:
+ from google.protobuf.internal.cpp import _message
+ else:
+ from google.protobuf.internal import cpp_message
class Error(Exception):
"""Base error for this module."""
+class TypeTransformationError(Error):
+ """Error transforming between python proto type and corresponding C++ type."""
+
+
class DescriptorBase(object):
"""Descriptors base class.
@@ -72,6 +79,18 @@
# Does this descriptor have non-default options?
self.has_options = options is not None
+ def _SetOptions(self, options, options_class_name):
+ """Sets the descriptor's options
+
+ This function is used in generated proto2 files to update descriptor
+ options. It must not be used outside proto2.
+ """
+ self._options = options
+ self._options_class_name = options_class_name
+
+ # Does this descriptor have non-default options?
+ self.has_options = options is not None
+
def GetOptions(self):
"""Retrieves descriptor options.
@@ -250,6 +269,24 @@
self._serialized_start = serialized_start
self._serialized_end = serialized_end
+ def EnumValueName(self, enum, value):
+ """Returns the string name of an enum value.
+
+ This is just a small helper method to simplify a common operation.
+
+ Args:
+ enum: string name of the Enum.
+ value: int, value of the enum.
+
+ Returns:
+ string name of the enum value.
+
+ Raises:
+ KeyError if either the Enum doesn't exist or the value is not a valid
+ value for the enum.
+ """
+ return self.enum_types_by_name[enum].values_by_number[value].name
+
def CopyToProto(self, proto):
"""Copies this to a descriptor_pb2.DescriptorProto.
@@ -275,7 +312,7 @@
"""Descriptor for a single field in a .proto file.
- A FieldDescriptor instance has the following attriubtes:
+ A FieldDescriptor instance has the following attributes:
name: (str) Name of this field, exactly as it appears in .proto.
full_name: (str) Name of this field, including containing scope. This is
@@ -358,6 +395,27 @@
CPPTYPE_MESSAGE = 10
MAX_CPPTYPE = 10
+ _PYTHON_TO_CPP_PROTO_TYPE_MAP = {
+ TYPE_DOUBLE: CPPTYPE_DOUBLE,
+ TYPE_FLOAT: CPPTYPE_FLOAT,
+ TYPE_ENUM: CPPTYPE_ENUM,
+ TYPE_INT64: CPPTYPE_INT64,
+ TYPE_SINT64: CPPTYPE_INT64,
+ TYPE_SFIXED64: CPPTYPE_INT64,
+ TYPE_UINT64: CPPTYPE_UINT64,
+ TYPE_FIXED64: CPPTYPE_UINT64,
+ TYPE_INT32: CPPTYPE_INT32,
+ TYPE_SFIXED32: CPPTYPE_INT32,
+ TYPE_SINT32: CPPTYPE_INT32,
+ TYPE_UINT32: CPPTYPE_UINT32,
+ TYPE_FIXED32: CPPTYPE_UINT32,
+ TYPE_BYTES: CPPTYPE_STRING,
+ TYPE_STRING: CPPTYPE_STRING,
+ TYPE_BOOL: CPPTYPE_BOOL,
+ TYPE_MESSAGE: CPPTYPE_MESSAGE,
+ TYPE_GROUP: CPPTYPE_MESSAGE
+ }
+
# Must be consistent with C++ FieldDescriptor::Label enum in
# descriptor.h.
#
@@ -395,12 +453,38 @@
self.extension_scope = extension_scope
if api_implementation.Type() == 'cpp':
if is_extension:
- self._cdescriptor = cpp_message.GetExtensionDescriptor(full_name)
+ if api_implementation.Version() == 2:
+ self._cdescriptor = _message.GetExtensionDescriptor(full_name)
+ else:
+ self._cdescriptor = cpp_message.GetExtensionDescriptor(full_name)
else:
- self._cdescriptor = cpp_message.GetFieldDescriptor(full_name)
+ if api_implementation.Version() == 2:
+ self._cdescriptor = _message.GetFieldDescriptor(full_name)
+ else:
+ self._cdescriptor = cpp_message.GetFieldDescriptor(full_name)
else:
self._cdescriptor = None
+ @staticmethod
+ def ProtoTypeToCppProtoType(proto_type):
+ """Converts from a Python proto type to a C++ Proto Type.
+
+ The Python ProtocolBuffer classes specify both the 'Python' datatype and the
+ 'C++' datatype - and they're not the same. This helper method should
+ translate from one to another.
+
+ Args:
+ proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*)
+ Returns:
+ descriptor.FieldDescriptor.CPPTYPE_*, the C++ type.
+ Raises:
+ TypeTransformationError: when the Python proto type isn't known.
+ """
+ try:
+ return FieldDescriptor._PYTHON_TO_CPP_PROTO_TYPE_MAP[proto_type]
+ except KeyError:
+ raise TypeTransformationError('Unknown proto_type: %s' % proto_type)
+
class EnumDescriptor(_NestedDescriptorBase):
@@ -577,7 +661,10 @@
self.serialized_pb = serialized_pb
if (api_implementation.Type() == 'cpp' and
self.serialized_pb is not None):
- cpp_message.BuildFile(self.serialized_pb)
+ if api_implementation.Version() == 2:
+ _message.BuildFile(self.serialized_pb)
+ else:
+ cpp_message.BuildFile(self.serialized_pb)
def CopyToProto(self, proto):
"""Copies this to a descriptor_pb2.FileDescriptorProto.
@@ -596,3 +683,31 @@
"""
message.ParseFromString(string)
return message
+
+
+def MakeDescriptor(desc_proto, package=''):
+ """Make a protobuf Descriptor given a DescriptorProto protobuf.
+
+ Args:
+ desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
+ package: Optional package name for the new message Descriptor (string).
+
+ Returns:
+ A Descriptor for protobuf messages.
+ """
+ full_message_name = [desc_proto.name]
+ if package: full_message_name.insert(0, package)
+ fields = []
+ for field_proto in desc_proto.field:
+ full_name = '.'.join(full_message_name + [field_proto.name])
+ field = FieldDescriptor(
+ field_proto.name, full_name, field_proto.number - 1,
+ field_proto.number, field_proto.type,
+ FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type),
+ field_proto.label, None, None, None, None, False, None,
+ has_default_value=False)
+ fields.append(field)
+
+ desc_name = '.'.join(full_message_name)
+ return Descriptor(desc_proto.name, desc_name, None, None, fields,
+ [], [], [])
diff --git a/third_party/protobuf/python/google/protobuf/descriptor_database.py b/third_party/protobuf/python/google/protobuf/descriptor_database.py
new file mode 100644
index 0000000..8665d3c
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/descriptor_database.py
@@ -0,0 +1,120 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# http://code.google.com/p/protobuf/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Provides a container for DescriptorProtos."""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+
+class DescriptorDatabase(object):
+ """A container accepting FileDescriptorProtos and maps DescriptorProtos."""
+
+ def __init__(self):
+ self._file_desc_protos_by_file = {}
+ self._file_desc_protos_by_symbol = {}
+
+ def Add(self, file_desc_proto):
+ """Adds the FileDescriptorProto and its types to this database.
+
+ Args:
+ file_desc_proto: The FileDescriptorProto to add.
+ """
+
+ self._file_desc_protos_by_file[file_desc_proto.name] = file_desc_proto
+ package = file_desc_proto.package
+ for message in file_desc_proto.message_type:
+ self._file_desc_protos_by_symbol.update(
+ (name, file_desc_proto) for name in _ExtractSymbols(message, package))
+ for enum in file_desc_proto.enum_type:
+ self._file_desc_protos_by_symbol[
+ '.'.join((package, enum.name))] = file_desc_proto
+
+ def FindFileByName(self, name):
+ """Finds the file descriptor proto by file name.
+
+ Typically the file name is a relative path ending to a .proto file. The
+ proto with the given name will have to have been added to this database
+ using the Add method or else an error will be raised.
+
+ Args:
+ name: The file name to find.
+
+ Returns:
+ The file descriptor proto matching the name.
+
+ Raises:
+ KeyError if no file by the given name was added.
+ """
+
+ return self._file_desc_protos_by_file[name]
+
+ def FindFileContainingSymbol(self, symbol):
+ """Finds the file descriptor proto containing the specified symbol.
+
+ The symbol should be a fully qualified name including the file descriptor's
+ package and any containing messages. Some examples:
+
+ 'some.package.name.Message'
+ 'some.package.name.Message.NestedEnum'
+
+ The file descriptor proto containing the specified symbol must be added to
+ this database using the Add method or else an error will be raised.
+
+ Args:
+ symbol: The fully qualified symbol name.
+
+ Returns:
+ The file descriptor proto containing the symbol.
+
+ Raises:
+ KeyError if no file contains the specified symbol.
+ """
+
+ return self._file_desc_protos_by_symbol[symbol]
+
+
+def _ExtractSymbols(desc_proto, package):
+ """Pulls out all the symbols from a descriptor proto.
+
+ Args:
+ desc_proto: The proto to extract symbols from.
+ package: The package containing the descriptor type.
+
+ Yields:
+ The fully qualified name found in the descriptor.
+ """
+
+ message_name = '.'.join((package, desc_proto.name))
+ yield message_name
+ for nested_type in desc_proto.nested_type:
+ for symbol in _ExtractSymbols(nested_type, message_name):
+ yield symbol
+ for enum_type in desc_proto.enum_type:
+ yield '.'.join((message_name, enum_type.name))
diff --git a/third_party/protobuf/python/google/protobuf/descriptor_pool.py b/third_party/protobuf/python/google/protobuf/descriptor_pool.py
new file mode 100644
index 0000000..8f1f445
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/descriptor_pool.py
@@ -0,0 +1,527 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# http://code.google.com/p/protobuf/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Provides DescriptorPool to use as a container for proto2 descriptors.
+
+The DescriptorPool is used in conjection with a DescriptorDatabase to maintain
+a collection of protocol buffer descriptors for use when dynamically creating
+message types at runtime.
+
+For most applications protocol buffers should be used via modules generated by
+the protocol buffer compiler tool. This should only be used when the type of
+protocol buffers used in an application or library cannot be predetermined.
+
+Below is a straightforward example on how to use this class:
+
+ pool = DescriptorPool()
+ file_descriptor_protos = [ ... ]
+ for file_descriptor_proto in file_descriptor_protos:
+ pool.Add(file_descriptor_proto)
+ my_message_descriptor = pool.FindMessageTypeByName('some.package.MessageType')
+
+The message descriptor can be used in conjunction with the message_factory
+module in order to create a protocol buffer class that can be encoded and
+decoded.
+"""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+from google.protobuf import descriptor_pb2
+from google.protobuf import descriptor
+from google.protobuf import descriptor_database
+
+
+class DescriptorPool(object):
+ """A collection of protobufs dynamically constructed by descriptor protos."""
+
+ def __init__(self, descriptor_db=None):
+ """Initializes a Pool of proto buffs.
+
+ The descriptor_db argument to the constructor is provided to allow
+ specialized file descriptor proto lookup code to be triggered on demand. An
+ example would be an implementation which will read and compile a file
+ specified in a call to FindFileByName() and not require the call to Add()
+ at all. Results from this database will be cached internally here as well.
+
+ Args:
+ descriptor_db: A secondary source of file descriptors.
+ """
+
+ self._internal_db = descriptor_database.DescriptorDatabase()
+ self._descriptor_db = descriptor_db
+ self._descriptors = {}
+ self._enum_descriptors = {}
+ self._file_descriptors = {}
+
+ def Add(self, file_desc_proto):
+ """Adds the FileDescriptorProto and its types to this pool.
+
+ Args:
+ file_desc_proto: The FileDescriptorProto to add.
+ """
+
+ self._internal_db.Add(file_desc_proto)
+
+ def FindFileByName(self, file_name):
+ """Gets a FileDescriptor by file name.
+
+ Args:
+ file_name: The path to the file to get a descriptor for.
+
+ Returns:
+ A FileDescriptor for the named file.
+
+ Raises:
+ KeyError: if the file can not be found in the pool.
+ """
+
+ try:
+ file_proto = self._internal_db.FindFileByName(file_name)
+ except KeyError as error:
+ if self._descriptor_db:
+ file_proto = self._descriptor_db.FindFileByName(file_name)
+ else:
+ raise error
+ if not file_proto:
+ raise KeyError('Cannot find a file named %s' % file_name)
+ return self._ConvertFileProtoToFileDescriptor(file_proto)
+
+ def FindFileContainingSymbol(self, symbol):
+ """Gets the FileDescriptor for the file containing the specified symbol.
+
+ Args:
+ symbol: The name of the symbol to search for.
+
+ Returns:
+ A FileDescriptor that contains the specified symbol.
+
+ Raises:
+ KeyError: if the file can not be found in the pool.
+ """
+
+ try:
+ file_proto = self._internal_db.FindFileContainingSymbol(symbol)
+ except KeyError as error:
+ if self._descriptor_db:
+ file_proto = self._descriptor_db.FindFileContainingSymbol(symbol)
+ else:
+ raise error
+ if not file_proto:
+ raise KeyError('Cannot find a file containing %s' % symbol)
+ return self._ConvertFileProtoToFileDescriptor(file_proto)
+
+ def FindMessageTypeByName(self, full_name):
+ """Loads the named descriptor from the pool.
+
+ Args:
+ full_name: The full name of the descriptor to load.
+
+ Returns:
+ The descriptor for the named type.
+ """
+
+ full_name = full_name.lstrip('.') # fix inconsistent qualified name formats
+ if full_name not in self._descriptors:
+ self.FindFileContainingSymbol(full_name)
+ return self._descriptors[full_name]
+
+ def FindEnumTypeByName(self, full_name):
+ """Loads the named enum descriptor from the pool.
+
+ Args:
+ full_name: The full name of the enum descriptor to load.
+
+ Returns:
+ The enum descriptor for the named type.
+ """
+
+ full_name = full_name.lstrip('.') # fix inconsistent qualified name formats
+ if full_name not in self._enum_descriptors:
+ self.FindFileContainingSymbol(full_name)
+ return self._enum_descriptors[full_name]
+
+ def _ConvertFileProtoToFileDescriptor(self, file_proto):
+ """Creates a FileDescriptor from a proto or returns a cached copy.
+
+ This method also has the side effect of loading all the symbols found in
+ the file into the appropriate dictionaries in the pool.
+
+ Args:
+ file_proto: The proto to convert.
+
+ Returns:
+ A FileDescriptor matching the passed in proto.
+ """
+
+ if file_proto.name not in self._file_descriptors:
+ file_descriptor = descriptor.FileDescriptor(
+ name=file_proto.name,
+ package=file_proto.package,
+ options=file_proto.options,
+ serialized_pb=file_proto.SerializeToString())
+ scope = {}
+ dependencies = list(self._GetDeps(file_proto))
+
+ for dependency in dependencies:
+ dep_desc = self.FindFileByName(dependency.name)
+ dep_proto = descriptor_pb2.FileDescriptorProto.FromString(
+ dep_desc.serialized_pb)
+ package = '.' + dep_proto.package
+ package_prefix = package + '.'
+
+ def _strip_package(symbol):
+ if symbol.startswith(package_prefix):
+ return symbol[len(package_prefix):]
+ return symbol
+
+ symbols = list(self._ExtractSymbols(dep_proto.message_type, package))
+ scope.update(symbols)
+ scope.update((_strip_package(k), v) for k, v in symbols)
+
+ symbols = list(self._ExtractEnums(dep_proto.enum_type, package))
+ scope.update(symbols)
+ scope.update((_strip_package(k), v) for k, v in symbols)
+
+ for message_type in file_proto.message_type:
+ message_desc = self._ConvertMessageDescriptor(
+ message_type, file_proto.package, file_descriptor, scope)
+ file_descriptor.message_types_by_name[message_desc.name] = message_desc
+ for enum_type in file_proto.enum_type:
+ self._ConvertEnumDescriptor(enum_type, file_proto.package,
+ file_descriptor, None, scope)
+ for desc_proto in self._ExtractMessages(file_proto.message_type):
+ self._SetFieldTypes(desc_proto, scope)
+
+ for desc_proto in file_proto.message_type:
+ desc = scope[desc_proto.name]
+ file_descriptor.message_types_by_name[desc_proto.name] = desc
+ self.Add(file_proto)
+ self._file_descriptors[file_proto.name] = file_descriptor
+
+ return self._file_descriptors[file_proto.name]
+
+ def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None,
+ scope=None):
+ """Adds the proto to the pool in the specified package.
+
+ Args:
+ desc_proto: The descriptor_pb2.DescriptorProto protobuf message.
+ package: The package the proto should be located in.
+ file_desc: The file containing this message.
+ scope: Dict mapping short and full symbols to message and enum types.
+
+ Returns:
+ The added descriptor.
+ """
+
+ if package:
+ desc_name = '.'.join((package, desc_proto.name))
+ else:
+ desc_name = desc_proto.name
+
+ if file_desc is None:
+ file_name = None
+ else:
+ file_name = file_desc.name
+
+ if scope is None:
+ scope = {}
+
+ nested = [
+ self._ConvertMessageDescriptor(nested, desc_name, file_desc, scope)
+ for nested in desc_proto.nested_type]
+ enums = [
+ self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope)
+ for enum in desc_proto.enum_type]
+ fields = [self._MakeFieldDescriptor(field, desc_name, index)
+ for index, field in enumerate(desc_proto.field)]
+ extensions = [self._MakeFieldDescriptor(extension, desc_name, True)
+ for index, extension in enumerate(desc_proto.extension)]
+ extension_ranges = [(r.start, r.end) for r in desc_proto.extension_range]
+ if extension_ranges:
+ is_extendable = True
+ else:
+ is_extendable = False
+ desc = descriptor.Descriptor(
+ name=desc_proto.name,
+ full_name=desc_name,
+ filename=file_name,
+ containing_type=None,
+ fields=fields,
+ nested_types=nested,
+ enum_types=enums,
+ extensions=extensions,
+ options=desc_proto.options,
+ is_extendable=is_extendable,
+ extension_ranges=extension_ranges,
+ file=file_desc,
+ serialized_start=None,
+ serialized_end=None)
+ for nested in desc.nested_types:
+ nested.containing_type = desc
+ for enum in desc.enum_types:
+ enum.containing_type = desc
+ scope[desc_proto.name] = desc
+ scope['.' + desc_name] = desc
+ self._descriptors[desc_name] = desc
+ return desc
+
+ def _ConvertEnumDescriptor(self, enum_proto, package=None, file_desc=None,
+ containing_type=None, scope=None):
+ """Make a protobuf EnumDescriptor given an EnumDescriptorProto protobuf.
+
+ Args:
+ enum_proto: The descriptor_pb2.EnumDescriptorProto protobuf message.
+ package: Optional package name for the new message EnumDescriptor.
+ file_desc: The file containing the enum descriptor.
+ containing_type: The type containing this enum.
+ scope: Scope containing available types.
+
+ Returns:
+ The added descriptor
+ """
+
+ if package:
+ enum_name = '.'.join((package, enum_proto.name))
+ else:
+ enum_name = enum_proto.name
+
+ if file_desc is None:
+ file_name = None
+ else:
+ file_name = file_desc.name
+
+ values = [self._MakeEnumValueDescriptor(value, index)
+ for index, value in enumerate(enum_proto.value)]
+ desc = descriptor.EnumDescriptor(name=enum_proto.name,
+ full_name=enum_name,
+ filename=file_name,
+ file=file_desc,
+ values=values,
+ containing_type=containing_type,
+ options=enum_proto.options)
+ scope[enum_proto.name] = desc
+ scope['.%s' % enum_name] = desc
+ self._enum_descriptors[enum_name] = desc
+ return desc
+
+ def _MakeFieldDescriptor(self, field_proto, message_name, index,
+ is_extension=False):
+ """Creates a field descriptor from a FieldDescriptorProto.
+
+ For message and enum type fields, this method will do a look up
+ in the pool for the appropriate descriptor for that type. If it
+ is unavailable, it will fall back to the _source function to
+ create it. If this type is still unavailable, construction will
+ fail.
+
+ Args:
+ field_proto: The proto describing the field.
+ message_name: The name of the containing message.
+ index: Index of the field
+ is_extension: Indication that this field is for an extension.
+
+ Returns:
+ An initialized FieldDescriptor object
+ """
+
+ if message_name:
+ full_name = '.'.join((message_name, field_proto.name))
+ else:
+ full_name = field_proto.name
+
+ return descriptor.FieldDescriptor(
+ name=field_proto.name,
+ full_name=full_name,
+ index=index,
+ number=field_proto.number,
+ type=field_proto.type,
+ cpp_type=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ label=field_proto.label,
+ has_default_value=False,
+ default_value=None,
+ is_extension=is_extension,
+ extension_scope=None,
+ options=field_proto.options)
+
+ def _SetFieldTypes(self, desc_proto, scope):
+ """Sets the field's type, cpp_type, message_type and enum_type.
+
+ Args:
+ desc_proto: The message descriptor to update.
+ scope: Enclosing scope of available types.
+ """
+
+ desc = scope[desc_proto.name]
+ for field_proto, field_desc in zip(desc_proto.field, desc.fields):
+ if field_proto.type_name:
+ type_name = field_proto.type_name
+ if type_name not in scope:
+ type_name = '.' + type_name
+ desc = scope[type_name]
+ else:
+ desc = None
+
+ if not field_proto.HasField('type'):
+ if isinstance(desc, descriptor.Descriptor):
+ field_proto.type = descriptor.FieldDescriptor.TYPE_MESSAGE
+ else:
+ field_proto.type = descriptor.FieldDescriptor.TYPE_ENUM
+
+ field_desc.cpp_type = descriptor.FieldDescriptor.ProtoTypeToCppProtoType(
+ field_proto.type)
+
+ if (field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE
+ or field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP):
+ field_desc.message_type = desc
+
+ if field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
+ field_desc.enum_type = desc
+
+ if field_proto.label == descriptor.FieldDescriptor.LABEL_REPEATED:
+ field_desc.has_default = False
+ field_desc.default_value = []
+ elif field_proto.HasField('default_value'):
+ field_desc.has_default = True
+ if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or
+ field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT):
+ field_desc.default_value = float(field_proto.default_value)
+ elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING:
+ field_desc.default_value = field_proto.default_value
+ elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL:
+ field_desc.default_value = field_proto.default_value.lower() == 'true'
+ elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
+ field_desc.default_value = field_desc.enum_type.values_by_name[
+ field_proto.default_value].index
+ else:
+ field_desc.default_value = int(field_proto.default_value)
+ else:
+ field_desc.has_default = False
+ field_desc.default_value = None
+
+ field_desc.type = field_proto.type
+
+ for nested_type in desc_proto.nested_type:
+ self._SetFieldTypes(nested_type, scope)
+
+ def _MakeEnumValueDescriptor(self, value_proto, index):
+ """Creates a enum value descriptor object from a enum value proto.
+
+ Args:
+ value_proto: The proto describing the enum value.
+ index: The index of the enum value.
+
+ Returns:
+ An initialized EnumValueDescriptor object.
+ """
+
+ return descriptor.EnumValueDescriptor(
+ name=value_proto.name,
+ index=index,
+ number=value_proto.number,
+ options=value_proto.options,
+ type=None)
+
+ def _ExtractSymbols(self, desc_protos, package):
+ """Pulls out all the symbols from descriptor protos.
+
+ Args:
+ desc_protos: The protos to extract symbols from.
+ package: The package containing the descriptor type.
+ Yields:
+ A two element tuple of the type name and descriptor object.
+ """
+
+ for desc_proto in desc_protos:
+ if package:
+ message_name = '.'.join((package, desc_proto.name))
+ else:
+ message_name = desc_proto.name
+ message_desc = self.FindMessageTypeByName(message_name)
+ yield (message_name, message_desc)
+ for symbol in self._ExtractSymbols(desc_proto.nested_type, message_name):
+ yield symbol
+ for symbol in self._ExtractEnums(desc_proto.enum_type, message_name):
+ yield symbol
+
+ def _ExtractEnums(self, enum_protos, package):
+ """Pulls out all the symbols from enum protos.
+
+ Args:
+ enum_protos: The protos to extract symbols from.
+ package: The package containing the enum type.
+
+ Yields:
+ A two element tuple of the type name and enum descriptor object.
+ """
+
+ for enum_proto in enum_protos:
+ if package:
+ enum_name = '.'.join((package, enum_proto.name))
+ else:
+ enum_name = enum_proto.name
+ enum_desc = self.FindEnumTypeByName(enum_name)
+ yield (enum_name, enum_desc)
+
+ def _ExtractMessages(self, desc_protos):
+ """Pulls out all the message protos from descriptos.
+
+ Args:
+ desc_protos: The protos to extract symbols from.
+
+ Yields:
+ Descriptor protos.
+ """
+
+ for desc_proto in desc_protos:
+ yield desc_proto
+ for message in self._ExtractMessages(desc_proto.nested_type):
+ yield message
+
+ def _GetDeps(self, file_proto):
+ """Recursively finds dependencies for file protos.
+
+ Args:
+ file_proto: The proto to get dependencies from.
+
+ Yields:
+ Each direct and indirect dependency.
+ """
+
+ for dependency in file_proto.dependency:
+ dep_desc = self.FindFileByName(dependency)
+ dep_proto = descriptor_pb2.FileDescriptorProto.FromString(
+ dep_desc.serialized_pb)
+ yield dep_proto
+ for parent_dep in self._GetDeps(dep_proto):
+ yield parent_dep
diff --git a/third_party/protobuf/python/google/protobuf/internal/api_implementation.py b/third_party/protobuf/python/google/protobuf/internal/api_implementation.py
index b3e412e..ce02a32 100644
--- a/third_party/protobuf/python/google/protobuf/internal/api_implementation.py
+++ b/third_party/protobuf/python/google/protobuf/internal/api_implementation.py
@@ -56,9 +56,32 @@
# _implementation_type = 'python'
+# This environment variable can be used to switch between the two
+# 'cpp' implementations. Right now only 1 and 2 are valid values. Any
+# other value will be ignored.
+_implementation_version_str = os.getenv(
+ 'PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION',
+ '1')
+
+
+if _implementation_version_str not in ('1', '2'):
+ raise ValueError(
+ "unsupported PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION: '" +
+ _implementation_version_str + "' (supported versions: 1, 2)"
+ )
+
+
+_implementation_version = int(_implementation_version_str)
+
+
+
# Usage of this function is discouraged. Clients shouldn't care which
# implementation of the API is in use. Note that there is no guarantee
# that differences between APIs will be maintained.
# Please don't use this function if possible.
def Type():
return _implementation_type
+
+# See comment on 'Type' above.
+def Version():
+ return _implementation_version
diff --git a/third_party/protobuf/python/google/protobuf/internal/containers.py b/third_party/protobuf/python/google/protobuf/internal/containers.py
index 097a3c2..34b35f8 100755
--- a/third_party/protobuf/python/google/protobuf/internal/containers.py
+++ b/third_party/protobuf/python/google/protobuf/internal/containers.py
@@ -78,8 +78,13 @@
def __repr__(self):
return repr(self._values)
- def sort(self, sort_function=cmp):
- self._values.sort(sort_function)
+ def sort(self, *args, **kwargs):
+ # Continue to support the old sort_function keyword argument.
+ # This is expected to be a rare occurrence, so use LBYL to avoid
+ # the overhead of actually catching KeyError.
+ if 'sort_function' in kwargs:
+ kwargs['cmp'] = kwargs.pop('sort_function')
+ self._values.sort(*args, **kwargs)
class RepeatedScalarFieldContainer(BaseContainer):
@@ -235,6 +240,11 @@
"""
self.extend(other._values)
+ def remove(self, elem):
+ """Removes an item from the list. Similar to list.remove()."""
+ self._values.remove(elem)
+ self._message_listener.Modified()
+
def __getslice__(self, start, stop):
"""Retrieves the subset of items from between the specified indices."""
return self._values[start:stop]
diff --git a/third_party/protobuf/python/google/protobuf/internal/cpp_message.py b/third_party/protobuf/python/google/protobuf/internal/cpp_message.py
index 3f42650..23ab9ba 100644
--- a/third_party/protobuf/python/google/protobuf/internal/cpp_message.py
+++ b/third_party/protobuf/python/google/protobuf/internal/cpp_message.py
@@ -34,8 +34,10 @@
__author__ = 'petar@google.com (Petar Petrov)'
+import copy_reg
import operator
from google.protobuf.internal import _net_proto2___python
+from google.protobuf.internal import enum_type_wrapper
from google.protobuf import message
@@ -156,10 +158,12 @@
def __hash__(self):
raise TypeError('unhashable object')
- def sort(self, sort_function=cmp):
- values = self[slice(None, None, None)]
- values.sort(sort_function)
- self._cmsg.AssignRepeatedScalar(self._cfield_descriptor, values)
+ def sort(self, *args, **kwargs):
+ # Maintain compatibility with the previous interface.
+ if 'sort_function' in kwargs:
+ kwargs['cmp'] = kwargs.pop('sort_function')
+ self._cmsg.AssignRepeatedScalar(self._cfield_descriptor,
+ sorted(self, *args, **kwargs))
def RepeatedScalarProperty(cdescriptor):
@@ -202,6 +206,12 @@
for message in elem_seq:
self.add().MergeFrom(message)
+ def remove(self, value):
+ # TODO(protocol-devel): This is inefficient as it needs to generate a
+ # message pointer for each message only to do index(). Move this to a C++
+ # extension function.
+ self.__delitem__(self[slice(None, None, None)].index(value))
+
def MergeFrom(self, other):
for message in other[:]:
self.add().MergeFrom(message)
@@ -236,27 +246,29 @@
def __hash__(self):
raise TypeError('unhashable object')
- def sort(self, sort_function=cmp):
- messages = []
- for index in range(len(self)):
- # messages[i][0] is where the i-th element of the new array has to come
- # from.
- # messages[i][1] is where the i-th element of the old array has to go.
- messages.append([index, 0, self[index]])
- messages.sort(lambda x,y: sort_function(x[2], y[2]))
+ def sort(self, cmp=None, key=None, reverse=False, **kwargs):
+ # Maintain compatibility with the old interface.
+ if cmp is None and 'sort_function' in kwargs:
+ cmp = kwargs.pop('sort_function')
- # Remember which position each elements has to move to.
- for i in range(len(messages)):
- messages[messages[i][0]][1] = i
+ # The cmp function, if provided, is passed the results of the key function,
+ # so we only need to wrap one of them.
+ if key is None:
+ index_key = self.__getitem__
+ else:
+ index_key = lambda i: key(self[i])
+
+ # Sort the list of current indexes by the underlying object.
+ indexes = range(len(self))
+ indexes.sort(cmp=cmp, key=index_key, reverse=reverse)
# Apply the transposition.
- for i in range(len(messages)):
- from_position = messages[i][0]
- if i == from_position:
+ for dest, src in enumerate(indexes):
+ if dest == src:
continue
- self._cmsg.SwapRepeatedFieldElements(
- self._cfield_descriptor, i, from_position)
- messages[messages[i][1]][0] = from_position
+ self._cmsg.SwapRepeatedFieldElements(self._cfield_descriptor, dest, src)
+ # Don't swap the same value twice.
+ indexes[src] = src
def RepeatedCompositeProperty(cdescriptor, message_type):
@@ -359,11 +371,12 @@
return None
-def NewMessage(message_descriptor, dictionary):
+def NewMessage(bases, message_descriptor, dictionary):
"""Creates a new protocol message *class*."""
_AddClassAttributesForNestedExtensions(message_descriptor, dictionary)
_AddEnumValues(message_descriptor, dictionary)
_AddDescriptors(message_descriptor, dictionary)
+ return bases
def InitMessage(message_descriptor, cls):
@@ -372,6 +385,7 @@
_AddInitMethod(message_descriptor, cls)
_AddMessageMethods(message_descriptor, cls)
_AddPropertiesForExtensions(message_descriptor, cls)
+ copy_reg.pickle(cls, lambda obj: (cls, (), obj.__getstate__()))
def _AddDescriptors(message_descriptor, dictionary):
@@ -387,7 +401,7 @@
field.full_name)
dictionary['__slots__'] = list(dictionary['__descriptors'].iterkeys()) + [
- '_cmsg', '_owner', '_composite_fields', 'Extensions']
+ '_cmsg', '_owner', '_composite_fields', 'Extensions', '_HACK_REFCOUNTS']
def _AddEnumValues(message_descriptor, dictionary):
@@ -398,6 +412,7 @@
dictionary: Class dictionary that should be populated.
"""
for enum_type in message_descriptor.enum_types:
+ dictionary[enum_type.name] = enum_type_wrapper.EnumTypeWrapper(enum_type)
for enum_value in enum_type.values:
dictionary[enum_value.name] = enum_value.number
@@ -439,28 +454,35 @@
def Init(self, **kwargs):
"""Message constructor."""
cmessage = kwargs.pop('__cmessage', None)
- if cmessage is None:
- self._cmsg = NewCMessage(message_descriptor.full_name)
- else:
+ if cmessage:
self._cmsg = cmessage
+ else:
+ self._cmsg = NewCMessage(message_descriptor.full_name)
# Keep a reference to the owner, as the owner keeps a reference to the
# underlying protocol buffer message.
owner = kwargs.pop('__owner', None)
- if owner is not None:
+ if owner:
self._owner = owner
- self.Extensions = ExtensionDict(self)
+ if message_descriptor.is_extendable:
+ self.Extensions = ExtensionDict(self)
+ else:
+ # Reference counting in the C++ code is broken and depends on
+ # the Extensions reference to keep this object alive during unit
+ # tests (see b/4856052). Remove this once b/4945904 is fixed.
+ self._HACK_REFCOUNTS = self
self._composite_fields = {}
for field_name, field_value in kwargs.iteritems():
field_cdescriptor = self.__descriptors.get(field_name, None)
- if field_cdescriptor is None:
+ if not field_cdescriptor:
raise ValueError('Protocol message has no "%s" field.' % field_name)
if field_cdescriptor.label == _LABEL_REPEATED:
if field_cdescriptor.cpp_type == _CPPTYPE_MESSAGE:
+ field_name = getattr(self, field_name)
for val in field_value:
- getattr(self, field_name).add().MergeFrom(val)
+ field_name.add().MergeFrom(val)
else:
getattr(self, field_name).extend(field_value)
elif field_cdescriptor.cpp_type == _CPPTYPE_MESSAGE:
@@ -497,12 +519,34 @@
return self._cmsg.HasField(field_name)
def ClearField(self, field_name):
+ child_cmessage = None
if field_name in self._composite_fields:
+ child_field = self._composite_fields[field_name]
del self._composite_fields[field_name]
- self._cmsg.ClearField(field_name)
+
+ child_cdescriptor = self.__descriptors[field_name]
+ # TODO(anuraag): Support clearing repeated message fields as well.
+ if (child_cdescriptor.label != _LABEL_REPEATED and
+ child_cdescriptor.cpp_type == _CPPTYPE_MESSAGE):
+ child_field._owner = None
+ child_cmessage = child_field._cmsg
+
+ if child_cmessage is not None:
+ self._cmsg.ClearField(field_name, child_cmessage)
+ else:
+ self._cmsg.ClearField(field_name)
def Clear(self):
- return self._cmsg.Clear()
+ cmessages_to_release = []
+ for field_name, child_field in self._composite_fields.iteritems():
+ child_cdescriptor = self.__descriptors[field_name]
+ # TODO(anuraag): Support clearing repeated message fields as well.
+ if (child_cdescriptor.label != _LABEL_REPEATED and
+ child_cdescriptor.cpp_type == _CPPTYPE_MESSAGE):
+ child_field._owner = None
+ cmessages_to_release.append((child_cdescriptor, child_field._cmsg))
+ self._composite_fields.clear()
+ self._cmsg.Clear(cmessages_to_release)
def IsInitialized(self, errors=None):
if self._cmsg.IsInitialized():
@@ -514,8 +558,8 @@
def SerializeToString(self):
if not self.IsInitialized():
raise message.EncodeError(
- 'Message is missing required fields: ' +
- ','.join(self.FindInitializationErrors()))
+ 'Message %s is missing required fields: %s' % (
+ self._cmsg.full_name, ','.join(self.FindInitializationErrors())))
return self._cmsg.SerializeToString()
def SerializePartialToString(self):
@@ -534,7 +578,8 @@
def MergeFrom(self, msg):
if not isinstance(msg, cls):
raise TypeError(
- "Parameter to MergeFrom() must be instance of same class.")
+ "Parameter to MergeFrom() must be instance of same class: "
+ "expected %s got %s." % (cls.__name__, type(msg).__name__))
self._cmsg.MergeFrom(msg._cmsg)
def CopyFrom(self, msg):
@@ -581,6 +626,8 @@
raise TypeError('unhashable object')
def __unicode__(self):
+ # Lazy import to prevent circular import when text_format imports this file.
+ from google.protobuf import text_format
return text_format.MessageToString(self, as_utf8=True).decode('utf-8')
# Attach the local methods to the message class.
diff --git a/third_party/protobuf/python/google/protobuf/internal/decoder.py b/third_party/protobuf/python/google/protobuf/internal/decoder.py
index 55f746f..cb6f572 100755
--- a/third_party/protobuf/python/google/protobuf/internal/decoder.py
+++ b/third_party/protobuf/python/google/protobuf/internal/decoder.py
@@ -576,6 +576,7 @@
local_SkipField = SkipField
def DecodeItem(buffer, pos, end, message, field_dict):
+ message_set_item_start = pos
type_id = -1
message_start = -1
message_end = -1
@@ -614,6 +615,11 @@
# The only reason _InternalParse would return early is if it encountered
# an end-group tag.
raise _DecodeError('Unexpected end-group tag.')
+ else:
+ if not message._unknown_fields:
+ message._unknown_fields = []
+ message._unknown_fields.append((MESSAGE_SET_ITEM_TAG,
+ buffer[message_set_item_start:pos]))
return pos
diff --git a/third_party/protobuf/python/google/protobuf/internal/descriptor_database_test.py b/third_party/protobuf/python/google/protobuf/internal/descriptor_database_test.py
new file mode 100644
index 0000000..d0ca789
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/descriptor_database_test.py
@@ -0,0 +1,63 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# http://code.google.com/p/protobuf/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests for google.protobuf.descriptor_database."""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+import unittest
+from google.protobuf import descriptor_pb2
+from google.protobuf.internal import factory_test2_pb2
+from google.protobuf import descriptor_database
+
+
+class DescriptorDatabaseTest(unittest.TestCase):
+
+ def testAdd(self):
+ db = descriptor_database.DescriptorDatabase()
+ file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString(
+ factory_test2_pb2.DESCRIPTOR.serialized_pb)
+ db.Add(file_desc_proto)
+
+ self.assertEquals(file_desc_proto, db.FindFileByName(
+ 'net/proto2/python/internal/factory_test2.proto'))
+ self.assertEquals(file_desc_proto, db.FindFileContainingSymbol(
+ 'net.proto2.python.internal.Factory2Message'))
+ self.assertEquals(file_desc_proto, db.FindFileContainingSymbol(
+ 'net.proto2.python.internal.Factory2Message.NestedFactory2Message'))
+ self.assertEquals(file_desc_proto, db.FindFileContainingSymbol(
+ 'net.proto2.python.internal.Factory2Enum'))
+ self.assertEquals(file_desc_proto, db.FindFileContainingSymbol(
+ 'net.proto2.python.internal.Factory2Message.NestedFactory2Enum'))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/descriptor_pool_test.py b/third_party/protobuf/python/google/protobuf/internal/descriptor_pool_test.py
new file mode 100644
index 0000000..a615d78
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/descriptor_pool_test.py
@@ -0,0 +1,220 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# http://code.google.com/p/protobuf/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests for google.protobuf.descriptor_pool."""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+import unittest
+from google.protobuf import descriptor_pb2
+from google.protobuf.internal import factory_test1_pb2
+from google.protobuf.internal import factory_test2_pb2
+from google.protobuf import descriptor
+from google.protobuf import descriptor_database
+from google.protobuf import descriptor_pool
+
+
+class DescriptorPoolTest(unittest.TestCase):
+
+ def setUp(self):
+ self.pool = descriptor_pool.DescriptorPool()
+ self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString(
+ factory_test1_pb2.DESCRIPTOR.serialized_pb)
+ self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString(
+ factory_test2_pb2.DESCRIPTOR.serialized_pb)
+ self.pool.Add(self.factory_test1_fd)
+ self.pool.Add(self.factory_test2_fd)
+
+ def testFindFileByName(self):
+ name1 = 'net/proto2/python/internal/factory_test1.proto'
+ file_desc1 = self.pool.FindFileByName(name1)
+ self.assertIsInstance(file_desc1, descriptor.FileDescriptor)
+ self.assertEquals(name1, file_desc1.name)
+ self.assertEquals('net.proto2.python.internal', file_desc1.package)
+ self.assertIn('Factory1Message', file_desc1.message_types_by_name)
+
+ name2 = 'net/proto2/python/internal/factory_test2.proto'
+ file_desc2 = self.pool.FindFileByName(name2)
+ self.assertIsInstance(file_desc2, descriptor.FileDescriptor)
+ self.assertEquals(name2, file_desc2.name)
+ self.assertEquals('net.proto2.python.internal', file_desc2.package)
+ self.assertIn('Factory2Message', file_desc2.message_types_by_name)
+
+ def testFindFileByNameFailure(self):
+ try:
+ self.pool.FindFileByName('Does not exist')
+ self.fail('Expected KeyError')
+ except KeyError:
+ pass
+
+ def testFindFileContainingSymbol(self):
+ file_desc1 = self.pool.FindFileContainingSymbol(
+ 'net.proto2.python.internal.Factory1Message')
+ self.assertIsInstance(file_desc1, descriptor.FileDescriptor)
+ self.assertEquals('net/proto2/python/internal/factory_test1.proto',
+ file_desc1.name)
+ self.assertEquals('net.proto2.python.internal', file_desc1.package)
+ self.assertIn('Factory1Message', file_desc1.message_types_by_name)
+
+ file_desc2 = self.pool.FindFileContainingSymbol(
+ 'net.proto2.python.internal.Factory2Message')
+ self.assertIsInstance(file_desc2, descriptor.FileDescriptor)
+ self.assertEquals('net/proto2/python/internal/factory_test2.proto',
+ file_desc2.name)
+ self.assertEquals('net.proto2.python.internal', file_desc2.package)
+ self.assertIn('Factory2Message', file_desc2.message_types_by_name)
+
+ def testFindFileContainingSymbolFailure(self):
+ try:
+ self.pool.FindFileContainingSymbol('Does not exist')
+ self.fail('Expected KeyError')
+ except KeyError:
+ pass
+
+ def testFindMessageTypeByName(self):
+ msg1 = self.pool.FindMessageTypeByName(
+ 'net.proto2.python.internal.Factory1Message')
+ self.assertIsInstance(msg1, descriptor.Descriptor)
+ self.assertEquals('Factory1Message', msg1.name)
+ self.assertEquals('net.proto2.python.internal.Factory1Message',
+ msg1.full_name)
+ self.assertEquals(None, msg1.containing_type)
+
+ nested_msg1 = msg1.nested_types[0]
+ self.assertEquals('NestedFactory1Message', nested_msg1.name)
+ self.assertEquals(msg1, nested_msg1.containing_type)
+
+ nested_enum1 = msg1.enum_types[0]
+ self.assertEquals('NestedFactory1Enum', nested_enum1.name)
+ self.assertEquals(msg1, nested_enum1.containing_type)
+
+ self.assertEquals(nested_msg1, msg1.fields_by_name[
+ 'nested_factory_1_message'].message_type)
+ self.assertEquals(nested_enum1, msg1.fields_by_name[
+ 'nested_factory_1_enum'].enum_type)
+
+ msg2 = self.pool.FindMessageTypeByName(
+ 'net.proto2.python.internal.Factory2Message')
+ self.assertIsInstance(msg2, descriptor.Descriptor)
+ self.assertEquals('Factory2Message', msg2.name)
+ self.assertEquals('net.proto2.python.internal.Factory2Message',
+ msg2.full_name)
+ self.assertIsNone(msg2.containing_type)
+
+ nested_msg2 = msg2.nested_types[0]
+ self.assertEquals('NestedFactory2Message', nested_msg2.name)
+ self.assertEquals(msg2, nested_msg2.containing_type)
+
+ nested_enum2 = msg2.enum_types[0]
+ self.assertEquals('NestedFactory2Enum', nested_enum2.name)
+ self.assertEquals(msg2, nested_enum2.containing_type)
+
+ self.assertEquals(nested_msg2, msg2.fields_by_name[
+ 'nested_factory_2_message'].message_type)
+ self.assertEquals(nested_enum2, msg2.fields_by_name[
+ 'nested_factory_2_enum'].enum_type)
+
+ self.assertTrue(msg2.fields_by_name['int_with_default'].has_default)
+ self.assertEquals(
+ 1776, msg2.fields_by_name['int_with_default'].default_value)
+
+ self.assertTrue(msg2.fields_by_name['double_with_default'].has_default)
+ self.assertEquals(
+ 9.99, msg2.fields_by_name['double_with_default'].default_value)
+
+ self.assertTrue(msg2.fields_by_name['string_with_default'].has_default)
+ self.assertEquals(
+ 'hello world', msg2.fields_by_name['string_with_default'].default_value)
+
+ self.assertTrue(msg2.fields_by_name['bool_with_default'].has_default)
+ self.assertFalse(msg2.fields_by_name['bool_with_default'].default_value)
+
+ self.assertTrue(msg2.fields_by_name['enum_with_default'].has_default)
+ self.assertEquals(
+ 1, msg2.fields_by_name['enum_with_default'].default_value)
+
+ msg3 = self.pool.FindMessageTypeByName(
+ 'net.proto2.python.internal.Factory2Message.NestedFactory2Message')
+ self.assertEquals(nested_msg2, msg3)
+
+ def testFindMessageTypeByNameFailure(self):
+ try:
+ self.pool.FindMessageTypeByName('Does not exist')
+ self.fail('Expected KeyError')
+ except KeyError:
+ pass
+
+ def testFindEnumTypeByName(self):
+ enum1 = self.pool.FindEnumTypeByName(
+ 'net.proto2.python.internal.Factory1Enum')
+ self.assertIsInstance(enum1, descriptor.EnumDescriptor)
+ self.assertEquals(0, enum1.values_by_name['FACTORY_1_VALUE_0'].number)
+ self.assertEquals(1, enum1.values_by_name['FACTORY_1_VALUE_1'].number)
+
+ nested_enum1 = self.pool.FindEnumTypeByName(
+ 'net.proto2.python.internal.Factory1Message.NestedFactory1Enum')
+ self.assertIsInstance(nested_enum1, descriptor.EnumDescriptor)
+ self.assertEquals(
+ 0, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_0'].number)
+ self.assertEquals(
+ 1, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_1'].number)
+
+ enum2 = self.pool.FindEnumTypeByName(
+ 'net.proto2.python.internal.Factory2Enum')
+ self.assertIsInstance(enum2, descriptor.EnumDescriptor)
+ self.assertEquals(0, enum2.values_by_name['FACTORY_2_VALUE_0'].number)
+ self.assertEquals(1, enum2.values_by_name['FACTORY_2_VALUE_1'].number)
+
+ nested_enum2 = self.pool.FindEnumTypeByName(
+ 'net.proto2.python.internal.Factory2Message.NestedFactory2Enum')
+ self.assertIsInstance(nested_enum2, descriptor.EnumDescriptor)
+ self.assertEquals(
+ 0, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_0'].number)
+ self.assertEquals(
+ 1, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_1'].number)
+
+ def testFindEnumTypeByNameFailure(self):
+ try:
+ self.pool.FindEnumTypeByName('Does not exist')
+ self.fail('Expected KeyError')
+ except KeyError:
+ pass
+
+ def testUserDefinedDB(self):
+ db = descriptor_database.DescriptorDatabase()
+ self.pool = descriptor_pool.DescriptorPool(db)
+ db.Add(self.factory_test1_fd)
+ db.Add(self.factory_test2_fd)
+ self.testFindMessageTypeByName()
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/descriptor_test.py b/third_party/protobuf/python/google/protobuf/internal/descriptor_test.py
index 05c2745..c74f882 100755
--- a/third_party/protobuf/python/google/protobuf/internal/descriptor_test.py
+++ b/third_party/protobuf/python/google/protobuf/internal/descriptor_test.py
@@ -35,6 +35,7 @@
__author__ = 'robinson@google.com (Will Robinson)'
import unittest
+from google.protobuf import unittest_custom_options_pb2
from google.protobuf import unittest_import_pb2
from google.protobuf import unittest_pb2
from google.protobuf import descriptor_pb2
@@ -101,6 +102,15 @@
self.my_method
])
+ def testEnumValueName(self):
+ self.assertEqual(self.my_message.EnumValueName('ForeignEnum', 4),
+ 'FOREIGN_FOO')
+
+ self.assertEqual(
+ self.my_message.enum_types_by_name[
+ 'ForeignEnum'].values_by_number[4].name,
+ self.my_message.EnumValueName('ForeignEnum', 4))
+
def testEnumFixups(self):
self.assertEqual(self.my_enum, self.my_enum.values[0].type)
@@ -125,6 +135,257 @@
self.assertEqual(self.my_service.GetOptions(),
descriptor_pb2.ServiceOptions())
+ def testSimpleCustomOptions(self):
+ file_descriptor = unittest_custom_options_pb2.DESCRIPTOR
+ message_descriptor =\
+ unittest_custom_options_pb2.TestMessageWithCustomOptions.DESCRIPTOR
+ field_descriptor = message_descriptor.fields_by_name["field1"]
+ enum_descriptor = message_descriptor.enum_types_by_name["AnEnum"]
+ enum_value_descriptor =\
+ message_descriptor.enum_values_by_name["ANENUM_VAL2"]
+ service_descriptor =\
+ unittest_custom_options_pb2.TestServiceWithCustomOptions.DESCRIPTOR
+ method_descriptor = service_descriptor.FindMethodByName("Foo")
+
+ file_options = file_descriptor.GetOptions()
+ file_opt1 = unittest_custom_options_pb2.file_opt1
+ self.assertEqual(9876543210, file_options.Extensions[file_opt1])
+ message_options = message_descriptor.GetOptions()
+ message_opt1 = unittest_custom_options_pb2.message_opt1
+ self.assertEqual(-56, message_options.Extensions[message_opt1])
+ field_options = field_descriptor.GetOptions()
+ field_opt1 = unittest_custom_options_pb2.field_opt1
+ self.assertEqual(8765432109, field_options.Extensions[field_opt1])
+ field_opt2 = unittest_custom_options_pb2.field_opt2
+ self.assertEqual(42, field_options.Extensions[field_opt2])
+ enum_options = enum_descriptor.GetOptions()
+ enum_opt1 = unittest_custom_options_pb2.enum_opt1
+ self.assertEqual(-789, enum_options.Extensions[enum_opt1])
+ enum_value_options = enum_value_descriptor.GetOptions()
+ enum_value_opt1 = unittest_custom_options_pb2.enum_value_opt1
+ self.assertEqual(123, enum_value_options.Extensions[enum_value_opt1])
+
+ service_options = service_descriptor.GetOptions()
+ service_opt1 = unittest_custom_options_pb2.service_opt1
+ self.assertEqual(-9876543210, service_options.Extensions[service_opt1])
+ method_options = method_descriptor.GetOptions()
+ method_opt1 = unittest_custom_options_pb2.method_opt1
+ self.assertEqual(unittest_custom_options_pb2.METHODOPT1_VAL2,
+ method_options.Extensions[method_opt1])
+
+ def testDifferentCustomOptionTypes(self):
+ kint32min = -2**31
+ kint64min = -2**63
+ kint32max = 2**31 - 1
+ kint64max = 2**63 - 1
+ kuint32max = 2**32 - 1
+ kuint64max = 2**64 - 1
+
+ message_descriptor =\
+ unittest_custom_options_pb2.CustomOptionMinIntegerValues.DESCRIPTOR
+ message_options = message_descriptor.GetOptions()
+ self.assertEqual(False, message_options.Extensions[
+ unittest_custom_options_pb2.bool_opt])
+ self.assertEqual(kint32min, message_options.Extensions[
+ unittest_custom_options_pb2.int32_opt])
+ self.assertEqual(kint64min, message_options.Extensions[
+ unittest_custom_options_pb2.int64_opt])
+ self.assertEqual(0, message_options.Extensions[
+ unittest_custom_options_pb2.uint32_opt])
+ self.assertEqual(0, message_options.Extensions[
+ unittest_custom_options_pb2.uint64_opt])
+ self.assertEqual(kint32min, message_options.Extensions[
+ unittest_custom_options_pb2.sint32_opt])
+ self.assertEqual(kint64min, message_options.Extensions[
+ unittest_custom_options_pb2.sint64_opt])
+ self.assertEqual(0, message_options.Extensions[
+ unittest_custom_options_pb2.fixed32_opt])
+ self.assertEqual(0, message_options.Extensions[
+ unittest_custom_options_pb2.fixed64_opt])
+ self.assertEqual(kint32min, message_options.Extensions[
+ unittest_custom_options_pb2.sfixed32_opt])
+ self.assertEqual(kint64min, message_options.Extensions[
+ unittest_custom_options_pb2.sfixed64_opt])
+
+ message_descriptor =\
+ unittest_custom_options_pb2.CustomOptionMaxIntegerValues.DESCRIPTOR
+ message_options = message_descriptor.GetOptions()
+ self.assertEqual(True, message_options.Extensions[
+ unittest_custom_options_pb2.bool_opt])
+ self.assertEqual(kint32max, message_options.Extensions[
+ unittest_custom_options_pb2.int32_opt])
+ self.assertEqual(kint64max, message_options.Extensions[
+ unittest_custom_options_pb2.int64_opt])
+ self.assertEqual(kuint32max, message_options.Extensions[
+ unittest_custom_options_pb2.uint32_opt])
+ self.assertEqual(kuint64max, message_options.Extensions[
+ unittest_custom_options_pb2.uint64_opt])
+ self.assertEqual(kint32max, message_options.Extensions[
+ unittest_custom_options_pb2.sint32_opt])
+ self.assertEqual(kint64max, message_options.Extensions[
+ unittest_custom_options_pb2.sint64_opt])
+ self.assertEqual(kuint32max, message_options.Extensions[
+ unittest_custom_options_pb2.fixed32_opt])
+ self.assertEqual(kuint64max, message_options.Extensions[
+ unittest_custom_options_pb2.fixed64_opt])
+ self.assertEqual(kint32max, message_options.Extensions[
+ unittest_custom_options_pb2.sfixed32_opt])
+ self.assertEqual(kint64max, message_options.Extensions[
+ unittest_custom_options_pb2.sfixed64_opt])
+
+ message_descriptor =\
+ unittest_custom_options_pb2.CustomOptionOtherValues.DESCRIPTOR
+ message_options = message_descriptor.GetOptions()
+ self.assertEqual(-100, message_options.Extensions[
+ unittest_custom_options_pb2.int32_opt])
+ self.assertAlmostEqual(12.3456789, message_options.Extensions[
+ unittest_custom_options_pb2.float_opt], 6)
+ self.assertAlmostEqual(1.234567890123456789, message_options.Extensions[
+ unittest_custom_options_pb2.double_opt])
+ self.assertEqual("Hello, \"World\"", message_options.Extensions[
+ unittest_custom_options_pb2.string_opt])
+ self.assertEqual("Hello\0World", message_options.Extensions[
+ unittest_custom_options_pb2.bytes_opt])
+ dummy_enum = unittest_custom_options_pb2.DummyMessageContainingEnum
+ self.assertEqual(
+ dummy_enum.TEST_OPTION_ENUM_TYPE2,
+ message_options.Extensions[unittest_custom_options_pb2.enum_opt])
+
+ message_descriptor =\
+ unittest_custom_options_pb2.SettingRealsFromPositiveInts.DESCRIPTOR
+ message_options = message_descriptor.GetOptions()
+ self.assertAlmostEqual(12, message_options.Extensions[
+ unittest_custom_options_pb2.float_opt], 6)
+ self.assertAlmostEqual(154, message_options.Extensions[
+ unittest_custom_options_pb2.double_opt])
+
+ message_descriptor =\
+ unittest_custom_options_pb2.SettingRealsFromNegativeInts.DESCRIPTOR
+ message_options = message_descriptor.GetOptions()
+ self.assertAlmostEqual(-12, message_options.Extensions[
+ unittest_custom_options_pb2.float_opt], 6)
+ self.assertAlmostEqual(-154, message_options.Extensions[
+ unittest_custom_options_pb2.double_opt])
+
+ def testComplexExtensionOptions(self):
+ descriptor =\
+ unittest_custom_options_pb2.VariousComplexOptions.DESCRIPTOR
+ options = descriptor.GetOptions()
+ self.assertEqual(42, options.Extensions[
+ unittest_custom_options_pb2.complex_opt1].foo)
+ self.assertEqual(324, options.Extensions[
+ unittest_custom_options_pb2.complex_opt1].Extensions[
+ unittest_custom_options_pb2.quux])
+ self.assertEqual(876, options.Extensions[
+ unittest_custom_options_pb2.complex_opt1].Extensions[
+ unittest_custom_options_pb2.corge].qux)
+ self.assertEqual(987, options.Extensions[
+ unittest_custom_options_pb2.complex_opt2].baz)
+ self.assertEqual(654, options.Extensions[
+ unittest_custom_options_pb2.complex_opt2].Extensions[
+ unittest_custom_options_pb2.grault])
+ self.assertEqual(743, options.Extensions[
+ unittest_custom_options_pb2.complex_opt2].bar.foo)
+ self.assertEqual(1999, options.Extensions[
+ unittest_custom_options_pb2.complex_opt2].bar.Extensions[
+ unittest_custom_options_pb2.quux])
+ self.assertEqual(2008, options.Extensions[
+ unittest_custom_options_pb2.complex_opt2].bar.Extensions[
+ unittest_custom_options_pb2.corge].qux)
+ self.assertEqual(741, options.Extensions[
+ unittest_custom_options_pb2.complex_opt2].Extensions[
+ unittest_custom_options_pb2.garply].foo)
+ self.assertEqual(1998, options.Extensions[
+ unittest_custom_options_pb2.complex_opt2].Extensions[
+ unittest_custom_options_pb2.garply].Extensions[
+ unittest_custom_options_pb2.quux])
+ self.assertEqual(2121, options.Extensions[
+ unittest_custom_options_pb2.complex_opt2].Extensions[
+ unittest_custom_options_pb2.garply].Extensions[
+ unittest_custom_options_pb2.corge].qux)
+ self.assertEqual(1971, options.Extensions[
+ unittest_custom_options_pb2.ComplexOptionType2
+ .ComplexOptionType4.complex_opt4].waldo)
+ self.assertEqual(321, options.Extensions[
+ unittest_custom_options_pb2.complex_opt2].fred.waldo)
+ self.assertEqual(9, options.Extensions[
+ unittest_custom_options_pb2.complex_opt3].qux)
+ self.assertEqual(22, options.Extensions[
+ unittest_custom_options_pb2.complex_opt3].complexoptiontype5.plugh)
+ self.assertEqual(24, options.Extensions[
+ unittest_custom_options_pb2.complexopt6].xyzzy)
+
+ # Check that aggregate options were parsed and saved correctly in
+ # the appropriate descriptors.
+ def testAggregateOptions(self):
+ file_descriptor = unittest_custom_options_pb2.DESCRIPTOR
+ message_descriptor =\
+ unittest_custom_options_pb2.AggregateMessage.DESCRIPTOR
+ field_descriptor = message_descriptor.fields_by_name["fieldname"]
+ enum_descriptor = unittest_custom_options_pb2.AggregateEnum.DESCRIPTOR
+ enum_value_descriptor = enum_descriptor.values_by_name["VALUE"]
+ service_descriptor =\
+ unittest_custom_options_pb2.AggregateService.DESCRIPTOR
+ method_descriptor = service_descriptor.FindMethodByName("Method")
+
+ # Tests for the different types of data embedded in fileopt
+ file_options = file_descriptor.GetOptions().Extensions[
+ unittest_custom_options_pb2.fileopt]
+ self.assertEqual(100, file_options.i)
+ self.assertEqual("FileAnnotation", file_options.s)
+ self.assertEqual("NestedFileAnnotation", file_options.sub.s)
+ self.assertEqual("FileExtensionAnnotation", file_options.file.Extensions[
+ unittest_custom_options_pb2.fileopt].s)
+ self.assertEqual("EmbeddedMessageSetElement", file_options.mset.Extensions[
+ unittest_custom_options_pb2.AggregateMessageSetElement
+ .message_set_extension].s)
+
+ # Simple tests for all the other types of annotations
+ self.assertEqual(
+ "MessageAnnotation",
+ message_descriptor.GetOptions().Extensions[
+ unittest_custom_options_pb2.msgopt].s)
+ self.assertEqual(
+ "FieldAnnotation",
+ field_descriptor.GetOptions().Extensions[
+ unittest_custom_options_pb2.fieldopt].s)
+ self.assertEqual(
+ "EnumAnnotation",
+ enum_descriptor.GetOptions().Extensions[
+ unittest_custom_options_pb2.enumopt].s)
+ self.assertEqual(
+ "EnumValueAnnotation",
+ enum_value_descriptor.GetOptions().Extensions[
+ unittest_custom_options_pb2.enumvalopt].s)
+ self.assertEqual(
+ "ServiceAnnotation",
+ service_descriptor.GetOptions().Extensions[
+ unittest_custom_options_pb2.serviceopt].s)
+ self.assertEqual(
+ "MethodAnnotation",
+ method_descriptor.GetOptions().Extensions[
+ unittest_custom_options_pb2.methodopt].s)
+
+ def testNestedOptions(self):
+ nested_message =\
+ unittest_custom_options_pb2.NestedOptionType.NestedMessage.DESCRIPTOR
+ self.assertEqual(1001, nested_message.GetOptions().Extensions[
+ unittest_custom_options_pb2.message_opt1])
+ nested_field = nested_message.fields_by_name["nested_field"]
+ self.assertEqual(1002, nested_field.GetOptions().Extensions[
+ unittest_custom_options_pb2.field_opt1])
+ outer_message =\
+ unittest_custom_options_pb2.NestedOptionType.DESCRIPTOR
+ nested_enum = outer_message.enum_types_by_name["NestedEnum"]
+ self.assertEqual(1003, nested_enum.GetOptions().Extensions[
+ unittest_custom_options_pb2.enum_opt1])
+ nested_enum_value = outer_message.enum_values_by_name["NESTED_ENUM_VALUE"]
+ self.assertEqual(1004, nested_enum_value.GetOptions().Extensions[
+ unittest_custom_options_pb2.enum_value_opt1])
+ nested_extension = outer_message.extensions_by_name["nested_extension"]
+ self.assertEqual(1005, nested_extension.GetOptions().Extensions[
+ unittest_custom_options_pb2.field_opt2])
+
def testFileDescriptorReferences(self):
self.assertEqual(self.my_enum.file, self.my_file)
self.assertEqual(self.my_message.file, self.my_file)
@@ -273,6 +534,7 @@
UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = ("""
name: 'google/protobuf/unittest_import.proto'
package: 'protobuf_unittest_import'
+ dependency: 'google/protobuf/unittest_import_public.proto'
message_type: <
name: 'ImportMessage'
field: <
@@ -302,6 +564,7 @@
java_package: 'com.google.protobuf.test'
optimize_for: 1 # SPEED
>
+ public_dependency: 0
""")
self._InternalTestCopyToProto(
@@ -330,5 +593,21 @@
TEST_SERVICE_ASCII)
+class MakeDescriptorTest(unittest.TestCase):
+ def testMakeDescriptorWithUnsignedIntField(self):
+ file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
+ file_descriptor_proto.name = 'Foo'
+ message_type = file_descriptor_proto.message_type.add()
+ message_type.name = file_descriptor_proto.name
+ field = message_type.field.add()
+ field.number = 1
+ field.name = 'uint64_field'
+ field.label = descriptor.FieldDescriptor.LABEL_REQUIRED
+ field.type = descriptor.FieldDescriptor.TYPE_UINT64
+ result = descriptor.MakeDescriptor(message_type)
+ self.assertEqual(result.fields[0].cpp_type,
+ descriptor.FieldDescriptor.CPPTYPE_UINT64)
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/enum_type_wrapper.py b/third_party/protobuf/python/google/protobuf/internal/enum_type_wrapper.py
new file mode 100644
index 0000000..7b28645
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/enum_type_wrapper.py
@@ -0,0 +1,89 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# http://code.google.com/p/protobuf/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""A simple wrapper around enum types to expose utility functions.
+
+Instances are created as properties with the same name as the enum they wrap
+on proto classes. For usage, see:
+ reflection_test.py
+"""
+
+__author__ = 'rabsatt@google.com (Kevin Rabsatt)'
+
+
+class EnumTypeWrapper(object):
+ """A utility for finding the names of enum values."""
+
+ DESCRIPTOR = None
+
+ def __init__(self, enum_type):
+ """Inits EnumTypeWrapper with an EnumDescriptor."""
+ self._enum_type = enum_type
+ self.DESCRIPTOR = enum_type;
+
+ def Name(self, number):
+ """Returns a string containing the name of an enum value."""
+ if number in self._enum_type.values_by_number:
+ return self._enum_type.values_by_number[number].name
+ raise ValueError('Enum %s has no name defined for value %d' % (
+ self._enum_type.name, number))
+
+ def Value(self, name):
+ """Returns the value coresponding to the given enum name."""
+ if name in self._enum_type.values_by_name:
+ return self._enum_type.values_by_name[name].number
+ raise ValueError('Enum %s has no value defined for name %s' % (
+ self._enum_type.name, name))
+
+ def keys(self):
+ """Return a list of the string names in the enum.
+
+ These are returned in the order they were defined in the .proto file.
+ """
+
+ return [value_descriptor.name
+ for value_descriptor in self._enum_type.values]
+
+ def values(self):
+ """Return a list of the integer values in the enum.
+
+ These are returned in the order they were defined in the .proto file.
+ """
+
+ return [value_descriptor.number
+ for value_descriptor in self._enum_type.values]
+
+ def items(self):
+ """Return a list of the (name, value) pairs of the enum.
+
+ These are returned in the order they were defined in the .proto file.
+ """
+ return [(value_descriptor.name, value_descriptor.number)
+ for value_descriptor in self._enum_type.values]
diff --git a/third_party/protobuf/python/google/protobuf/internal/factory_test1.proto b/third_party/protobuf/python/google/protobuf/internal/factory_test1.proto
new file mode 100644
index 0000000..9f55e03
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/factory_test1.proto
@@ -0,0 +1,55 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: matthewtoia@google.com (Matt Toia)
+
+
+package google.protobuf.python.internal;
+
+
+enum Factory1Enum {
+ FACTORY_1_VALUE_0 = 0;
+ FACTORY_1_VALUE_1 = 1;
+}
+
+message Factory1Message {
+ optional Factory1Enum factory_1_enum = 1;
+ enum NestedFactory1Enum {
+ NESTED_FACTORY_1_VALUE_0 = 0;
+ NESTED_FACTORY_1_VALUE_1 = 1;
+ }
+ optional NestedFactory1Enum nested_factory_1_enum = 2;
+ message NestedFactory1Message {
+ optional string value = 1;
+ }
+ optional NestedFactory1Message nested_factory_1_message = 3;
+ optional int32 scalar_value = 4;
+ repeated string list_value = 5;
+}
diff --git a/third_party/protobuf/python/google/protobuf/internal/factory_test2.proto b/third_party/protobuf/python/google/protobuf/internal/factory_test2.proto
new file mode 100644
index 0000000..d3ce4d7
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/factory_test2.proto
@@ -0,0 +1,77 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: matthewtoia@google.com (Matt Toia)
+
+
+package google.protobuf.python.internal;
+
+import "google/protobuf/internal/factory_test1.proto";
+
+
+enum Factory2Enum {
+ FACTORY_2_VALUE_0 = 0;
+ FACTORY_2_VALUE_1 = 1;
+}
+
+message Factory2Message {
+ required int32 mandatory = 1;
+ optional Factory2Enum factory_2_enum = 2;
+ enum NestedFactory2Enum {
+ NESTED_FACTORY_2_VALUE_0 = 0;
+ NESTED_FACTORY_2_VALUE_1 = 1;
+ }
+ optional NestedFactory2Enum nested_factory_2_enum = 3;
+ message NestedFactory2Message {
+ optional string value = 1;
+ }
+ optional NestedFactory2Message nested_factory_2_message = 4;
+ optional Factory1Message factory_1_message = 5;
+ optional Factory1Enum factory_1_enum = 6;
+ optional Factory1Message.NestedFactory1Enum nested_factory_1_enum = 7;
+ optional Factory1Message.NestedFactory1Message nested_factory_1_message = 8;
+ optional Factory2Message circular_message = 9;
+ optional string scalar_value = 10;
+ repeated string list_value = 11;
+ repeated group Grouped = 12 {
+ optional string part_1 = 13;
+ optional string part_2 = 14;
+ }
+ optional LoopMessage loop = 15;
+ optional int32 int_with_default = 16 [default = 1776];
+ optional double double_with_default = 17 [default = 9.99];
+ optional string string_with_default = 18 [default = "hello world"];
+ optional bool bool_with_default = 19 [default = false];
+ optional Factory2Enum enum_with_default = 20 [default = FACTORY_2_VALUE_1];
+}
+
+message LoopMessage {
+ optional Factory2Message loop = 1;
+}
diff --git a/third_party/protobuf/python/google/protobuf/internal/generator_test.py b/third_party/protobuf/python/google/protobuf/internal/generator_test.py
index b3f7d9b..8343aba 100755
--- a/third_party/protobuf/python/google/protobuf/internal/generator_test.py
+++ b/third_party/protobuf/python/google/protobuf/internal/generator_test.py
@@ -42,8 +42,10 @@
__author__ = 'robinson@google.com (Will Robinson)'
import unittest
+from google.protobuf.internal import test_bad_identifiers_pb2
from google.protobuf import unittest_custom_options_pb2
from google.protobuf import unittest_import_pb2
+from google.protobuf import unittest_import_public_pb2
from google.protobuf import unittest_mset_pb2
from google.protobuf import unittest_pb2
from google.protobuf import unittest_no_generic_services_pb2
@@ -239,6 +241,29 @@
unittest_pb2._TESTALLTYPES_NESTEDMESSAGE.name in
file_type.message_types_by_name)
+ def testPublicImports(self):
+ # Test public imports as embedded message.
+ all_type_proto = unittest_pb2.TestAllTypes()
+ self.assertEqual(0, all_type_proto.optional_public_import_message.e)
+
+ # PublicImportMessage is actually defined in unittest_import_public_pb2
+ # module, and is public imported by unittest_import_pb2 module.
+ public_import_proto = unittest_import_pb2.PublicImportMessage()
+ self.assertEqual(0, public_import_proto.e)
+ self.assertTrue(unittest_import_public_pb2.PublicImportMessage is
+ unittest_import_pb2.PublicImportMessage)
+
+ def testBadIdentifiers(self):
+ # We're just testing that the code was imported without problems.
+ message = test_bad_identifiers_pb2.TestBadIdentifiers()
+ self.assertEqual(message.Extensions[test_bad_identifiers_pb2.message],
+ "foo")
+ self.assertEqual(message.Extensions[test_bad_identifiers_pb2.descriptor],
+ "bar")
+ self.assertEqual(message.Extensions[test_bad_identifiers_pb2.reflection],
+ "baz")
+ self.assertEqual(message.Extensions[test_bad_identifiers_pb2.service],
+ "qux")
if __name__ == '__main__':
unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/message_cpp_test.py b/third_party/protobuf/python/google/protobuf/internal/message_cpp_test.py
new file mode 100644
index 0000000..0d84b32
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/message_cpp_test.py
@@ -0,0 +1,45 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# http://code.google.com/p/protobuf/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests for google.protobuf.internal.message_cpp."""
+
+__author__ = 'shahms@google.com (Shahms King)'
+
+import os
+os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
+
+import unittest
+from google.protobuf.internal.message_test import *
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/message_factory_test.py b/third_party/protobuf/python/google/protobuf/internal/message_factory_test.py
new file mode 100644
index 0000000..0bc9be9
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/message_factory_test.py
@@ -0,0 +1,113 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# http://code.google.com/p/protobuf/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests for google.protobuf.message_factory."""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+import unittest
+from google.protobuf import descriptor_pb2
+from google.protobuf.internal import factory_test1_pb2
+from google.protobuf.internal import factory_test2_pb2
+from google.protobuf import descriptor_database
+from google.protobuf import descriptor_pool
+from google.protobuf import message_factory
+
+
+class MessageFactoryTest(unittest.TestCase):
+
+ def setUp(self):
+ self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString(
+ factory_test1_pb2.DESCRIPTOR.serialized_pb)
+ self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString(
+ factory_test2_pb2.DESCRIPTOR.serialized_pb)
+
+ def _ExerciseDynamicClass(self, cls):
+ msg = cls()
+ msg.mandatory = 42
+ msg.nested_factory_2_enum = 0
+ msg.nested_factory_2_message.value = 'nested message value'
+ msg.factory_1_message.factory_1_enum = 1
+ msg.factory_1_message.nested_factory_1_enum = 0
+ msg.factory_1_message.nested_factory_1_message.value = (
+ 'nested message value')
+ msg.factory_1_message.scalar_value = 22
+ msg.factory_1_message.list_value.extend(['one', 'two', 'three'])
+ msg.factory_1_message.list_value.append('four')
+ msg.factory_1_enum = 1
+ msg.nested_factory_1_enum = 0
+ msg.nested_factory_1_message.value = 'nested message value'
+ msg.circular_message.mandatory = 1
+ msg.circular_message.circular_message.mandatory = 2
+ msg.circular_message.scalar_value = 'one deep'
+ msg.scalar_value = 'zero deep'
+ msg.list_value.extend(['four', 'three', 'two'])
+ msg.list_value.append('one')
+ msg.grouped.add()
+ msg.grouped[0].part_1 = 'hello'
+ msg.grouped[0].part_2 = 'world'
+ msg.grouped.add(part_1='testing', part_2='123')
+ msg.loop.loop.mandatory = 2
+ msg.loop.loop.loop.loop.mandatory = 4
+ serialized = msg.SerializeToString()
+ converted = factory_test2_pb2.Factory2Message.FromString(serialized)
+ reserialized = converted.SerializeToString()
+ self.assertEquals(serialized, reserialized)
+ result = cls.FromString(reserialized)
+ self.assertEquals(msg, result)
+
+ def testGetPrototype(self):
+ db = descriptor_database.DescriptorDatabase()
+ pool = descriptor_pool.DescriptorPool(db)
+ db.Add(self.factory_test1_fd)
+ db.Add(self.factory_test2_fd)
+ factory = message_factory.MessageFactory()
+ cls = factory.GetPrototype(pool.FindMessageTypeByName(
+ 'net.proto2.python.internal.Factory2Message'))
+ self.assertIsNot(cls, factory_test2_pb2.Factory2Message)
+ self._ExerciseDynamicClass(cls)
+ cls2 = factory.GetPrototype(pool.FindMessageTypeByName(
+ 'net.proto2.python.internal.Factory2Message'))
+ self.assertIs(cls, cls2)
+
+ def testGetMessages(self):
+ messages = message_factory.GetMessages([self.factory_test2_fd,
+ self.factory_test1_fd])
+ self.assertContainsSubset(
+ ['net.proto2.python.internal.Factory2Message',
+ 'net.proto2.python.internal.Factory1Message'],
+ messages.keys())
+ self._ExerciseDynamicClass(
+ messages['net.proto2.python.internal.Factory2Message'])
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/message_test.py b/third_party/protobuf/python/google/protobuf/internal/message_test.py
index 6517437..53e9d50 100755
--- a/third_party/protobuf/python/google/protobuf/internal/message_test.py
+++ b/third_party/protobuf/python/google/protobuf/internal/message_test.py
@@ -45,10 +45,15 @@
import copy
import math
+import operator
+import pickle
+
import unittest
from google.protobuf import unittest_import_pb2
from google.protobuf import unittest_pb2
+from google.protobuf.internal import api_implementation
from google.protobuf.internal import test_util
+from google.protobuf import message
# Python pre-2.6 does not have isinf() or isnan() functions, so we have
# to provide our own.
@@ -70,9 +75,9 @@
golden_message = unittest_pb2.TestAllTypes()
golden_message.ParseFromString(golden_data)
test_util.ExpectAllFieldsSet(self, golden_message)
- self.assertTrue(golden_message.SerializeToString() == golden_data)
+ self.assertEqual(golden_data, golden_message.SerializeToString())
golden_copy = copy.deepcopy(golden_message)
- self.assertTrue(golden_copy.SerializeToString() == golden_data)
+ self.assertEqual(golden_data, golden_copy.SerializeToString())
def testGoldenExtensions(self):
golden_data = test_util.GoldenFile('golden_message').read()
@@ -81,9 +86,9 @@
all_set = unittest_pb2.TestAllExtensions()
test_util.SetAllExtensions(all_set)
self.assertEquals(all_set, golden_message)
- self.assertTrue(golden_message.SerializeToString() == golden_data)
+ self.assertEqual(golden_data, golden_message.SerializeToString())
golden_copy = copy.deepcopy(golden_message)
- self.assertTrue(golden_copy.SerializeToString() == golden_data)
+ self.assertEqual(golden_data, golden_copy.SerializeToString())
def testGoldenPackedMessage(self):
golden_data = test_util.GoldenFile('golden_packed_fields_message').read()
@@ -92,9 +97,9 @@
all_set = unittest_pb2.TestPackedTypes()
test_util.SetAllPackedFields(all_set)
self.assertEquals(all_set, golden_message)
- self.assertTrue(all_set.SerializeToString() == golden_data)
+ self.assertEqual(golden_data, all_set.SerializeToString())
golden_copy = copy.deepcopy(golden_message)
- self.assertTrue(golden_copy.SerializeToString() == golden_data)
+ self.assertEqual(golden_data, golden_copy.SerializeToString())
def testGoldenPackedExtensions(self):
golden_data = test_util.GoldenFile('golden_packed_fields_message').read()
@@ -103,9 +108,28 @@
all_set = unittest_pb2.TestPackedExtensions()
test_util.SetAllPackedExtensions(all_set)
self.assertEquals(all_set, golden_message)
- self.assertTrue(all_set.SerializeToString() == golden_data)
+ self.assertEqual(golden_data, all_set.SerializeToString())
golden_copy = copy.deepcopy(golden_message)
- self.assertTrue(golden_copy.SerializeToString() == golden_data)
+ self.assertEqual(golden_data, golden_copy.SerializeToString())
+
+ def testPickleSupport(self):
+ golden_data = test_util.GoldenFile('golden_message').read()
+ golden_message = unittest_pb2.TestAllTypes()
+ golden_message.ParseFromString(golden_data)
+ pickled_message = pickle.dumps(golden_message)
+
+ unpickled_message = pickle.loads(pickled_message)
+ self.assertEquals(unpickled_message, golden_message)
+
+ def testPickleIncompleteProto(self):
+ golden_message = unittest_pb2.TestRequired(a=1)
+ pickled_message = pickle.dumps(golden_message)
+
+ unpickled_message = pickle.loads(pickled_message)
+ self.assertEquals(unpickled_message, golden_message)
+ self.assertEquals(unpickled_message.a, 1)
+ # This is still an incomplete proto - so serializing should fail
+ self.assertRaises(message.EncodeError, unpickled_message.SerializeToString)
def testPositiveInfinity(self):
golden_data = ('\x5D\x00\x00\x80\x7F'
@@ -118,7 +142,7 @@
self.assertTrue(IsPosInf(golden_message.optional_double))
self.assertTrue(IsPosInf(golden_message.repeated_float[0]))
self.assertTrue(IsPosInf(golden_message.repeated_double[0]))
- self.assertTrue(golden_message.SerializeToString() == golden_data)
+ self.assertEqual(golden_data, golden_message.SerializeToString())
def testNegativeInfinity(self):
golden_data = ('\x5D\x00\x00\x80\xFF'
@@ -131,7 +155,7 @@
self.assertTrue(IsNegInf(golden_message.optional_double))
self.assertTrue(IsNegInf(golden_message.repeated_float[0]))
self.assertTrue(IsNegInf(golden_message.repeated_double[0]))
- self.assertTrue(golden_message.SerializeToString() == golden_data)
+ self.assertEqual(golden_data, golden_message.SerializeToString())
def testNotANumber(self):
golden_data = ('\x5D\x00\x00\xC0\x7F'
@@ -144,7 +168,18 @@
self.assertTrue(isnan(golden_message.optional_double))
self.assertTrue(isnan(golden_message.repeated_float[0]))
self.assertTrue(isnan(golden_message.repeated_double[0]))
- self.assertTrue(golden_message.SerializeToString() == golden_data)
+
+ # The protocol buffer may serialize to any one of multiple different
+ # representations of a NaN. Rather than verify a specific representation,
+ # verify the serialized string can be converted into a correctly
+ # behaving protocol buffer.
+ serialized = golden_message.SerializeToString()
+ message = unittest_pb2.TestAllTypes()
+ message.ParseFromString(serialized)
+ self.assertTrue(isnan(message.optional_float))
+ self.assertTrue(isnan(message.optional_double))
+ self.assertTrue(isnan(message.repeated_float[0]))
+ self.assertTrue(isnan(message.repeated_double[0]))
def testPositiveInfinityPacked(self):
golden_data = ('\xA2\x06\x04\x00\x00\x80\x7F'
@@ -153,7 +188,7 @@
golden_message.ParseFromString(golden_data)
self.assertTrue(IsPosInf(golden_message.packed_float[0]))
self.assertTrue(IsPosInf(golden_message.packed_double[0]))
- self.assertTrue(golden_message.SerializeToString() == golden_data)
+ self.assertEqual(golden_data, golden_message.SerializeToString())
def testNegativeInfinityPacked(self):
golden_data = ('\xA2\x06\x04\x00\x00\x80\xFF'
@@ -162,7 +197,7 @@
golden_message.ParseFromString(golden_data)
self.assertTrue(IsNegInf(golden_message.packed_float[0]))
self.assertTrue(IsNegInf(golden_message.packed_double[0]))
- self.assertTrue(golden_message.SerializeToString() == golden_data)
+ self.assertEqual(golden_data, golden_message.SerializeToString())
def testNotANumberPacked(self):
golden_data = ('\xA2\x06\x04\x00\x00\xC0\x7F'
@@ -171,7 +206,12 @@
golden_message.ParseFromString(golden_data)
self.assertTrue(isnan(golden_message.packed_float[0]))
self.assertTrue(isnan(golden_message.packed_double[0]))
- self.assertTrue(golden_message.SerializeToString() == golden_data)
+
+ serialized = golden_message.SerializeToString()
+ message = unittest_pb2.TestPackedTypes()
+ message.ParseFromString(serialized)
+ self.assertTrue(isnan(message.packed_float[0]))
+ self.assertTrue(isnan(message.packed_double[0]))
def testExtremeFloatValues(self):
message = unittest_pb2.TestAllTypes()
@@ -218,7 +258,7 @@
message.ParseFromString(message.SerializeToString())
self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit)
- def testExtremeFloatValues(self):
+ def testExtremeDoubleValues(self):
message = unittest_pb2.TestAllTypes()
# Most positive exponent, no significand bits set.
@@ -338,6 +378,117 @@
self.assertEqual(message.repeated_nested_message[4].bb, 5)
self.assertEqual(message.repeated_nested_message[5].bb, 6)
+ def testRepeatedCompositeFieldSortArguments(self):
+ """Check sorting a repeated composite field using list.sort() arguments."""
+ message = unittest_pb2.TestAllTypes()
+
+ get_bb = operator.attrgetter('bb')
+ cmp_bb = lambda a, b: cmp(a.bb, b.bb)
+ message.repeated_nested_message.add().bb = 1
+ message.repeated_nested_message.add().bb = 3
+ message.repeated_nested_message.add().bb = 2
+ message.repeated_nested_message.add().bb = 6
+ message.repeated_nested_message.add().bb = 5
+ message.repeated_nested_message.add().bb = 4
+ message.repeated_nested_message.sort(key=get_bb)
+ self.assertEqual([k.bb for k in message.repeated_nested_message],
+ [1, 2, 3, 4, 5, 6])
+ message.repeated_nested_message.sort(key=get_bb, reverse=True)
+ self.assertEqual([k.bb for k in message.repeated_nested_message],
+ [6, 5, 4, 3, 2, 1])
+ message.repeated_nested_message.sort(sort_function=cmp_bb)
+ self.assertEqual([k.bb for k in message.repeated_nested_message],
+ [1, 2, 3, 4, 5, 6])
+ message.repeated_nested_message.sort(cmp=cmp_bb, reverse=True)
+ self.assertEqual([k.bb for k in message.repeated_nested_message],
+ [6, 5, 4, 3, 2, 1])
+
+ def testRepeatedScalarFieldSortArguments(self):
+ """Check sorting a scalar field using list.sort() arguments."""
+ message = unittest_pb2.TestAllTypes()
+
+ abs_cmp = lambda a, b: cmp(abs(a), abs(b))
+ message.repeated_int32.append(-3)
+ message.repeated_int32.append(-2)
+ message.repeated_int32.append(-1)
+ message.repeated_int32.sort(key=abs)
+ self.assertEqual(list(message.repeated_int32), [-1, -2, -3])
+ message.repeated_int32.sort(key=abs, reverse=True)
+ self.assertEqual(list(message.repeated_int32), [-3, -2, -1])
+ message.repeated_int32.sort(sort_function=abs_cmp)
+ self.assertEqual(list(message.repeated_int32), [-1, -2, -3])
+ message.repeated_int32.sort(cmp=abs_cmp, reverse=True)
+ self.assertEqual(list(message.repeated_int32), [-3, -2, -1])
+
+ len_cmp = lambda a, b: cmp(len(a), len(b))
+ message.repeated_string.append('aaa')
+ message.repeated_string.append('bb')
+ message.repeated_string.append('c')
+ message.repeated_string.sort(key=len)
+ self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa'])
+ message.repeated_string.sort(key=len, reverse=True)
+ self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c'])
+ message.repeated_string.sort(sort_function=len_cmp)
+ self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa'])
+ message.repeated_string.sort(cmp=len_cmp, reverse=True)
+ self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c'])
+
+ def testParsingMerge(self):
+ """Check the merge behavior when a required or optional field appears
+ multiple times in the input."""
+ messages = [
+ unittest_pb2.TestAllTypes(),
+ unittest_pb2.TestAllTypes(),
+ unittest_pb2.TestAllTypes() ]
+ messages[0].optional_int32 = 1
+ messages[1].optional_int64 = 2
+ messages[2].optional_int32 = 3
+ messages[2].optional_string = 'hello'
+
+ merged_message = unittest_pb2.TestAllTypes()
+ merged_message.optional_int32 = 3
+ merged_message.optional_int64 = 2
+ merged_message.optional_string = 'hello'
+
+ generator = unittest_pb2.TestParsingMerge.RepeatedFieldsGenerator()
+ generator.field1.extend(messages)
+ generator.field2.extend(messages)
+ generator.field3.extend(messages)
+ generator.ext1.extend(messages)
+ generator.ext2.extend(messages)
+ generator.group1.add().field1.MergeFrom(messages[0])
+ generator.group1.add().field1.MergeFrom(messages[1])
+ generator.group1.add().field1.MergeFrom(messages[2])
+ generator.group2.add().field1.MergeFrom(messages[0])
+ generator.group2.add().field1.MergeFrom(messages[1])
+ generator.group2.add().field1.MergeFrom(messages[2])
+
+ data = generator.SerializeToString()
+ parsing_merge = unittest_pb2.TestParsingMerge()
+ parsing_merge.ParseFromString(data)
+
+ # Required and optional fields should be merged.
+ self.assertEqual(parsing_merge.required_all_types, merged_message)
+ self.assertEqual(parsing_merge.optional_all_types, merged_message)
+ self.assertEqual(parsing_merge.optionalgroup.optional_group_all_types,
+ merged_message)
+ self.assertEqual(parsing_merge.Extensions[
+ unittest_pb2.TestParsingMerge.optional_ext],
+ merged_message)
+
+ # Repeated fields should not be merged.
+ self.assertEqual(len(parsing_merge.repeated_all_types), 3)
+ self.assertEqual(len(parsing_merge.repeatedgroup), 3)
+ self.assertEqual(len(parsing_merge.Extensions[
+ unittest_pb2.TestParsingMerge.repeated_ext]), 3)
+
+
+ def testSortEmptyRepeatedCompositeContainer(self):
+ """Exercise a scenario that has led to segfaults in the past.
+ """
+ m = unittest_pb2.TestAllTypes()
+ m.repeated_nested_message.sort()
+
if __name__ == '__main__':
unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/more_extensions_dynamic.proto b/third_party/protobuf/python/google/protobuf/internal/more_extensions_dynamic.proto
new file mode 100644
index 0000000..df98ac4
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/more_extensions_dynamic.proto
@@ -0,0 +1,49 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: jasonh@google.com (Jason Hsueh)
+//
+// This file is used to test a corner case in the CPP implementation where the
+// generated C++ type is available for the extendee, but the extension is
+// defined in a file whose C++ type is not in the binary.
+
+
+import "google/protobuf/internal/more_extensions.proto";
+
+package google.protobuf.internal;
+
+message DynamicMessageType {
+ optional int32 a = 1;
+}
+
+extend ExtendedMessage {
+ optional int32 dynamic_int32_extension = 100;
+ optional DynamicMessageType dynamic_message_extension = 101;
+}
diff --git a/third_party/protobuf/python/google/protobuf/internal/python_message.py b/third_party/protobuf/python/google/protobuf/internal/python_message.py
index 66fca91..4bea57a 100644
--- a/third_party/protobuf/python/google/protobuf/internal/python_message.py
+++ b/third_party/protobuf/python/google/protobuf/internal/python_message.py
@@ -54,6 +54,7 @@
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
+import copy_reg
import struct
import weakref
@@ -61,6 +62,7 @@
from google.protobuf.internal import containers
from google.protobuf.internal import decoder
from google.protobuf.internal import encoder
+from google.protobuf.internal import enum_type_wrapper
from google.protobuf.internal import message_listener as message_listener_mod
from google.protobuf.internal import type_checkers
from google.protobuf.internal import wire_format
@@ -71,9 +73,10 @@
_FieldDescriptor = descriptor_mod.FieldDescriptor
-def NewMessage(descriptor, dictionary):
+def NewMessage(bases, descriptor, dictionary):
_AddClassAttributesForNestedExtensions(descriptor, dictionary)
_AddSlots(descriptor, dictionary)
+ return bases
def InitMessage(descriptor, cls):
@@ -96,6 +99,7 @@
_AddStaticMethods(cls)
_AddMessageMethods(descriptor, cls)
_AddPrivateHelperMethods(cls)
+ copy_reg.pickle(cls, lambda obj: (cls, (), obj.__getstate__()))
# Stateless helpers for GeneratedProtocolMessageType below.
@@ -145,6 +149,10 @@
if not extension_handle.is_extension:
raise KeyError('"%s" is not an extension.' % extension_handle.full_name)
+ if not extension_handle.containing_type:
+ raise KeyError('"%s" is missing a containing_type.'
+ % extension_handle.full_name)
+
if extension_handle.containing_type is not message.DESCRIPTOR:
raise KeyError('Extension "%s" extends message type "%s", but this '
'message is of type "%s".' %
@@ -164,6 +172,7 @@
dictionary['__slots__'] = ['_cached_byte_size',
'_cached_byte_size_dirty',
'_fields',
+ '_unknown_fields',
'_is_present_in_parent',
'_listener',
'_listener_for_children',
@@ -224,11 +233,14 @@
def _AddEnumValues(descriptor, cls):
"""Sets class-level attributes for all enum fields defined in this message.
+ Also exporting a class-level object that can name enum values.
+
Args:
descriptor: Descriptor object for this message type.
cls: Class we're constructing for this message type.
"""
for enum_type in descriptor.enum_types:
+ setattr(cls, enum_type.name, enum_type_wrapper.EnumTypeWrapper(enum_type))
for enum_value in enum_type.values:
setattr(cls, enum_value.name, enum_value.number)
@@ -248,7 +260,7 @@
"""
if field.label == _FieldDescriptor.LABEL_REPEATED:
- if field.default_value != []:
+ if field.has_default_value and field.default_value != []:
raise ValueError('Repeated field default value not empty list: %s' % (
field.default_value))
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
@@ -276,6 +288,8 @@
return MakeSubMessageDefault
def MakeScalarDefault(message):
+ # TODO(protobuf-team): This may be broken since there may not be
+ # default_value. Combine with has_default_value somehow.
return field.default_value
return MakeScalarDefault
@@ -287,6 +301,9 @@
self._cached_byte_size = 0
self._cached_byte_size_dirty = len(kwargs) > 0
self._fields = {}
+ # _unknown_fields is () when empty for efficiency, and will be turned into
+ # a list if fields are added.
+ self._unknown_fields = ()
self._is_present_in_parent = False
self._listener = message_listener_mod.NullMessageListener()
self._listener_for_children = _Listener(self)
@@ -428,6 +445,8 @@
valid_values = set()
def getter(self):
+ # TODO(protobuf-team): This may be broken since there may not be
+ # default_value. Combine with has_default_value somehow.
return self._fields.get(field, default_value)
getter.__module__ = None
getter.__doc__ = 'Getter for %s.' % proto_field_name
@@ -462,13 +481,18 @@
# for non-repeated scalars.
proto_field_name = field.name
property_name = _PropertyName(proto_field_name)
+
+ # TODO(komarek): Can anyone explain to me why we cache the message_type this
+ # way, instead of referring to field.message_type inside of getter(self)?
+ # What if someone sets message_type later on (which makes for simpler
+ # dyanmic proto descriptor and class creation code).
message_type = field.message_type
def getter(self):
field_value = self._fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
- field_value = message_type._concrete_class()
+ field_value = message_type._concrete_class() # use field.message_type?
field_value._SetListener(self._listener_for_children)
# Atomically check if another thread has preempted us and, if not, swap
@@ -620,6 +644,7 @@
def Clear(self):
# Clear fields.
self._fields = {}
+ self._unknown_fields = ()
self._Modified()
cls.Clear = Clear
@@ -649,7 +674,16 @@
if self is other:
return True
- return self.ListFields() == other.ListFields()
+ if not self.ListFields() == other.ListFields():
+ return False
+
+ # Sort unknown fields because their order shouldn't affect equality test.
+ unknown_fields = list(self._unknown_fields)
+ unknown_fields.sort()
+ other_unknown_fields = list(other._unknown_fields)
+ other_unknown_fields.sort()
+
+ return unknown_fields == other_unknown_fields
cls.__eq__ = __eq__
@@ -710,6 +744,9 @@
for field_descriptor, field_value in self.ListFields():
size += field_descriptor._sizer(field_value)
+ for tag_bytes, value_bytes in self._unknown_fields:
+ size += len(tag_bytes) + len(value_bytes)
+
self._cached_byte_size = size
self._cached_byte_size_dirty = False
self._listener_for_children.dirty = False
@@ -726,8 +763,8 @@
errors = []
if not self.IsInitialized():
raise message_mod.EncodeError(
- 'Message is missing required fields: ' +
- ','.join(self.FindInitializationErrors()))
+ 'Message %s is missing required fields: %s' % (
+ self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors())))
return self.SerializePartialToString()
cls.SerializeToString = SerializeToString
@@ -744,6 +781,9 @@
def InternalSerialize(self, write_bytes):
for field_descriptor, field_value in self.ListFields():
field_descriptor._encoder(write_bytes, field_value)
+ for tag_bytes, value_bytes in self._unknown_fields:
+ write_bytes(tag_bytes)
+ write_bytes(value_bytes)
cls._InternalSerialize = InternalSerialize
@@ -770,13 +810,18 @@
def InternalParse(self, buffer, pos, end):
self._Modified()
field_dict = self._fields
+ unknown_field_list = self._unknown_fields
while pos != end:
(tag_bytes, new_pos) = local_ReadTag(buffer, pos)
field_decoder = decoders_by_tag.get(tag_bytes)
if field_decoder is None:
+ value_start_pos = new_pos
new_pos = local_SkipField(buffer, new_pos, end, tag_bytes)
if new_pos == -1:
return pos
+ if not unknown_field_list:
+ unknown_field_list = self._unknown_fields = []
+ unknown_field_list.append((tag_bytes, buffer[value_start_pos:new_pos]))
pos = new_pos
else:
pos = field_decoder(buffer, new_pos, end, self, field_dict)
@@ -873,7 +918,8 @@
def MergeFrom(self, msg):
if not isinstance(msg, cls):
raise TypeError(
- "Parameter to MergeFrom() must be instance of same class.")
+ "Parameter to MergeFrom() must be instance of same class: "
+ "expected %s got %s." % (cls.__name__, type(msg).__name__))
assert msg is not self
self._Modified()
@@ -898,6 +944,12 @@
field_value.MergeFrom(value)
else:
self._fields[field] = value
+
+ if msg._unknown_fields:
+ if not self._unknown_fields:
+ self._unknown_fields = []
+ self._unknown_fields.extend(msg._unknown_fields)
+
cls.MergeFrom = MergeFrom
diff --git a/third_party/protobuf/python/google/protobuf/internal/reflection_cpp_generated_test.py b/third_party/protobuf/python/google/protobuf/internal/reflection_cpp_generated_test.py
new file mode 100644
index 0000000..2a0a512
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/reflection_cpp_generated_test.py
@@ -0,0 +1,91 @@
+#! /usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# http://code.google.com/p/protobuf/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unittest for reflection.py, which tests the generated C++ implementation."""
+
+__author__ = 'jasonh@google.com (Jason Hsueh)'
+
+import os
+os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
+
+import unittest
+from google.protobuf.internal import api_implementation
+from google.protobuf.internal import more_extensions_dynamic_pb2
+from google.protobuf.internal import more_extensions_pb2
+from google.protobuf.internal.reflection_test import *
+
+
+class ReflectionCppTest(unittest.TestCase):
+ def testImplementationSetting(self):
+ self.assertEqual('cpp', api_implementation.Type())
+
+ def testExtensionOfGeneratedTypeInDynamicFile(self):
+ """Tests that a file built dynamically can extend a generated C++ type.
+
+ The C++ implementation uses a DescriptorPool that has the generated
+ DescriptorPool as an underlay. Typically, a type can only find
+ extensions in its own pool. With the python C-extension, the generated C++
+ extendee may be available, but not the extension. This tests that the
+ C-extension implements the correct special handling to make such extensions
+ available.
+ """
+ pb1 = more_extensions_pb2.ExtendedMessage()
+ # Test that basic accessors work.
+ self.assertFalse(
+ pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension))
+ self.assertFalse(
+ pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension))
+ pb1.Extensions[more_extensions_dynamic_pb2.dynamic_int32_extension] = 17
+ pb1.Extensions[more_extensions_dynamic_pb2.dynamic_message_extension].a = 24
+ self.assertTrue(
+ pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension))
+ self.assertTrue(
+ pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension))
+
+ # Now serialize the data and parse to a new message.
+ pb2 = more_extensions_pb2.ExtendedMessage()
+ pb2.MergeFromString(pb1.SerializeToString())
+
+ self.assertTrue(
+ pb2.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension))
+ self.assertTrue(
+ pb2.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension))
+ self.assertEqual(
+ 17, pb2.Extensions[more_extensions_dynamic_pb2.dynamic_int32_extension])
+ self.assertEqual(
+ 24,
+ pb2.Extensions[more_extensions_dynamic_pb2.dynamic_message_extension].a)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/reflection_test.py b/third_party/protobuf/python/google/protobuf/internal/reflection_test.py
index 7b9d339..ed28646 100755
--- a/third_party/protobuf/python/google/protobuf/internal/reflection_test.py
+++ b/third_party/protobuf/python/google/protobuf/internal/reflection_test.py
@@ -37,6 +37,7 @@
__author__ = 'robinson@google.com (Will Robinson)'
+import gc
import operator
import struct
@@ -318,15 +319,6 @@
# ...and ensure that the scalar field has returned to its default.
self.assertEqual(0, getattr(composite_field, scalar_field_name))
- # Finally, ensure that modifications to the old composite field object
- # don't have any effect on the parent. Possible only with the pure-python
- # implementation of the API.
- #
- # (NOTE that when we clear the composite field in the parent, we actually
- # don't recursively clear down the tree. Instead, we just disconnect the
- # cleared composite from the tree.)
- if api_implementation.Type() != 'python':
- return
self.assertTrue(old_composite_field is not composite_field)
setattr(old_composite_field, scalar_field_name, new_val)
self.assertTrue(not composite_field.HasField(scalar_field_name))
@@ -348,8 +340,6 @@
nested.bb = 23
def testDisconnectingNestedMessageBeforeSettingField(self):
- if api_implementation.Type() != 'python':
- return
proto = unittest_pb2.TestAllTypes()
nested = proto.optional_nested_message
proto.ClearField('optional_nested_message') # Should disconnect from parent
@@ -358,6 +348,64 @@
self.assertTrue(not proto.HasField('optional_nested_message'))
self.assertEqual(0, proto.optional_nested_message.bb)
+ def testGetDefaultMessageAfterDisconnectingDefaultMessage(self):
+ proto = unittest_pb2.TestAllTypes()
+ nested = proto.optional_nested_message
+ proto.ClearField('optional_nested_message')
+ del proto
+ del nested
+ # Force a garbage collect so that the underlying CMessages are freed along
+ # with the Messages they point to. This is to make sure we're not deleting
+ # default message instances.
+ gc.collect()
+ proto = unittest_pb2.TestAllTypes()
+ nested = proto.optional_nested_message
+
+ def testDisconnectingNestedMessageAfterSettingField(self):
+ proto = unittest_pb2.TestAllTypes()
+ nested = proto.optional_nested_message
+ nested.bb = 5
+ self.assertTrue(proto.HasField('optional_nested_message'))
+ proto.ClearField('optional_nested_message') # Should disconnect from parent
+ self.assertEqual(5, nested.bb)
+ self.assertEqual(0, proto.optional_nested_message.bb)
+ self.assertTrue(nested is not proto.optional_nested_message)
+ nested.bb = 23
+ self.assertTrue(not proto.HasField('optional_nested_message'))
+ self.assertEqual(0, proto.optional_nested_message.bb)
+
+ def testDisconnectingNestedMessageBeforeGettingField(self):
+ proto = unittest_pb2.TestAllTypes()
+ self.assertTrue(not proto.HasField('optional_nested_message'))
+ proto.ClearField('optional_nested_message')
+ self.assertTrue(not proto.HasField('optional_nested_message'))
+
+ def testDisconnectingNestedMessageAfterMerge(self):
+ # This test exercises the code path that does not use ReleaseMessage().
+ # The underlying fear is that if we use ReleaseMessage() incorrectly,
+ # we will have memory leaks. It's hard to check that that doesn't happen,
+ # but at least we can exercise that code path to make sure it works.
+ proto1 = unittest_pb2.TestAllTypes()
+ proto2 = unittest_pb2.TestAllTypes()
+ proto2.optional_nested_message.bb = 5
+ proto1.MergeFrom(proto2)
+ self.assertTrue(proto1.HasField('optional_nested_message'))
+ proto1.ClearField('optional_nested_message')
+ self.assertTrue(not proto1.HasField('optional_nested_message'))
+
+ def testDisconnectingLazyNestedMessage(self):
+ # This test exercises releasing a nested message that is lazy. This test
+ # only exercises real code in the C++ implementation as Python does not
+ # support lazy parsing, but the current C++ implementation results in
+ # memory corruption and a crash.
+ if api_implementation.Type() != 'python':
+ return
+ proto = unittest_pb2.TestAllTypes()
+ proto.optional_lazy_message.bb = 5
+ proto.ClearField('optional_lazy_message')
+ del proto
+ gc.collect()
+
def testHasBitsWhenModifyingRepeatedFields(self):
# Test nesting when we add an element to a repeated field in a submessage.
proto = unittest_pb2.TestNestedMessageHasBits()
@@ -635,6 +683,77 @@
self.assertEqual(3, proto.BAZ)
self.assertEqual(3, unittest_pb2.TestAllTypes.BAZ)
+ def testEnum_Name(self):
+ self.assertEqual('FOREIGN_FOO',
+ unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_FOO))
+ self.assertEqual('FOREIGN_BAR',
+ unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_BAR))
+ self.assertEqual('FOREIGN_BAZ',
+ unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_BAZ))
+ self.assertRaises(ValueError,
+ unittest_pb2.ForeignEnum.Name, 11312)
+
+ proto = unittest_pb2.TestAllTypes()
+ self.assertEqual('FOO',
+ proto.NestedEnum.Name(proto.FOO))
+ self.assertEqual('FOO',
+ unittest_pb2.TestAllTypes.NestedEnum.Name(proto.FOO))
+ self.assertEqual('BAR',
+ proto.NestedEnum.Name(proto.BAR))
+ self.assertEqual('BAR',
+ unittest_pb2.TestAllTypes.NestedEnum.Name(proto.BAR))
+ self.assertEqual('BAZ',
+ proto.NestedEnum.Name(proto.BAZ))
+ self.assertEqual('BAZ',
+ unittest_pb2.TestAllTypes.NestedEnum.Name(proto.BAZ))
+ self.assertRaises(ValueError,
+ proto.NestedEnum.Name, 11312)
+ self.assertRaises(ValueError,
+ unittest_pb2.TestAllTypes.NestedEnum.Name, 11312)
+
+ def testEnum_Value(self):
+ self.assertEqual(unittest_pb2.FOREIGN_FOO,
+ unittest_pb2.ForeignEnum.Value('FOREIGN_FOO'))
+ self.assertEqual(unittest_pb2.FOREIGN_BAR,
+ unittest_pb2.ForeignEnum.Value('FOREIGN_BAR'))
+ self.assertEqual(unittest_pb2.FOREIGN_BAZ,
+ unittest_pb2.ForeignEnum.Value('FOREIGN_BAZ'))
+ self.assertRaises(ValueError,
+ unittest_pb2.ForeignEnum.Value, 'FO')
+
+ proto = unittest_pb2.TestAllTypes()
+ self.assertEqual(proto.FOO,
+ proto.NestedEnum.Value('FOO'))
+ self.assertEqual(proto.FOO,
+ unittest_pb2.TestAllTypes.NestedEnum.Value('FOO'))
+ self.assertEqual(proto.BAR,
+ proto.NestedEnum.Value('BAR'))
+ self.assertEqual(proto.BAR,
+ unittest_pb2.TestAllTypes.NestedEnum.Value('BAR'))
+ self.assertEqual(proto.BAZ,
+ proto.NestedEnum.Value('BAZ'))
+ self.assertEqual(proto.BAZ,
+ unittest_pb2.TestAllTypes.NestedEnum.Value('BAZ'))
+ self.assertRaises(ValueError,
+ proto.NestedEnum.Value, 'Foo')
+ self.assertRaises(ValueError,
+ unittest_pb2.TestAllTypes.NestedEnum.Value, 'Foo')
+
+ def testEnum_KeysAndValues(self):
+ self.assertEqual(['FOREIGN_FOO', 'FOREIGN_BAR', 'FOREIGN_BAZ'],
+ unittest_pb2.ForeignEnum.keys())
+ self.assertEqual([4, 5, 6],
+ unittest_pb2.ForeignEnum.values())
+ self.assertEqual([('FOREIGN_FOO', 4), ('FOREIGN_BAR', 5),
+ ('FOREIGN_BAZ', 6)],
+ unittest_pb2.ForeignEnum.items())
+
+ proto = unittest_pb2.TestAllTypes()
+ self.assertEqual(['FOO', 'BAR', 'BAZ'], proto.NestedEnum.keys())
+ self.assertEqual([1, 2, 3], proto.NestedEnum.values())
+ self.assertEqual([('FOO', 1), ('BAR', 2), ('BAZ', 3)],
+ proto.NestedEnum.items())
+
def testRepeatedScalars(self):
proto = unittest_pb2.TestAllTypes()
@@ -826,6 +945,35 @@
self.assertEqual(1, len(proto.repeated_nested_message))
self.assertEqual(23, proto.repeated_nested_message[0].bb)
+ def testRepeatedCompositeRemove(self):
+ proto = unittest_pb2.TestAllTypes()
+
+ self.assertEqual(0, len(proto.repeated_nested_message))
+ m0 = proto.repeated_nested_message.add()
+ # Need to set some differentiating variable so m0 != m1 != m2:
+ m0.bb = len(proto.repeated_nested_message)
+ m1 = proto.repeated_nested_message.add()
+ m1.bb = len(proto.repeated_nested_message)
+ self.assertTrue(m0 != m1)
+ m2 = proto.repeated_nested_message.add()
+ m2.bb = len(proto.repeated_nested_message)
+ self.assertListsEqual([m0, m1, m2], proto.repeated_nested_message)
+
+ self.assertEqual(3, len(proto.repeated_nested_message))
+ proto.repeated_nested_message.remove(m0)
+ self.assertEqual(2, len(proto.repeated_nested_message))
+ self.assertEqual(m1, proto.repeated_nested_message[0])
+ self.assertEqual(m2, proto.repeated_nested_message[1])
+
+ # Removing m0 again or removing None should raise error
+ self.assertRaises(ValueError, proto.repeated_nested_message.remove, m0)
+ self.assertRaises(ValueError, proto.repeated_nested_message.remove, None)
+ self.assertEqual(2, len(proto.repeated_nested_message))
+
+ proto.repeated_nested_message.remove(m2)
+ self.assertEqual(1, len(proto.repeated_nested_message))
+ self.assertEqual(m1, proto.repeated_nested_message[0])
+
def testHandWrittenReflection(self):
# Hand written extensions are only supported by the pure-Python
# implementation of the API.
@@ -856,6 +1004,68 @@
self.assertEqual(23, myproto_instance.foo_field)
self.assertTrue(myproto_instance.HasField('foo_field'))
+ def testDescriptorProtoSupport(self):
+ # Hand written descriptors/reflection are only supported by the pure-Python
+ # implementation of the API.
+ if api_implementation.Type() != 'python':
+ return
+
+ def AddDescriptorField(proto, field_name, field_type):
+ AddDescriptorField.field_index += 1
+ new_field = proto.field.add()
+ new_field.name = field_name
+ new_field.type = field_type
+ new_field.number = AddDescriptorField.field_index
+ new_field.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL
+
+ AddDescriptorField.field_index = 0
+
+ desc_proto = descriptor_pb2.DescriptorProto()
+ desc_proto.name = 'Car'
+ fdp = descriptor_pb2.FieldDescriptorProto
+ AddDescriptorField(desc_proto, 'name', fdp.TYPE_STRING)
+ AddDescriptorField(desc_proto, 'year', fdp.TYPE_INT64)
+ AddDescriptorField(desc_proto, 'automatic', fdp.TYPE_BOOL)
+ AddDescriptorField(desc_proto, 'price', fdp.TYPE_DOUBLE)
+ # Add a repeated field
+ AddDescriptorField.field_index += 1
+ new_field = desc_proto.field.add()
+ new_field.name = 'owners'
+ new_field.type = fdp.TYPE_STRING
+ new_field.number = AddDescriptorField.field_index
+ new_field.label = descriptor_pb2.FieldDescriptorProto.LABEL_REPEATED
+
+ desc = descriptor.MakeDescriptor(desc_proto)
+ self.assertTrue(desc.fields_by_name.has_key('name'))
+ self.assertTrue(desc.fields_by_name.has_key('year'))
+ self.assertTrue(desc.fields_by_name.has_key('automatic'))
+ self.assertTrue(desc.fields_by_name.has_key('price'))
+ self.assertTrue(desc.fields_by_name.has_key('owners'))
+
+ class CarMessage(message.Message):
+ __metaclass__ = reflection.GeneratedProtocolMessageType
+ DESCRIPTOR = desc
+
+ prius = CarMessage()
+ prius.name = 'prius'
+ prius.year = 2010
+ prius.automatic = True
+ prius.price = 25134.75
+ prius.owners.extend(['bob', 'susan'])
+
+ serialized_prius = prius.SerializeToString()
+ new_prius = reflection.ParseMessage(desc, serialized_prius)
+ self.assertTrue(new_prius is not prius)
+ self.assertEqual(prius, new_prius)
+
+ # these are unnecessary assuming message equality works as advertised but
+ # explicitly check to be safe since we're mucking about in metaclass foo
+ self.assertEqual(prius.name, new_prius.name)
+ self.assertEqual(prius.year, new_prius.year)
+ self.assertEqual(prius.automatic, new_prius.automatic)
+ self.assertEqual(prius.price, new_prius.price)
+ self.assertEqual(prius.owners, new_prius.owners)
+
def testTopLevelExtensionsForOptionalScalar(self):
extendee_proto = unittest_pb2.TestAllExtensions()
extension = unittest_pb2.optional_int32_extension
@@ -1243,7 +1453,12 @@
def testClear(self):
proto = unittest_pb2.TestAllTypes()
- test_util.SetAllFields(proto)
+ # C++ implementation does not support lazy fields right now so leave it
+ # out for now.
+ if api_implementation.Type() == 'python':
+ test_util.SetAllFields(proto)
+ else:
+ test_util.SetAllNonLazyFields(proto)
# Clear the message.
proto.Clear()
self.assertEquals(proto.ByteSize(), 0)
@@ -1259,6 +1474,33 @@
empty_proto = unittest_pb2.TestAllExtensions()
self.assertEquals(proto, empty_proto)
+ def testDisconnectingBeforeClear(self):
+ proto = unittest_pb2.TestAllTypes()
+ nested = proto.optional_nested_message
+ proto.Clear()
+ self.assertTrue(nested is not proto.optional_nested_message)
+ nested.bb = 23
+ self.assertTrue(not proto.HasField('optional_nested_message'))
+ self.assertEqual(0, proto.optional_nested_message.bb)
+
+ proto = unittest_pb2.TestAllTypes()
+ nested = proto.optional_nested_message
+ nested.bb = 5
+ foreign = proto.optional_foreign_message
+ foreign.c = 6
+
+ proto.Clear()
+ self.assertTrue(nested is not proto.optional_nested_message)
+ self.assertTrue(foreign is not proto.optional_foreign_message)
+ self.assertEqual(5, nested.bb)
+ self.assertEqual(6, foreign.c)
+ nested.bb = 15
+ foreign.c = 16
+ self.assertTrue(not proto.HasField('optional_nested_message'))
+ self.assertEqual(0, proto.optional_nested_message.bb)
+ self.assertTrue(not proto.HasField('optional_foreign_message'))
+ self.assertEqual(0, proto.optional_foreign_message.c)
+
def assertInitialized(self, proto):
self.assertTrue(proto.IsInitialized())
# Neither method should raise an exception.
@@ -1408,7 +1650,7 @@
unicode_decode_failed = False
try:
message2.MergeFromString(bytes)
- except UnicodeDecodeError, e:
+ except UnicodeDecodeError as e:
unicode_decode_failed = True
string_field = message2.str
self.assertTrue(unicode_decode_failed or type(string_field) == str)
@@ -2119,7 +2361,7 @@
"""This method checks if the excpetion type and message are as expected."""
try:
callable_obj()
- except exc_class, ex:
+ except exc_class as ex:
# Check if the exception message is the right one.
self.assertEqual(exception, str(ex))
return
@@ -2131,15 +2373,22 @@
self._CheckRaises(
message.EncodeError,
proto.SerializeToString,
- 'Message is missing required fields: a,b,c')
+ 'Message protobuf_unittest.TestRequired is missing required fields: '
+ 'a,b,c')
# Shouldn't raise exceptions.
partial = proto.SerializePartialToString()
+ proto2 = unittest_pb2.TestRequired()
+ self.assertFalse(proto2.HasField('a'))
+ # proto2 ParseFromString does not check that required fields are set.
+ proto2.ParseFromString(partial)
+ self.assertFalse(proto2.HasField('a'))
+
proto.a = 1
self._CheckRaises(
message.EncodeError,
proto.SerializeToString,
- 'Message is missing required fields: b,c')
+ 'Message protobuf_unittest.TestRequired is missing required fields: b,c')
# Shouldn't raise exceptions.
partial = proto.SerializePartialToString()
@@ -2147,7 +2396,7 @@
self._CheckRaises(
message.EncodeError,
proto.SerializeToString,
- 'Message is missing required fields: c')
+ 'Message protobuf_unittest.TestRequired is missing required fields: c')
# Shouldn't raise exceptions.
partial = proto.SerializePartialToString()
@@ -2176,7 +2425,8 @@
self._CheckRaises(
message.EncodeError,
proto.SerializeToString,
- 'Message is missing required fields: '
+ 'Message protobuf_unittest.TestRequiredForeign '
+ 'is missing required fields: '
'optional_message.b,optional_message.c')
proto.optional_message.b = 2
@@ -2188,7 +2438,7 @@
self._CheckRaises(
message.EncodeError,
proto.SerializeToString,
- 'Message is missing required fields: '
+ 'Message protobuf_unittest.TestRequiredForeign is missing required fields: '
'repeated_message[0].b,repeated_message[0].c,'
'repeated_message[1].a,repeated_message[1].c')
diff --git a/third_party/protobuf/python/google/protobuf/internal/test_bad_identifiers.proto b/third_party/protobuf/python/google/protobuf/internal/test_bad_identifiers.proto
new file mode 100644
index 0000000..6a82299
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/test_bad_identifiers.proto
@@ -0,0 +1,52 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+
+package protobuf_unittest;
+
+option py_generic_services = true;
+
+message TestBadIdentifiers {
+ extensions 100 to max;
+}
+
+// Make sure these reasonable extension names don't conflict with internal
+// variables.
+extend TestBadIdentifiers {
+ optional string message = 100 [default="foo"];
+ optional string descriptor = 101 [default="bar"];
+ optional string reflection = 102 [default="baz"];
+ optional string service = 103 [default="qux"];
+}
+
+message AnotherMessage {}
+service AnotherService {}
diff --git a/third_party/protobuf/python/google/protobuf/internal/test_util.py b/third_party/protobuf/python/google/protobuf/internal/test_util.py
index 1df1619..be8ae7b 100755
--- a/third_party/protobuf/python/google/protobuf/internal/test_util.py
+++ b/third_party/protobuf/python/google/protobuf/internal/test_util.py
@@ -42,8 +42,8 @@
from google.protobuf import unittest_pb2
-def SetAllFields(message):
- """Sets every field in the message to a unique value.
+def SetAllNonLazyFields(message):
+ """Sets every non-lazy field in the message to a unique value.
Args:
message: A unittest_pb2.TestAllTypes instance.
@@ -79,6 +79,7 @@
message.optional_nested_message.bb = 118
message.optional_foreign_message.c = 119
message.optional_import_message.d = 120
+ message.optional_public_import_message.e = 126
message.optional_nested_enum = unittest_pb2.TestAllTypes.BAZ
message.optional_foreign_enum = unittest_pb2.FOREIGN_BAZ
@@ -111,6 +112,7 @@
message.repeated_nested_message.add().bb = 218
message.repeated_foreign_message.add().c = 219
message.repeated_import_message.add().d = 220
+ message.repeated_lazy_message.add().bb = 227
message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAR)
message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAR)
@@ -140,6 +142,7 @@
message.repeated_nested_message.add().bb = 318
message.repeated_foreign_message.add().c = 319
message.repeated_import_message.add().d = 320
+ message.repeated_lazy_message.add().bb = 327
message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAZ)
message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAZ)
@@ -176,6 +179,11 @@
message.default_cord = '425'
+def SetAllFields(message):
+ SetAllNonLazyFields(message)
+ message.optional_lazy_message.bb = 127
+
+
def SetAllExtensions(message):
"""Sets every extension in the message to a unique value.
@@ -211,6 +219,8 @@
extensions[pb2.optional_nested_message_extension].bb = 118
extensions[pb2.optional_foreign_message_extension].c = 119
extensions[pb2.optional_import_message_extension].d = 120
+ extensions[pb2.optional_public_import_message_extension].e = 126
+ extensions[pb2.optional_lazy_message_extension].bb = 127
extensions[pb2.optional_nested_enum_extension] = pb2.TestAllTypes.BAZ
extensions[pb2.optional_nested_enum_extension] = pb2.TestAllTypes.BAZ
@@ -244,6 +254,7 @@
extensions[pb2.repeated_nested_message_extension].add().bb = 218
extensions[pb2.repeated_foreign_message_extension].add().c = 219
extensions[pb2.repeated_import_message_extension].add().d = 220
+ extensions[pb2.repeated_lazy_message_extension].add().bb = 227
extensions[pb2.repeated_nested_enum_extension].append(pb2.TestAllTypes.BAR)
extensions[pb2.repeated_foreign_enum_extension].append(pb2.FOREIGN_BAR)
@@ -273,6 +284,7 @@
extensions[pb2.repeated_nested_message_extension].add().bb = 318
extensions[pb2.repeated_foreign_message_extension].add().c = 319
extensions[pb2.repeated_import_message_extension].add().d = 320
+ extensions[pb2.repeated_lazy_message_extension].add().bb = 327
extensions[pb2.repeated_nested_enum_extension].append(pb2.TestAllTypes.BAZ)
extensions[pb2.repeated_foreign_enum_extension].append(pb2.FOREIGN_BAZ)
@@ -407,6 +419,8 @@
test_case.assertEqual(118, message.optional_nested_message.bb)
test_case.assertEqual(119, message.optional_foreign_message.c)
test_case.assertEqual(120, message.optional_import_message.d)
+ test_case.assertEqual(126, message.optional_public_import_message.e)
+ test_case.assertEqual(127, message.optional_lazy_message.bb)
test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ,
message.optional_nested_enum)
@@ -464,6 +478,7 @@
test_case.assertEqual(218, message.repeated_nested_message[0].bb)
test_case.assertEqual(219, message.repeated_foreign_message[0].c)
test_case.assertEqual(220, message.repeated_import_message[0].d)
+ test_case.assertEqual(227, message.repeated_lazy_message[0].bb)
test_case.assertEqual(unittest_pb2.TestAllTypes.BAR,
message.repeated_nested_enum[0])
@@ -492,6 +507,7 @@
test_case.assertEqual(318, message.repeated_nested_message[1].bb)
test_case.assertEqual(319, message.repeated_foreign_message[1].c)
test_case.assertEqual(320, message.repeated_import_message[1].d)
+ test_case.assertEqual(327, message.repeated_lazy_message[1].bb)
test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ,
message.repeated_nested_enum[1])
diff --git a/third_party/protobuf/python/google/protobuf/internal/text_format_test.py b/third_party/protobuf/python/google/protobuf/internal/text_format_test.py
index 73d97d1..23b50eb 100755
--- a/third_party/protobuf/python/google/protobuf/internal/text_format_test.py
+++ b/third_party/protobuf/python/google/protobuf/internal/text_format_test.py
@@ -94,6 +94,28 @@
' }\n'
'}\n')
+ def testPrintBadEnumValue(self):
+ message = unittest_pb2.TestAllTypes()
+ message.optional_nested_enum = 100
+ message.optional_foreign_enum = 101
+ message.optional_import_enum = 102
+ self.CompareToGoldenText(
+ text_format.MessageToString(message),
+ 'optional_nested_enum: 100\n'
+ 'optional_foreign_enum: 101\n'
+ 'optional_import_enum: 102\n')
+
+ def testPrintBadEnumValueExtensions(self):
+ message = unittest_pb2.TestAllExtensions()
+ message.Extensions[unittest_pb2.optional_nested_enum_extension] = 100
+ message.Extensions[unittest_pb2.optional_foreign_enum_extension] = 101
+ message.Extensions[unittest_pb2.optional_import_enum_extension] = 102
+ self.CompareToGoldenText(
+ text_format.MessageToString(message),
+ '[protobuf_unittest.optional_nested_enum_extension]: 100\n'
+ '[protobuf_unittest.optional_foreign_enum_extension]: 101\n'
+ '[protobuf_unittest.optional_import_enum_extension]: 102\n')
+
def testPrintExotic(self):
message = unittest_pb2.TestAllTypes()
message.repeated_int64.append(-9223372036854775808)
@@ -399,6 +421,14 @@
'has no value with number 100.'),
text_format.Merge, text, message)
+ def testMergeBadIntValue(self):
+ message = unittest_pb2.TestAllTypes()
+ text = 'optional_int32: bork'
+ self.assertRaisesWithMessage(
+ text_format.ParseError,
+ ('1:17 : Couldn\'t parse integer: bork'),
+ text_format.Merge, text, message)
+
def assertRaisesWithMessage(self, e_class, e, func, *args, **kwargs):
"""Same as assertRaises, but also compares the exception message."""
if hasattr(e_class, '__name__'):
@@ -408,7 +438,7 @@
try:
func(*args, **kwargs)
- except e_class, expr:
+ except e_class as expr:
if str(expr) != e:
msg = '%s raised, but with wrong message: "%s" instead of "%s"'
raise self.failureException(msg % (exc_name,
@@ -427,7 +457,7 @@
'identifiER_4 : 1.1e+2 ID5:-0.23 ID6:\'aaaa\\\'bbbb\'\n'
'ID7 : "aa\\"bb"\n\n\n\n ID8: {A:inf B:-inf C:true D:false}\n'
'ID9: 22 ID10: -111111111111111111 ID11: -22\n'
- 'ID12: 2222222222222222222 '
+ 'ID12: 2222222222222222222 ID13: 1.23456f ID14: 1.2e+2f '
'false_bool: 0 true_BOOL:t \n true_bool1: 1 false_BOOL1:f ' )
tokenizer = text_format._Tokenizer(text)
methods = [(tokenizer.ConsumeIdentifier, 'identifier1'),
@@ -456,10 +486,10 @@
'{',
(tokenizer.ConsumeIdentifier, 'A'),
':',
- (tokenizer.ConsumeFloat, text_format._INFINITY),
+ (tokenizer.ConsumeFloat, float('inf')),
(tokenizer.ConsumeIdentifier, 'B'),
':',
- (tokenizer.ConsumeFloat, -text_format._INFINITY),
+ (tokenizer.ConsumeFloat, -float('inf')),
(tokenizer.ConsumeIdentifier, 'C'),
':',
(tokenizer.ConsumeBool, True),
@@ -479,6 +509,12 @@
(tokenizer.ConsumeIdentifier, 'ID12'),
':',
(tokenizer.ConsumeUint64, 2222222222222222222),
+ (tokenizer.ConsumeIdentifier, 'ID13'),
+ ':',
+ (tokenizer.ConsumeFloat, 1.23456),
+ (tokenizer.ConsumeIdentifier, 'ID14'),
+ ':',
+ (tokenizer.ConsumeFloat, 1.2e+2),
(tokenizer.ConsumeIdentifier, 'false_bool'),
':',
(tokenizer.ConsumeBool, False),
@@ -556,16 +592,6 @@
tokenizer = text_format._Tokenizer(text)
self.assertRaises(text_format.ParseError, tokenizer.ConsumeBool)
- def testInfNan(self):
- # Make sure our infinity and NaN definitions are sound.
- self.assertEquals(float, type(text_format._INFINITY))
- self.assertEquals(float, type(text_format._NAN))
- self.assertTrue(text_format._NAN != text_format._NAN)
-
- inf_times_zero = text_format._INFINITY * 0
- self.assertTrue(inf_times_zero != inf_times_zero)
- self.assertTrue(text_format._INFINITY > 0)
-
if __name__ == '__main__':
unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/internal/unknown_fields_test.py b/third_party/protobuf/python/google/protobuf/internal/unknown_fields_test.py
new file mode 100644
index 0000000..84984b4
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/internal/unknown_fields_test.py
@@ -0,0 +1,170 @@
+#! /usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# http://code.google.com/p/protobuf/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Test for preservation of unknown fields in the pure Python implementation."""
+
+__author__ = 'bohdank@google.com (Bohdan Koval)'
+
+import unittest
+from google.protobuf import unittest_mset_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf.internal import encoder
+from google.protobuf.internal import test_util
+from google.protobuf.internal import type_checkers
+
+
+class UnknownFieldsTest(unittest.TestCase):
+
+ def setUp(self):
+ self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
+ self.all_fields = unittest_pb2.TestAllTypes()
+ test_util.SetAllFields(self.all_fields)
+ self.all_fields_data = self.all_fields.SerializeToString()
+ self.empty_message = unittest_pb2.TestEmptyMessage()
+ self.empty_message.ParseFromString(self.all_fields_data)
+ self.unknown_fields = self.empty_message._unknown_fields
+
+ def GetField(self, name):
+ field_descriptor = self.descriptor.fields_by_name[name]
+ wire_type = type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type]
+ field_tag = encoder.TagBytes(field_descriptor.number, wire_type)
+ for tag_bytes, value in self.unknown_fields:
+ if tag_bytes == field_tag:
+ decoder = unittest_pb2.TestAllTypes._decoders_by_tag[tag_bytes]
+ result_dict = {}
+ decoder(value, 0, len(value), self.all_fields, result_dict)
+ return result_dict[field_descriptor]
+
+ def testVarint(self):
+ value = self.GetField('optional_int32')
+ self.assertEqual(self.all_fields.optional_int32, value)
+
+ def testFixed32(self):
+ value = self.GetField('optional_fixed32')
+ self.assertEqual(self.all_fields.optional_fixed32, value)
+
+ def testFixed64(self):
+ value = self.GetField('optional_fixed64')
+ self.assertEqual(self.all_fields.optional_fixed64, value)
+
+ def testLengthDelimited(self):
+ value = self.GetField('optional_string')
+ self.assertEqual(self.all_fields.optional_string, value)
+
+ def testGroup(self):
+ value = self.GetField('optionalgroup')
+ self.assertEqual(self.all_fields.optionalgroup, value)
+
+ def testSerialize(self):
+ data = self.empty_message.SerializeToString()
+
+ # Don't use assertEqual because we don't want to dump raw binary data to
+ # stdout.
+ self.assertTrue(data == self.all_fields_data)
+
+ def testCopyFrom(self):
+ message = unittest_pb2.TestEmptyMessage()
+ message.CopyFrom(self.empty_message)
+ self.assertEqual(self.unknown_fields, message._unknown_fields)
+
+ def testMergeFrom(self):
+ message = unittest_pb2.TestAllTypes()
+ message.optional_int32 = 1
+ message.optional_uint32 = 2
+ source = unittest_pb2.TestEmptyMessage()
+ source.ParseFromString(message.SerializeToString())
+
+ message.ClearField('optional_int32')
+ message.optional_int64 = 3
+ message.optional_uint32 = 4
+ destination = unittest_pb2.TestEmptyMessage()
+ destination.ParseFromString(message.SerializeToString())
+ unknown_fields = destination._unknown_fields[:]
+
+ destination.MergeFrom(source)
+ self.assertEqual(unknown_fields + source._unknown_fields,
+ destination._unknown_fields)
+
+ def testClear(self):
+ self.empty_message.Clear()
+ self.assertEqual(0, len(self.empty_message._unknown_fields))
+
+ def testByteSize(self):
+ self.assertEqual(self.all_fields.ByteSize(), self.empty_message.ByteSize())
+
+ def testUnknownExtensions(self):
+ message = unittest_pb2.TestEmptyMessageWithExtensions()
+ message.ParseFromString(self.all_fields_data)
+ self.assertEqual(self.empty_message._unknown_fields,
+ message._unknown_fields)
+
+ def testListFields(self):
+ # Make sure ListFields doesn't return unknown fields.
+ self.assertEqual(0, len(self.empty_message.ListFields()))
+
+ def testSerializeMessageSetWireFormatUnknownExtension(self):
+ # Create a message using the message set wire format with an unknown
+ # message.
+ raw = unittest_mset_pb2.RawMessageSet()
+
+ # Add an unknown extension.
+ item = raw.item.add()
+ item.type_id = 1545009
+ message1 = unittest_mset_pb2.TestMessageSetExtension1()
+ message1.i = 12345
+ item.message = message1.SerializeToString()
+
+ serialized = raw.SerializeToString()
+
+ # Parse message using the message set wire format.
+ proto = unittest_mset_pb2.TestMessageSet()
+ proto.MergeFromString(serialized)
+
+ # Verify that the unknown extension is serialized unchanged
+ reserialized = proto.SerializeToString()
+ new_raw = unittest_mset_pb2.RawMessageSet()
+ new_raw.MergeFromString(reserialized)
+ self.assertEqual(raw, new_raw)
+
+ def testEquals(self):
+ message = unittest_pb2.TestEmptyMessage()
+ message.ParseFromString(self.all_fields_data)
+ self.assertEqual(self.empty_message, message)
+
+ self.all_fields.ClearField('optional_string')
+ message.ParseFromString(self.all_fields.SerializeToString())
+ self.assertNotEqual(self.empty_message, message)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/third_party/protobuf/python/google/protobuf/message.py b/third_party/protobuf/python/google/protobuf/message.py
index 6f19f85..6ec2f8b 100755
--- a/third_party/protobuf/python/google/protobuf/message.py
+++ b/third_party/protobuf/python/google/protobuf/message.py
@@ -73,6 +73,7 @@
return clone
def __eq__(self, other_msg):
+ """Recursively compares two messages by value and structure."""
raise NotImplementedError
def __ne__(self, other_msg):
@@ -83,9 +84,11 @@
raise TypeError('unhashable object')
def __str__(self):
+ """Outputs a human-readable representation of the message."""
raise NotImplementedError
def __unicode__(self):
+ """Outputs a human-readable representation of the message."""
raise NotImplementedError
def MergeFrom(self, other_msg):
@@ -266,3 +269,12 @@
via a previous _SetListener() call.
"""
raise NotImplementedError
+
+ def __getstate__(self):
+ """Support the pickle protocol."""
+ return dict(serialized=self.SerializePartialToString())
+
+ def __setstate__(self, state):
+ """Support the pickle protocol."""
+ self.__init__()
+ self.ParseFromString(state['serialized'])
diff --git a/third_party/protobuf/python/google/protobuf/message_factory.py b/third_party/protobuf/python/google/protobuf/message_factory.py
new file mode 100644
index 0000000..36e2fef
--- /dev/null
+++ b/third_party/protobuf/python/google/protobuf/message_factory.py
@@ -0,0 +1,113 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# http://code.google.com/p/protobuf/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Provides a factory class for generating dynamic messages."""
+
+__author__ = 'matthewtoia@google.com (Matt Toia)'
+
+from google.protobuf import descriptor_database
+from google.protobuf import descriptor_pool
+from google.protobuf import message
+from google.protobuf import reflection
+
+
+class MessageFactory(object):
+ """Factory for creating Proto2 messages from descriptors in a pool."""
+
+ def __init__(self):
+ """Initializes a new factory."""
+ self._classes = {}
+
+ def GetPrototype(self, descriptor):
+ """Builds a proto2 message class based on the passed in descriptor.
+
+ Passing a descriptor with a fully qualified name matching a previous
+ invocation will cause the same class to be returned.
+
+ Args:
+ descriptor: The descriptor to build from.
+
+ Returns:
+ A class describing the passed in descriptor.
+ """
+
+ if descriptor.full_name not in self._classes:
+ result_class = reflection.GeneratedProtocolMessageType(
+ descriptor.name.encode('ascii', 'ignore'),
+ (message.Message,),
+ {'DESCRIPTOR': descriptor})
+ self._classes[descriptor.full_name] = result_class
+ for field in descriptor.fields:
+ if field.message_type:
+ self.GetPrototype(field.message_type)
+ return self._classes[descriptor.full_name]
+
+
+_DB = descriptor_database.DescriptorDatabase()
+_POOL = descriptor_pool.DescriptorPool(_DB)
+_FACTORY = MessageFactory()
+
+
+def GetMessages(file_protos):
+ """Builds a dictionary of all the messages available in a set of files.
+
+ Args:
+ file_protos: A sequence of file protos to build messages out of.
+
+ Returns:
+ A dictionary containing all the message types in the files mapping the
+ fully qualified name to a Message subclass for the descriptor.
+ """
+
+ result = {}
+ for file_proto in file_protos:
+ _DB.Add(file_proto)
+ for file_proto in file_protos:
+ for desc in _GetAllDescriptors(file_proto.message_type, file_proto.package):
+ result[desc.full_name] = _FACTORY.GetPrototype(desc)
+ return result
+
+
+def _GetAllDescriptors(desc_protos, package):
+ """Gets all levels of nested message types as a flattened list of descriptors.
+
+ Args:
+ desc_protos: The descriptor protos to process.
+ package: The package where the protos are defined.
+
+ Yields:
+ Each message descriptor for each nested type.
+ """
+
+ for desc_proto in desc_protos:
+ name = '.'.join((package, desc_proto.name))
+ yield _POOL.FindMessageTypeByName(name)
+ for nested_desc in _GetAllDescriptors(desc_proto.nested_type, name):
+ yield nested_desc
diff --git a/third_party/protobuf/python/google/protobuf/pyext/python-proto2.cc b/third_party/protobuf/python/google/protobuf/pyext/python-proto2.cc
index 181d7e9..6275341 100644
--- a/third_party/protobuf/python/google/protobuf/pyext/python-proto2.cc
+++ b/third_party/protobuf/python/google/protobuf/pyext/python-proto2.cc
@@ -207,9 +207,9 @@
"Clears and sets the values of a repeated scalar field."),
CMETHOD(ByteSize, METH_NOARGS,
"Returns the size of the message in bytes."),
- CMETHOD(Clear, METH_NOARGS,
+ CMETHOD(Clear, METH_O,
"Clears a protocol message."),
- CMETHOD(ClearField, METH_O,
+ CMETHOD(ClearField, METH_VARARGS,
"Clears a protocol message field by name."),
CMETHOD(ClearFieldByDescriptor, METH_O,
"Clears a protocol message field by descriptor."),
@@ -274,7 +274,7 @@
PyTypeObject CMessage_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
- C("google3.net.google.protobuf.python.internal."
+ C("google.protobuf.internal."
"_net_proto2___python."
"CMessage"), // tp_name
sizeof(CMessage), // tp_basicsize
@@ -319,14 +319,12 @@
// ------ Helper Functions:
static void FormatTypeError(PyObject* arg, char* expected_types) {
- PyObject* s = PyObject_Str(PyObject_Type(arg));
- PyObject* repr = PyObject_Repr(PyObject_Type(arg));
+ PyObject* repr = PyObject_Repr(arg);
PyErr_Format(PyExc_TypeError,
"%.100s has type %.100s, but expected one of: %s",
PyString_AS_STRING(repr),
- PyString_AS_STRING(s),
+ arg->ob_type->tp_name,
expected_types);
- Py_DECREF(s);
Py_DECREF(repr);
}
@@ -398,6 +396,28 @@
return global_message_factory->GetPrototype(descriptor);
}
+static void ReleaseSubMessage(google::protobuf::Message* message,
+ const google::protobuf::FieldDescriptor* field_descriptor,
+ CMessage* child_cmessage) {
+ Message* released_message = message->GetReflection()->ReleaseMessage(
+ message, field_descriptor, global_message_factory);
+ GOOGLE_DCHECK(child_cmessage->message != NULL);
+ // ReleaseMessage will return NULL which differs from
+ // child_cmessage->message, if the field does not exist. In this case,
+ // the latter points to the default instance via a const_cast<>, so we
+ // have to reset it to a new mutable object since we are taking ownership.
+ if (released_message == NULL) {
+ const Message* prototype = global_message_factory->GetPrototype(
+ child_cmessage->message->GetDescriptor());
+ GOOGLE_DCHECK(prototype != NULL);
+ child_cmessage->message = prototype->New();
+ }
+ child_cmessage->parent = NULL;
+ child_cmessage->parent_field = NULL;
+ child_cmessage->free_message = true;
+ child_cmessage->read_only = false;
+}
+
static bool CheckAndSetString(
PyObject* arg, google::protobuf::Message* message,
const google::protobuf::FieldDescriptor* descriptor,
@@ -407,6 +427,9 @@
GOOGLE_DCHECK(descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING ||
descriptor->type() == google::protobuf::FieldDescriptor::TYPE_BYTES);
if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
+#else
+ if (descriptor->file()->options().cc_api_version() == 2 &&
+ descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
if (!PyString_Check(arg) && !PyUnicode_Check(arg)) {
FormatTypeError(arg, "str, unicode");
return false;
@@ -434,6 +457,9 @@
PyObject* encoded_string = NULL;
if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
+#else
+ if (descriptor->file()->options().cc_api_version() == 2 &&
+ descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
if (PyString_Check(arg)) {
encoded_string = PyString_AsEncodedObject(arg, "utf-8", NULL);
} else {
@@ -504,8 +530,6 @@
self->message = reflection->MutableMessage(
message, self->parent_field->descriptor, global_message_factory);
self->read_only = false;
- self->parent = NULL;
- self->parent_field = NULL;
}
static PyObject* InternalGetScalar(
@@ -955,9 +979,41 @@
// ------ Methods:
-static PyObject* CMessage_Clear(CMessage* self, PyObject* args) {
+static PyObject* CMessage_Clear(CMessage* self, PyObject* arg) {
AssureWritable(self);
- self->message->Clear();
+ google::protobuf::Message* message = self->message;
+
+ // This block of code is equivalent to the following:
+ // for cfield_descriptor, child_cmessage in arg:
+ // ReleaseSubMessage(cfield_descriptor, child_cmessage)
+ if (!PyList_Check(arg)) {
+ PyErr_SetString(PyExc_TypeError, "Must be a list");
+ return NULL;
+ }
+ PyObject* messages_to_clear = arg;
+ Py_ssize_t num_messages_to_clear = PyList_GET_SIZE(messages_to_clear);
+ for(int i = 0; i < num_messages_to_clear; ++i) {
+ PyObject* message_tuple = PyList_GET_ITEM(messages_to_clear, i);
+ if (!PyTuple_Check(message_tuple) || PyTuple_GET_SIZE(message_tuple) != 2) {
+ PyErr_SetString(PyExc_TypeError, "Must be a tuple of size 2");
+ return NULL;
+ }
+
+ PyObject* py_cfield_descriptor = PyTuple_GET_ITEM(message_tuple, 0);
+ PyObject* py_child_cmessage = PyTuple_GET_ITEM(message_tuple, 1);
+ if (!PyObject_TypeCheck(py_cfield_descriptor, &CFieldDescriptor_Type) ||
+ !PyObject_TypeCheck(py_child_cmessage, &CMessage_Type)) {
+ PyErr_SetString(PyExc_ValueError, "Invalid Tuple");
+ return NULL;
+ }
+
+ CFieldDescriptor* cfield_descriptor = reinterpret_cast<CFieldDescriptor *>(
+ py_cfield_descriptor);
+ CMessage* child_cmessage = reinterpret_cast<CMessage *>(py_child_cmessage);
+ ReleaseSubMessage(message, cfield_descriptor->descriptor, child_cmessage);
+ }
+
+ message->Clear();
Py_RETURN_NONE;
}
@@ -1039,9 +1095,11 @@
Py_RETURN_NONE;
}
-static PyObject* CMessage_ClearField(CMessage* self, PyObject* arg) {
+static PyObject* CMessage_ClearField(CMessage* self, PyObject* args) {
char* field_name;
- if (PyString_AsStringAndSize(arg, &field_name, NULL) < 0) {
+ CMessage* child_cmessage = NULL;
+ if (!PyArg_ParseTuple(args, C("s|O!:ClearField"), &field_name,
+ &CMessage_Type, &child_cmessage)) {
return NULL;
}
@@ -1054,7 +1112,11 @@
return NULL;
}
- message->GetReflection()->ClearField(message, field_descriptor);
+ if (child_cmessage != NULL && !FIELD_IS_REPEATED(field_descriptor)) {
+ ReleaseSubMessage(message, field_descriptor, child_cmessage);
+ } else {
+ message->GetReflection()->ClearField(message, field_descriptor);
+ }
Py_RETURN_NONE;
}
@@ -1313,6 +1375,7 @@
AssureWritable(self);
google::protobuf::io::CodedInputStream input(
reinterpret_cast<const uint8*>(data), data_length);
+ input.SetExtensionRegistry(GetDescriptorPool(), global_message_factory);
bool success = self->message->MergePartialFromCodedStream(&input);
if (success) {
return PyInt_FromLong(self->message->ByteSize());
diff --git a/third_party/protobuf/python/google/protobuf/pyext/python_descriptor.cc b/third_party/protobuf/python/google/protobuf/pyext/python_descriptor.cc
index fb87bad..5e3e9ea 100644
--- a/third_party/protobuf/python/google/protobuf/pyext/python_descriptor.cc
+++ b/third_party/protobuf/python/google/protobuf/pyext/python_descriptor.cc
@@ -31,6 +31,7 @@
// Author: petar@google.com (Petar Petrov)
#include <Python.h>
+#include <string>
#include <google/protobuf/pyext/python_descriptor.h>
#include <google/protobuf/descriptor.pb.h>
@@ -41,6 +42,7 @@
namespace protobuf {
namespace python {
+
static void CFieldDescriptorDealloc(CFieldDescriptor* self);
static google::protobuf::DescriptorPool* g_descriptor_pool = NULL;
@@ -93,7 +95,7 @@
PyTypeObject CFieldDescriptor_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
- C("google3.net.google.protobuf.python.internal."
+ C("google.protobuf.internal."
"_net_proto2___python."
"CFieldDescriptor"), // tp_name
sizeof(CFieldDescriptor), // tp_basicsize
@@ -181,6 +183,8 @@
const google::protobuf::FieldDescriptor* field_descriptor = NULL;
field_descriptor = self->pool->FindFieldByName(full_field_name);
+
+
if (field_descriptor == NULL) {
PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s",
full_field_name);
@@ -223,7 +227,7 @@
PyTypeObject CDescriptorPool_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
- C("google3.net.google.protobuf.python.internal."
+ C("google.protobuf.internal."
"_net_proto2___python."
"CFieldDescriptor"), // tp_name
sizeof(CDescriptorPool), // tp_basicsize
@@ -301,7 +305,6 @@
return NULL;
}
- // If this file is already in the generated pool, don't add it again.
if (google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
file_proto.name()) != NULL) {
Py_RETURN_NONE;
diff --git a/third_party/protobuf/python/google/protobuf/reflection.py b/third_party/protobuf/python/google/protobuf/reflection.py
index 1373c88..9570fd5 100755
--- a/third_party/protobuf/python/google/protobuf/reflection.py
+++ b/third_party/protobuf/python/google/protobuf/reflection.py
@@ -50,13 +50,20 @@
from google.protobuf.internal import api_implementation
from google.protobuf import descriptor as descriptor_mod
+from google.protobuf import message
+
_FieldDescriptor = descriptor_mod.FieldDescriptor
if api_implementation.Type() == 'cpp':
- from google.protobuf.internal import cpp_message
- _NewMessage = cpp_message.NewMessage
- _InitMessage = cpp_message.InitMessage
+ if api_implementation.Version() == 2:
+ from google.protobuf.internal.cpp import cpp_message
+ _NewMessage = cpp_message.NewMessage
+ _InitMessage = cpp_message.InitMessage
+ else:
+ from google.protobuf.internal import cpp_message
+ _NewMessage = cpp_message.NewMessage
+ _InitMessage = cpp_message.InitMessage
else:
from google.protobuf.internal import python_message
_NewMessage = python_message.NewMessage
@@ -112,7 +119,7 @@
Newly-allocated class.
"""
descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
- _NewMessage(descriptor, dictionary)
+ bases = _NewMessage(bases, descriptor, dictionary)
superclass = super(GeneratedProtocolMessageType, cls)
new_class = superclass.__new__(cls, name, bases, dictionary)
@@ -140,3 +147,23 @@
_InitMessage(descriptor, cls)
superclass = super(GeneratedProtocolMessageType, cls)
superclass.__init__(name, bases, dictionary)
+
+
+def ParseMessage(descriptor, byte_str):
+ """Generate a new Message instance from this Descriptor and a byte string.
+
+ Args:
+ descriptor: Protobuf Descriptor object
+ byte_str: Serialized protocol buffer byte string
+
+ Returns:
+ Newly created protobuf Message object.
+ """
+
+ class _ResultClass(message.Message):
+ __metaclass__ = GeneratedProtocolMessageType
+ DESCRIPTOR = descriptor
+
+ new_msg = _ResultClass()
+ new_msg.ParseFromString(byte_str)
+ return new_msg
diff --git a/third_party/protobuf/python/google/protobuf/text_format.py b/third_party/protobuf/python/google/protobuf/text_format.py
index c3a1cf6..0714c39 100755
--- a/third_party/protobuf/python/google/protobuf/text_format.py
+++ b/third_party/protobuf/python/google/protobuf/text_format.py
@@ -43,10 +43,12 @@
'PrintFieldValue', 'Merge' ]
-# Infinity and NaN are not explicitly supported by Python pre-2.6, and
-# float('inf') does not work on Windows (pre-2.6).
-_INFINITY = 1e10000 # overflows, thus will actually be infinity.
-_NAN = _INFINITY * 0
+_INTEGER_CHECKERS = (type_checkers.Uint32ValueChecker(),
+ type_checkers.Int32ValueChecker(),
+ type_checkers.Uint64ValueChecker(),
+ type_checkers.Int64ValueChecker())
+_FLOAT_INFINITY = re.compile('-?inf(?:inity)?f?', re.IGNORECASE)
+_FLOAT_NAN = re.compile('nanf?', re.IGNORECASE)
class ParseError(Exception):
@@ -120,7 +122,11 @@
PrintMessage(value, out, indent + 2, as_utf8, as_one_line)
out.write(' ' * indent + '}')
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
- out.write(field.enum_type.values_by_number[value].name)
+ enum_value = field.enum_type.values_by_number.get(value, None)
+ if enum_value is not None:
+ out.write(enum_value.name)
+ else:
+ out.write(str(value))
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING:
out.write('\"')
if type(value) is unicode:
@@ -271,24 +277,7 @@
elif field.type == descriptor.FieldDescriptor.TYPE_BYTES:
value = tokenizer.ConsumeByteString()
elif field.type == descriptor.FieldDescriptor.TYPE_ENUM:
- # Enum can be specified by a number (the enum value), or by
- # a string literal (the enum name).
- enum_descriptor = field.enum_type
- if tokenizer.LookingAtInteger():
- number = tokenizer.ConsumeInt32()
- enum_value = enum_descriptor.values_by_number.get(number, None)
- if enum_value is None:
- raise tokenizer.ParseErrorPreviousToken(
- 'Enum type "%s" has no value with number %d.' % (
- enum_descriptor.full_name, number))
- else:
- identifier = tokenizer.ConsumeIdentifier()
- enum_value = enum_descriptor.values_by_name.get(identifier, None)
- if enum_value is None:
- raise tokenizer.ParseErrorPreviousToken(
- 'Enum type "%s" has no value named %s.' % (
- enum_descriptor.full_name, identifier))
- value = enum_value.number
+ value = tokenizer.ConsumeEnum(field)
else:
raise RuntimeError('Unknown field type %d' % field.type)
@@ -320,12 +309,6 @@
'\"([^\"\n\\\\]|\\\\.)*(\"|\\\\?$)|' # a double-quoted string
'\'([^\'\n\\\\]|\\\\.)*(\'|\\\\?$)') # a single-quoted string
_IDENTIFIER = re.compile('\w+')
- _INTEGER_CHECKERS = [type_checkers.Uint32ValueChecker(),
- type_checkers.Int32ValueChecker(),
- type_checkers.Uint64ValueChecker(),
- type_checkers.Int64ValueChecker()]
- _FLOAT_INFINITY = re.compile('-?inf(inity)?f?', re.IGNORECASE)
- _FLOAT_NAN = re.compile("nanf?", re.IGNORECASE)
def __init__(self, text_message):
self._text_message = text_message
@@ -394,17 +377,6 @@
if not self.TryConsume(token):
raise self._ParseError('Expected "%s".' % token)
- def LookingAtInteger(self):
- """Checks if the current token is an integer.
-
- Returns:
- True iff the current token is an integer.
- """
- if not self.token:
- return False
- c = self.token[0]
- return (c >= '0' and c <= '9') or c == '-' or c == '+'
-
def ConsumeIdentifier(self):
"""Consumes protocol message field identifier.
@@ -430,9 +402,9 @@
ParseError: If a signed 32bit integer couldn't be consumed.
"""
try:
- result = self._ParseInteger(self.token, is_signed=True, is_long=False)
+ result = ParseInteger(self.token, is_signed=True, is_long=False)
except ValueError, e:
- raise self._IntegerParseError(e)
+ raise self._ParseError(str(e))
self.NextToken()
return result
@@ -446,9 +418,9 @@
ParseError: If an unsigned 32bit integer couldn't be consumed.
"""
try:
- result = self._ParseInteger(self.token, is_signed=False, is_long=False)
+ result = ParseInteger(self.token, is_signed=False, is_long=False)
except ValueError, e:
- raise self._IntegerParseError(e)
+ raise self._ParseError(str(e))
self.NextToken()
return result
@@ -462,9 +434,9 @@
ParseError: If a signed 64bit integer couldn't be consumed.
"""
try:
- result = self._ParseInteger(self.token, is_signed=True, is_long=True)
+ result = ParseInteger(self.token, is_signed=True, is_long=True)
except ValueError, e:
- raise self._IntegerParseError(e)
+ raise self._ParseError(str(e))
self.NextToken()
return result
@@ -478,9 +450,9 @@
ParseError: If an unsigned 64bit integer couldn't be consumed.
"""
try:
- result = self._ParseInteger(self.token, is_signed=False, is_long=True)
+ result = ParseInteger(self.token, is_signed=False, is_long=True)
except ValueError, e:
- raise self._IntegerParseError(e)
+ raise self._ParseError(str(e))
self.NextToken()
return result
@@ -493,21 +465,10 @@
Raises:
ParseError: If a floating point number couldn't be consumed.
"""
- text = self.token
- if self._FLOAT_INFINITY.match(text):
- self.NextToken()
- if text.startswith('-'):
- return -_INFINITY
- return _INFINITY
-
- if self._FLOAT_NAN.match(text):
- self.NextToken()
- return _NAN
-
try:
- result = float(text)
+ result = ParseFloat(self.token)
except ValueError, e:
- raise self._FloatParseError(e)
+ raise self._ParseError(str(e))
self.NextToken()
return result
@@ -520,14 +481,12 @@
Raises:
ParseError: If a boolean value couldn't be consumed.
"""
- if self.token in ('true', 't', '1'):
- self.NextToken()
- return True
- elif self.token in ('false', 'f', '0'):
- self.NextToken()
- return False
- else:
- raise self._ParseError('Expected "true" or "false".')
+ try:
+ result = ParseBool(self.token)
+ except ValueError, e:
+ raise self._ParseError(str(e))
+ self.NextToken()
+ return result
def ConsumeString(self):
"""Consumes a string value.
@@ -567,7 +526,7 @@
"""
text = self.token
if len(text) < 1 or text[0] not in ('\'', '"'):
- raise self._ParseError('Exptected string.')
+ raise self._ParseError('Expected string.')
if len(text) < 2 or text[-1] != text[0]:
raise self._ParseError('String missing ending quote.')
@@ -579,36 +538,12 @@
self.NextToken()
return result
- def _ParseInteger(self, text, is_signed=False, is_long=False):
- """Parses an integer.
-
- Args:
- text: The text to parse.
- is_signed: True if a signed integer must be parsed.
- is_long: True if a long integer must be parsed.
-
- Returns:
- The integer value.
-
- Raises:
- ValueError: Thrown Iff the text is not a valid integer.
- """
- pos = 0
- if text.startswith('-'):
- pos += 1
-
- base = 10
- if text.startswith('0x', pos) or text.startswith('0X', pos):
- base = 16
- elif text.startswith('0', pos):
- base = 8
-
- # Do the actual parsing. Exception handling is propagated to caller.
- result = int(text, base)
-
- # Check if the integer is sane. Exceptions handled by callers.
- checker = self._INTEGER_CHECKERS[2 * int(is_long) + int(is_signed)]
- checker.CheckValue(result)
+ def ConsumeEnum(self, field):
+ try:
+ result = ParseEnum(field, self.token)
+ except ValueError, e:
+ raise self._ParseError(str(e))
+ self.NextToken()
return result
def ParseErrorPreviousToken(self, message):
@@ -626,13 +561,7 @@
def _ParseError(self, message):
"""Creates and *returns* a ParseError for the current token."""
return ParseError('%d:%d : %s' % (
- self._line + 1, self._column - len(self.token) + 1, message))
-
- def _IntegerParseError(self, e):
- return self._ParseError('Couldn\'t parse integer: ' + str(e))
-
- def _FloatParseError(self, e):
- return self._ParseError('Couldn\'t parse number: ' + str(e))
+ self._line + 1, self._column + 1, message))
def _StringParseError(self, e):
return self._ParseError('Couldn\'t parse string: ' + str(e))
@@ -689,3 +618,117 @@
# allow single-digit hex escapes (like '\xf').
result = _CUNESCAPE_HEX.sub(ReplaceHex, text)
return result.decode('string_escape')
+
+
+def ParseInteger(text, is_signed=False, is_long=False):
+ """Parses an integer.
+
+ Args:
+ text: The text to parse.
+ is_signed: True if a signed integer must be parsed.
+ is_long: True if a long integer must be parsed.
+
+ Returns:
+ The integer value.
+
+ Raises:
+ ValueError: Thrown Iff the text is not a valid integer.
+ """
+ # Do the actual parsing. Exception handling is propagated to caller.
+ try:
+ result = int(text, 0)
+ except ValueError:
+ raise ValueError('Couldn\'t parse integer: %s' % text)
+
+ # Check if the integer is sane. Exceptions handled by callers.
+ checker = _INTEGER_CHECKERS[2 * int(is_long) + int(is_signed)]
+ checker.CheckValue(result)
+ return result
+
+
+def ParseFloat(text):
+ """Parse a floating point number.
+
+ Args:
+ text: Text to parse.
+
+ Returns:
+ The number parsed.
+
+ Raises:
+ ValueError: If a floating point number couldn't be parsed.
+ """
+ try:
+ # Assume Python compatible syntax.
+ return float(text)
+ except ValueError:
+ # Check alternative spellings.
+ if _FLOAT_INFINITY.match(text):
+ if text[0] == '-':
+ return float('-inf')
+ else:
+ return float('inf')
+ elif _FLOAT_NAN.match(text):
+ return float('nan')
+ else:
+ # assume '1.0f' format
+ try:
+ return float(text.rstrip('f'))
+ except ValueError:
+ raise ValueError('Couldn\'t parse float: %s' % text)
+
+
+def ParseBool(text):
+ """Parse a boolean value.
+
+ Args:
+ text: Text to parse.
+
+ Returns:
+ Boolean values parsed
+
+ Raises:
+ ValueError: If text is not a valid boolean.
+ """
+ if text in ('true', 't', '1'):
+ return True
+ elif text in ('false', 'f', '0'):
+ return False
+ else:
+ raise ValueError('Expected "true" or "false".')
+
+
+def ParseEnum(field, value):
+ """Parse an enum value.
+
+ The value can be specified by a number (the enum value), or by
+ a string literal (the enum name).
+
+ Args:
+ field: Enum field descriptor.
+ value: String value.
+
+ Returns:
+ Enum value number.
+
+ Raises:
+ ValueError: If the enum value could not be parsed.
+ """
+ enum_descriptor = field.enum_type
+ try:
+ number = int(value, 0)
+ except ValueError:
+ # Identifier.
+ enum_value = enum_descriptor.values_by_name.get(value, None)
+ if enum_value is None:
+ raise ValueError(
+ 'Enum type "%s" has no value named %s.' % (
+ enum_descriptor.full_name, value))
+ else:
+ # Numeric value.
+ enum_value = enum_descriptor.values_by_number.get(number, None)
+ if enum_value is None:
+ raise ValueError(
+ 'Enum type "%s" has no value with number %d.' % (
+ enum_descriptor.full_name, number))
+ return enum_value.number
diff --git a/third_party/protobuf/python/setup.py b/third_party/protobuf/python/setup.py
index 7d9714e..fbe2766 100755
--- a/third_party/protobuf/python/setup.py
+++ b/third_party/protobuf/python/setup.py
@@ -1,18 +1,28 @@
#! /usr/bin/python
#
# See README for usage instructions.
-
-# We must use setuptools, not distutils, because we need to use the
-# namespace_packages option for the "google" package.
-from ez_setup import use_setuptools
-use_setuptools()
-
-from setuptools import setup, Extension
-from distutils.spawn import find_executable
import sys
import os
import subprocess
+# We must use setuptools, not distutils, because we need to use the
+# namespace_packages option for the "google" package.
+try:
+ from setuptools import setup, Extension
+except ImportError:
+ try:
+ from ez_setup import use_setuptools
+ use_setuptools()
+ from setuptools import setup, Extension
+ except ImportError:
+ sys.stderr.write(
+ "Could not import setuptools; make sure you have setuptools or "
+ "ez_setup installed.\n")
+ raise
+from distutils.command.clean import clean as _clean
+from distutils.command.build_py import build_py as _build_py
+from distutils.spawn import find_executable
+
maintainer_email = "protobuf@googlegroups.com"
# Find the Protocol Compiler.
@@ -34,15 +44,15 @@
output = source.replace(".proto", "_pb2.py").replace("../src/", "")
- if not os.path.exists(source):
- print "Can't find required file: " + source
- sys.exit(-1)
-
if (not os.path.exists(output) or
(os.path.exists(source) and
os.path.getmtime(source) > os.path.getmtime(output))):
print "Generating %s..." % output
+ if not os.path.exists(source):
+ sys.stderr.write("Can't find required file: %s\n" % source)
+ sys.exit(-1)
+
if protoc == None:
sys.stderr.write(
"protoc is not installed nor found in ../src. Please compile it "
@@ -53,19 +63,26 @@
if subprocess.call(protoc_command) != 0:
sys.exit(-1)
+def GenerateUnittestProtos():
+ generate_proto("../src/google/protobuf/unittest.proto")
+ generate_proto("../src/google/protobuf/unittest_custom_options.proto")
+ generate_proto("../src/google/protobuf/unittest_import.proto")
+ generate_proto("../src/google/protobuf/unittest_import_public.proto")
+ generate_proto("../src/google/protobuf/unittest_mset.proto")
+ generate_proto("../src/google/protobuf/unittest_no_generic_services.proto")
+ generate_proto("google/protobuf/internal/test_bad_identifiers.proto")
+ generate_proto("google/protobuf/internal/more_extensions.proto")
+ generate_proto("google/protobuf/internal/more_extensions_dynamic.proto")
+ generate_proto("google/protobuf/internal/more_messages.proto")
+ generate_proto("google/protobuf/internal/factory_test1.proto")
+ generate_proto("google/protobuf/internal/factory_test2.proto")
+
def MakeTestSuite():
# This is apparently needed on some systems to make sure that the tests
# work even if a previous version is already installed.
if 'google' in sys.modules:
del sys.modules['google']
-
- generate_proto("../src/google/protobuf/unittest.proto")
- generate_proto("../src/google/protobuf/unittest_custom_options.proto")
- generate_proto("../src/google/protobuf/unittest_import.proto")
- generate_proto("../src/google/protobuf/unittest_mset.proto")
- generate_proto("../src/google/protobuf/unittest_no_generic_services.proto")
- generate_proto("google/protobuf/internal/more_extensions.proto")
- generate_proto("google/protobuf/internal/more_messages.proto")
+ GenerateUnittestProtos()
import unittest
import google.protobuf.internal.generator_test as generator_test
@@ -75,6 +92,14 @@
as service_reflection_test
import google.protobuf.internal.text_format_test as text_format_test
import google.protobuf.internal.wire_format_test as wire_format_test
+ import google.protobuf.internal.unknown_fields_test as unknown_fields_test
+ import google.protobuf.internal.descriptor_database_test \
+ as descriptor_database_test
+ import google.protobuf.internal.descriptor_pool_test as descriptor_pool_test
+ import google.protobuf.internal.message_factory_test as message_factory_test
+ import google.protobuf.internal.message_cpp_test as message_cpp_test
+ import google.protobuf.internal.reflection_cpp_generated_test \
+ as reflection_cpp_generated_test
loader = unittest.defaultTestLoader
suite = unittest.TestSuite()
@@ -88,22 +113,33 @@
return suite
-if __name__ == '__main__':
- # TODO(kenton): Integrate this into setuptools somehow?
- if len(sys.argv) >= 2 and sys.argv[1] == "clean":
- # Delete generated _pb2.py files and .pyc files in the code tree.
+
+class clean(_clean):
+ def run(self):
+ # Delete generated files in the code tree.
for (dirpath, dirnames, filenames) in os.walk("."):
for filename in filenames:
filepath = os.path.join(dirpath, filename)
if filepath.endswith("_pb2.py") or filepath.endswith(".pyc") or \
- filepath.endswith(".so") or filepath.endswith(".o"):
+ filepath.endswith(".so") or filepath.endswith(".o") or \
+ filepath.endswith('google/protobuf/compiler/__init__.py'):
os.remove(filepath)
- else:
+ # _clean is an old-style class, so super() doesn't work.
+ _clean.run(self)
+
+class build_py(_build_py):
+ def run(self):
# Generate necessary .proto file if it doesn't exist.
- # TODO(kenton): Maybe we should hook this into a distutils command?
generate_proto("../src/google/protobuf/descriptor.proto")
generate_proto("../src/google/protobuf/compiler/plugin.proto")
+ GenerateUnittestProtos()
+ # Make sure google.protobuf.compiler is a valid package.
+ open('google/protobuf/compiler/__init__.py', 'a').close()
+ # _build_py is an old-style class, so super() doesn't work.
+ _build_py.run(self)
+
+if __name__ == '__main__':
ext_module_list = []
# C++ implementation extension
@@ -137,10 +173,15 @@
'google.protobuf.descriptor_pb2',
'google.protobuf.compiler.plugin_pb2',
'google.protobuf.message',
+ 'google.protobuf.descriptor_database',
+ 'google.protobuf.descriptor_pool',
+ 'google.protobuf.message_factory',
'google.protobuf.reflection',
'google.protobuf.service',
'google.protobuf.service_reflection',
'google.protobuf.text_format' ],
+ cmdclass = { 'clean': clean, 'build_py': build_py },
+ install_requires = ['setuptools'],
ext_modules = ext_module_list,
url = 'http://code.google.com/p/protobuf/',
maintainer = maintainer_email,
diff --git a/third_party/protobuf/src/Makefile.am b/third_party/protobuf/src/Makefile.am
index db9e7af..172d0cd 100644
--- a/third_party/protobuf/src/Makefile.am
+++ b/third_party/protobuf/src/Makefile.am
@@ -52,6 +52,7 @@
google/protobuf/descriptor_database.h \
google/protobuf/dynamic_message.h \
google/protobuf/extension_set.h \
+ google/protobuf/generated_enum_reflection.h \
google/protobuf/generated_message_util.h \
google/protobuf/generated_message_reflection.h \
google/protobuf/message.h \
@@ -91,7 +92,11 @@
google/protobuf/stubs/once.cc \
google/protobuf/stubs/hash.h \
google/protobuf/stubs/map-util.h \
- google/protobuf/stubs/stl_util-inl.h \
+ google/protobuf/stubs/stl_util.h \
+ google/protobuf/stubs/stringprintf.cc \
+ google/protobuf/stubs/stringprintf.h \
+ google/protobuf/stubs/template_util.h \
+ google/protobuf/stubs/type_traits.h \
google/protobuf/extension_set.cc \
google/protobuf/generated_message_util.cc \
google/protobuf/message_lite.cc \
@@ -158,6 +163,7 @@
google/protobuf/compiler/cpp/cpp_message.h \
google/protobuf/compiler/cpp/cpp_message_field.cc \
google/protobuf/compiler/cpp/cpp_message_field.h \
+ google/protobuf/compiler/cpp/cpp_options.h \
google/protobuf/compiler/cpp/cpp_primitive_field.cc \
google/protobuf/compiler/cpp/cpp_primitive_field.h \
google/protobuf/compiler/cpp/cpp_service.cc \
@@ -187,6 +193,8 @@
google/protobuf/compiler/java/java_service.h \
google/protobuf/compiler/java/java_string_field.cc \
google/protobuf/compiler/java/java_string_field.h \
+ google/protobuf/compiler/java/java_doc_comment.cc \
+ google/protobuf/compiler/java/java_doc_comment.h \
google/protobuf/compiler/python/python_generator.cc
bin_PROGRAMS = protoc
@@ -199,12 +207,14 @@
google/protobuf/unittest.proto \
google/protobuf/unittest_empty.proto \
google/protobuf/unittest_import.proto \
+ google/protobuf/unittest_import_public.proto \
google/protobuf/unittest_mset.proto \
google/protobuf/unittest_optimize_for.proto \
google/protobuf/unittest_embed_optimize_for.proto \
google/protobuf/unittest_custom_options.proto \
google/protobuf/unittest_lite.proto \
google/protobuf/unittest_import_lite.proto \
+ google/protobuf/unittest_import_public_lite.proto \
google/protobuf/unittest_lite_imports_nonlite.proto \
google/protobuf/unittest_no_generic_services.proto \
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -228,7 +238,9 @@
google/protobuf/unittest_lite.pb.cc \
google/protobuf/unittest_lite.pb.h \
google/protobuf/unittest_import_lite.pb.cc \
- google/protobuf/unittest_import_lite.pb.h
+ google/protobuf/unittest_import_lite.pb.h \
+ google/protobuf/unittest_import_public_lite.pb.cc \
+ google/protobuf/unittest_import_public_lite.pb.h
protoc_outputs = \
$(protoc_lite_outputs) \
@@ -238,6 +250,8 @@
google/protobuf/unittest_empty.pb.h \
google/protobuf/unittest_import.pb.cc \
google/protobuf/unittest_import.pb.h \
+ google/protobuf/unittest_import_public.pb.cc \
+ google/protobuf/unittest_import_public.pb.h \
google/protobuf/unittest_mset.pb.cc \
google/protobuf/unittest_mset.pb.h \
google/protobuf/unittest_optimize_for.pb.cc \
@@ -298,6 +312,9 @@
google/protobuf/stubs/once_unittest.cc \
google/protobuf/stubs/strutil_unittest.cc \
google/protobuf/stubs/structurally_valid_unittest.cc \
+ google/protobuf/stubs/stringprintf_unittest.cc \
+ google/protobuf/stubs/template_util_unittest.cc \
+ google/protobuf/stubs/type_traits_unittest.cc \
google/protobuf/descriptor_database_unittest.cc \
google/protobuf/descriptor_unittest.cc \
google/protobuf/dynamic_message_unittest.cc \
@@ -306,6 +323,7 @@
google/protobuf/message_unittest.cc \
google/protobuf/reflection_ops_unittest.cc \
google/protobuf/repeated_field_unittest.cc \
+ google/protobuf/repeated_field_reflection_unittest.cc \
google/protobuf/text_format_unittest.cc \
google/protobuf/unknown_field_set_unittest.cc \
google/protobuf/wire_format_unittest.cc \
@@ -319,9 +337,11 @@
google/protobuf/compiler/mock_code_generator.h \
google/protobuf/compiler/parser_unittest.cc \
google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc \
+ google/protobuf/compiler/cpp/cpp_unittest.h \
google/protobuf/compiler/cpp/cpp_unittest.cc \
google/protobuf/compiler/cpp/cpp_plugin_unittest.cc \
google/protobuf/compiler/java/java_plugin_unittest.cc \
+ google/protobuf/compiler/java/java_doc_comment_unittest.cc \
google/protobuf/compiler/python/python_plugin_unittest.cc \
$(COMMON_TEST_SOURCES)
nodist_protobuf_test_SOURCES = $(protoc_outputs)
diff --git a/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.cc b/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.cc
index c5be9b4..b9293c9 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.cc
@@ -59,12 +59,13 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/stubs/map-util.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
@@ -145,7 +146,7 @@
bool VerifyDirectoryExists(const string& path) {
if (path.empty()) return true;
- if (access(path.c_str(), W_OK) == -1) {
+ if (access(path.c_str(), F_OK) == -1) {
cerr << path << ": " << strerror(errno) << endl;
return false;
} else {
@@ -566,6 +567,7 @@
: mode_(MODE_COMPILE),
error_format_(ERROR_FORMAT_GCC),
imports_in_descriptor_set_(false),
+ source_info_in_descriptor_set_(false),
disallow_services_(false),
inputs_are_proto_path_relative_(false) {}
CommandLineInterface::~CommandLineInterface() {}
@@ -574,9 +576,23 @@
CodeGenerator* generator,
const string& help_text) {
GeneratorInfo info;
+ info.flag_name = flag_name;
info.generator = generator;
info.help_text = help_text;
- generators_[flag_name] = info;
+ generators_by_flag_name_[flag_name] = info;
+}
+
+void CommandLineInterface::RegisterGenerator(const string& flag_name,
+ const string& option_flag_name,
+ CodeGenerator* generator,
+ const string& help_text) {
+ GeneratorInfo info;
+ info.flag_name = flag_name;
+ info.option_flag_name = option_flag_name;
+ info.generator = generator;
+ info.help_text = help_text;
+ generators_by_flag_name_[flag_name] = info;
+ generators_by_option_name_[option_flag_name] = info;
}
void CommandLineInterface::AllowPlugins(const string& exe_name_prefix) {
@@ -585,7 +601,14 @@
int CommandLineInterface::Run(int argc, const char* const argv[]) {
Clear();
- if (!ParseArguments(argc, argv)) return 1;
+ switch (ParseArguments(argc, argv)) {
+ case PARSE_ARGUMENT_DONE_AND_EXIT:
+ return 0;
+ case PARSE_ARGUMENT_FAIL:
+ return 1;
+ case PARSE_ARGUMENT_DONE_AND_CONTINUE:
+ break;
+ }
// Set up the source tree.
DiskSourceTree source_tree;
@@ -713,6 +736,7 @@
mode_ = MODE_COMPILE;
imports_in_descriptor_set_ = false;
+ source_info_in_descriptor_set_ = false;
disallow_services_ = false;
}
@@ -755,7 +779,8 @@
return true;
}
-bool CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
+CommandLineInterface::ParseArgumentStatus
+CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
executable_name_ = argv[0];
// Iterate through all arguments and parse them.
@@ -769,41 +794,50 @@
if (name == "--decode") {
cerr << "To decode an unknown message, use --decode_raw." << endl;
}
- return false;
+ return PARSE_ARGUMENT_FAIL;
} else {
++i;
value = argv[i];
}
}
- if (!InterpretArgument(name, value)) return false;
+ ParseArgumentStatus status = InterpretArgument(name, value);
+ if (status != PARSE_ARGUMENT_DONE_AND_CONTINUE)
+ return status;
}
// If no --proto_path was given, use the current working directory.
if (proto_path_.empty()) {
- proto_path_.push_back(make_pair<string, string>("", "."));
+ // Don't use make_pair as the old/default standard library on Solaris
+ // doesn't support it without explicit template parameters, which are
+ // incompatible with C++0x's make_pair.
+ proto_path_.push_back(pair<string, string>("", "."));
}
// Check some errror cases.
bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty();
if (decoding_raw && !input_files_.empty()) {
cerr << "When using --decode_raw, no input files should be given." << endl;
- return false;
+ return PARSE_ARGUMENT_FAIL;
} else if (!decoding_raw && input_files_.empty()) {
cerr << "Missing input file." << endl;
- return false;
+ return PARSE_ARGUMENT_FAIL;
}
if (mode_ == MODE_COMPILE && output_directives_.empty() &&
descriptor_set_name_.empty()) {
cerr << "Missing output directives." << endl;
- return false;
+ return PARSE_ARGUMENT_FAIL;
}
if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) {
cerr << "--include_imports only makes sense when combined with "
"--descriptor_set_out." << endl;
}
+ if (source_info_in_descriptor_set_ && descriptor_set_name_.empty()) {
+ cerr << "--include_source_info only makes sense when combined with "
+ "--descriptor_set_out." << endl;
+ }
- return true;
+ return PARSE_ARGUMENT_DONE_AND_CONTINUE;
}
bool CommandLineInterface::ParseArgument(const char* arg,
@@ -853,6 +887,7 @@
if (*name == "-h" || *name == "--help" ||
*name == "--disallow_services" ||
*name == "--include_imports" ||
+ *name == "--include_source_info" ||
*name == "--version" ||
*name == "--decode_raw") {
// HACK: These are the only flags that don't take a value.
@@ -865,8 +900,9 @@
return true;
}
-bool CommandLineInterface::InterpretArgument(const string& name,
- const string& value) {
+CommandLineInterface::ParseArgumentStatus
+CommandLineInterface::InterpretArgument(const string& name,
+ const string& value) {
if (name.empty()) {
// Not a flag. Just a filename.
if (value.empty()) {
@@ -874,7 +910,7 @@
"arguments to " << executable_name_ << ". This is actually "
"sort of hard to do. Congrats. Unfortunately it is not valid "
"input so the program is going to die now." << endl;
- return false;
+ return PARSE_ARGUMENT_FAIL;
}
input_files_.push_back(value);
@@ -902,7 +938,7 @@
if (disk_path.empty()) {
cerr << "--proto_path passed empty directory name. (Use \".\" for "
"current directory.)" << endl;
- return false;
+ return PARSE_ARGUMENT_FAIL;
}
// Make sure disk path exists, warn otherwise.
@@ -910,35 +946,45 @@
cerr << disk_path << ": warning: directory does not exist." << endl;
}
- proto_path_.push_back(make_pair(virtual_path, disk_path));
+ // Don't use make_pair as the old/default standard library on Solaris
+ // doesn't support it without explicit template parameters, which are
+ // incompatible with C++0x's make_pair.
+ proto_path_.push_back(pair<string, string>(virtual_path, disk_path));
}
} else if (name == "-o" || name == "--descriptor_set_out") {
if (!descriptor_set_name_.empty()) {
cerr << name << " may only be passed once." << endl;
- return false;
+ return PARSE_ARGUMENT_FAIL;
}
if (value.empty()) {
cerr << name << " requires a non-empty value." << endl;
- return false;
+ return PARSE_ARGUMENT_FAIL;
}
if (mode_ != MODE_COMPILE) {
cerr << "Cannot use --encode or --decode and generate descriptors at the "
"same time." << endl;
- return false;
+ return PARSE_ARGUMENT_FAIL;
}
descriptor_set_name_ = value;
} else if (name == "--include_imports") {
if (imports_in_descriptor_set_) {
cerr << name << " may only be passed once." << endl;
- return false;
+ return PARSE_ARGUMENT_FAIL;
}
imports_in_descriptor_set_ = true;
+ } else if (name == "--include_source_info") {
+ if (source_info_in_descriptor_set_) {
+ cerr << name << " may only be passed once." << endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ source_info_in_descriptor_set_ = true;
+
} else if (name == "-h" || name == "--help") {
PrintHelpText();
- return false; // Exit without running compiler.
+ return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler.
} else if (name == "--version") {
if (!version_info_.empty()) {
@@ -947,7 +993,7 @@
cout << "libprotoc "
<< protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION)
<< endl;
- return false; // Exit without running compiler.
+ return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler.
} else if (name == "--disallow_services") {
disallow_services_ = true;
@@ -956,12 +1002,12 @@
name == "--decode_raw") {
if (mode_ != MODE_COMPILE) {
cerr << "Only one of --encode and --decode can be specified." << endl;
- return false;
+ return PARSE_ARGUMENT_FAIL;
}
if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
cerr << "Cannot use " << name
<< " and generate code or descriptors at the same time." << endl;
- return false;
+ return PARSE_ARGUMENT_FAIL;
}
mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE;
@@ -971,10 +1017,10 @@
if (name == "--decode") {
cerr << "To decode an unknown message, use --decode_raw." << endl;
}
- return false;
+ return PARSE_ARGUMENT_FAIL;
} else if (!value.empty() && name == "--decode_raw") {
cerr << "--decode_raw does not take a parameter." << endl;
- return false;
+ return PARSE_ARGUMENT_FAIL;
}
codec_type_ = value;
@@ -986,16 +1032,16 @@
error_format_ = ERROR_FORMAT_MSVS;
} else {
cerr << "Unknown error format: " << value << endl;
- return false;
+ return PARSE_ARGUMENT_FAIL;
}
} else if (name == "--plugin") {
if (plugin_prefix_.empty()) {
cerr << "This compiler does not support plugins." << endl;
- return false;
+ return PARSE_ARGUMENT_FAIL;
}
- string name;
+ string plugin_name;
string path;
string::size_type equals_pos = value.find_first_of('=');
@@ -1003,57 +1049,68 @@
// Use the basename of the file.
string::size_type slash_pos = value.find_last_of('/');
if (slash_pos == string::npos) {
- name = value;
+ plugin_name = value;
} else {
- name = value.substr(slash_pos + 1);
+ plugin_name = value.substr(slash_pos + 1);
}
path = value;
} else {
- name = value.substr(0, equals_pos);
+ plugin_name = value.substr(0, equals_pos);
path = value.substr(equals_pos + 1);
}
- plugins_[name] = path;
+ plugins_[plugin_name] = path;
} else {
// Some other flag. Look it up in the generators list.
- const GeneratorInfo* generator_info = FindOrNull(generators_, name);
+ const GeneratorInfo* generator_info =
+ FindOrNull(generators_by_flag_name_, name);
if (generator_info == NULL &&
(plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) {
- cerr << "Unknown flag: " << name << endl;
- return false;
- }
-
- // It's an output flag. Add it to the output directives.
- if (mode_ != MODE_COMPILE) {
- cerr << "Cannot use --encode or --decode and generate code at the "
- "same time." << endl;
- return false;
- }
-
- OutputDirective directive;
- directive.name = name;
- if (generator_info == NULL) {
- directive.generator = NULL;
+ // Check if it's a generator option flag.
+ generator_info = FindOrNull(generators_by_option_name_, name);
+ if (generator_info == NULL) {
+ cerr << "Unknown flag: " << name << endl;
+ return PARSE_ARGUMENT_FAIL;
+ } else {
+ string* parameters = &generator_parameters_[generator_info->flag_name];
+ if (!parameters->empty()) {
+ parameters->append(",");
+ }
+ parameters->append(value);
+ }
} else {
- directive.generator = generator_info->generator;
- }
+ // It's an output flag. Add it to the output directives.
+ if (mode_ != MODE_COMPILE) {
+ cerr << "Cannot use --encode or --decode and generate code at the "
+ "same time." << endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
- // Split value at ':' to separate the generator parameter from the
- // filename. However, avoid doing this if the colon is part of a valid
- // Windows-style absolute path.
- string::size_type colon_pos = value.find_first_of(':');
- if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) {
- directive.output_location = value;
- } else {
- directive.parameter = value.substr(0, colon_pos);
- directive.output_location = value.substr(colon_pos + 1);
- }
+ OutputDirective directive;
+ directive.name = name;
+ if (generator_info == NULL) {
+ directive.generator = NULL;
+ } else {
+ directive.generator = generator_info->generator;
+ }
- output_directives_.push_back(directive);
+ // Split value at ':' to separate the generator parameter from the
+ // filename. However, avoid doing this if the colon is part of a valid
+ // Windows-style absolute path.
+ string::size_type colon_pos = value.find_first_of(':');
+ if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) {
+ directive.output_location = value;
+ } else {
+ directive.parameter = value.substr(0, colon_pos);
+ directive.output_location = value.substr(colon_pos + 1);
+ }
+
+ output_directives_.push_back(directive);
+ }
}
- return true;
+ return PARSE_ARGUMENT_DONE_AND_CONTINUE;
}
void CommandLineInterface::PrintHelpText() {
@@ -1086,6 +1143,12 @@
" --include_imports When using --descriptor_set_out, also include\n"
" all dependencies of the input files in the\n"
" set, so that the set is self-contained.\n"
+" --include_source_info When using --descriptor_set_out, do not strip\n"
+" SourceCodeInfo from the FileDescriptorProto.\n"
+" This results in vastly larger descriptors that\n"
+" include information about the original\n"
+" location of each decl in the source file as\n"
+" well as surrounding comments.\n"
" --error_format=FORMAT Set the format in which to print errors.\n"
" FORMAT may be 'gcc' (the default) or 'msvs'\n"
" (Microsoft Visual Studio format)." << endl;
@@ -1101,8 +1164,8 @@
" the executable's own name differs." << endl;
}
- for (GeneratorMap::iterator iter = generators_.begin();
- iter != generators_.end(); ++iter) {
+ for (GeneratorMap::iterator iter = generators_by_flag_name_.begin();
+ iter != generators_by_flag_name_.end(); ++iter) {
// FIXME(kenton): If the text is long enough it will wrap, which is ugly,
// but fixing this nicely (e.g. splitting on spaces) is probably more
// trouble than it's worth.
@@ -1136,10 +1199,16 @@
}
} else {
// Regular generator.
+ string parameters = output_directive.parameter;
+ if (!generator_parameters_[output_directive.name].empty()) {
+ if (!parameters.empty()) {
+ parameters.append(",");
+ }
+ parameters.append(generator_parameters_[output_directive.name]);
+ }
for (int i = 0; i < parsed_files.size(); i++) {
- if (!output_directive.generator->Generate(
- parsed_files[i], output_directive.parameter,
- generator_context, &error)) {
+ if (!output_directive.generator->Generate(parsed_files[i], parameters,
+ generator_context, &error)) {
// Generator returned an error.
cerr << output_directive.name << ": " << parsed_files[i]->name() << ": "
<< error << endl;
@@ -1168,8 +1237,9 @@
set<const FileDescriptor*> already_seen;
for (int i = 0; i < parsed_files.size(); i++) {
request.add_file_to_generate(parsed_files[i]->name());
- GetTransitiveDependencies(parsed_files[i], &already_seen,
- request.mutable_proto_file());
+ GetTransitiveDependencies(parsed_files[i],
+ true, // Include source code info.
+ &already_seen, request.mutable_proto_file());
}
// Invoke the plugin.
@@ -1299,12 +1369,17 @@
if (imports_in_descriptor_set_) {
set<const FileDescriptor*> already_seen;
for (int i = 0; i < parsed_files.size(); i++) {
- GetTransitiveDependencies(
- parsed_files[i], &already_seen, file_set.mutable_file());
+ GetTransitiveDependencies(parsed_files[i],
+ source_info_in_descriptor_set_,
+ &already_seen, file_set.mutable_file());
}
} else {
for (int i = 0; i < parsed_files.size(); i++) {
- parsed_files[i]->CopyTo(file_set.add_file());
+ FileDescriptorProto* file_proto = file_set.add_file();
+ parsed_files[i]->CopyTo(file_proto);
+ if (source_info_in_descriptor_set_) {
+ parsed_files[i]->CopySourceCodeInfoTo(file_proto);
+ }
}
}
@@ -1334,7 +1409,7 @@
}
void CommandLineInterface::GetTransitiveDependencies(
- const FileDescriptor* file,
+ const FileDescriptor* file, bool include_source_code_info,
set<const FileDescriptor*>* already_seen,
RepeatedPtrField<FileDescriptorProto>* output) {
if (!already_seen->insert(file).second) {
@@ -1344,11 +1419,16 @@
// Add all dependencies.
for (int i = 0; i < file->dependency_count(); i++) {
- GetTransitiveDependencies(file->dependency(i), already_seen, output);
+ GetTransitiveDependencies(file->dependency(i), include_source_code_info,
+ already_seen, output);
}
// Add this file.
- file->CopyTo(output->Add());
+ FileDescriptorProto* new_descriptor = output->Add();
+ file->CopyTo(new_descriptor);
+ if (include_source_code_info) {
+ file->CopySourceCodeInfoTo(new_descriptor);
+ }
}
diff --git a/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.h b/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.h
index 0b507d8..86ea9bd 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/command_line_interface.h
@@ -112,6 +112,19 @@
CodeGenerator* generator,
const string& help_text);
+ // Register a code generator for a language.
+ // Besides flag_name you can specify another option_flag_name that could be
+ // used to pass extra parameters to the registered code generator.
+ // Suppose you have registered a generator by calling:
+ // command_line_interface.RegisterGenerator("--foo_out", "--foo_opt", ...)
+ // Then you could invoke the compiler with a command like:
+ // protoc --foo_out=enable_bar:outdir --foo_opt=enable_baz
+ // This will pass "enable_bar,enable_baz" as the parameter to the generator.
+ void RegisterGenerator(const string& flag_name,
+ const string& option_flag_name,
+ CodeGenerator* generator,
+ const string& help_text);
+
// Enables "plugins". In this mode, if a command-line flag ends with "_out"
// but does not match any registered generator, the compiler will attempt to
// find a "plugin" to implement the generator. Plugins are just executables.
@@ -186,8 +199,15 @@
bool MakeInputsBeProtoPathRelative(
DiskSourceTree* source_tree);
+ // Return status for ParseArguments() and InterpretArgument().
+ enum ParseArgumentStatus {
+ PARSE_ARGUMENT_DONE_AND_CONTINUE,
+ PARSE_ARGUMENT_DONE_AND_EXIT,
+ PARSE_ARGUMENT_FAIL
+ };
+
// Parse all command-line arguments.
- bool ParseArguments(int argc, const char* const argv[]);
+ ParseArgumentStatus ParseArguments(int argc, const char* const argv[]);
// Parses a command-line argument into a name/value pair. Returns
// true if the next argument in the argv should be used as the value,
@@ -203,7 +223,8 @@
bool ParseArgument(const char* arg, string* name, string* value);
// Interprets arguments parsed with ParseArgument.
- bool InterpretArgument(const string& name, const string& value);
+ ParseArgumentStatus InterpretArgument(const string& name,
+ const string& value);
// Print the --help text to stderr.
void PrintHelpText();
@@ -230,9 +251,11 @@
// protos will be ordered such that every file is listed before any file that
// depends on it, so that you can call DescriptorPool::BuildFile() on them
// in order. Any files in *already_seen will not be added, and each file
- // added will be inserted into *already_seen.
+ // added will be inserted into *already_seen. If include_source_code_info is
+ // true then include the source code information in the FileDescriptorProtos.
static void GetTransitiveDependencies(
const FileDescriptor* file,
+ bool include_source_code_info,
set<const FileDescriptor*>* already_seen,
RepeatedPtrField<FileDescriptorProto>* output);
@@ -244,13 +267,21 @@
// Version info set with SetVersionInfo().
string version_info_;
- // Map from flag names to registered generators.
+ // Registered generators.
struct GeneratorInfo {
+ string flag_name;
+ string option_flag_name;
CodeGenerator* generator;
string help_text;
};
typedef map<string, GeneratorInfo> GeneratorMap;
- GeneratorMap generators_;
+ GeneratorMap generators_by_flag_name_;
+ GeneratorMap generators_by_option_name_;
+ // A map from generator names to the parameters specified using the option
+ // flag. For example, if the user invokes the compiler with:
+ // protoc --foo_out=outputdir --foo_opt=enable_bar ...
+ // Then there will be an entry ("--foo_out", "enable_bar") in this map.
+ map<string, string> generator_parameters_;
// See AllowPlugins(). If this is empty, plugins aren't allowed.
string plugin_prefix_;
@@ -302,6 +333,10 @@
// the .proto files listed on the command-line are added.
bool imports_in_descriptor_set_;
+ // True if --include_source_info was given, meaning that we should not strip
+ // SourceCodeInfo from the DescriptorSet.
+ bool source_info_in_descriptor_set_;
+
// Was the --disallow_services flag used?
bool disallow_services_;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/command_line_interface_unittest.cc b/third_party/protobuf/src/google/protobuf/compiler/command_line_interface_unittest.cc
index d5b3a1d..1655992 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -122,6 +122,10 @@
// substring.
void ExpectErrorSubstring(const string& expected_substring);
+ // Like ExpectErrorSubstring, but checks that Run() returned zero.
+ void ExpectErrorSubstringWithZeroReturnCode(
+ const string& expected_substring);
+
// Returns true if ExpectErrorSubstring(expected_substring) would pass, but
// does not fail otherwise.
bool HasAlternateErrorSubstring(const string& expected_substring);
@@ -225,7 +229,7 @@
// Register generators.
CodeGenerator* generator = new MockCodeGenerator("test_generator");
mock_generators_to_delete_.push_back(generator);
- cli_.RegisterGenerator("--test_out", generator, "Test output.");
+ cli_.RegisterGenerator("--test_out", "--test_opt", generator, "Test output.");
cli_.RegisterGenerator("-t", generator, "Test output.");
generator = new MockCodeGenerator("alt_generator");
@@ -345,6 +349,12 @@
EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
}
+void CommandLineInterfaceTest::ExpectErrorSubstringWithZeroReturnCode(
+ const string& expected_substring) {
+ EXPECT_EQ(0, return_code_);
+ EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
+}
+
bool CommandLineInterfaceTest::HasAlternateErrorSubstring(
const string& expected_substring) {
EXPECT_NE(0, return_code_);
@@ -544,6 +554,32 @@
ExpectGenerated("test_plugin", "TestPluginParameter", "foo.proto", "Foo");
}
+TEST_F(CommandLineInterfaceTest, ExtraGeneratorParameters) {
+ // Test that generator parameters specified with the option flag are
+ // correctly passed to the code generator.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ // Create the "a" and "b" sub-directories.
+ CreateTempDir("a");
+ CreateTempDir("b");
+
+ Run("protocol_compiler "
+ "--test_opt=foo1 "
+ "--test_out=bar:$tmpdir/a "
+ "--test_opt=foo2 "
+ "--test_out=baz:$tmpdir/b "
+ "--test_opt=foo3 "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated(
+ "test_generator", "bar,foo1,foo2,foo3", "foo.proto", "Foo", "a");
+ ExpectGenerated(
+ "test_generator", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b");
+}
+
TEST_F(CommandLineInterfaceTest, Insert) {
// Test running a generator that inserts code into another's output.
@@ -779,6 +815,33 @@
if (HasFatalFailure()) return;
ASSERT_EQ(1, descriptor_set.file_size());
EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
+ // Descriptor set should not have source code info.
+ EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
+}
+
+TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "import \"foo.proto\";\n"
+ "message Bar {\n"
+ " optional Foo foo = 1;\n"
+ "}\n");
+
+ Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
+ "--include_source_info --proto_path=$tmpdir bar.proto");
+
+ ExpectNoErrors();
+
+ FileDescriptorSet descriptor_set;
+ ReadDescriptorSet("descriptor_set", &descriptor_set);
+ if (HasFatalFailure()) return;
+ ASSERT_EQ(1, descriptor_set.file_size());
+ EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
+ // Source code info included.
+ EXPECT_TRUE(descriptor_set.file(0).has_source_code_info());
}
TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) {
@@ -807,6 +870,40 @@
}
EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
EXPECT_EQ("bar.proto", descriptor_set.file(1).name());
+ // Descriptor set should not have source code info.
+ EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
+ EXPECT_FALSE(descriptor_set.file(1).has_source_code_info());
+}
+
+TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "import \"foo.proto\";\n"
+ "message Bar {\n"
+ " optional Foo foo = 1;\n"
+ "}\n");
+
+ Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
+ "--include_imports --include_source_info --proto_path=$tmpdir bar.proto");
+
+ ExpectNoErrors();
+
+ FileDescriptorSet descriptor_set;
+ ReadDescriptorSet("descriptor_set", &descriptor_set);
+ if (HasFatalFailure()) return;
+ ASSERT_EQ(2, descriptor_set.file_size());
+ if (descriptor_set.file(0).name() == "bar.proto") {
+ std::swap(descriptor_set.mutable_file()->mutable_data()[0],
+ descriptor_set.mutable_file()->mutable_data()[1]);
+ }
+ EXPECT_EQ("foo.proto", descriptor_set.file(0).name());
+ EXPECT_EQ("bar.proto", descriptor_set.file(1).name());
+ // Source code info included.
+ EXPECT_TRUE(descriptor_set.file(0).has_source_code_info());
+ EXPECT_TRUE(descriptor_set.file(1).has_source_code_info());
}
// -------------------------------------------------------------------
@@ -1129,6 +1226,17 @@
#endif
}
+TEST_F(CommandLineInterfaceTest, PluginReceivesSourceCodeInfo) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message MockCodeGenerator_HasSourceCodeInfo {}\n");
+
+ Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring(
+ "Saw message type MockCodeGenerator_HasSourceCodeInfo: 1.");
+}
+
TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) {
// Test what happens if the plugin isn't found.
@@ -1171,11 +1279,11 @@
TEST_F(CommandLineInterfaceTest, HelpText) {
Run("test_exec_name --help");
- ExpectErrorSubstring("Usage: test_exec_name ");
- ExpectErrorSubstring("--test_out=OUT_DIR");
- ExpectErrorSubstring("Test output.");
- ExpectErrorSubstring("--alt_out=OUT_DIR");
- ExpectErrorSubstring("Alt output.");
+ ExpectErrorSubstringWithZeroReturnCode("Usage: test_exec_name ");
+ ExpectErrorSubstringWithZeroReturnCode("--test_out=OUT_DIR");
+ ExpectErrorSubstringWithZeroReturnCode("Test output.");
+ ExpectErrorSubstringWithZeroReturnCode("--alt_out=OUT_DIR");
+ ExpectErrorSubstringWithZeroReturnCode("Alt output.");
}
TEST_F(CommandLineInterfaceTest, GccFormatErrors) {
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index bcfa502..b7c1766 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -48,8 +48,8 @@
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
#include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/stl_util.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 76d2b79..67c12d7 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -46,10 +46,10 @@
namespace cpp {
EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
- const string& dllexport_decl)
+ const Options& options)
: descriptor_(descriptor),
classname_(ClassName(descriptor, false)),
- dllexport_decl_(dllexport_decl) {
+ options_(options) {
}
EnumGenerator::~EnumGenerator() {}
@@ -88,10 +88,10 @@
vars["min_name"] = min_value->name();
vars["max_name"] = max_value->name();
- if (dllexport_decl_.empty()) {
+ if (options_.dllexport_decl.empty()) {
vars["dllexport"] = "";
} else {
- vars["dllexport"] = dllexport_decl_ + " ";
+ vars["dllexport"] = options_.dllexport_decl + " ";
}
printer->Print(vars,
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.h
index 58f7721..2e85a0b 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.h
@@ -36,8 +36,10 @@
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
#include <string>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
#include <google/protobuf/descriptor.h>
+
namespace google {
namespace protobuf {
namespace io {
@@ -53,7 +55,7 @@
public:
// See generator.cc for the meaning of dllexport_decl.
explicit EnumGenerator(const EnumDescriptor* descriptor,
- const string& dllexport_decl);
+ const Options& options);
~EnumGenerator();
// Header stuff.
@@ -86,7 +88,7 @@
private:
const EnumDescriptor* descriptor_;
string classname_;
- string dllexport_decl_;
+ Options options_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
};
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index a369f41..6e1620d 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -46,8 +46,9 @@
namespace {
void SetEnumVariables(const FieldDescriptor* descriptor,
- map<string, string>* variables) {
- SetCommonFieldVariables(descriptor, variables);
+ map<string, string>* variables,
+ const Options& options) {
+ SetCommonFieldVariables(descriptor, variables, options);
const EnumValueDescriptor* default_value = descriptor->default_value_enum();
(*variables)["type"] = ClassName(descriptor->enum_type(), true);
(*variables)["default"] = SimpleItoa(default_value->number());
@@ -58,9 +59,10 @@
// ===================================================================
EnumFieldGenerator::
-EnumFieldGenerator(const FieldDescriptor* descriptor)
+EnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetEnumVariables(descriptor, &variables_);
+ SetEnumVariables(descriptor, &variables_, options);
}
EnumFieldGenerator::~EnumFieldGenerator() {}
@@ -84,7 +86,7 @@
" return static_cast< $type$ >($name$_);\n"
"}\n"
"inline void $classname$::set_$name$($type$ value) {\n"
- " GOOGLE_DCHECK($type$_IsValid(value));\n"
+ " assert($type$_IsValid(value));\n"
" set_has_$name$();\n"
" $name$_ = value;\n"
"}\n");
@@ -152,9 +154,10 @@
// ===================================================================
RepeatedEnumFieldGenerator::
-RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor)
+RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetEnumVariables(descriptor, &variables_);
+ SetEnumVariables(descriptor, &variables_, options);
}
RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
@@ -187,11 +190,11 @@
" return static_cast< $type$ >($name$_.Get(index));\n"
"}\n"
"inline void $classname$::set_$name$(int index, $type$ value) {\n"
- " GOOGLE_DCHECK($type$_IsValid(value));\n"
+ " assert($type$_IsValid(value));\n"
" $name$_.Set(index, value);\n"
"}\n"
"inline void $classname$::add_$name$($type$ value) {\n"
- " GOOGLE_DCHECK($type$_IsValid(value));\n"
+ " assert($type$_IsValid(value));\n"
" $name$_.Add(value);\n"
"}\n");
printer->Print(variables_,
@@ -345,7 +348,9 @@
" total_size += $tag_size$ +\n"
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
"}\n"
+ "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
"_$name$_cached_byte_size_ = data_size;\n"
+ "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
"total_size += data_size;\n");
} else {
printer->Print(variables_,
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.h
index 0793430..6577008 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -46,7 +46,8 @@
class EnumFieldGenerator : public FieldGenerator {
public:
- explicit EnumFieldGenerator(const FieldDescriptor* descriptor);
+ explicit EnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~EnumFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -71,7 +72,8 @@
class RepeatedEnumFieldGenerator : public FieldGenerator {
public:
- explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor);
+ explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~RepeatedEnumFieldGenerator();
// implements FieldGenerator ---------------------------------------
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc
index 658a707..ef56b5e 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc
@@ -57,9 +57,9 @@
} // anonymous namespace
ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
- const string& dllexport_decl)
+ const Options& options)
: descriptor_(descriptor),
- dllexport_decl_(dllexport_decl) {
+ options_(options) {
// Construct type_traits_.
if (descriptor_->is_repeated()) {
type_traits_ = "Repeated";
@@ -106,8 +106,8 @@
// export/import specifier.
if (descriptor_->extension_scope() == NULL) {
vars["qualifier"] = "extern";
- if (!dllexport_decl_.empty()) {
- vars["qualifier"] = dllexport_decl_ + " " + vars["qualifier"];
+ if (!options_.dllexport_decl.empty()) {
+ vars["qualifier"] = options_.dllexport_decl + " " + vars["qualifier"];
}
} else {
vars["qualifier"] = "static";
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.h
index 3068b09..50ad035 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.h
@@ -37,6 +37,7 @@
#include <string>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
namespace google {
namespace protobuf {
@@ -56,8 +57,8 @@
class ExtensionGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
- explicit ExtensionGenerator(const FieldDescriptor* descriptor,
- const string& dllexport_decl);
+ explicit ExtensionGenerator(const FieldDescriptor* desycriptor,
+ const Options& options);
~ExtensionGenerator();
// Header stuff.
@@ -72,7 +73,7 @@
private:
const FieldDescriptor* descriptor_;
string type_traits_;
- string dllexport_decl_;
+ Options options_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
};
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc
index 103cac4..0786176 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -52,7 +52,8 @@
using internal::WireFormat;
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
- map<string, string>* variables) {
+ map<string, string>* variables,
+ const Options& options) {
(*variables)["name"] = FieldName(descriptor);
(*variables)["index"] = SimpleItoa(descriptor->index());
(*variables)["number"] = SimpleItoa(descriptor->number());
@@ -64,6 +65,7 @@
(*variables)["deprecation"] = descriptor->options().deprecated()
? " PROTOBUF_DEPRECATED" : "";
+ (*variables)["cppget"] = "Get";
}
FieldGenerator::~FieldGenerator() {}
@@ -80,46 +82,47 @@
}
-FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
+FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor),
- field_generators_(
- new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
+ field_generators_(new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
// Construct all the FieldGenerators.
for (int i = 0; i < descriptor->field_count(); i++) {
- field_generators_[i].reset(MakeGenerator(descriptor->field(i)));
+ field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
}
}
-FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
+FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
+ const Options& options) {
if (field->is_repeated()) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
- return new RepeatedMessageFieldGenerator(field);
+ return new RepeatedMessageFieldGenerator(field, options);
case FieldDescriptor::CPPTYPE_STRING:
switch (field->options().ctype()) {
default: // RepeatedStringFieldGenerator handles unknown ctypes.
case FieldOptions::STRING:
- return new RepeatedStringFieldGenerator(field);
+ return new RepeatedStringFieldGenerator(field, options);
}
case FieldDescriptor::CPPTYPE_ENUM:
- return new RepeatedEnumFieldGenerator(field);
+ return new RepeatedEnumFieldGenerator(field, options);
default:
- return new RepeatedPrimitiveFieldGenerator(field);
+ return new RepeatedPrimitiveFieldGenerator(field, options);
}
} else {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
- return new MessageFieldGenerator(field);
+ return new MessageFieldGenerator(field, options);
case FieldDescriptor::CPPTYPE_STRING:
switch (field->options().ctype()) {
default: // StringFieldGenerator handles unknown ctypes.
case FieldOptions::STRING:
- return new StringFieldGenerator(field);
+ return new StringFieldGenerator(field, options);
}
case FieldDescriptor::CPPTYPE_ENUM:
- return new EnumFieldGenerator(field);
+ return new EnumFieldGenerator(field, options);
default:
- return new PrimitiveFieldGenerator(field);
+ return new PrimitiveFieldGenerator(field, options);
}
}
}
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.h
index c303a33..f7d99b1 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -40,6 +40,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
namespace google {
namespace protobuf {
@@ -57,7 +58,8 @@
// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
// 'deprecation'].
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
- map<string, string>* variables);
+ map<string, string>* variables,
+ const Options& options);
class FieldGenerator {
public:
@@ -114,6 +116,13 @@
// Most field types don't need this, so the default implementation is empty.
virtual void GenerateDestructorCode(io::Printer* printer) const {}
+ // Generate code that allocates the fields's default instance.
+ virtual void GenerateDefaultInstanceAllocator(io::Printer* printer) const {}
+
+ // Generate code that should be run when ShutdownProtobufLibrary() is called,
+ // to delete all dynamically-allocated objects.
+ virtual void GenerateShutdownCode(io::Printer* printer) const {}
+
// Generate lines to decode this field, which will be placed inside the
// message's MergeFromCodedStream() method.
virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0;
@@ -144,7 +153,7 @@
// Convenience class which constructs FieldGenerators for a Descriptor.
class FieldGeneratorMap {
public:
- explicit FieldGeneratorMap(const Descriptor* descriptor);
+ explicit FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
~FieldGeneratorMap();
const FieldGenerator& get(const FieldDescriptor* field) const;
@@ -153,7 +162,8 @@
const Descriptor* descriptor_;
scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
- static FieldGenerator* MakeGenerator(const FieldDescriptor* field);
+ static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
+ const Options& options);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
};
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc
index 3e6d414..4eb89f4 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -51,7 +51,7 @@
// ===================================================================
FileGenerator::FileGenerator(const FileDescriptor* file,
- const string& dllexport_decl)
+ const Options& options)
: file_(file),
message_generators_(
new scoped_ptr<MessageGenerator>[file->message_type_count()]),
@@ -61,26 +61,26 @@
new scoped_ptr<ServiceGenerator>[file->service_count()]),
extension_generators_(
new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
- dllexport_decl_(dllexport_decl) {
+ options_(options) {
for (int i = 0; i < file->message_type_count(); i++) {
message_generators_[i].reset(
- new MessageGenerator(file->message_type(i), dllexport_decl));
+ new MessageGenerator(file->message_type(i), options));
}
for (int i = 0; i < file->enum_type_count(); i++) {
enum_generators_[i].reset(
- new EnumGenerator(file->enum_type(i), dllexport_decl));
+ new EnumGenerator(file->enum_type(i), options));
}
for (int i = 0; i < file->service_count(); i++) {
service_generators_[i].reset(
- new ServiceGenerator(file->service(i), dllexport_decl));
+ new ServiceGenerator(file->service(i), options));
}
for (int i = 0; i < file->extension_count(); i++) {
extension_generators_[i].reset(
- new ExtensionGenerator(file->extension(i), dllexport_decl));
+ new ExtensionGenerator(file->extension(i), options));
}
SplitStringUsing(file_->package(), ".", &package_parts_);
@@ -104,6 +104,7 @@
"filename", file_->name(),
"filename_identifier", filename_identifier);
+
printer->Print(
"#include <google/protobuf/stubs/common.h>\n"
"\n");
@@ -128,7 +129,17 @@
// OK, it's now safe to #include other files.
printer->Print(
- "#include <google/protobuf/generated_message_util.h>\n"
+ "#include <google/protobuf/generated_message_util.h>\n");
+ if (file_->message_type_count() > 0) {
+ if (HasDescriptorMethods(file_)) {
+ printer->Print(
+ "#include <google/protobuf/message.h>\n");
+ } else {
+ printer->Print(
+ "#include <google/protobuf/message_lite.h>\n");
+ }
+ }
+ printer->Print(
"#include <google/protobuf/repeated_field.h>\n"
"#include <google/protobuf/extension_set.h>\n");
@@ -137,9 +148,9 @@
"#include <google/protobuf/unknown_field_set.h>\n");
}
- if (HasDescriptorMethods(file_)) {
+ if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) {
printer->Print(
- "#include <google/protobuf/generated_message_reflection.h>\n");
+ "#include <google/protobuf/generated_enum_reflection.h>\n");
}
if (HasGenericServices(file_)) {
@@ -147,6 +158,11 @@
"#include <google/protobuf/service.h>\n");
}
+ if (HasUnknownFields(file_) && file_->message_type_count() > 0) {
+ printer->Print(
+ "#include <google/protobuf/unknown_field_set.h>\n");
+ }
+
for (int i = 0; i < file_->dependency_count(); i++) {
printer->Print(
@@ -154,9 +170,11 @@
"dependency", StripProto(file_->dependency(i)->name()));
}
+
printer->Print(
"// @@protoc_insertion_point(includes)\n");
+
// Open namespace.
GenerateNamespaceOpeners(printer);
@@ -167,7 +185,7 @@
"// Internal implementation detail -- do not call these.\n"
"void $dllexport_decl$ $adddescriptorsname$();\n",
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
- "dllexport_decl", dllexport_decl_);
+ "dllexport_decl", options_.dllexport_decl);
printer->Print(
// Note that we don't put dllexport_decl on these because they are only
@@ -287,6 +305,7 @@
void FileGenerator::GenerateSource(io::Printer* printer) {
printer->Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
"\n"
// The generated code calls accessors that might be deprecated. We don't
@@ -296,14 +315,17 @@
"\n"
"#include <algorithm>\n" // for swap()
"\n"
+ "#include <google/protobuf/stubs/common.h>\n"
"#include <google/protobuf/stubs/once.h>\n"
"#include <google/protobuf/io/coded_stream.h>\n"
"#include <google/protobuf/wire_format_lite_inl.h>\n",
+ "filename", file_->name(),
"basename", StripProto(file_->name()));
if (HasDescriptorMethods(file_)) {
printer->Print(
"#include <google/protobuf/descriptor.h>\n"
+ "#include <google/protobuf/generated_message_reflection.h>\n"
"#include <google/protobuf/reflection_ops.h>\n"
"#include <google/protobuf/wire_format.h>\n");
}
@@ -509,10 +531,12 @@
" static bool already_here = false;\n"
" if (already_here) return;\n"
" already_here = true;\n"
- " GOOGLE_PROTOBUF_VERIFY_VERSION;\n",
+ " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
+ "\n",
// Without.
"void $adddescriptorsname$_impl() {\n"
- " GOOGLE_PROTOBUF_VERIFY_VERSION;\n",
+ " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
+ "\n",
// Vars.
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
@@ -526,9 +550,9 @@
vector<string> dependency_package_parts;
SplitStringUsing(dependency->package(), ".", &dependency_package_parts);
printer->Print("::");
- for (int i = 0; i < dependency_package_parts.size(); i++) {
+ for (int j = 0; j < dependency_package_parts.size(); j++) {
printer->Print("$name$::",
- "name", dependency_package_parts[i]);
+ "name", dependency_package_parts[j]);
}
// Call its AddDescriptors function.
printer->Print(
@@ -552,10 +576,12 @@
static const int kBytesPerLine = 40;
for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
printer->Print("\n \"$data$\"",
- "data", EscapeTrigraphs(CEscape(file_data.substr(i, kBytesPerLine))));
+ "data",
+ EscapeTrigraphs(
+ CEscape(file_data.substr(i, kBytesPerLine))));
}
printer->Print(
- ", $size$);\n",
+ ", $size$);\n",
"size", SimpleItoa(file_data.size()));
// Call MessageFactory::InternalRegisterGeneratedFile().
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.h
index b4e0128..2deefaa 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -39,6 +39,7 @@
#include <vector>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
namespace google {
namespace protobuf {
@@ -61,7 +62,7 @@
public:
// See generator.cc for the meaning of dllexport_decl.
explicit FileGenerator(const FileDescriptor* file,
- const string& dllexport_decl);
+ const Options& options);
~FileGenerator();
void GenerateHeader(io::Printer* printer);
@@ -85,7 +86,7 @@
// E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.
vector<string> package_parts_;
- string dllexport_decl_;
+ const Options options_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
};
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc
index bb84e2a..1813510 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -78,11 +78,13 @@
// }
// FOO_EXPORT is a macro which should expand to __declspec(dllexport) or
// __declspec(dllimport) depending on what is being compiled.
- string dllexport_decl;
+ Options file_options;
for (int i = 0; i < options.size(); i++) {
if (options[i].first == "dllexport_decl") {
- dllexport_decl = options[i].second;
+ file_options.dllexport_decl = options[i].second;
+ } else if (options[i].first == "safe_boundary_check") {
+ file_options.safe_boundary_check = true;
} else {
*error = "Unknown generator option: " + options[i].first;
return false;
@@ -95,7 +97,7 @@
string basename = StripProto(file->name());
basename.append(".pb");
- FileGenerator file_generator(file, dllexport_decl);
+ FileGenerator file_generator(file, file_options);
// Generate header.
{
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index c4b868c..c53d5d3 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -148,7 +148,7 @@
string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
if (enum_descriptor->containing_type() == NULL) {
if (qualified) {
- return DotsToColons(enum_descriptor->full_name());
+ return "::" + DotsToColons(enum_descriptor->full_name());
} else {
return enum_descriptor->name();
}
@@ -259,10 +259,27 @@
string DefaultValue(const FieldDescriptor* field) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
+ // gcc rejects the decimal form of kint32min and kint64min.
+ if (field->default_value_int32() == kint32min) {
+ // Make sure we are in a 2's complement system.
+ GOOGLE_COMPILE_ASSERT(
+ (uint32)kint32min == (uint32)0 - (uint32)0x80000000,
+ kint32min_value_error);
+ return "-0x80000000";
+ }
return SimpleItoa(field->default_value_int32());
case FieldDescriptor::CPPTYPE_UINT32:
return SimpleItoa(field->default_value_uint32()) + "u";
case FieldDescriptor::CPPTYPE_INT64:
+ // See the comments for CPPTYPE_INT32.
+ if (field->default_value_int64() == kint64min) {
+ // Make sure we are in a 2's complement system.
+ GOOGLE_COMPILE_ASSERT(
+ (uint64)kint64min ==
+ (uint64)0 - (uint64)GOOGLE_LONGLONG(0x8000000000000000),
+ kint64min_value_error);
+ return "GOOGLE_LONGLONG(-0x8000000000000000)";
+ }
return "GOOGLE_LONGLONG(" + SimpleItoa(field->default_value_int64()) + ")";
case FieldDescriptor::CPPTYPE_UINT64:
return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
@@ -308,8 +325,9 @@
ClassName(field->enum_type(), true),
field->default_value_enum()->number());
case FieldDescriptor::CPPTYPE_STRING:
- return "\"" + EscapeTrigraphs(CEscape(field->default_value_string())) +
- "\"";
+ return "\"" + EscapeTrigraphs(
+ CEscape(field->default_value_string())) +
+ "\"";
case FieldDescriptor::CPPTYPE_MESSAGE:
return FieldMessageTypeName(field) + "::default_instance()";
}
@@ -401,6 +419,23 @@
}
}
+
+static bool HasEnumDefinitions(const Descriptor* message_type) {
+ if (message_type->enum_type_count() > 0) return true;
+ for (int i = 0; i < message_type->nested_type_count(); ++i) {
+ if (HasEnumDefinitions(message_type->nested_type(i))) return true;
+ }
+ return false;
+}
+
+bool HasEnumDefinitions(const FileDescriptor* file) {
+ if (file->enum_type_count() > 0) return true;
+ for (int i = 0; i < file->message_type_count(); ++i) {
+ if (HasEnumDefinitions(file->message_type(i))) return true;
+ }
+ return false;
+}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 690fbec..1b5b1ac 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -122,24 +122,27 @@
string EscapeTrigraphs(const string& to_escape);
// Do message classes in this file keep track of unknown fields?
-inline bool HasUnknownFields(const FileDescriptor *file) {
+inline bool HasUnknownFields(const FileDescriptor* file) {
return file->options().optimize_for() != FileOptions::LITE_RUNTIME ||
file->options().retain_unknown_fields();
}
+// Does this file have any enum type definitions?
+bool HasEnumDefinitions(const FileDescriptor* file);
+
// Does this file have generated parsing, serialization, and other
// standard methods for which reflection-based fallback implementations exist?
-inline bool HasGeneratedMethods(const FileDescriptor *file) {
+inline bool HasGeneratedMethods(const FileDescriptor* file) {
return file->options().optimize_for() != FileOptions::CODE_SIZE;
}
// Do message classes in this file have descriptor and refelction methods?
-inline bool HasDescriptorMethods(const FileDescriptor *file) {
+inline bool HasDescriptorMethods(const FileDescriptor* file) {
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
}
// Should we generate generic services for this file?
-inline bool HasGenericServices(const FileDescriptor *file) {
+inline bool HasGenericServices(const FileDescriptor* file) {
return file->service_count() > 0 &&
file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
file->options().cc_generic_services();
@@ -174,6 +177,7 @@
io::Printer* printer, const char* with_static_init,
const char* without_static_init);
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc
index 4248747..a7a81b0 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -48,6 +48,7 @@
#include <google/protobuf/wire_format.h>
#include <google/protobuf/descriptor.pb.h>
+
namespace google {
namespace protobuf {
namespace compiler {
@@ -103,6 +104,13 @@
}
};
+// Returns true if the "required" restriction check should be ignored for the
+// given field.
+inline static bool ShouldIgnoreRequiredFieldCheck(
+ const FieldDescriptor* field) {
+ return false;
+}
+
// Returns true if the message type has any required fields. If it doesn't,
// we can optimize out calls to its IsInitialized() method.
//
@@ -129,7 +137,8 @@
if (field->is_required()) {
return true;
}
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ !ShouldIgnoreRequiredFieldCheck(field)) {
if (HasRequiredFields(field->message_type(), already_seen)) {
return true;
}
@@ -280,11 +289,11 @@
// ===================================================================
MessageGenerator::MessageGenerator(const Descriptor* descriptor,
- const string& dllexport_decl)
+ const Options& options)
: descriptor_(descriptor),
classname_(ClassName(descriptor, false)),
- dllexport_decl_(dllexport_decl),
- field_generators_(descriptor),
+ options_(options),
+ field_generators_(descriptor, options),
nested_generators_(new scoped_ptr<MessageGenerator>[
descriptor->nested_type_count()]),
enum_generators_(new scoped_ptr<EnumGenerator>[
@@ -294,17 +303,17 @@
for (int i = 0; i < descriptor->nested_type_count(); i++) {
nested_generators_[i].reset(
- new MessageGenerator(descriptor->nested_type(i), dllexport_decl));
+ new MessageGenerator(descriptor->nested_type(i), options));
}
for (int i = 0; i < descriptor->enum_type_count(); i++) {
enum_generators_[i].reset(
- new EnumGenerator(descriptor->enum_type(i), dllexport_decl));
+ new EnumGenerator(descriptor->enum_type(i), options));
}
for (int i = 0; i < descriptor->extension_count(); i++) {
extension_generators_[i].reset(
- new ExtensionGenerator(descriptor->extension(i), dllexport_decl));
+ new ExtensionGenerator(descriptor->extension(i), options));
}
}
@@ -349,7 +358,7 @@
PrintFieldComment(printer, field);
map<string, string> vars;
- SetCommonFieldVariables(field, &vars);
+ SetCommonFieldVariables(field, &vars, options_);
vars["constant_name"] = FieldConstantName(field);
if (field->is_repeated()) {
@@ -386,7 +395,7 @@
PrintFieldComment(printer, field);
map<string, string> vars;
- SetCommonFieldVariables(field, &vars);
+ SetCommonFieldVariables(field, &vars, options_);
// Generate has_$name$() or $name$_size().
if (field->is_repeated()) {
@@ -446,10 +455,10 @@
map<string, string> vars;
vars["classname"] = classname_;
vars["field_count"] = SimpleItoa(descriptor_->field_count());
- if (dllexport_decl_.empty()) {
+ if (options_.dllexport_decl.empty()) {
vars["dllexport"] = "";
} else {
- vars["dllexport"] = dllexport_decl_ + " ";
+ vars["dllexport"] = options_.dllexport_decl + " ";
}
vars["superclass"] = SuperClassName(descriptor_);
@@ -507,6 +516,7 @@
"\n");
}
+
printer->Print(vars,
"void Swap($classname$* other);\n"
"\n"
@@ -605,6 +615,7 @@
printer->Print(" private:\n");
printer->Indent();
+
for (int i = 0; i < descriptor_->field_count(); i++) {
if (!descriptor_->field(i)->is_repeated()) {
printer->Print(
@@ -680,7 +691,7 @@
// Without.
"friend void $dllexport_decl$ $adddescriptorsname$_impl();\n",
// Vars.
- "dllexport_decl", dllexport_decl_,
+ "dllexport_decl", options_.dllexport_decl,
"adddescriptorsname",
GlobalAddDescriptorsName(descriptor_->file()->name()));
@@ -772,9 +783,11 @@
printer->Print(vars,
" -1,\n");
}
+ printer->Print(
+ " ::google::protobuf::DescriptorPool::generated_pool(),\n");
printer->Print(vars,
- " ::google::protobuf::DescriptorPool::generated_pool(),\n"
- " ::google::protobuf::MessageFactory::generated_factory(),\n"
+ " ::google::protobuf::MessageFactory::generated_factory(),\n");
+ printer->Print(vars,
" sizeof($classname$));\n");
// Handle nested types.
@@ -803,6 +816,13 @@
void MessageGenerator::
GenerateDefaultInstanceAllocator(io::Printer* printer) {
+ // Construct the default instances of all fields, as they will be used
+ // when creating the default instance of the entire message.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateDefaultInstanceAllocator(printer);
+ }
+
// Construct the default instance. We can't call InitAsDefaultInstance() yet
// because we need to make sure all default instances that this one might
// depend on are constructed first.
@@ -846,6 +866,12 @@
"classname", classname_);
}
+ // Handle default instances of fields.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateShutdownCode(printer);
+ }
+
// Handle nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
nested_generators_[i]->GenerateShutdownCode(printer);
@@ -1956,6 +1982,7 @@
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ !ShouldIgnoreRequiredFieldCheck(field) &&
HasRequiredFields(field->message_type())) {
if (field->is_repeated()) {
printer->Print(
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.h
index 04778f6..a7e43d9 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -38,6 +38,7 @@
#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/cpp/cpp_field.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
namespace google {
namespace protobuf {
@@ -57,7 +58,7 @@
public:
// See generator.cc for the meaning of dllexport_decl.
explicit MessageGenerator(const Descriptor* descriptor,
- const string& dllexport_decl);
+ const Options& options);
~MessageGenerator();
// Header stuff.
@@ -153,7 +154,7 @@
const Descriptor* descriptor_;
string classname_;
- string dllexport_decl_;
+ Options options_;
FieldGeneratorMap field_generators_;
scoped_array<scoped_ptr<MessageGenerator> > nested_generators_;
scoped_array<scoped_ptr<EnumGenerator> > enum_generators_;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index 7c785e7..447f975 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -45,8 +45,9 @@
namespace {
void SetMessageVariables(const FieldDescriptor* descriptor,
- map<string, string>* variables) {
- SetCommonFieldVariables(descriptor, variables);
+ map<string, string>* variables,
+ const Options& options) {
+ SetCommonFieldVariables(descriptor, variables, options);
(*variables)["type"] = FieldMessageTypeName(descriptor);
(*variables)["stream_writer"] = (*variables)["declared_type"] +
(HasFastArraySerialization(descriptor->message_type()->file()) ?
@@ -59,9 +60,10 @@
// ===================================================================
MessageFieldGenerator::
-MessageFieldGenerator(const FieldDescriptor* descriptor)
+MessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetMessageVariables(descriptor, &variables_);
+ SetMessageVariables(descriptor, &variables_, options);
}
MessageFieldGenerator::~MessageFieldGenerator() {}
@@ -76,7 +78,8 @@
printer->Print(variables_,
"inline const $type$& $name$() const$deprecation$;\n"
"inline $type$* mutable_$name$()$deprecation$;\n"
- "inline $type$* release_$name$()$deprecation$;\n");
+ "inline $type$* release_$name$()$deprecation$;\n"
+ "inline void set_allocated_$name$($type$* $name$)$deprecation$;\n");
}
void MessageFieldGenerator::
@@ -103,6 +106,15 @@
" $type$* temp = $name$_;\n"
" $name$_ = NULL;\n"
" return temp;\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ " delete $name$_;\n"
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " set_has_$name$();\n"
+ " } else {\n"
+ " clear_has_$name$();\n"
+ " }\n"
"}\n");
}
@@ -167,9 +179,10 @@
// ===================================================================
RepeatedMessageFieldGenerator::
-RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor)
+RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetMessageVariables(descriptor, &variables_);
+ SetMessageVariables(descriptor, &variables_, options);
}
RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
@@ -197,7 +210,7 @@
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline const $type$& $classname$::$name$(int index) const {\n"
- " return $name$_.Get(index);\n"
+ " return $name$_.$cppget$(index);\n"
"}\n"
"inline $type$* $classname$::mutable_$name$(int index) {\n"
" return $name$_.Mutable(index);\n"
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.h
index f514727..a5ed68a 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -46,7 +46,8 @@
class MessageFieldGenerator : public FieldGenerator {
public:
- explicit MessageFieldGenerator(const FieldDescriptor* descriptor);
+ explicit MessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~MessageFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -71,7 +72,8 @@
class RepeatedMessageFieldGenerator : public FieldGenerator {
public:
- explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor);
+ explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~RepeatedMessageFieldGenerator();
// implements FieldGenerator ---------------------------------------
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_options.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_options.h
new file mode 100644
index 0000000..7877066
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_options.h
@@ -0,0 +1,58 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: rennie@google.com (Jeffrey Rennie)
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Generator options:
+struct Options {
+ Options() : safe_boundary_check(false) {
+ }
+ string dllexport_decl;
+ bool safe_boundary_check;
+};
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 5e8df0f..1c35fef 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -80,8 +80,9 @@
}
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
- map<string, string>* variables) {
- SetCommonFieldVariables(descriptor, variables);
+ map<string, string>* variables,
+ const Options& options) {
+ SetCommonFieldVariables(descriptor, variables, options);
(*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
(*variables)["default"] = DefaultValue(descriptor);
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
@@ -99,9 +100,10 @@
// ===================================================================
PrimitiveFieldGenerator::
-PrimitiveFieldGenerator(const FieldDescriptor* descriptor)
+PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetPrimitiveVariables(descriptor, &variables_);
+ SetPrimitiveVariables(descriptor, &variables_, options);
}
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
@@ -190,9 +192,10 @@
// ===================================================================
RepeatedPrimitiveFieldGenerator::
-RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor)
+RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetPrimitiveVariables(descriptor, &variables_);
+ SetPrimitiveVariables(descriptor, &variables_, options);
if (descriptor->options().packed()) {
variables_["packed_reader"] = "ReadPackedPrimitive";
@@ -366,7 +369,9 @@
" total_size += $tag_size$ +\n"
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
"}\n"
+ "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
"_$name$_cached_byte_size_ = data_size;\n"
+ "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
"total_size += data_size;\n");
} else {
printer->Print(variables_,
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
index 8fcd74a..48249c4 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -46,7 +46,8 @@
class PrimitiveFieldGenerator : public FieldGenerator {
public:
- explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+ explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~PrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -71,7 +72,8 @@
class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
public:
- explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+ explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~RepeatedPrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc
index c282568..d20018e 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc
@@ -43,14 +43,14 @@
namespace cpp {
ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor,
- const string& dllexport_decl)
+ const Options& options)
: descriptor_(descriptor) {
vars_["classname"] = descriptor_->name();
vars_["full_name"] = descriptor_->full_name();
- if (dllexport_decl.empty()) {
+ if (options.dllexport_decl.empty()) {
vars_["dllexport"] = "";
} else {
- vars_["dllexport"] = dllexport_decl + " ";
+ vars_["dllexport"] = options.dllexport_decl + " ";
}
}
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.h
index 10e9dd3..820f9f5 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.h
@@ -38,6 +38,7 @@
#include <map>
#include <string>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/cpp/cpp_options.h>
#include <google/protobuf/descriptor.h>
namespace google {
@@ -55,7 +56,7 @@
public:
// See generator.cc for the meaning of dllexport_decl.
explicit ServiceGenerator(const ServiceDescriptor* descriptor,
- const string& dllexport_decl);
+ const Options& options);
~ServiceGenerator();
// Header stuff.
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 3cec2b6..9c0911a 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -46,11 +46,14 @@
namespace {
void SetStringVariables(const FieldDescriptor* descriptor,
- map<string, string>* variables) {
- SetCommonFieldVariables(descriptor, variables);
+ map<string, string>* variables,
+ const Options& options) {
+ SetCommonFieldVariables(descriptor, variables, options);
(*variables)["default"] = DefaultValue(descriptor);
+ (*variables)["default_length"] =
+ SimpleItoa(descriptor->default_value_string().length());
(*variables)["default_variable"] = descriptor->default_value_string().empty()
- ? "::google::protobuf::internal::kEmptyString"
+ ? "&::google::protobuf::internal::kEmptyString"
: "_default_" + FieldName(descriptor) + "_";
(*variables)["pointer_type"] =
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
@@ -61,9 +64,10 @@
// ===================================================================
StringFieldGenerator::
-StringFieldGenerator(const FieldDescriptor* descriptor)
+StringFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetStringVariables(descriptor, &variables_);
+ SetStringVariables(descriptor, &variables_, options);
}
StringFieldGenerator::~StringFieldGenerator() {}
@@ -72,7 +76,7 @@
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_, "::std::string* $name$_;\n");
if (!descriptor_->default_value_string().empty()) {
- printer->Print(variables_, "static const ::std::string $default_variable$;\n");
+ printer->Print(variables_, "static ::std::string* $default_variable$;\n");
}
}
@@ -109,7 +113,9 @@
"inline void set_$name$(const $pointer_type$* value, size_t size)"
"$deprecation$;\n"
"inline ::std::string* mutable_$name$()$deprecation$;\n"
- "inline ::std::string* release_$name$()$deprecation$;\n");
+ "inline ::std::string* release_$name$()$deprecation$;\n"
+ "inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
+
if (descriptor_->options().ctype() != FieldOptions::STRING) {
printer->Outdent();
@@ -126,14 +132,14 @@
"}\n"
"inline void $classname$::set_$name$(const ::std::string& value) {\n"
" set_has_$name$();\n"
- " if ($name$_ == &$default_variable$) {\n"
+ " if ($name$_ == $default_variable$) {\n"
" $name$_ = new ::std::string;\n"
" }\n"
" $name$_->assign(value);\n"
"}\n"
"inline void $classname$::set_$name$(const char* value) {\n"
" set_has_$name$();\n"
- " if ($name$_ == &$default_variable$) {\n"
+ " if ($name$_ == $default_variable$) {\n"
" $name$_ = new ::std::string;\n"
" }\n"
" $name$_->assign(value);\n"
@@ -141,20 +147,20 @@
"inline "
"void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
" set_has_$name$();\n"
- " if ($name$_ == &$default_variable$) {\n"
+ " if ($name$_ == $default_variable$) {\n"
" $name$_ = new ::std::string;\n"
" }\n"
" $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
"}\n"
"inline ::std::string* $classname$::mutable_$name$() {\n"
" set_has_$name$();\n"
- " if ($name$_ == &$default_variable$) {\n");
+ " if ($name$_ == $default_variable$) {\n");
if (descriptor_->default_value_string().empty()) {
printer->Print(variables_,
" $name$_ = new ::std::string;\n");
} else {
printer->Print(variables_,
- " $name$_ = new ::std::string($default_variable$);\n");
+ " $name$_ = new ::std::string(*$default_variable$);\n");
}
printer->Print(variables_,
" }\n"
@@ -162,21 +168,34 @@
"}\n"
"inline ::std::string* $classname$::release_$name$() {\n"
" clear_has_$name$();\n"
- " if ($name$_ == &$default_variable$) {\n"
+ " if ($name$_ == $default_variable$) {\n"
" return NULL;\n"
" } else {\n"
" ::std::string* temp = $name$_;\n"
- " $name$_ = const_cast< ::std::string*>(&$default_variable$);\n"
+ " $name$_ = const_cast< ::std::string*>($default_variable$);\n"
" return temp;\n"
" }\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ " if ($name$_ != $default_variable$) {\n"
+ " delete $name$_;\n"
+ " }\n"
+ " if ($name$) {\n"
+ " set_has_$name$();\n"
+ " $name$_ = $name$;\n"
+ " } else {\n"
+ " clear_has_$name$();\n"
+ " $name$_ = const_cast< ::std::string*>($default_variable$);\n"
+ " }\n"
"}\n");
}
void StringFieldGenerator::
GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
if (!descriptor_->default_value_string().empty()) {
+ // Initialized in GenerateDefaultInstanceAllocator.
printer->Print(variables_,
- "const ::std::string $classname$::$default_variable$($default$);\n");
+ "::std::string* $classname$::$default_variable$ = NULL;\n");
}
}
@@ -184,13 +203,13 @@
GenerateClearingCode(io::Printer* printer) const {
if (descriptor_->default_value_string().empty()) {
printer->Print(variables_,
- "if ($name$_ != &$default_variable$) {\n"
+ "if ($name$_ != $default_variable$) {\n"
" $name$_->clear();\n"
"}\n");
} else {
printer->Print(variables_,
- "if ($name$_ != &$default_variable$) {\n"
- " $name$_->assign($default_variable$);\n"
+ "if ($name$_ != $default_variable$) {\n"
+ " $name$_->assign(*$default_variable$);\n"
"}\n");
}
}
@@ -208,18 +227,35 @@
void StringFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
printer->Print(variables_,
- "$name$_ = const_cast< ::std::string*>(&$default_variable$);\n");
+ "$name$_ = const_cast< ::std::string*>($default_variable$);\n");
}
void StringFieldGenerator::
GenerateDestructorCode(io::Printer* printer) const {
printer->Print(variables_,
- "if ($name$_ != &$default_variable$) {\n"
+ "if ($name$_ != $default_variable$) {\n"
" delete $name$_;\n"
"}\n");
}
void StringFieldGenerator::
+GenerateDefaultInstanceAllocator(io::Printer* printer) const {
+ if (!descriptor_->default_value_string().empty()) {
+ printer->Print(variables_,
+ "$classname$::$default_variable$ =\n"
+ " new ::std::string($default$, $default_length$);\n");
+ }
+}
+
+void StringFieldGenerator::
+GenerateShutdownCode(io::Printer* printer) const {
+ if (!descriptor_->default_value_string().empty()) {
+ printer->Print(variables_,
+ "delete $classname$::$default_variable$;\n");
+ }
+}
+
+void StringFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
@@ -273,9 +309,10 @@
// ===================================================================
RepeatedStringFieldGenerator::
-RepeatedStringFieldGenerator(const FieldDescriptor* descriptor)
+RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options)
: descriptor_(descriptor) {
- SetStringVariables(descriptor, &variables_);
+ SetStringVariables(descriptor, &variables_, options);
}
RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
@@ -328,7 +365,7 @@
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline const ::std::string& $classname$::$name$(int index) const {\n"
- " return $name$_.Get(index);\n"
+ " return $name$_.$cppget$(index);\n"
"}\n"
"inline ::std::string* $classname$::mutable_$name$(int index) {\n"
" return $name$_.Mutable(index);\n"
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.h
index 7f45107..3264134 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -46,7 +46,8 @@
class StringFieldGenerator : public FieldGenerator {
public:
- explicit StringFieldGenerator(const FieldDescriptor* descriptor);
+ explicit StringFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~StringFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -59,6 +60,8 @@
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateDestructorCode(io::Printer* printer) const;
+ void GenerateDefaultInstanceAllocator(io::Printer* printer) const;
+ void GenerateShutdownCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
@@ -73,7 +76,8 @@
class RepeatedStringFieldGenerator : public FieldGenerator {
public:
- explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor);
+ explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
+ const Options& options);
~RepeatedStringFieldGenerator();
// implements FieldGenerator ---------------------------------------
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
index 54d830f..e14a818 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -103,9 +103,19 @@
message DO {}
optional DO do = 32;
+ // Some template parameter names for extensions.
+ optional int32 field_type = 33;
+ optional bool is_packed = 34;
+
extensions 1000 to max;
}
+message TestConflictingSymbolNamesExtension {
+ extend TestConflictingSymbolNames {
+ repeated int32 repeated_int32_ext = 20423638 [packed=true];
+ }
+}
+
message DummyMessage {}
service TestConflictingMethodNames {
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 301a7ce..b5f9ab5 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -44,6 +44,8 @@
// correctly and produces the interfaces we expect, which is why this test
// is written this way.
+#include <google/protobuf/compiler/cpp/cpp_unittest.h>
+
#include <vector>
#include <google/protobuf/unittest.pb.h>
@@ -64,7 +66,7 @@
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
@@ -74,6 +76,8 @@
// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
namespace cpp_unittest {
+namespace protobuf_unittest = ::protobuf_unittest;
+
class MockErrorCollector : public MultiFileErrorCollector {
public:
@@ -174,6 +178,15 @@
EXPECT_EQ("? ? ?? ?? ??? ?\?/ ?\?-", extreme_default.cpp_trigraph());
}
+TEST(GeneratedMessageTest, ExtremeSmallIntegerDefault) {
+ const unittest::TestExtremeDefaultValues& extreme_default =
+ unittest::TestExtremeDefaultValues::default_instance();
+ EXPECT_EQ(-0x80000000, kint32min);
+ EXPECT_EQ(GOOGLE_LONGLONG(-0x8000000000000000), kint64min);
+ EXPECT_EQ(kint32min, extreme_default.really_small_int32());
+ EXPECT_EQ(kint64min, extreme_default.really_small_int64());
+}
+
TEST(GeneratedMessageTest, Accessors) {
// Set every field to a unique value then go back and check all those
// values.
@@ -202,6 +215,13 @@
EXPECT_EQ("hello", *message.mutable_default_string());
}
+TEST(GeneratedMessageTest, StringDefaults) {
+ unittest::TestExtremeDefaultValues message;
+ // Check if '\000' can be used in default string value.
+ EXPECT_EQ(string("hel\000lo", 6), message.string_with_zero());
+ EXPECT_EQ(string("wor\000ld", 6), message.bytes_with_zero());
+}
+
TEST(GeneratedMessageTest, ReleaseString) {
// Check that release_foo() starts out NULL, and gives us a value
// that we can delete after it's been set.
@@ -244,6 +264,49 @@
EXPECT_FALSE(message.has_optional_nested_message());
}
+TEST(GeneratedMessageTest, SetAllocatedString) {
+ // Check that set_allocated_foo() works for strings.
+ unittest::TestAllTypes message;
+
+ EXPECT_FALSE(message.has_optional_string());
+ const string kHello("hello");
+ message.set_optional_string(kHello);
+ EXPECT_TRUE(message.has_optional_string());
+
+ message.set_allocated_optional_string(NULL);
+ EXPECT_FALSE(message.has_optional_string());
+ EXPECT_EQ("", message.optional_string());
+
+ message.set_allocated_optional_string(new string(kHello));
+ EXPECT_TRUE(message.has_optional_string());
+ EXPECT_EQ(kHello, message.optional_string());
+}
+
+TEST(GeneratedMessageTest, SetAllocatedMessage) {
+ // Check that set_allocated_foo() can be called in all cases.
+ unittest::TestAllTypes message;
+
+ EXPECT_FALSE(message.has_optional_nested_message());
+
+ message.mutable_optional_nested_message()->set_bb(1);
+ EXPECT_TRUE(message.has_optional_nested_message());
+
+ message.set_allocated_optional_nested_message(NULL);
+ EXPECT_FALSE(message.has_optional_nested_message());
+ EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(),
+ &message.optional_nested_message());
+
+ message.mutable_optional_nested_message()->set_bb(1);
+ unittest::TestAllTypes::NestedMessage* nest =
+ message.release_optional_nested_message();
+ ASSERT_TRUE(nest != NULL);
+ EXPECT_FALSE(message.has_optional_nested_message());
+
+ message.set_allocated_optional_nested_message(nest);
+ EXPECT_TRUE(message.has_optional_nested_message());
+ EXPECT_EQ(1, message.optional_nested_message().bb());
+}
+
TEST(GeneratedMessageTest, Clear) {
// Set every field to a unique value, clear the message, then check that
// it is cleared.
@@ -695,6 +758,13 @@
message.set_friend_(5);
EXPECT_EQ(5, message.friend_());
+
+ // Instantiate extension template functions to test conflicting template
+ // parameter names.
+ typedef protobuf_unittest::TestConflictingSymbolNamesExtension ExtensionMessage;
+ message.AddExtension(ExtensionMessage::repeated_int32_ext, 123);
+ EXPECT_EQ(123,
+ message.GetExtension(ExtensionMessage::repeated_int32_ext, 0));
}
#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
@@ -869,11 +939,10 @@
EXPECT_NE(null_pointer, &unittest::ForeignEnum_MAX);
EXPECT_NE(null_pointer, &unittest::ForeignEnum_ARRAYSIZE);
- // Make sure we can use _MIN, _MAX and _ARRAYSIZE as switch cases.
+ // Make sure we can use _MIN and _MAX as switch cases.
switch (unittest::SPARSE_A) {
case unittest::TestSparseEnum_MIN:
case unittest::TestSparseEnum_MAX:
- case unittest::TestSparseEnum_ARRAYSIZE:
break;
default:
break;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.h b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.h
new file mode 100644
index 0000000..a3a1d1b
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.h
@@ -0,0 +1,51 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This header declares the namespace google::protobuf::protobuf_unittest in order to expose
+// any problems with the generated class names. We use this header to ensure
+// unittest.cc will declare the namespace prior to other includes, while obeying
+// normal include ordering.
+//
+// When generating a class name of "foo.Bar" we must ensure we prefix the class
+// name with "::", in case the namespace google::protobuf::foo exists. We intentionally
+// trigger that case here by declaring google::protobuf::protobuf_unittest.
+//
+// See ClassName in helpers.h for more details.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
+#define GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
+
+namespace google {
+namespace protobuf {
+namespace protobuf_unittest {}
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__
diff --git a/third_party/protobuf/src/google/protobuf/compiler/importer.h b/third_party/protobuf/src/google/protobuf/compiler/importer.h
index 7a2efc2..7a62fa0 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/importer.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/importer.h
@@ -280,8 +280,9 @@
string virtual_path;
string disk_path;
- inline Mapping(const string& virtual_path, const string& disk_path)
- : virtual_path(virtual_path), disk_path(disk_path) {}
+ inline Mapping(const string& virtual_path_param,
+ const string& disk_path_param)
+ : virtual_path(virtual_path_param), disk_path(disk_path_param) {}
};
vector<Mapping> mappings_;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc
new file mode 100644
index 0000000..60b4f2a
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc
@@ -0,0 +1,236 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+
+#include <vector>
+
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+string EscapeJavadoc(const string& input) {
+ string result;
+ result.reserve(input.size() * 2);
+
+ char prev = '*';
+
+ for (string::size_type i = 0; i < input.size(); i++) {
+ char c = input[i];
+ switch (c) {
+ case '*':
+ // Avoid "/*".
+ if (prev == '/') {
+ result.append("*");
+ } else {
+ result.push_back(c);
+ }
+ break;
+ case '/':
+ // Avoid "*/".
+ if (prev == '*') {
+ result.append("/");
+ } else {
+ result.push_back(c);
+ }
+ break;
+ case '@':
+ // "{@" starts Javadoc markup.
+ if (prev == '{') {
+ result.append("@");
+ } else {
+ result.push_back(c);
+ }
+ break;
+ case '<':
+ // Avoid interpretation as HTML.
+ result.append("<");
+ break;
+ case '>':
+ // Avoid interpretation as HTML.
+ result.append(">");
+ break;
+ case '&':
+ // Avoid interpretation as HTML.
+ result.append("&");
+ break;
+ case '\\':
+ // Java interprets Unicode escape sequences anywhere!
+ result.append("\");
+ break;
+ default:
+ result.push_back(c);
+ break;
+ }
+
+ prev = c;
+ }
+
+ return result;
+}
+
+static void WriteDocCommentBodyForLocation(
+ io::Printer* printer, const SourceLocation& location) {
+ string comments = location.leading_comments.empty() ?
+ location.trailing_comments : location.leading_comments;
+ if (!comments.empty()) {
+ // TODO(kenton): Ideally we should parse the comment text as Markdown and
+ // write it back as HTML, but this requires a Markdown parser. For now
+ // we just use <pre> to get fixed-width text formatting.
+
+ // If the comment itself contains block comment start or end markers,
+ // HTML-escape them so that they don't accidentally close the doc comment.
+ comments = EscapeJavadoc(comments);
+
+ vector<string> lines;
+ SplitStringAllowEmpty(comments, "\n", &lines);
+ while (!lines.empty() && lines.back().empty()) {
+ lines.pop_back();
+ }
+
+ printer->Print(
+ " *\n"
+ " * <pre>\n");
+ for (int i = 0; i < lines.size(); i++) {
+ // Most lines should start with a space. Watch out for lines that start
+ // with a /, since putting that right after the leading asterisk will
+ // close the comment.
+ if (!lines[i].empty() && lines[i][0] == '/') {
+ printer->Print(" * $line$\n", "line", lines[i]);
+ } else {
+ printer->Print(" *$line$\n", "line", lines[i]);
+ }
+ }
+ printer->Print(" * </pre>\n");
+ }
+}
+
+template <typename DescriptorType>
+static void WriteDocCommentBody(
+ io::Printer* printer, const DescriptorType* descriptor) {
+ SourceLocation location;
+ if (descriptor->GetSourceLocation(&location)) {
+ WriteDocCommentBodyForLocation(printer, location);
+ }
+}
+
+static string FirstLineOf(const string& value) {
+ string result = value;
+
+ string::size_type pos = result.find_first_of('\n');
+ if (pos != string::npos) {
+ result.erase(pos);
+ }
+
+ // If line ends in an opening brace, make it "{ ... }" so it looks nice.
+ if (!result.empty() && result[result.size() - 1] == '{') {
+ result.append(" ... }");
+ }
+
+ return result;
+}
+
+void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
+ printer->Print(
+ "/**\n"
+ " * Protobuf type {@code $fullname$}\n",
+ "fullname", EscapeJavadoc(message->full_name()));
+ WriteDocCommentBody(printer, message);
+ printer->Print(" */\n");
+}
+
+void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) {
+ // In theory we should have slightly different comments for setters, getters,
+ // etc., but in practice everyone already knows the difference between these
+ // so it's redundant information.
+
+ // We use the field declaration as the first line of the comment, e.g.:
+ // optional string foo = 5;
+ // This communicates a lot of information about the field in a small space.
+ // If the field is a group, the debug string might end with {.
+ printer->Print(
+ "/**\n"
+ " * <code>$def$</code>\n",
+ "def", EscapeJavadoc(FirstLineOf(field->DebugString())));
+ WriteDocCommentBody(printer, field);
+ printer->Print(" */\n");
+}
+
+void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) {
+ printer->Print(
+ "/**\n"
+ " * Protobuf enum {@code $fullname$}\n",
+ "fullname", EscapeJavadoc(enum_->full_name()));
+ WriteDocCommentBody(printer, enum_);
+ printer->Print(" */\n");
+}
+
+void WriteEnumValueDocComment(io::Printer* printer,
+ const EnumValueDescriptor* value) {
+ printer->Print(
+ "/**\n"
+ " * <code>$def$</code>\n",
+ "def", EscapeJavadoc(FirstLineOf(value->DebugString())));
+ WriteDocCommentBody(printer, value);
+ printer->Print(" */\n");
+}
+
+void WriteServiceDocComment(io::Printer* printer,
+ const ServiceDescriptor* service) {
+ printer->Print(
+ "/**\n"
+ " * Protobuf service {@code $fullname$}\n",
+ "fullname", EscapeJavadoc(service->full_name()));
+ WriteDocCommentBody(printer, service);
+ printer->Print(" */\n");
+}
+
+void WriteMethodDocComment(io::Printer* printer,
+ const MethodDescriptor* method) {
+ printer->Print(
+ "/**\n"
+ " * <code>$def$</code>\n",
+ "def", EscapeJavadoc(FirstLineOf(method->DebugString())));
+ WriteDocCommentBody(printer, method);
+ printer->Print(" */\n");
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.h
new file mode 100644
index 0000000..f77720b
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.h
@@ -0,0 +1,69 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
+
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+void WriteMessageDocComment(io::Printer* printer, const Descriptor* message);
+void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field);
+void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_);
+void WriteEnumValueDocComment(io::Printer* printer,
+ const EnumValueDescriptor* value);
+void WriteServiceDocComment(io::Printer* printer,
+ const ServiceDescriptor* service);
+void WriteMethodDocComment(io::Printer* printer,
+ const MethodDescriptor* method);
+
+// Exposed for testing only.
+string EscapeJavadoc(const string& input);
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc
new file mode 100644
index 0000000..28b6d8b
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc
@@ -0,0 +1,66 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+namespace {
+
+TEST(JavaDocCommentTest, Escaping) {
+ EXPECT_EQ("foo /* bar */ baz", EscapeJavadoc("foo /* bar */ baz"));
+ EXPECT_EQ("foo /*/ baz", EscapeJavadoc("foo /*/ baz"));
+ EXPECT_EQ("{@foo}", EscapeJavadoc("{@foo}"));
+ EXPECT_EQ("<i>&</i>", EscapeJavadoc("<i>&</i>"));
+ EXPECT_EQ("foo\u1234bar", EscapeJavadoc("foo\\u1234bar"));
+}
+
+// TODO(kenton): It's hard to write a robust test of the doc comments -- we
+// can only really compare the output against a golden value, which is a
+// fairly tedious and fragile testing strategy. If we want to go that route,
+// it probably makes sense to bite the bullet and write a test that compares
+// the whole generated output for unittest.proto against a golden value, with
+// a very simple script that can be run to regenerate it with the latest code.
+// This would mean that updates to the golden file would have to be included
+// in any change to the code generator, which would actually be fairly useful
+// as it allows the reviewer to see clearly how the generated code is
+// changing.
+
+} // namespace
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc
index 9d7bcab..cfed815 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc
@@ -36,6 +36,7 @@
#include <string>
#include <google/protobuf/compiler/java/java_enum.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
@@ -67,6 +68,7 @@
EnumGenerator::~EnumGenerator() {}
void EnumGenerator::Generate(io::Printer* printer) {
+ WriteEnumDocComment(printer, descriptor_);
if (HasDescriptorMethods(descriptor_)) {
printer->Print(
"public enum $classname$\n"
@@ -85,6 +87,7 @@
vars["name"] = canonical_values_[i]->name();
vars["index"] = SimpleItoa(canonical_values_[i]->index());
vars["number"] = SimpleItoa(canonical_values_[i]->number());
+ WriteEnumValueDocComment(printer, canonical_values_[i]);
printer->Print(vars,
"$name$($index$, $number$),\n");
}
@@ -100,6 +103,7 @@
vars["classname"] = descriptor_->name();
vars["name"] = aliases_[i].value->name();
vars["canonical_name"] = aliases_[i].canonical_value->name();
+ WriteEnumValueDocComment(printer, aliases_[i].value);
printer->Print(vars,
"public static final $classname$ $name$ = $canonical_name$;\n");
}
@@ -108,6 +112,7 @@
map<string, string> vars;
vars["name"] = descriptor_->value(i)->name();
vars["number"] = SimpleItoa(descriptor_->value(i)->number());
+ WriteEnumValueDocComment(printer, descriptor_->value(i));
printer->Print(vars,
"public static final int $name$_VALUE = $number$;\n");
}
@@ -187,19 +192,30 @@
printer->Print(
"}\n"
"\n"
- "private static final $classname$[] VALUES = {\n"
- " ",
+ "private static final $classname$[] VALUES = ",
"classname", descriptor_->name());
- for (int i = 0; i < descriptor_->value_count(); i++) {
- printer->Print("$name$, ",
- "name", descriptor_->value(i)->name());
+ if (CanUseEnumValues()) {
+ // If the constants we are going to output are exactly the ones we
+ // have declared in the Java enum in the same order, then we can use
+ // the values() method that the Java compiler automatically generates
+ // for every enum.
+ printer->Print("values();\n");
+ } else {
+ printer->Print(
+ "{\n"
+ " ");
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ printer->Print("$name$, ",
+ "name", descriptor_->value(i)->name());
+ }
+ printer->Print(
+ "\n"
+ "};\n");
}
printer->Print(
"\n"
- "};\n"
- "\n"
"public static $classname$ valueOf(\n"
" com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n"
" if (desc.getType() != getDescriptor()) {\n"
@@ -237,6 +253,18 @@
printer->Print("}\n\n");
}
+bool EnumGenerator::CanUseEnumValues() {
+ if (canonical_values_.size() != descriptor_->value_count()) {
+ return false;
+ }
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ if (descriptor_->value(i)->name() != canonical_values_[i]->name()) {
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.h
index 05ece1f..9a9e574 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum.h
@@ -73,6 +73,8 @@
};
vector<Alias> aliases_;
+ bool CanUseEnumValues();
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
};
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.cc
index 72caa10..ec0b067 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -36,6 +36,7 @@
#include <string>
#include <google/protobuf/compiler/java/java_enum_field.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/io/printer.h>
@@ -75,6 +76,7 @@
// For singular messages and builders, one bit is used for the hasField bit.
(*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+ (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
(*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
@@ -86,6 +88,13 @@
(*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
(*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+ // For repeated fields, one bit is used for whether the array is immutable
+ // in the parsing constructor.
+ (*variables)["get_mutable_bit_parser"] =
+ GenerateGetBitMutableLocal(builderBitIndex);
+ (*variables)["set_mutable_bit_parser"] =
+ GenerateSetBitMutableLocal(builderBitIndex);
+
(*variables)["get_has_field_bit_from_local"] =
GenerateGetBitFromLocal(builderBitIndex);
(*variables)["set_has_field_bit_to_local"] =
@@ -117,18 +126,25 @@
void EnumFieldGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "$deprecation$boolean has$capitalized_name$();\n"
+ "$deprecation$boolean has$capitalized_name$();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$$type$ get$capitalized_name$();\n");
}
void EnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private $type$ $name$_;\n"
+ "private $type$ $name$_;\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public boolean has$capitalized_name$() {\n"
" return $get_has_field_bit_message$;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
" return $name$_;\n"
"}\n");
@@ -137,13 +153,19 @@
void EnumFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private $type$ $name$_ = $default$;\n"
+ "private $type$ $name$_ = $default$;\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public boolean has$capitalized_name$() {\n"
" return $get_has_field_bit_builder$;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
" return $name$_;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
" if (value == null) {\n"
" throw new NullPointerException();\n"
@@ -152,7 +174,9 @@
" $name$_ = value;\n"
" $on_changed$\n"
" return this;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder clear$capitalized_name$() {\n"
" $clear_has_field_bit_builder$;\n"
" $name$_ = $default$;\n"
@@ -210,12 +234,17 @@
"if (value != null) {\n");
}
printer->Print(variables_,
- " $set_has_field_bit_builder$;\n"
+ " $set_has_field_bit_message$;\n"
" $name$_ = value;\n"
"}\n");
}
void EnumFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // noop for enums
+}
+
+void EnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($get_has_field_bit_message$) {\n"
@@ -273,22 +302,33 @@
void RepeatedEnumFieldGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"
- "$deprecation$int get$capitalized_name$Count();\n"
+ "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$$type$ get$capitalized_name$(int index);\n");
}
void RepeatedEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private java.util.List<$type$> $name$_;\n"
+ "private java.util.List<$type$> $name$_;\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
" return $name$_;\n" // note: unmodifiable list
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public int get$capitalized_name$Count() {\n"
" return $name$_.size();\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
" return $name$_.get(index);\n"
"}\n");
@@ -320,21 +360,29 @@
" $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
" $set_mutable_bit_builder$;\n"
" }\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
// Note: We return an unmodifiable list because otherwise the caller
// could hold on to the returned list and modify it after the message
// has been built, thus mutating the message which is supposed to be
// immutable.
"$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
" return java.util.Collections.unmodifiableList($name$_);\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public int get$capitalized_name$Count() {\n"
" return $name$_.size();\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
" return $name$_.get(index);\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder set$capitalized_name$(\n"
" int index, $type$ value) {\n"
" if (value == null) {\n"
@@ -344,7 +392,9 @@
" $name$_.set(index, value);\n"
" $on_changed$\n"
" return this;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
" if (value == null) {\n"
" throw new NullPointerException();\n"
@@ -353,14 +403,18 @@
" $name$_.add(value);\n"
" $on_changed$\n"
" return this;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder addAll$capitalized_name$(\n"
" java.lang.Iterable<? extends $type$> values) {\n"
" ensure$capitalized_name$IsMutable();\n"
" super.addAll(values, $name$_);\n"
" $on_changed$\n"
" return this;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder clear$capitalized_name$() {\n"
" $name$_ = java.util.Collections.emptyList();\n"
" $clear_mutable_bit_builder$;\n"
@@ -434,7 +488,11 @@
"if (value != null) {\n");
}
printer->Print(variables_,
- " add$capitalized_name$(value);\n"
+ " if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = new java.util.ArrayList<$type$>();\n"
+ " $set_mutable_bit_parser$;\n"
+ " }\n"
+ " $name$_.add(value);\n"
"}\n");
}
@@ -457,6 +515,14 @@
}
void RepeatedEnumFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($get_mutable_bit_parser$) {\n"
+ " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+ "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
if (descriptor_->options().packed()) {
printer->Print(variables_,
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.h
index 0cad6be..90fae63 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.h
@@ -61,6 +61,7 @@
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
@@ -96,6 +97,7 @@
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_extension.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_extension.cc
index 9b147c7..921fe65 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_extension.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_extension.cc
@@ -33,6 +33,7 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/io/printer.h>
@@ -130,6 +131,7 @@
printer->Print(vars,
"public static final int $constant_name$ = $number$;\n");
+ WriteFieldDocComment(printer, descriptor_);
if (HasDescriptorMethods(descriptor_->file())) {
// Non-lite extensions
if (descriptor_->extension_scope() == NULL) {
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_field.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_field.h
index 6097f35..4dd0efd 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_field.h
@@ -66,6 +66,7 @@
virtual void GenerateBuildingCode(io::Printer* printer) const = 0;
virtual void GenerateParsingCode(io::Printer* printer) const = 0;
virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+ virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0;
virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer)
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_file.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_file.cc
index 8968069..f43e550 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_file.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_file.cc
@@ -42,6 +42,7 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
@@ -51,18 +52,24 @@
namespace {
-// Recursively searches the given message to see if it contains any extensions.
-bool UsesExtensions(const Message& message) {
+
+// Recursively searches the given message to collect extensions.
+// Returns true if all the extensions can be recognized. The extensions will be
+// appended in to the extensions parameter.
+// Returns false when there are unknown fields, in which case the data in the
+// extensions output parameter is not reliable and should be discarded.
+bool CollectExtensions(const Message& message,
+ vector<const FieldDescriptor*>* extensions) {
const Reflection* reflection = message.GetReflection();
- // We conservatively assume that unknown fields are extensions.
- if (reflection->GetUnknownFields(message).field_count() > 0) return true;
+ // There are unknown fields that could be extensions, thus this call fails.
+ if (reflection->GetUnknownFields(message).field_count() > 0) return false;
vector<const FieldDescriptor*> fields;
reflection->ListFields(message, &fields);
for (int i = 0; i < fields.size(); i++) {
- if (fields[i]->is_extension()) return true;
+ if (fields[i]->is_extension()) extensions->push_back(fields[i]);
if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
if (fields[i]->is_repeated()) {
@@ -70,16 +77,56 @@
for (int j = 0; j < size; j++) {
const Message& sub_message =
reflection->GetRepeatedMessage(message, fields[i], j);
- if (UsesExtensions(sub_message)) return true;
+ if (!CollectExtensions(sub_message, extensions)) return false;
}
} else {
const Message& sub_message = reflection->GetMessage(message, fields[i]);
- if (UsesExtensions(sub_message)) return true;
+ if (!CollectExtensions(sub_message, extensions)) return false;
}
}
}
- return false;
+ return true;
+}
+
+// Finds all extensions in the given message and its sub-messages. If the
+// message contains unknown fields (which could be extensions), then those
+// extensions are defined in alternate_pool.
+// The message will be converted to a DynamicMessage backed by alternate_pool
+// in order to handle this case.
+void CollectExtensions(const FileDescriptorProto& file_proto,
+ const DescriptorPool& alternate_pool,
+ vector<const FieldDescriptor*>* extensions,
+ const string& file_data) {
+ if (!CollectExtensions(file_proto, extensions)) {
+ // There are unknown fields in the file_proto, which are probably
+ // extensions. We need to parse the data into a dynamic message based on the
+ // builder-pool to find out all extensions.
+ const Descriptor* file_proto_desc = alternate_pool.FindMessageTypeByName(
+ file_proto.GetDescriptor()->full_name());
+ GOOGLE_CHECK(file_proto_desc)
+ << "Find unknown fields in FileDescriptorProto when building "
+ << file_proto.name()
+ << ". It's likely that those fields are custom options, however, "
+ "descriptor.proto is not in the transitive dependencies. "
+ "This normally should not happen. Please report a bug.";
+ DynamicMessageFactory factory;
+ scoped_ptr<Message> dynamic_file_proto(
+ factory.GetPrototype(file_proto_desc)->New());
+ GOOGLE_CHECK(dynamic_file_proto.get() != NULL);
+ GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data));
+
+ // Collect the extensions again from the dynamic message. There should be no
+ // more unknown fields this time, i.e. all the custom options should be
+ // parsed as extensions now.
+ extensions->clear();
+ GOOGLE_CHECK(CollectExtensions(*dynamic_file_proto, extensions))
+ << "Find unknown fields in FileDescriptorProto when building "
+ << file_proto.name()
+ << ". It's likely that those fields are custom options, however, "
+ "those options cannot be recognized in the builder pool. "
+ "This normally should not happen. Please report a bug.";
+ }
}
@@ -306,19 +353,32 @@
.GenerateNonNestedInitializationCode(printer);
}
- if (UsesExtensions(file_proto)) {
- // Must construct an ExtensionRegistry containing all possible extensions
+ // Proto compiler builds a DescriptorPool, which holds all the descriptors to
+ // generate, when processing the ".proto" files. We call this DescriptorPool
+ // the parsed pool (a.k.a. file_->pool()).
+ //
+ // Note that when users try to extend the (.*)DescriptorProto in their
+ // ".proto" files, it does not affect the pre-built FileDescriptorProto class
+ // in proto compiler. When we put the descriptor data in the file_proto, those
+ // extensions become unknown fields.
+ //
+ // Now we need to find out all the extension value to the (.*)DescriptorProto
+ // in the file_proto message, and prepare an ExtensionRegistry to return.
+ //
+ // To find those extensions, we need to parse the data into a dynamic message
+ // of the FileDescriptor based on the builder-pool, then we can use
+ // reflections to find all extension fields
+ vector<const FieldDescriptor*> extensions;
+ CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
+
+ if (extensions.size() > 0) {
+ // Must construct an ExtensionRegistry containing all existing extensions
// and return it.
printer->Print(
"com.google.protobuf.ExtensionRegistry registry =\n"
- " com.google.protobuf.ExtensionRegistry.newInstance();\n"
- "registerAllExtensions(registry);\n");
- for (int i = 0; i < file_->dependency_count(); i++) {
- if (ShouldIncludeDependency(file_->dependency(i))) {
- printer->Print(
- "$dependency$.registerAllExtensions(registry);\n",
- "dependency", ClassName(file_->dependency(i)));
- }
+ " com.google.protobuf.ExtensionRegistry.newInstance();\n");
+ for (int i = 0; i < extensions.size(); i++) {
+ ExtensionGenerator(extensions[i]).GenerateRegistrationCode(printer);
}
printer->Print(
"return registry;\n");
@@ -375,7 +435,9 @@
printer.Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
- "\n");
+ "// source: $filename$\n"
+ "\n",
+ "filename", descriptor->file()->name());
if (!java_package.empty()) {
printer.Print(
"package $package$;\n"
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.cc
index 1b6f165..cf241b8 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.cc
@@ -177,6 +177,18 @@
return result;
}
+string ClassName(const Descriptor* descriptor) {
+ return ToJavaName(descriptor->full_name(), descriptor->file());
+}
+
+string ClassName(const EnumDescriptor* descriptor) {
+ return ToJavaName(descriptor->full_name(), descriptor->file());
+}
+
+string ClassName(const ServiceDescriptor* descriptor) {
+ return ToJavaName(descriptor->full_name(), descriptor->file());
+}
+
string ClassName(const FileDescriptor* descriptor) {
string result = FileJavaPackage(descriptor);
if (!result.empty()) result += '.';
@@ -326,14 +338,14 @@
} else {
// See comments in Internal.java for gory details.
return strings::Substitute(
- "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
- CEscape(field->default_value_string()));
+ "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
+ CEscape(field->default_value_string()));
}
}
case FieldDescriptor::CPPTYPE_ENUM:
return ClassName(field->enum_type()) + "." +
- field->default_value_enum()->name();
+ field->default_value_enum()->name();
case FieldDescriptor::CPPTYPE_MESSAGE:
return ClassName(field->message_type()) + ".getDefaultInstance()";
@@ -427,8 +439,10 @@
return GetBitFieldName(bitIndex / 32);
}
-string GenerateGetBit(int bitIndex) {
- string varName = GetBitFieldNameForBit(bitIndex);
+namespace {
+
+string GenerateGetBitInternal(const string& prefix, int bitIndex) {
+ string varName = prefix + GetBitFieldNameForBit(bitIndex);
int bitInVarIndex = bitIndex % 32;
string mask = bit_masks[bitInVarIndex];
@@ -436,8 +450,8 @@
return result;
}
-string GenerateSetBit(int bitIndex) {
- string varName = GetBitFieldNameForBit(bitIndex);
+string GenerateSetBitInternal(const string& prefix, int bitIndex) {
+ string varName = prefix + GetBitFieldNameForBit(bitIndex);
int bitInVarIndex = bitIndex % 32;
string mask = bit_masks[bitInVarIndex];
@@ -445,6 +459,16 @@
return result;
}
+} // namespace
+
+string GenerateGetBit(int bitIndex) {
+ return GenerateGetBitInternal("", bitIndex);
+}
+
+string GenerateSetBit(int bitIndex) {
+ return GenerateSetBitInternal("", bitIndex);
+}
+
string GenerateClearBit(int bitIndex) {
string varName = GetBitFieldNameForBit(bitIndex);
int bitInVarIndex = bitIndex % 32;
@@ -455,21 +479,19 @@
}
string GenerateGetBitFromLocal(int bitIndex) {
- string varName = "from_" + GetBitFieldNameForBit(bitIndex);
- int bitInVarIndex = bitIndex % 32;
-
- string mask = bit_masks[bitInVarIndex];
- string result = "((" + varName + " & " + mask + ") == " + mask + ")";
- return result;
+ return GenerateGetBitInternal("from_", bitIndex);
}
string GenerateSetBitToLocal(int bitIndex) {
- string varName = "to_" + GetBitFieldNameForBit(bitIndex);
- int bitInVarIndex = bitIndex % 32;
+ return GenerateSetBitInternal("to_", bitIndex);
+}
- string mask = bit_masks[bitInVarIndex];
- string result = varName + " |= " + mask;
- return result;
+string GenerateGetBitMutableLocal(int bitIndex) {
+ return GenerateGetBitInternal("mutable_", bitIndex);
+}
+
+string GenerateSetBitMutableLocal(int bitIndex) {
+ return GenerateSetBitInternal("mutable_", bitIndex);
}
} // namespace java
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.h
index 88efd45..3ef7149 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.h
@@ -78,19 +78,14 @@
// These return the fully-qualified class name corresponding to the given
// descriptor.
-inline string ClassName(const Descriptor* descriptor) {
- return ToJavaName(descriptor->full_name(), descriptor->file());
-}
-inline string ClassName(const EnumDescriptor* descriptor) {
- return ToJavaName(descriptor->full_name(), descriptor->file());
-}
-inline string ClassName(const ServiceDescriptor* descriptor) {
- return ToJavaName(descriptor->full_name(), descriptor->file());
-}
+string ClassName(const Descriptor* descriptor);
+string ClassName(const EnumDescriptor* descriptor);
+string ClassName(const ServiceDescriptor* descriptor);
+string ClassName(const FileDescriptor* descriptor);
+
inline string ExtensionIdentifierName(const FieldDescriptor* descriptor) {
return ToJavaName(descriptor->full_name(), descriptor->file());
}
-string ClassName(const FileDescriptor* descriptor);
// Get the unqualified name that should be used for a field's field
// number constant.
@@ -206,6 +201,18 @@
// Example: "to_bitField1_ = (to_bitField1_ | 0x04)"
string GenerateSetBitToLocal(int bitIndex);
+// Does the same as GenerateGetBit but operates on the bit field on a local
+// variable. This is used by the parsing constructor to record if a repeated
+// field is mutable.
+// Example: "((mutable_bitField1_ & 0x04) == 0x04)"
+string GenerateGetBitMutableLocal(int bitIndex);
+
+// Does the same as GenerateSetBit but operates on the bit field on a local
+// variable. This is used by the parsing constructor to record if a repeated
+// field is mutable.
+// Example: "mutable_bitField1_ = (mutable_bitField1_ | 0x04)"
+string GenerateSetBitMutableLocal(int bitIndex);
+
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc
index 4c087db..9322e24 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc
@@ -32,17 +32,23 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <google/protobuf/compiler/java/java_message.h>
+
#include <algorithm>
#include <google/protobuf/stubs/hash.h>
-#include <google/protobuf/compiler/java/java_message.h>
+#include <map>
+#include <vector>
+
+#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/compiler/java/java_enum.h>
#include <google/protobuf/compiler/java/java_extension.h>
#include <google/protobuf/compiler/java/java_helpers.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/wire_format.h>
+#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
namespace google {
namespace protobuf {
@@ -233,10 +239,8 @@
"field_name",
UnderscoresToCapitalizedCamelCase(descriptor_->field(i)));
}
- printer->Print("},\n"
- " $classname$.class,\n"
- " $classname$.Builder.class);\n",
- "classname", ClassName(descriptor_));
+ printer->Print(
+ "});\n");
}
// Generate static member initializers for all nested types.
@@ -250,7 +254,6 @@
// ===================================================================
void MessageGenerator::GenerateInterface(io::Printer* printer) {
-
if (descriptor_->extension_range_count() > 0) {
if (HasDescriptorMethods(descriptor_)) {
printer->Print(
@@ -298,6 +301,10 @@
descriptor_->containing_type() == NULL &&
descriptor_->file()->options().java_multiple_files();
+ WriteMessageDocComment(printer, descriptor_);
+
+ // The builder_type stores the super type name of the nested Builder class.
+ string builder_type;
if (descriptor_->extension_range_count() > 0) {
if (HasDescriptorMethods(descriptor_)) {
printer->Print(
@@ -306,6 +313,9 @@
" $classname$> implements $classname$OrBuilder {\n",
"static", is_own_file ? "" : "static",
"classname", descriptor_->name());
+ builder_type = strings::Substitute(
+ "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>",
+ ClassName(descriptor_));
} else {
printer->Print(
"public $static$ final class $classname$ extends\n"
@@ -313,6 +323,9 @@
" $classname$> implements $classname$OrBuilder {\n",
"static", is_own_file ? "" : "static",
"classname", descriptor_->name());
+ builder_type = strings::Substitute(
+ "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>",
+ ClassName(descriptor_));
}
} else {
if (HasDescriptorMethods(descriptor_)) {
@@ -322,6 +335,7 @@
" implements $classname$OrBuilder {\n",
"static", is_own_file ? "" : "static",
"classname", descriptor_->name());
+ builder_type = "com.google.protobuf.GeneratedMessage.Builder<?>";
} else {
printer->Print(
"public $static$ final class $classname$ extends\n"
@@ -329,17 +343,28 @@
" implements $classname$OrBuilder {\n",
"static", is_own_file ? "" : "static",
"classname", descriptor_->name());
+ builder_type = "com.google.protobuf.GeneratedMessageLite.Builder";
}
}
printer->Indent();
+ // Using builder_type, instead of Builder, prevents the Builder class from
+ // being loaded into PermGen space when the default instance is created.
+ // This optimizes the PermGen space usage for clients that do not modify
+ // messages.
printer->Print(
"// Use $classname$.newBuilder() to construct.\n"
- "private $classname$(Builder builder) {\n"
+ "private $classname$($buildertype$ builder) {\n"
" super(builder);\n"
- "}\n"
+ "$set_unknown_fields$\n"
+ "}\n",
+ "classname", descriptor_->name(),
+ "buildertype", builder_type,
+ "set_unknown_fields", HasUnknownFields(descriptor_)
+ ? " this.unknownFields = builder.getUnknownFields();" : "");
+ printer->Print(
// Used when constructing the default instance, which cannot be initialized
// immediately because it may cyclically refer to other default instances.
- "private $classname$(boolean noInit) {}\n"
+ "private $classname$(boolean noInit) {$set_default_unknown_fields$}\n"
"\n"
"private static final $classname$ defaultInstance;\n"
"public static $classname$ getDefaultInstance() {\n"
@@ -350,9 +375,28 @@
" return defaultInstance;\n"
"}\n"
"\n",
- "classname", descriptor_->name());
+ "classname", descriptor_->name(),
+ "set_default_unknown_fields", HasUnknownFields(descriptor_)
+ ? " this.unknownFields ="
+ " com.google.protobuf.UnknownFieldSet.getDefaultInstance(); " : "");
+
+ if (HasUnknownFields(descriptor_)) {
+ printer->Print(
+ "private final com.google.protobuf.UnknownFieldSet unknownFields;\n"
+ ""
+ "@java.lang.Override\n"
+ "public final com.google.protobuf.UnknownFieldSet\n"
+ " getUnknownFields() {\n"
+ " return this.unknownFields;\n"
+ "}\n");
+ }
+
+ if (HasGeneratedMethods(descriptor_)) {
+ GenerateParsingConstructor(printer);
+ }
GenerateDescriptorMethods(printer);
+ GenerateParser(printer);
// Nested types
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
@@ -567,68 +611,54 @@
"public static $classname$ parseFrom(\n"
" com.google.protobuf.ByteString data)\n"
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
- " return newBuilder().mergeFrom(data).buildParsed();\n"
+ " return PARSER.parseFrom(data);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.ByteString data,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
- " return newBuilder().mergeFrom(data, extensionRegistry)\n"
- " .buildParsed();\n"
+ " return PARSER.parseFrom(data, extensionRegistry);\n"
"}\n"
"public static $classname$ parseFrom(byte[] data)\n"
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
- " return newBuilder().mergeFrom(data).buildParsed();\n"
+ " return PARSER.parseFrom(data);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" byte[] data,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
- " return newBuilder().mergeFrom(data, extensionRegistry)\n"
- " .buildParsed();\n"
+ " return PARSER.parseFrom(data, extensionRegistry);\n"
"}\n"
"public static $classname$ parseFrom(java.io.InputStream input)\n"
" throws java.io.IOException {\n"
- " return newBuilder().mergeFrom(input).buildParsed();\n"
+ " return PARSER.parseFrom(input);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" java.io.InputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return newBuilder().mergeFrom(input, extensionRegistry)\n"
- " .buildParsed();\n"
+ " return PARSER.parseFrom(input, extensionRegistry);\n"
"}\n"
"public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
" throws java.io.IOException {\n"
- " Builder builder = newBuilder();\n"
- " if (builder.mergeDelimitedFrom(input)) {\n"
- " return builder.buildParsed();\n"
- " } else {\n"
- " return null;\n"
- " }\n"
+ " return PARSER.parseDelimitedFrom(input);\n"
"}\n"
"public static $classname$ parseDelimitedFrom(\n"
" java.io.InputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " Builder builder = newBuilder();\n"
- " if (builder.mergeDelimitedFrom(input, extensionRegistry)) {\n"
- " return builder.buildParsed();\n"
- " } else {\n"
- " return null;\n"
- " }\n"
+ " return PARSER.parseDelimitedFrom(input, extensionRegistry);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.CodedInputStream input)\n"
" throws java.io.IOException {\n"
- " return newBuilder().mergeFrom(input).buildParsed();\n"
+ " return PARSER.parseFrom(input);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.CodedInputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return newBuilder().mergeFrom(input, extensionRegistry)\n"
- " .buildParsed();\n"
+ " return PARSER.parseFrom(input, extensionRegistry);\n"
"}\n"
"\n",
"classname", ClassName(descriptor_));
@@ -669,6 +699,8 @@
"}\n");
}
+ WriteMessageDocComment(printer, descriptor_);
+
if (descriptor_->extension_range_count() > 0) {
if (HasDescriptorMethods(descriptor_)) {
printer->Print(
@@ -739,17 +771,25 @@
void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) {
if (HasDescriptorMethods(descriptor_)) {
+ if (!descriptor_->options().no_standard_descriptor_accessor()) {
+ printer->Print(
+ "public static final com.google.protobuf.Descriptors.Descriptor\n"
+ " getDescriptor() {\n"
+ " return $fileclass$.internal_$identifier$_descriptor;\n"
+ "}\n"
+ "\n",
+ "fileclass", ClassName(descriptor_->file()),
+ "identifier", UniqueFileScopeIdentifier(descriptor_));
+ }
printer->Print(
- "public static final com.google.protobuf.Descriptors.Descriptor\n"
- " getDescriptor() {\n"
- " return $fileclass$.internal_$identifier$_descriptor;\n"
- "}\n"
- "\n"
"protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
" internalGetFieldAccessorTable() {\n"
- " return $fileclass$.internal_$identifier$_fieldAccessorTable;\n"
+ " return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
+ " .ensureFieldAccessorsInitialized(\n"
+ " $classname$.class, $classname$.Builder.class);\n"
"}\n"
"\n",
+ "classname", ClassName(descriptor_),
"fileclass", ClassName(descriptor_->file()),
"identifier", UniqueFileScopeIdentifier(descriptor_));
}
@@ -768,7 +808,8 @@
if (HasDescriptorMethods(descriptor_)) {
printer->Print(
- "private Builder(BuilderParent parent) {\n"
+ "private Builder(\n"
+ " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
" super(parent);\n"
" maybeForceBuilderInitialization();\n"
"}\n",
@@ -830,10 +871,11 @@
printer->Print(
"public com.google.protobuf.Descriptors.Descriptor\n"
" getDescriptorForType() {\n"
- " return $classname$.getDescriptor();\n"
+ " return $fileclass$.internal_$identifier$_descriptor;\n"
"}\n"
"\n",
- "classname", ClassName(descriptor_));
+ "fileclass", ClassName(descriptor_->file()),
+ "identifier", UniqueFileScopeIdentifier(descriptor_));
}
printer->Print(
"public $classname$ getDefaultInstanceForType() {\n"
@@ -853,16 +895,6 @@
" return result;\n"
"}\n"
"\n"
- "private $classname$ buildParsed()\n"
- " throws com.google.protobuf.InvalidProtocolBufferException {\n"
- " $classname$ result = buildPartial();\n"
- " if (!result.isInitialized()) {\n"
- " throw newUninitializedMessageException(\n"
- " result).asInvalidProtocolBufferException();\n"
- " }\n"
- " return result;\n"
- "}\n"
- "\n"
"public $classname$ buildPartial() {\n"
" $classname$ result = new $classname$(this);\n",
"classname", ClassName(descriptor_));
@@ -969,108 +1001,25 @@
// ===================================================================
void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
- scoped_array<const FieldDescriptor*> sorted_fields(
- SortFieldsByNumber(descriptor_));
-
printer->Print(
"public Builder mergeFrom(\n"
" com.google.protobuf.CodedInputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
- " throws java.io.IOException {\n");
- printer->Indent();
-
- if (HasUnknownFields(descriptor_)) {
- printer->Print(
- "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
- " com.google.protobuf.UnknownFieldSet.newBuilder(\n"
- " this.getUnknownFields());\n");
- }
-
- printer->Print(
- "while (true) {\n");
- printer->Indent();
-
- printer->Print(
- "int tag = input.readTag();\n"
- "switch (tag) {\n");
- printer->Indent();
-
- if (HasUnknownFields(descriptor_)) {
- printer->Print(
- "case 0:\n" // zero signals EOF / limit reached
- " this.setUnknownFields(unknownFields.build());\n"
- " $on_changed$\n"
- " return this;\n"
- "default: {\n"
- " if (!parseUnknownField(input, unknownFields,\n"
- " extensionRegistry, tag)) {\n"
- " this.setUnknownFields(unknownFields.build());\n"
- " $on_changed$\n"
- " return this;\n" // it's an endgroup tag
- " }\n"
- " break;\n"
- "}\n",
- "on_changed", HasDescriptorMethods(descriptor_) ? "onChanged();" : "");
- } else {
- printer->Print(
- "case 0:\n" // zero signals EOF / limit reached
- " $on_changed$\n"
- " return this;\n"
- "default: {\n"
- " if (!parseUnknownField(input, extensionRegistry, tag)) {\n"
- " $on_changed$\n"
- " return this;\n" // it's an endgroup tag
- " }\n"
- " break;\n"
- "}\n",
- "on_changed", HasDescriptorMethods(descriptor_) ? "onChanged();" : "");
- }
-
- for (int i = 0; i < descriptor_->field_count(); i++) {
- const FieldDescriptor* field = sorted_fields[i];
- uint32 tag = WireFormatLite::MakeTag(field->number(),
- WireFormat::WireTypeForFieldType(field->type()));
-
- printer->Print(
- "case $tag$: {\n",
- "tag", SimpleItoa(tag));
- printer->Indent();
-
- field_generators_.get(field).GenerateParsingCode(printer);
-
- printer->Outdent();
- printer->Print(
- " break;\n"
- "}\n");
-
- if (field->is_packable()) {
- // To make packed = true wire compatible, we generate parsing code from a
- // packed version of this field regardless of field->options().packed().
- uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
- WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
- printer->Print(
- "case $tag$: {\n",
- "tag", SimpleItoa(packed_tag));
- printer->Indent();
-
- field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
-
- printer->Outdent();
- printer->Print(
- " break;\n"
- "}\n");
- }
- }
-
- printer->Outdent();
- printer->Outdent();
- printer->Outdent();
- printer->Print(
- " }\n" // switch (tag)
- " }\n" // while (true)
- "}\n"
-
- "\n");
+ " throws java.io.IOException {\n"
+ " $classname$ parsedMessage = null;\n"
+ " try {\n"
+ " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n"
+ " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+ " parsedMessage = ($classname$) e.getUnfinishedMessage();\n"
+ " throw e;\n"
+ " } finally {\n"
+ " if (parsedMessage != null) {\n"
+ " mergeFrom(parsedMessage);\n"
+ " }\n"
+ " }\n"
+ " return this;\n"
+ "}\n",
+ "classname", ClassName(descriptor_));
}
// ===================================================================
@@ -1232,10 +1181,19 @@
"\n");
printer->Print(
+ "private int memoizedHashCode = 0;\n");
+ printer->Print(
"@java.lang.Override\n"
"public int hashCode() {\n");
printer->Indent();
printer->Print(
+ "if (memoizedHashCode != 0) {\n");
+ printer->Indent();
+ printer->Print(
+ "return memoizedHashCode;\n");
+ printer->Outdent();
+ printer->Print(
+ "}\n"
"int hash = 41;\n"
"hash = (19 * hash) + getDescriptorForType().hashCode();\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -1260,6 +1218,7 @@
}
printer->Print(
"hash = (29 * hash) + getUnknownFields().hashCode();\n"
+ "memoizedHashCode = hash;\n"
"return hash;\n");
printer->Outdent();
printer->Print(
@@ -1281,6 +1240,195 @@
}
}
+// ===================================================================
+void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) {
+ scoped_array<const FieldDescriptor*> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+
+ printer->Print(
+ "private $classname$(\n"
+ " com.google.protobuf.CodedInputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+
+ // Initialize all fields to default.
+ printer->Print(
+ "initFields();\n");
+
+ // Use builder bits to track mutable repeated fields.
+ int totalBuilderBits = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldGenerator& field = field_generators_.get(descriptor_->field(i));
+ totalBuilderBits += field.GetNumBitsForBuilder();
+ }
+ int totalBuilderInts = (totalBuilderBits + 31) / 32;
+ for (int i = 0; i < totalBuilderInts; i++) {
+ printer->Print("int mutable_$bit_field_name$ = 0;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+
+ if (HasUnknownFields(descriptor_)) {
+ printer->Print(
+ "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
+ " com.google.protobuf.UnknownFieldSet.newBuilder();\n");
+ }
+
+ printer->Print(
+ "try {\n");
+ printer->Indent();
+
+ printer->Print(
+ "boolean done = false;\n"
+ "while (!done) {\n");
+ printer->Indent();
+
+ printer->Print(
+ "int tag = input.readTag();\n"
+ "switch (tag) {\n");
+ printer->Indent();
+
+ printer->Print(
+ "case 0:\n" // zero signals EOF / limit reached
+ " done = true;\n"
+ " break;\n"
+ "default: {\n"
+ " if (!parseUnknownField(input,$unknown_fields$\n"
+ " extensionRegistry, tag)) {\n"
+ " done = true;\n" // it's an endgroup tag
+ " }\n"
+ " break;\n"
+ "}\n",
+ "unknown_fields", HasUnknownFields(descriptor_)
+ ? " unknownFields," : "");
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = sorted_fields[i];
+ uint32 tag = WireFormatLite::MakeTag(field->number(),
+ WireFormat::WireTypeForFieldType(field->type()));
+
+ printer->Print(
+ "case $tag$: {\n",
+ "tag", SimpleItoa(tag));
+ printer->Indent();
+
+ field_generators_.get(field).GenerateParsingCode(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " break;\n"
+ "}\n");
+
+ if (field->is_packable()) {
+ // To make packed = true wire compatible, we generate parsing code from a
+ // packed version of this field regardless of field->options().packed().
+ uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+ printer->Print(
+ "case $tag$: {\n",
+ "tag", SimpleItoa(packed_tag));
+ printer->Indent();
+
+ field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " break;\n"
+ "}\n");
+ }
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n" // switch (tag)
+ "}\n"); // while (!done)
+
+ printer->Outdent();
+ printer->Print(
+ "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+ " throw e.setUnfinishedMessage(this);\n"
+ "} catch (java.io.IOException e) {\n"
+ " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+ " e.getMessage()).setUnfinishedMessage(this);\n"
+ "} finally {\n");
+ printer->Indent();
+
+ // Make repeated field list immutable.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = sorted_fields[i];
+ field_generators_.get(field).GenerateParsingDoneCode(printer);
+ }
+
+ // Make unknown fields immutable.
+ if (HasUnknownFields(descriptor_)) {
+ printer->Print(
+ "this.unknownFields = unknownFields.build();\n");
+ }
+
+ // Make extensions immutable.
+ printer->Print(
+ "makeExtensionsImmutable();\n");
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n" // finally
+ "}\n");
+}
+
+// ===================================================================
+void MessageGenerator::GenerateParser(io::Printer* printer) {
+ printer->Print(
+ "public static com.google.protobuf.Parser<$classname$> PARSER =\n"
+ " new com.google.protobuf.AbstractParser<$classname$>() {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+ printer->Print(
+ "public $classname$ parsePartialFrom(\n"
+ " com.google.protobuf.CodedInputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n",
+ "classname", descriptor_->name());
+ if (HasGeneratedMethods(descriptor_)) {
+ printer->Print(
+ " return new $classname$(input, extensionRegistry);\n",
+ "classname", descriptor_->name());
+ } else {
+ // When parsing constructor isn't generated, use builder to parse messages.
+ // Note, will fallback to use reflection based mergeFieldFrom() in
+ // AbstractMessage.Builder.
+ printer->Indent();
+ printer->Print(
+ "Builder builder = newBuilder();\n"
+ "try {\n"
+ " builder.mergeFrom(input, extensionRegistry);\n"
+ "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+ " throw e.setUnfinishedMessage(builder.buildPartial());\n"
+ "} catch (java.io.IOException e) {\n"
+ " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+ " e.getMessage()).setUnfinishedMessage(builder.buildPartial());\n"
+ "}\n"
+ "return builder.buildPartial();\n");
+ printer->Outdent();
+ }
+ printer->Print(
+ "}\n");
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "\n");
+
+ printer->Print(
+ "@java.lang.Override\n"
+ "public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
+ " return PARSER;\n"
+ "}\n"
+ "\n",
+ "classname", descriptor_->name());
+}
+
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_message.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_message.h
index 4c6fbbe..a30f020 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_message.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_message.h
@@ -95,6 +95,9 @@
UseMemoization useMemoization);
void GenerateEqualsAndHashCode(io::Printer* printer);
+ void GenerateParser(io::Printer* printer);
+ void GenerateParsingConstructor(io::Printer* printer);
+
const Descriptor* descriptor_;
FieldGeneratorMap field_generators_;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.cc
index 251945a..b0b284f 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.cc
@@ -36,6 +36,7 @@
#include <string>
#include <google/protobuf/compiler/java/java_message_field.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
@@ -73,6 +74,7 @@
// For singular messages and builders, one bit is used for the hasField bit.
(*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+ (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
(*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
@@ -84,6 +86,13 @@
(*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
(*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+ // For repeated fields, one bit is used for whether the array is immutable
+ // in the parsing constructor.
+ (*variables)["get_mutable_bit_parser"] =
+ GenerateGetBitMutableLocal(builderBitIndex);
+ (*variables)["set_mutable_bit_parser"] =
+ GenerateSetBitMutableLocal(builderBitIndex);
+
(*variables)["get_has_field_bit_from_local"] =
GenerateGetBitFromLocal(builderBitIndex);
(*variables)["set_has_field_bit_to_local"] =
@@ -120,11 +129,15 @@
// interface so that builders can choose dynamically to either return a
// message or a nested builder, so that asking for the interface doesn't
// cause a message to ever be built.
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "$deprecation$boolean has$capitalized_name$();\n"
+ "$deprecation$boolean has$capitalized_name$();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$$type$ get$capitalized_name$();\n");
if (HasNestedBuilders(descriptor_->containing_type())) {
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n");
}
@@ -133,15 +146,20 @@
void MessageFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private $type$ $name$_;\n"
+ "private $type$ $name$_;\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public boolean has$capitalized_name$() {\n"
" return $get_has_field_bit_message$;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
" return $name$_;\n"
"}\n");
if (HasNestedBuilders(descriptor_->containing_type())) {
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
" return $name$_;\n"
@@ -208,12 +226,14 @@
// field of type "Field" called "Field".
// boolean hasField()
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public boolean has$capitalized_name$() {\n"
" return $get_has_field_bit_builder$;\n"
"}\n");
// Field getField()
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public $type$ get$capitalized_name$()",
@@ -224,6 +244,7 @@
NULL);
// Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder set$capitalized_name$($type$ value)",
@@ -239,6 +260,7 @@
"return this;\n");
// Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder set$capitalized_name$(\n"
" $type$.Builder builderForValue)",
@@ -252,6 +274,7 @@
"return this;\n");
// Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder merge$capitalized_name$($type$ value)",
@@ -270,6 +293,7 @@
"return this;\n");
// Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder clear$capitalized_name$()",
@@ -282,19 +306,24 @@
"return this;\n");
if (HasNestedBuilders(descriptor_->containing_type())) {
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
" $set_has_field_bit_builder$;\n"
" $on_changed$\n"
" return get$capitalized_name$FieldBuilder().getBuilder();\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
" if ($name$Builder_ != null) {\n"
" return $name$Builder_.getMessageOrBuilder();\n"
" } else {\n"
" return $name$_;\n"
" }\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"private com.google.protobuf.SingleFieldBuilder<\n"
" $type$, $type$.Builder, $type$OrBuilder> \n"
" get$capitalized_name$FieldBuilder() {\n"
@@ -357,21 +386,32 @@
void MessageFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
- "$type$.Builder subBuilder = $type$.newBuilder();\n"
- "if (has$capitalized_name$()) {\n"
- " subBuilder.mergeFrom(get$capitalized_name$());\n"
+ "$type$.Builder subBuilder = null;\n"
+ "if ($get_has_field_bit_message$) {\n"
+ " subBuilder = $name$_.toBuilder();\n"
"}\n");
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
- "input.readGroup($number$, subBuilder, extensionRegistry);\n");
+ "$name$_ = input.readGroup($number$, $type$.PARSER,\n"
+ " extensionRegistry);\n");
} else {
printer->Print(variables_,
- "input.readMessage(subBuilder, extensionRegistry);\n");
+ "$name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n");
}
printer->Print(variables_,
- "set$capitalized_name$(subBuilder.buildPartial());\n");
+ "if (subBuilder != null) {\n"
+ " subBuilder.mergeFrom($name$_);\n"
+ " $name$_ = subBuilder.buildPartial();\n"
+ "}\n");
+ printer->Print(variables_,
+ "$set_has_field_bit_message$;\n");
+}
+
+void MessageFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // noop for messages.
}
void MessageFieldGenerator::
@@ -437,15 +477,23 @@
// interface so that builders can choose dynamically to either return a
// message or a nested builder, so that asking for the interface doesn't
// cause a message to ever be built.
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$java.util.List<$type$> \n"
- " get$capitalized_name$List();\n"
- "$deprecation$$type$ get$capitalized_name$(int index);\n"
+ " get$capitalized_name$List();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$(int index);\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$int get$capitalized_name$Count();\n");
if (HasNestedBuilders(descriptor_->containing_type())) {
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$java.util.List<? extends $type$OrBuilder> \n"
- " get$capitalized_name$OrBuilderList();\n"
+ " get$capitalized_name$OrBuilderList();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n"
" int index);\n");
}
@@ -454,20 +502,30 @@
void RepeatedMessageFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private java.util.List<$type$> $name$_;\n"
+ "private java.util.List<$type$> $name$_;\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
" return $name$_;\n" // note: unmodifiable list
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
" get$capitalized_name$OrBuilderList() {\n"
" return $name$_;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public int get$capitalized_name$Count() {\n"
" return $name$_.size();\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
" return $name$_.get(index);\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
" int index) {\n"
" return $name$_.get(index);\n"
@@ -552,6 +610,7 @@
// repeated field of type "Field" called "RepeatedField".
// List<Field> getRepeatedFieldList()
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public java.util.List<$type$> get$capitalized_name$List()",
@@ -561,6 +620,7 @@
NULL);
// int getRepeatedFieldCount()
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public int get$capitalized_name$Count()",
@@ -570,6 +630,7 @@
NULL);
// Field getRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public $type$ get$capitalized_name$(int index)",
@@ -580,6 +641,7 @@
NULL);
// Builder setRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder set$capitalized_name$(\n"
" int index, $type$ value)",
@@ -593,6 +655,7 @@
"return this;\n");
// Builder setRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder set$capitalized_name$(\n"
" int index, $type$.Builder builderForValue)",
@@ -606,6 +669,7 @@
"return this;\n");
// Builder addRepeatedField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder add$capitalized_name$($type$ value)",
@@ -622,6 +686,7 @@
"return this;\n");
// Builder addRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder add$capitalized_name$(\n"
" int index, $type$ value)",
@@ -638,6 +703,7 @@
"return this;\n");
// Builder addRepeatedField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder add$capitalized_name$(\n"
" $type$.Builder builderForValue)",
@@ -651,6 +717,7 @@
"return this;\n");
// Builder addRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder add$capitalized_name$(\n"
" int index, $type$.Builder builderForValue)",
@@ -664,6 +731,7 @@
"return this;\n");
// Builder addAllRepeatedField(Iterable<Field> values)
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder addAll$capitalized_name$(\n"
" java.lang.Iterable<? extends $type$> values)",
@@ -677,6 +745,7 @@
"return this;\n");
// Builder clearAllRepeatedField()
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder clear$capitalized_name$()",
@@ -689,6 +758,7 @@
"return this;\n");
// Builder removeRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder remove$capitalized_name$(int index)",
@@ -701,12 +771,15 @@
"return this;\n");
if (HasNestedBuilders(descriptor_->containing_type())) {
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
" int index) {\n"
" return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
" int index) {\n"
" if ($name$Builder_ == null) {\n"
@@ -714,8 +787,10 @@
" } else {\n"
" return $name$Builder_.getMessageOrBuilder(index);\n"
" }\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
" get$capitalized_name$OrBuilderList() {\n"
" if ($name$Builder_ != null) {\n"
@@ -723,17 +798,23 @@
" } else {\n"
" return java.util.Collections.unmodifiableList($name$_);\n"
" }\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
" return get$capitalized_name$FieldBuilder().addBuilder(\n"
" $type$.getDefaultInstance());\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
" int index) {\n"
" return get$capitalized_name$FieldBuilder().addBuilder(\n"
" index, $type$.getDefaultInstance());\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public java.util.List<$type$.Builder> \n"
" get$capitalized_name$BuilderList() {\n"
" return get$capitalized_name$FieldBuilder().getBuilderList();\n"
@@ -827,18 +908,27 @@
void RepeatedMessageFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
- "$type$.Builder subBuilder = $type$.newBuilder();\n");
+ "if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = new java.util.ArrayList<$type$>();\n"
+ " $set_mutable_bit_parser$;\n"
+ "}\n");
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
- "input.readGroup($number$, subBuilder, extensionRegistry);\n");
+ "$name$_.add(input.readGroup($number$, $type$.PARSER,\n"
+ " extensionRegistry));\n");
} else {
printer->Print(variables_,
- "input.readMessage(subBuilder, extensionRegistry);\n");
+ "$name$_.add(input.readMessage($type$.PARSER, extensionRegistry));\n");
}
+}
+void RepeatedMessageFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
printer->Print(variables_,
- "add$capitalized_name$(subBuilder.buildPartial());\n");
+ "if ($get_mutable_bit_parser$) {\n"
+ " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+ "}\n");
}
void RepeatedMessageFieldGenerator::
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.h
index 2efbcd9..5c8078a 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.h
@@ -61,6 +61,7 @@
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
@@ -102,6 +103,7 @@
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc
index 712e047..0140e23 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -36,6 +36,7 @@
#include <string>
#include <google/protobuf/compiler/java/java_primitive_field.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/io/printer.h>
@@ -197,6 +198,7 @@
// For singular messages and builders, one bit is used for the hasField bit.
(*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+ (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
(*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
@@ -208,6 +210,13 @@
(*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
(*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+ // For repeated fields, one bit is used for whether the array is immutable
+ // in the parsing constructor.
+ (*variables)["get_mutable_bit_parser"] =
+ GenerateGetBitMutableLocal(builderBitIndex);
+ (*variables)["set_mutable_bit_parser"] =
+ GenerateSetBitMutableLocal(builderBitIndex);
+
(*variables)["get_has_field_bit_from_local"] =
GenerateGetBitFromLocal(builderBitIndex);
(*variables)["set_has_field_bit_to_local"] =
@@ -240,19 +249,26 @@
void PrimitiveFieldGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "$deprecation$boolean has$capitalized_name$();\n"
+ "$deprecation$boolean has$capitalized_name$();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$$type$ get$capitalized_name$();\n");
}
void PrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private $field_type$ $name$_;\n"
+ "private $field_type$ $name$_;\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public boolean has$capitalized_name$() {\n"
" return $get_has_field_bit_message$;\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
" return $name$_;\n"
@@ -262,16 +278,21 @@
void PrimitiveFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private $field_type$ $name$_ $default_init$;\n"
+ "private $field_type$ $name$_ $default_init$;\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public boolean has$capitalized_name$() {\n"
" return $get_has_field_bit_builder$;\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
" return $name$_;\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
"$null_check$"
@@ -279,7 +300,10 @@
" $name$_ = value;\n"
" $on_changed$\n"
" return this;\n"
- "}\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder clear$capitalized_name$() {\n"
" $clear_has_field_bit_builder$;\n");
JavaType type = GetJavaType(descriptor_);
@@ -335,11 +359,16 @@
void PrimitiveFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
- "$set_has_field_bit_builder$;\n"
+ "$set_has_field_bit_message$;\n"
"$name$_ = input.read$capitalized_type$();\n");
}
void PrimitiveFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // noop for primitives.
+}
+
+void PrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($get_has_field_bit_message$) {\n"
@@ -468,9 +497,14 @@
void RepeatedPrimitiveFieldGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n"
- "$deprecation$int get$capitalized_name$Count();\n"
+ "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$$type$ get$capitalized_name$(int index);\n");
}
@@ -478,14 +512,20 @@
void RepeatedPrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private $field_list_type$ $name$_;\n"
+ "private $field_list_type$ $name$_;\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public java.util.List<$boxed_type$>\n"
" get$capitalized_name$List() {\n"
" return $name$_;\n" // note: unmodifiable list
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public int get$capitalized_name$Count() {\n"
" return $name$_.size();\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
" return $name$_.get(index);\n"
"}\n");
@@ -523,17 +563,24 @@
// could hold on to the returned list and modify it after the message
// has been built, thus mutating the message which is supposed to be
// immutable.
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public java.util.List<$boxed_type$>\n"
" get$capitalized_name$List() {\n"
" return java.util.Collections.unmodifiableList($name$_);\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public int get$capitalized_name$Count() {\n"
" return $name$_.size();\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
" return $name$_.get(index);\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder set$capitalized_name$(\n"
" int index, $type$ value) {\n"
"$null_check$"
@@ -541,21 +588,27 @@
" $name$_.set(index, value);\n"
" $on_changed$\n"
" return this;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
"$null_check$"
" ensure$capitalized_name$IsMutable();\n"
" $name$_.add(value);\n"
" $on_changed$\n"
" return this;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder addAll$capitalized_name$(\n"
" java.lang.Iterable<? extends $boxed_type$> values) {\n"
" ensure$capitalized_name$IsMutable();\n"
" super.addAll(values, $name$_);\n"
" $on_changed$\n"
" return this;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder clear$capitalized_name$() {\n"
" $name$_ = $empty_list$;\n"
" $clear_mutable_bit_builder$;\n"
@@ -616,7 +669,10 @@
void RepeatedPrimitiveFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
- "ensure$capitalized_name$IsMutable();\n"
+ "if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = new java.util.ArrayList<$boxed_type$>();\n"
+ " $set_mutable_bit_parser$;\n"
+ "}\n"
"$name$_.add(input.read$capitalized_type$());\n");
}
@@ -625,13 +681,25 @@
printer->Print(variables_,
"int length = input.readRawVarint32();\n"
"int limit = input.pushLimit(length);\n"
+ "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n"
+ " $name$_ = new java.util.ArrayList<$boxed_type$>();\n"
+ " $set_mutable_bit_parser$;\n"
+ "}\n"
"while (input.getBytesUntilLimit() > 0) {\n"
- " add$capitalized_name$(input.read$capitalized_type$());\n"
+ " $name$_.add(input.read$capitalized_type$());\n"
"}\n"
"input.popLimit(limit);\n");
}
void RepeatedPrimitiveFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($get_mutable_bit_parser$) {\n"
+ " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
+ "}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
if (descriptor_->options().packed()) {
printer->Print(variables_,
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.h
index 7900fac..1b5b6d9 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.h
@@ -61,6 +61,7 @@
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
@@ -96,6 +97,7 @@
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_service.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_service.cc
index 2d85b7a..bcd8035 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_service.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_service.cc
@@ -33,6 +33,7 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/java/java_service.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
@@ -50,6 +51,7 @@
void ServiceGenerator::Generate(io::Printer* printer) {
bool is_own_file = descriptor_->file()->options().java_multiple_files();
+ WriteServiceDocComment(printer, descriptor_);
printer->Print(
"public $static$ abstract class $classname$\n"
" implements com.google.protobuf.Service {\n",
@@ -163,6 +165,7 @@
void ServiceGenerator::GenerateAbstractMethods(io::Printer* printer) {
for (int i = 0; i < descriptor_->method_count(); i++) {
const MethodDescriptor* method = descriptor_->method(i);
+ WriteMethodDocComment(printer, method);
GenerateMethodSignature(printer, method, IS_ABSTRACT);
printer->Print(";\n\n");
}
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.cc b/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.cc
index 222285b..4815663 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.cc
@@ -37,6 +37,7 @@
#include <string>
#include <google/protobuf/compiler/java/java_string_field.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/io/printer.h>
@@ -85,6 +86,7 @@
// For singular messages and builders, one bit is used for the hasField bit.
(*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+ (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
(*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
(*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
@@ -96,6 +98,13 @@
(*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
(*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
+ // For repeated fields, one bit is used for whether the array is immutable
+ // in the parsing constructor.
+ (*variables)["get_mutable_bit_parser"] =
+ GenerateGetBitMutableLocal(builderBitIndex);
+ (*variables)["set_mutable_bit_parser"] =
+ GenerateSetBitMutableLocal(builderBitIndex);
+
(*variables)["get_has_field_bit_from_local"] =
GenerateGetBitFromLocal(builderBitIndex);
(*variables)["set_has_field_bit_to_local"] =
@@ -160,19 +169,29 @@
// UnmodifiableLazyStringList.
void StringFieldGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "$deprecation$boolean has$capitalized_name$();\n"
+ "$deprecation$boolean has$capitalized_name$();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$java.lang.String get$capitalized_name$();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes();\n");
}
void StringFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private java.lang.Object $name$_;\n"
+ "private java.lang.Object $name$_;\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public boolean has$capitalized_name$() {\n"
" return $get_has_field_bit_message$;\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public java.lang.String get$capitalized_name$() {\n"
" java.lang.Object ref = $name$_;\n"
@@ -182,13 +201,16 @@
" com.google.protobuf.ByteString bs = \n"
" (com.google.protobuf.ByteString) ref;\n"
" java.lang.String s = bs.toStringUtf8();\n"
- " if (com.google.protobuf.Internal.isValidUtf8(bs)) {\n"
+ " if (bs.isValidUtf8()) {\n"
" $name$_ = s;\n"
" }\n"
" return s;\n"
" }\n"
- "}\n"
- "private com.google.protobuf.ByteString get$capitalized_name$Bytes() {\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes() {\n"
" java.lang.Object ref = $name$_;\n"
" if (ref instanceof java.lang.String) {\n"
" com.google.protobuf.ByteString b = \n"
@@ -205,11 +227,14 @@
void StringFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private java.lang.Object $name$_ $default_init$;\n"
+ "private java.lang.Object $name$_ $default_init$;\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public boolean has$capitalized_name$() {\n"
" return $get_has_field_bit_builder$;\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public java.lang.String get$capitalized_name$() {\n"
" java.lang.Object ref = $name$_;\n"
@@ -223,6 +248,23 @@
" }\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes() {\n"
+ " java.lang.Object ref = $name$_;\n"
+ " if (ref instanceof String) {\n"
+ " com.google.protobuf.ByteString b = \n"
+ " com.google.protobuf.ByteString.copyFromUtf8(\n"
+ " (java.lang.String) ref);\n"
+ " $name$_ = b;\n"
+ " return b;\n"
+ " } else {\n"
+ " return (com.google.protobuf.ByteString) ref;\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public Builder set$capitalized_name$(\n"
" java.lang.String value) {\n"
@@ -231,7 +273,9 @@
" $name$_ = value;\n"
" $on_changed$\n"
" return this;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder clear$capitalized_name$() {\n"
" $clear_has_field_bit_builder$;\n");
// The default value is not a simple literal so we want to avoid executing
@@ -243,11 +287,15 @@
" return this;\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "void set$capitalized_name$(com.google.protobuf.ByteString value) {\n"
+ "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ "$null_check$"
" $set_has_field_bit_builder$;\n"
" $name$_ = value;\n"
" $on_changed$\n"
+ " return this;\n"
"}\n");
}
@@ -270,9 +318,13 @@
void StringFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
+ // Allow a slight breach of abstraction here in order to avoid forcing
+ // all string fields to Strings when copying fields from a Message.
printer->Print(variables_,
"if (other.has$capitalized_name$()) {\n"
- " set$capitalized_name$(other.get$capitalized_name$());\n"
+ " $set_has_field_bit_builder$;\n"
+ " $name$_ = other.$name$_;\n"
+ " $on_changed$\n"
"}\n");
}
@@ -288,11 +340,16 @@
void StringFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
- "$set_has_field_bit_builder$;\n"
+ "$set_has_field_bit_message$;\n"
"$name$_ = input.readBytes();\n");
}
void StringFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // noop for strings.
+}
+
+void StringFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($get_has_field_bit_message$) {\n"
@@ -353,28 +410,49 @@
void RepeatedStringFieldGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$java.util.List<java.lang.String>\n"
- " get$capitalized_name$List();\n"
- "$deprecation$int get$capitalized_name$Count();\n"
+ "get$capitalized_name$List();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$java.lang.String get$capitalized_name$(int index);\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes(int index);\n");
}
void RepeatedStringFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private com.google.protobuf.LazyStringList $name$_;\n"
+ "private com.google.protobuf.LazyStringList $name$_;\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public java.util.List<java.lang.String>\n"
" get$capitalized_name$List() {\n"
" return $name$_;\n" // note: unmodifiable list
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public int get$capitalized_name$Count() {\n"
" return $name$_.size();\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
" return $name$_.get(index);\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes(int index) {\n"
+ " return $name$_.getByteString(index);\n"
+ "}\n");
if (descriptor_->options().packed() &&
HasGeneratedMethods(descriptor_->containing_type())) {
@@ -409,17 +487,30 @@
// could hold on to the returned list and modify it after the message
// has been built, thus mutating the message which is supposed to be
// immutable.
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public java.util.List<java.lang.String>\n"
" get$capitalized_name$List() {\n"
" return java.util.Collections.unmodifiableList($name$_);\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public int get$capitalized_name$Count() {\n"
" return $name$_.size();\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
" return $name$_.get(index);\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes(int index) {\n"
+ " return $name$_.getByteString(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder set$capitalized_name$(\n"
" int index, java.lang.String value) {\n"
"$null_check$"
@@ -427,7 +518,9 @@
" $name$_.set(index, value);\n"
" $on_changed$\n"
" return this;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder add$capitalized_name$(\n"
" java.lang.String value) {\n"
"$null_check$"
@@ -435,14 +528,18 @@
" $name$_.add(value);\n"
" $on_changed$\n"
" return this;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder addAll$capitalized_name$(\n"
" java.lang.Iterable<java.lang.String> values) {\n"
" ensure$capitalized_name$IsMutable();\n"
" super.addAll(values, $name$_);\n"
" $on_changed$\n"
" return this;\n"
- "}\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
"$deprecation$public Builder clear$capitalized_name$() {\n"
" $name$_ = $empty_list$;\n"
" $clear_mutable_bit_builder$;\n"
@@ -450,11 +547,15 @@
" return this;\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "void add$capitalized_name$(com.google.protobuf.ByteString value) {\n"
+ "$deprecation$public Builder add$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ "$null_check$"
" ensure$capitalized_name$IsMutable();\n"
" $name$_.add(value);\n"
" $on_changed$\n"
+ " return this;\n"
"}\n");
}
@@ -512,7 +613,10 @@
void RepeatedStringFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
- "ensure$capitalized_name$IsMutable();\n"
+ "if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
+ " $set_mutable_bit_parser$;\n"
+ "}\n"
"$name$_.add(input.readBytes());\n");
}
@@ -521,13 +625,25 @@
printer->Print(variables_,
"int length = input.readRawVarint32();\n"
"int limit = input.pushLimit(length);\n"
+ "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n"
+ " $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
+ " $set_mutable_bit_parser$;\n"
+ "}\n"
"while (input.getBytesUntilLimit() > 0) {\n"
- " add$capitalized_name$(input.read$capitalized_type$());\n"
+ " $name$.add(input.read$capitalized_type$());\n"
"}\n"
"input.popLimit(limit);\n");
}
void RepeatedStringFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($get_mutable_bit_parser$) {\n"
+ " $name$_ = new com.google.protobuf.UnmodifiableLazyStringList($name$_);\n"
+ "}\n");
+}
+
+void RepeatedStringFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
if (descriptor_->options().packed()) {
printer->Print(variables_,
diff --git a/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.h b/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.h
index 8cb4146..4f7532f 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.h
@@ -62,6 +62,7 @@
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
@@ -96,6 +97,7 @@
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/main.cc b/third_party/protobuf/src/google/protobuf/compiler/main.cc
index d9b0c3f..1afc5d6 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/main.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/main.cc
@@ -43,7 +43,7 @@
// Proto2 C++
google::protobuf::compiler::cpp::CppGenerator cpp_generator;
- cli.RegisterGenerator("--cpp_out", &cpp_generator,
+ cli.RegisterGenerator("--cpp_out", "--cpp_opt", &cpp_generator,
"Generate C++ header and source.");
// Proto2 Java
diff --git a/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.cc b/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.cc
index 5b76af2..0e35ed1 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.cc
@@ -33,13 +33,14 @@
#include <google/protobuf/compiler/mock_code_generator.h>
#include <google/protobuf/testing/file.h>
+#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
@@ -132,6 +133,15 @@
} else if (command == "Abort") {
cerr << "Saw message type MockCodeGenerator_Abort." << endl;
abort();
+ } else if (command == "HasSourceCodeInfo") {
+ FileDescriptorProto file_descriptor_proto;
+ file->CopySourceCodeInfoTo(&file_descriptor_proto);
+ bool has_source_code_info =
+ file_descriptor_proto.has_source_code_info() &&
+ file_descriptor_proto.source_code_info().location_size() > 0;
+ cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: "
+ << has_source_code_info << "." << endl;
+ abort();
} else {
GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command;
}
diff --git a/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.h b/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.h
index 5c7942b..506fd20 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/mock_code_generator.h
@@ -59,6 +59,10 @@
// MockCodeGenerator_Exit." to stderr and then calls exit(123).
// MockCodeGenerator_Abort: Generate() prints "Saw message type
// MockCodeGenerator_Abort." to stderr and then calls abort().
+// MockCodeGenerator_HasSourceCodeInfo: Causes Generate() to abort after
+// printing "Saw message type MockCodeGenerator_HasSourceCodeInfo: FOO." to
+// stderr, where FOO is "1" if the supplied FileDescriptorProto has source
+// code info, and "0" otherwise.
class MockCodeGenerator : public CodeGenerator {
public:
MockCodeGenerator(const string& name);
diff --git a/third_party/protobuf/src/google/protobuf/compiler/parser.cc b/third_party/protobuf/src/google/protobuf/compiler/parser.cc
index 34317b1..23aa01c 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/parser.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/parser.cc
@@ -174,6 +174,20 @@
}
}
+bool Parser::ConsumeSignedInteger(int* output, const char* error) {
+ bool is_negative = false;
+ uint64 max_value = kint32max;
+ if (TryConsume("-")) {
+ is_negative = true;
+ max_value += 1;
+ }
+ uint64 value = 0;
+ DO(ConsumeInteger64(max_value, &value, error));
+ if (is_negative) value *= -1;
+ *output = value;
+ return true;
+}
+
bool Parser::ConsumeInteger64(uint64 max_value, uint64* output,
const char* error) {
if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
@@ -237,6 +251,35 @@
}
}
+bool Parser::TryConsumeEndOfDeclaration(const char* text,
+ const LocationRecorder* location) {
+ if (LookingAt(text)) {
+ string leading, trailing;
+ input_->NextWithComments(&trailing, NULL, &leading);
+
+ // Save the leading comments for next time, and recall the leading comments
+ // from last time.
+ leading.swap(upcoming_doc_comments_);
+
+ if (location != NULL) {
+ location->AttachComments(&leading, &trailing);
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool Parser::ConsumeEndOfDeclaration(const char* text,
+ const LocationRecorder* location) {
+ if (TryConsumeEndOfDeclaration(text, location)) {
+ return true;
+ } else {
+ AddError("Expected \"" + string(text) + "\".");
+ return false;
+ }
+}
+
// -------------------------------------------------------------------
void Parser::AddError(int line, int column, const string& error) {
@@ -315,6 +358,19 @@
}
}
+void Parser::LocationRecorder::AttachComments(
+ string* leading, string* trailing) const {
+ GOOGLE_CHECK(!location_->has_leading_comments());
+ GOOGLE_CHECK(!location_->has_trailing_comments());
+
+ if (!leading->empty()) {
+ location_->mutable_leading_comments()->swap(*leading);
+ }
+ if (!trailing->empty()) {
+ location_->mutable_trailing_comments()->swap(*trailing);
+ }
+}
+
// -------------------------------------------------------------------
void Parser::SkipStatement() {
@@ -322,7 +378,7 @@
if (AtEnd()) {
return;
} else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) {
- if (TryConsume(";")) {
+ if (TryConsumeEndOfDeclaration(";", NULL)) {
return;
} else if (TryConsume("{")) {
SkipRestOfBlock();
@@ -340,7 +396,7 @@
if (AtEnd()) {
return;
} else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) {
- if (TryConsume("}")) {
+ if (TryConsumeEndOfDeclaration("}", NULL)) {
return;
} else if (TryConsume("{")) {
SkipRestOfBlock();
@@ -366,7 +422,7 @@
if (LookingAtType(io::Tokenizer::TYPE_START)) {
// Advance to first token.
- input_->Next();
+ input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_);
}
{
@@ -393,7 +449,7 @@
if (LookingAt("}")) {
AddError("Unmatched \"}\".");
- input_->Next();
+ input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_);
}
}
}
@@ -411,7 +467,7 @@
io::Tokenizer::Token syntax_token = input_->current();
string syntax;
DO(ConsumeString(&syntax, "Expected syntax identifier."));
- DO(Consume(";"));
+ DO(ConsumeEndOfDeclaration(";", NULL));
syntax_identifier_ = syntax;
@@ -427,7 +483,7 @@
bool Parser::ParseTopLevelStatement(FileDescriptorProto* file,
const LocationRecorder& root_location) {
- if (TryConsume(";")) {
+ if (TryConsumeEndOfDeclaration(";", NULL)) {
// empty statement; ignore
return true;
} else if (LookingAt("message")) {
@@ -451,14 +507,16 @@
FileDescriptorProto::kMessageTypeFieldNumber,
location);
} else if (LookingAt("import")) {
- int index = file->dependency_size();
- return ParseImport(file->add_dependency(), root_location, index);
+ return ParseImport(file->mutable_dependency(),
+ file->mutable_public_dependency(),
+ file->mutable_weak_dependency(),
+ root_location);
} else if (LookingAt("package")) {
return ParsePackage(file, root_location);
} else if (LookingAt("option")) {
LocationRecorder location(root_location,
FileDescriptorProto::kOptionsFieldNumber);
- return ParseOption(file->mutable_options(), location);
+ return ParseOption(file->mutable_options(), location, OPTION_STATEMENT);
} else {
AddError("Expected top-level statement (e.g. \"message\").");
return false;
@@ -482,11 +540,45 @@
return true;
}
+namespace {
+
+const int kMaxExtensionRangeSentinel = -1;
+
+bool IsMessageSetWireFormatMessage(const DescriptorProto& message) {
+ const MessageOptions& options = message.options();
+ for (int i = 0; i < options.uninterpreted_option_size(); ++i) {
+ const UninterpretedOption& uninterpreted = options.uninterpreted_option(i);
+ if (uninterpreted.name_size() == 1 &&
+ uninterpreted.name(0).name_part() == "message_set_wire_format" &&
+ uninterpreted.identifier_value() == "true") {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Modifies any extension ranges that specified 'max' as the end of the
+// extension range, and sets them to the type-specific maximum. The actual max
+// tag number can only be determined after all options have been parsed.
+void AdjustExtensionRangesWithMaxEndNumber(DescriptorProto* message) {
+ const bool is_message_set = IsMessageSetWireFormatMessage(*message);
+ const int max_extension_number = is_message_set ?
+ kint32max :
+ FieldDescriptor::kMaxNumber + 1;
+ for (int i = 0; i < message->extension_range_size(); ++i) {
+ if (message->extension_range(i).end() == kMaxExtensionRangeSentinel) {
+ message->mutable_extension_range(i)->set_end(max_extension_number);
+ }
+ }
+}
+
+} // namespace
+
bool Parser::ParseMessageBlock(DescriptorProto* message,
const LocationRecorder& message_location) {
- DO(Consume("{"));
+ DO(ConsumeEndOfDeclaration("{", &message_location));
- while (!TryConsume("}")) {
+ while (!TryConsumeEndOfDeclaration("}", NULL)) {
if (AtEnd()) {
AddError("Reached end of input in message definition (missing '}').");
return false;
@@ -499,12 +591,15 @@
}
}
+ if (message->extension_range_size() > 0) {
+ AdjustExtensionRangesWithMaxEndNumber(message);
+ }
return true;
}
bool Parser::ParseMessageStatement(DescriptorProto* message,
const LocationRecorder& message_location) {
- if (TryConsume(";")) {
+ if (TryConsumeEndOfDeclaration(";", NULL)) {
// empty statement; ignore
return true;
} else if (LookingAt("message")) {
@@ -532,7 +627,7 @@
} else if (LookingAt("option")) {
LocationRecorder location(message_location,
DescriptorProto::kOptionsFieldNumber);
- return ParseOption(message->mutable_options(), location);
+ return ParseOption(message->mutable_options(), location, OPTION_STATEMENT);
} else {
LocationRecorder location(message_location,
DescriptorProto::kFieldFieldNumber,
@@ -647,7 +742,7 @@
return false;
}
} else {
- DO(Consume(";"));
+ DO(ConsumeEndOfDeclaration(";", &field_location));
}
return true;
@@ -669,7 +764,7 @@
// the default value is not actually an option.
DO(ParseDefaultAssignment(field, field_location));
} else {
- DO(ParseOptionAssignment(field->mutable_options(), location));
+ DO(ParseOption(field->mutable_options(), location, OPTION_ASSIGNMENT));
}
} while (TryConsume(","));
@@ -835,6 +930,8 @@
bool Parser::ParseUninterpretedBlock(string* value) {
// Note that enclosing braces are not added to *value.
+ // We do NOT use ConsumeEndOfStatement for this brace because it's delimiting
+ // an expression, not a block of statements.
DO(Consume("{"));
int brace_depth = 1;
while (!AtEnd()) {
@@ -858,8 +955,9 @@
// We don't interpret the option here. Instead we store it in an
// UninterpretedOption, to be interpreted later.
-bool Parser::ParseOptionAssignment(Message* options,
- const LocationRecorder& options_location) {
+bool Parser::ParseOption(Message* options,
+ const LocationRecorder& options_location,
+ OptionStyle style) {
// Create an entry in the uninterpreted_option field.
const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()->
FindFieldByName("uninterpreted_option");
@@ -872,6 +970,10 @@
options_location, uninterpreted_option_field->number(),
reflection->FieldSize(*options, uninterpreted_option_field));
+ if (style == OPTION_STATEMENT) {
+ DO(Consume("option"));
+ }
+
UninterpretedOption* uninterpreted_option = down_cast<UninterpretedOption*>(
options->GetReflection()->AddMessage(options,
uninterpreted_option_field));
@@ -899,82 +1001,91 @@
DO(Consume("="));
- LocationRecorder value_location(location);
- value_location.RecordLegacyLocation(
- uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_VALUE);
+ {
+ LocationRecorder value_location(location);
+ value_location.RecordLegacyLocation(
+ uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_VALUE);
- // All values are a single token, except for negative numbers, which consist
- // of a single '-' symbol, followed by a positive number.
- bool is_negative = TryConsume("-");
+ // All values are a single token, except for negative numbers, which consist
+ // of a single '-' symbol, followed by a positive number.
+ bool is_negative = TryConsume("-");
- switch (input_->current().type) {
- case io::Tokenizer::TYPE_START:
- GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read.";
- return false;
-
- case io::Tokenizer::TYPE_END:
- AddError("Unexpected end of stream while parsing option value.");
- return false;
-
- case io::Tokenizer::TYPE_IDENTIFIER: {
- value_location.AddPath(UninterpretedOption::kIdentifierValueFieldNumber);
- if (is_negative) {
- AddError("Invalid '-' symbol before identifier.");
+ switch (input_->current().type) {
+ case io::Tokenizer::TYPE_START:
+ GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read.";
return false;
- }
- string value;
- DO(ConsumeIdentifier(&value, "Expected identifier."));
- uninterpreted_option->set_identifier_value(value);
- break;
- }
- case io::Tokenizer::TYPE_INTEGER: {
- uint64 value;
- uint64 max_value =
- is_negative ? static_cast<uint64>(kint64max) + 1 : kuint64max;
- DO(ConsumeInteger64(max_value, &value, "Expected integer."));
- if (is_negative) {
+ case io::Tokenizer::TYPE_END:
+ AddError("Unexpected end of stream while parsing option value.");
+ return false;
+
+ case io::Tokenizer::TYPE_IDENTIFIER: {
value_location.AddPath(
- UninterpretedOption::kNegativeIntValueFieldNumber);
- uninterpreted_option->set_negative_int_value(-static_cast<int64>(value));
- } else {
- value_location.AddPath(
- UninterpretedOption::kPositiveIntValueFieldNumber);
- uninterpreted_option->set_positive_int_value(value);
+ UninterpretedOption::kIdentifierValueFieldNumber);
+ if (is_negative) {
+ AddError("Invalid '-' symbol before identifier.");
+ return false;
+ }
+ string value;
+ DO(ConsumeIdentifier(&value, "Expected identifier."));
+ uninterpreted_option->set_identifier_value(value);
+ break;
}
- break;
- }
- case io::Tokenizer::TYPE_FLOAT: {
- value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber);
- double value;
- DO(ConsumeNumber(&value, "Expected number."));
- uninterpreted_option->set_double_value(is_negative ? -value : value);
- break;
- }
-
- case io::Tokenizer::TYPE_STRING: {
- value_location.AddPath(UninterpretedOption::kStringValueFieldNumber);
- if (is_negative) {
- AddError("Invalid '-' symbol before string.");
- return false;
+ case io::Tokenizer::TYPE_INTEGER: {
+ uint64 value;
+ uint64 max_value =
+ is_negative ? static_cast<uint64>(kint64max) + 1 : kuint64max;
+ DO(ConsumeInteger64(max_value, &value, "Expected integer."));
+ if (is_negative) {
+ value_location.AddPath(
+ UninterpretedOption::kNegativeIntValueFieldNumber);
+ uninterpreted_option->set_negative_int_value(
+ -static_cast<int64>(value));
+ } else {
+ value_location.AddPath(
+ UninterpretedOption::kPositiveIntValueFieldNumber);
+ uninterpreted_option->set_positive_int_value(value);
+ }
+ break;
}
- string value;
- DO(ConsumeString(&value, "Expected string."));
- uninterpreted_option->set_string_value(value);
- break;
- }
- case io::Tokenizer::TYPE_SYMBOL:
- if (LookingAt("{")) {
- value_location.AddPath(UninterpretedOption::kAggregateValueFieldNumber);
- DO(ParseUninterpretedBlock(
- uninterpreted_option->mutable_aggregate_value()));
- } else {
- AddError("Expected option value.");
- return false;
+ case io::Tokenizer::TYPE_FLOAT: {
+ value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber);
+ double value;
+ DO(ConsumeNumber(&value, "Expected number."));
+ uninterpreted_option->set_double_value(is_negative ? -value : value);
+ break;
}
- break;
+
+ case io::Tokenizer::TYPE_STRING: {
+ value_location.AddPath(UninterpretedOption::kStringValueFieldNumber);
+ if (is_negative) {
+ AddError("Invalid '-' symbol before string.");
+ return false;
+ }
+ string value;
+ DO(ConsumeString(&value, "Expected string."));
+ uninterpreted_option->set_string_value(value);
+ break;
+ }
+
+ case io::Tokenizer::TYPE_SYMBOL:
+ if (LookingAt("{")) {
+ value_location.AddPath(
+ UninterpretedOption::kAggregateValueFieldNumber);
+ DO(ParseUninterpretedBlock(
+ uninterpreted_option->mutable_aggregate_value()));
+ } else {
+ AddError("Expected option value.");
+ return false;
+ }
+ break;
+ }
+ }
+
+ if (style == OPTION_STATEMENT) {
+ DO(ConsumeEndOfDeclaration(";", &location));
}
return true;
@@ -1008,7 +1119,10 @@
LocationRecorder end_location(
location, DescriptorProto::ExtensionRange::kEndFieldNumber);
if (TryConsume("max")) {
- end = FieldDescriptor::kMaxNumber;
+ // Set to the sentinel value - 1 since we increment the value below.
+ // The actual value of the end of the range should be set with
+ // AdjustExtensionRangesWithMaxEndNumber.
+ end = kMaxExtensionRangeSentinel - 1;
} else {
DO(ConsumeInteger(&end, "Expected integer."));
}
@@ -1028,7 +1142,7 @@
range->set_end(end);
} while (TryConsume(","));
- DO(Consume(";"));
+ DO(ConsumeEndOfDeclaration(";", &extensions_location));
return true;
}
@@ -1046,7 +1160,7 @@
io::Tokenizer::Token extendee_end = input_->previous();
// Parse the block.
- DO(Consume("{"));
+ DO(ConsumeEndOfDeclaration("{", &extend_location));
bool is_first = true;
@@ -1083,7 +1197,7 @@
// other statements.
SkipStatement();
}
- } while(!TryConsume("}"));
+ } while (!TryConsumeEndOfDeclaration("}", NULL));
return true;
}
@@ -1109,9 +1223,9 @@
bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type,
const LocationRecorder& enum_location) {
- DO(Consume("{"));
+ DO(ConsumeEndOfDeclaration("{", &enum_location));
- while (!TryConsume("}")) {
+ while (!TryConsumeEndOfDeclaration("}", NULL)) {
if (AtEnd()) {
AddError("Reached end of input in enum definition (missing '}').");
return false;
@@ -1129,13 +1243,14 @@
bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type,
const LocationRecorder& enum_location) {
- if (TryConsume(";")) {
+ if (TryConsumeEndOfDeclaration(";", NULL)) {
// empty statement; ignore
return true;
} else if (LookingAt("option")) {
LocationRecorder location(enum_location,
EnumDescriptorProto::kOptionsFieldNumber);
- return ParseOption(enum_type->mutable_options(), location);
+ return ParseOption(enum_type->mutable_options(), location,
+ OPTION_STATEMENT);
} else {
LocationRecorder location(enum_location,
EnumDescriptorProto::kValueFieldNumber, enum_type->value_size());
@@ -1164,16 +1279,14 @@
location.RecordLegacyLocation(
enum_value, DescriptorPool::ErrorCollector::NUMBER);
- bool is_negative = TryConsume("-");
int number;
- DO(ConsumeInteger(&number, "Expected integer."));
- if (is_negative) number *= -1;
+ DO(ConsumeSignedInteger(&number, "Expected integer."));
enum_value->set_number(number);
}
DO(ParseEnumConstantOptions(enum_value, enum_value_location));
- DO(Consume(";"));
+ DO(ConsumeEndOfDeclaration(";", &enum_value_location));
return true;
}
@@ -1189,7 +1302,7 @@
DO(Consume("["));
do {
- DO(ParseOptionAssignment(value->mutable_options(), location));
+ DO(ParseOption(value->mutable_options(), location, OPTION_ASSIGNMENT));
} while (TryConsume(","));
DO(Consume("]"));
@@ -1217,9 +1330,9 @@
bool Parser::ParseServiceBlock(ServiceDescriptorProto* service,
const LocationRecorder& service_location) {
- DO(Consume("{"));
+ DO(ConsumeEndOfDeclaration("{", &service_location));
- while (!TryConsume("}")) {
+ while (!TryConsumeEndOfDeclaration("}", NULL)) {
if (AtEnd()) {
AddError("Reached end of input in service definition (missing '}').");
return false;
@@ -1237,13 +1350,13 @@
bool Parser::ParseServiceStatement(ServiceDescriptorProto* service,
const LocationRecorder& service_location) {
- if (TryConsume(";")) {
+ if (TryConsumeEndOfDeclaration(";", NULL)) {
// empty statement; ignore
return true;
} else if (LookingAt("option")) {
LocationRecorder location(
service_location, ServiceDescriptorProto::kOptionsFieldNumber);
- return ParseOption(service->mutable_options(), location);
+ return ParseOption(service->mutable_options(), location, OPTION_STATEMENT);
} else {
LocationRecorder location(service_location,
ServiceDescriptorProto::kMethodFieldNumber, service->method_size());
@@ -1286,28 +1399,41 @@
}
DO(Consume(")"));
- if (TryConsume("{")) {
+ if (LookingAt("{")) {
// Options!
- while (!TryConsume("}")) {
- if (AtEnd()) {
- AddError("Reached end of input in method options (missing '}').");
- return false;
- }
+ DO(ParseOptions(method_location,
+ MethodDescriptorProto::kOptionsFieldNumber,
+ method->mutable_options()));
+ } else {
+ DO(ConsumeEndOfDeclaration(";", &method_location));
+ }
- if (TryConsume(";")) {
- // empty statement; ignore
- } else {
- LocationRecorder location(method_location,
- MethodDescriptorProto::kOptionsFieldNumber);
- if (!ParseOption(method->mutable_options(), location)) {
- // This statement failed to parse. Skip it, but keep looping to
- // parse other statements.
- SkipStatement();
- }
+ return true;
+}
+
+
+bool Parser::ParseOptions(const LocationRecorder& parent_location,
+ const int optionsFieldNumber,
+ Message* mutable_options) {
+ // Options!
+ ConsumeEndOfDeclaration("{", &parent_location);
+ while (!TryConsumeEndOfDeclaration("}", NULL)) {
+ if (AtEnd()) {
+ AddError("Reached end of input in method options (missing '}').");
+ return false;
+ }
+
+ if (TryConsumeEndOfDeclaration(";", NULL)) {
+ // empty statement; ignore
+ } else {
+ LocationRecorder location(parent_location,
+ optionsFieldNumber);
+ if (!ParseOption(mutable_options, location, OPTION_STATEMENT)) {
+ // This statement failed to parse. Skip it, but keep looping to
+ // parse other statements.
+ SkipStatement();
}
}
- } else {
- DO(Consume(";"));
}
return true;
@@ -1406,32 +1532,44 @@
if (!TryConsume(".")) break;
file->mutable_package()->append(".");
}
+
+ location.EndAt(input_->previous());
+
+ DO(ConsumeEndOfDeclaration(";", &location));
}
- DO(Consume(";"));
return true;
}
-bool Parser::ParseImport(string* import_filename,
- const LocationRecorder& root_location,
- int index) {
+bool Parser::ParseImport(RepeatedPtrField<string>* dependency,
+ RepeatedField<int32>* public_dependency,
+ RepeatedField<int32>* weak_dependency,
+ const LocationRecorder& root_location) {
DO(Consume("import"));
+ if (LookingAt("public")) {
+ LocationRecorder location(
+ root_location, FileDescriptorProto::kPublicDependencyFieldNumber,
+ public_dependency->size());
+ DO(Consume("public"));
+ *public_dependency->Add() = dependency->size();
+ } else if (LookingAt("weak")) {
+ LocationRecorder location(
+ root_location, FileDescriptorProto::kWeakDependencyFieldNumber,
+ weak_dependency->size());
+ DO(Consume("weak"));
+ *weak_dependency->Add() = dependency->size();
+ }
{
LocationRecorder location(root_location,
FileDescriptorProto::kDependencyFieldNumber,
- index);
- DO(ConsumeString(import_filename,
+ dependency->size());
+ DO(ConsumeString(dependency->Add(),
"Expected a string naming the file to import."));
- }
- DO(Consume(";"));
- return true;
-}
-bool Parser::ParseOption(Message* options,
- const LocationRecorder& options_location) {
- DO(Consume("option"));
- DO(ParseOptionAssignment(options, options_location));
- DO(Consume(";"));
+ location.EndAt(input_->previous());
+
+ DO(ConsumeEndOfDeclaration(";", &location));
+ }
return true;
}
diff --git a/third_party/protobuf/src/google/protobuf/compiler/parser.h b/third_party/protobuf/src/google/protobuf/compiler/parser.h
index 4cc90a2..cfd3649 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/parser.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/parser.h
@@ -116,6 +116,8 @@
}
private:
+ class LocationRecorder;
+
// =================================================================
// Error recovery helpers
@@ -164,6 +166,8 @@
bool ConsumeIdentifier(string* output, const char* error);
// Consume an integer and store its value in "output".
bool ConsumeInteger(int* output, const char* error);
+ // Consume a signed integer and store its value in "output".
+ bool ConsumeSignedInteger(int* output, const char* error);
// Consume a 64-bit integer and store its value in "output". If the value
// is greater than max_value, an error will be reported.
bool ConsumeInteger64(uint64 max_value, uint64* output, const char* error);
@@ -173,6 +177,20 @@
// Consume a string literal and store its (unescaped) value in "output".
bool ConsumeString(string* output, const char* error);
+ // Consume a token representing the end of the statement. Comments between
+ // this token and the next will be harvested for documentation. The given
+ // LocationRecorder should refer to the declaration that was just parsed;
+ // it will be populated with these comments.
+ //
+ // TODO(kenton): The LocationRecorder is const because historically locations
+ // have been passed around by const reference, for no particularly good
+ // reason. We should probably go through and change them all to mutable
+ // pointer to make this more intuitive.
+ bool TryConsumeEndOfDeclaration(const char* text,
+ const LocationRecorder* location);
+ bool ConsumeEndOfDeclaration(const char* text,
+ const LocationRecorder* location);
+
// -----------------------------------------------------------------
// Error logging helpers
@@ -227,6 +245,14 @@
void RecordLegacyLocation(const Message* descriptor,
DescriptorPool::ErrorCollector::ErrorLocation location);
+ // Attaches leading and trailing comments to the location. The two strings
+ // will be swapped into place, so after this is called *leading and
+ // *trailing will be empty.
+ //
+ // TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for
+ // why this is const.
+ void AttachComments(string* leading, string* trailing) const;
+
private:
Parser* parser_;
SourceCodeInfo::Location* location_;
@@ -265,9 +291,10 @@
const LocationRecorder& service_location);
bool ParsePackage(FileDescriptorProto* file,
const LocationRecorder& root_location);
- bool ParseImport(string* import_filename,
- const LocationRecorder& root_location,
- int index);
+ bool ParseImport(RepeatedPtrField<string>* dependency,
+ RepeatedField<int32>* public_dependency,
+ RepeatedField<int32>* weak_dependency,
+ const LocationRecorder& root_location);
bool ParseOption(Message* options,
const LocationRecorder& options_location);
@@ -329,6 +356,12 @@
bool ParseServiceMethod(MethodDescriptorProto* method,
const LocationRecorder& method_location);
+
+ // Parse options of a single method or stream.
+ bool ParseOptions(const LocationRecorder& parent_location,
+ const int optionsFieldNumber,
+ Message* mutable_options);
+
// Parse "required", "optional", or "repeated" and fill in "label"
// with the value.
bool ParseLabel(FieldDescriptorProto::Label* label);
@@ -351,11 +384,17 @@
bool ParseDefaultAssignment(FieldDescriptorProto* field,
const LocationRecorder& field_location);
+ enum OptionStyle {
+ OPTION_ASSIGNMENT, // just "name = value"
+ OPTION_STATEMENT // "option name = value;"
+ };
+
// Parse a single option name/value pair, e.g. "ctype = CORD". The name
// identifies a field of the given Message, and the value of that field
// is set to the parsed value.
- bool ParseOptionAssignment(Message* options,
- const LocationRecorder& options_location);
+ bool ParseOption(Message* options,
+ const LocationRecorder& options_location,
+ OptionStyle style);
// Parses a single part of a multipart option name. A multipart name consists
// of names separated by dots. Each name is either an identifier or a series
@@ -387,6 +426,10 @@
bool stop_after_syntax_identifier_;
string syntax_identifier_;
+ // Leading doc comments for the next declaration. These are not complete
+ // yet; use ConsumeEndOfDeclaration() to get the complete comments.
+ string upcoming_doc_comments_;
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
};
diff --git a/third_party/protobuf/src/google/protobuf/compiler/parser_unittest.cc b/third_party/protobuf/src/google/protobuf/compiler/parser_unittest.cc
index 156c0dc..c61ac60 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/parser_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/parser_unittest.cc
@@ -44,6 +44,7 @@
#include <google/protobuf/wire_format.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_custom_options.pb.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/stubs/map-util.h>
@@ -509,6 +510,31 @@
"}");
}
+TEST_F(ParseMessageTest, LargerMaxForMessageSetWireFormatMessages) {
+ // Messages using the message_set_wire_format option can accept larger
+ // extension numbers, as the numbers are not encoded as int32 field values
+ // rather than tags.
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " extensions 4 to max;\n"
+ " option message_set_wire_format = true;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " extension_range { start:4 end: 0x7fffffff }"
+ " options {\n"
+ " uninterpreted_option { \n"
+ " name {\n"
+ " name_part: \"message_set_wire_format\"\n"
+ " is_extension: false\n"
+ " }\n"
+ " identifier_value: \"true\"\n"
+ " }\n"
+ " }\n"
+ "}");
+}
+
TEST_F(ParseMessageTest, Extensions) {
ExpectParsesTo(
"extend Extendee1 { optional int32 foo = 12; }\n"
@@ -571,6 +597,10 @@
" FOO = 13;\n"
" BAR = -10;\n"
" BAZ = 500;\n"
+ " HEX_MAX = 0x7FFFFFFF;\n"
+ " HEX_MIN = -0x80000000;\n"
+ " INT_MAX = 2147483647;\n"
+ " INT_MIN = -2147483648;\n"
"}\n",
"enum_type {"
@@ -578,6 +608,10 @@
" value { name:\"FOO\" number:13 }"
" value { name:\"BAR\" number:-10 }"
" value { name:\"BAZ\" number:500 }"
+ " value { name:\"HEX_MAX\" number:2147483647 }"
+ " value { name:\"HEX_MIN\" number:-2147483648 }"
+ " value { name:\"INT_MAX\" number:2147483647 }"
+ " value { name:\"INT_MIN\" number:-2147483648 }"
"}");
}
@@ -631,7 +665,7 @@
"}");
}
-TEST_F(ParseServiceTest, Methods) {
+TEST_F(ParseServiceTest, MethodsAndStreams) {
ExpectParsesTo(
"service TestService {\n"
" rpc Foo(In1) returns (Out1);\n"
@@ -668,6 +702,20 @@
"dependency: \"baz.proto\"");
}
+TEST_F(ParseMiscTest, ParsePublicImports) {
+ ExpectParsesTo(
+ "import \"foo.proto\";\n"
+ "import public \"bar.proto\";\n"
+ "import \"baz.proto\";\n"
+ "import public \"qux.proto\";\n",
+ "dependency: \"foo.proto\""
+ "dependency: \"bar.proto\""
+ "dependency: \"baz.proto\""
+ "dependency: \"qux.proto\""
+ "public_dependency: 1 "
+ "public_dependency: 3 ");
+}
+
TEST_F(ParseMiscTest, ParsePackage) {
ExpectParsesTo(
"package foo.bar.baz;\n",
@@ -867,6 +915,20 @@
"6:36: Integer out of range.\n");
}
+TEST_F(ParseErrorTest, EnumValueOutOfRange) {
+ ExpectHasErrors(
+ "enum TestEnum {\n"
+ " HEX_TOO_BIG = 0x80000000;\n"
+ " HEX_TOO_SMALL = -0x80000001;\n"
+ " INT_TOO_BIG = 2147483648;\n"
+ " INT_TOO_SMALL = -2147483649;\n"
+ "}\n",
+ "1:19: Integer out of range.\n"
+ "2:19: Integer out of range.\n"
+ "3:19: Integer out of range.\n"
+ "4:19: Integer out of range.\n");
+}
+
TEST_F(ParseErrorTest, DefaultValueMissing) {
ExpectHasErrors(
"message TestMessage {\n"
@@ -976,6 +1038,7 @@
"1:26: Expected message type.\n");
}
+
TEST_F(ParseErrorTest, EofInMethodOptions) {
ExpectHasErrors(
"service TestService {\n"
@@ -984,6 +1047,7 @@
"1:29: Reached end of input in service definition (missing '}').\n");
}
+
TEST_F(ParseErrorTest, PrimitiveMethodInput) {
ExpectHasErrors(
"service TestService {\n"
@@ -992,6 +1056,7 @@
"1:10: Expected message type.\n");
}
+
TEST_F(ParseErrorTest, MethodOptionTypeError) {
// This used to cause an infinite loop.
ExpectHasErrors(
@@ -1002,6 +1067,7 @@
"2:45: Expected \"=\".\n");
}
+
// -------------------------------------------------------------------
// Import and package errors
@@ -1157,6 +1223,7 @@
"3:6: \"Bar\" is already defined in \"Foo\".\n");
}
+
TEST_F(ParserValidationErrorTest, MethodInputTypeError) {
ExpectHasValidationErrors(
"message Baz {}\n"
@@ -1166,6 +1233,7 @@
"2:10: \"Qux\" is not defined.\n");
}
+
TEST_F(ParserValidationErrorTest, MethodOutputTypeError) {
ExpectHasValidationErrors(
"message Baz {}\n"
@@ -1175,6 +1243,7 @@
"2:23: \"Qux\" is not defined.\n");
}
+
// ===================================================================
// Test that the output from FileDescriptor::DebugString() (and all other
// descriptor types) is parseable, and results in the same Descriptor
@@ -1236,6 +1305,11 @@
// also need to give it the same name as the original.
parsed.set_name("google/protobuf/unittest.proto");
// We need the imported dependency before we can build our parsed proto
+ const FileDescriptor* public_import =
+ protobuf_unittest_import::PublicImportMessage::descriptor()->file();
+ FileDescriptorProto public_import_proto;
+ public_import->CopyTo(&public_import_proto);
+ ASSERT_TRUE(pool_.BuildFile(public_import_proto) != NULL);
const FileDescriptor* import =
protobuf_unittest_import::ImportMessage::descriptor()->file();
FileDescriptorProto import_proto;
@@ -1258,6 +1332,45 @@
EXPECT_EQ(expected.DebugString(), parsed.DebugString());
}
+TEST_F(ParseDecriptorDebugTest, TestCustomOptions) {
+ const FileDescriptor* original_file =
+ protobuf_unittest::AggregateMessage::descriptor()->file();
+ FileDescriptorProto expected;
+ original_file->CopyTo(&expected);
+
+ string debug_string = original_file->DebugString();
+
+ // Parse the debug string
+ SetupParser(debug_string.c_str());
+ FileDescriptorProto parsed;
+ parser_->Parse(input_.get(), &parsed);
+ EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+ ASSERT_EQ("", error_collector_.text_);
+
+ // We now have a FileDescriptorProto, but to compare with the expected we
+ // need to link to a FileDecriptor, then output back to a proto. We'll
+ // also need to give it the same name as the original.
+ parsed.set_name(original_file->name());
+
+ // unittest_custom_options.proto depends on descriptor.proto.
+ const FileDescriptor* import = FileDescriptorProto::descriptor()->file();
+ FileDescriptorProto import_proto;
+ import->CopyTo(&import_proto);
+ ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL);
+ const FileDescriptor* actual = pool_.BuildFile(parsed);
+ ASSERT_TRUE(actual != NULL);
+ parsed.Clear();
+ actual->CopyTo(&parsed);
+
+ // The messages might be in different orders, making them hard to compare.
+ // So, sort the messages in the descriptor protos (including nested messages,
+ // recursively).
+ SortMessages(&expected);
+ SortMessages(&parsed);
+
+ EXPECT_EQ(expected.DebugString(), parsed.DebugString());
+}
+
// ===================================================================
// SourceCodeInfo tests.
@@ -1353,67 +1466,6 @@
}
}
-// Split some text on line breaks. The line breaks are retained in the output,
-// so each line (except the last) ends with a '\n', and the lines can be
-// concatenated to produce the original text.
-//
-// I couldn't find the proper string utility function for this. Our
-// split-on-delimiter functions don't include the delimiter in the output.
-void SplitLines(const string& text, vector<string>* lines) {
- string::size_type pos = 0;
-
- while (pos != string::npos) {
- string::size_type last_pos = pos;
- pos = text.find_first_of('\n', pos);
- if (pos != string::npos) ++pos;
- lines->push_back(text.substr(last_pos, pos - last_pos));
- }
-}
-
-// Look for the given tags in the given text and construct a span (as defined
-// by SourceCodeInfo.Location.span) from them. E.g. for text like:
-// /*a*/message /*b*/Foo/*c*/ {}/*d*/
-// There are four tags: "a", "b", "c", and "d". The constructed span starts
-// immediately after the start tag's trailing '/' and ends immediately before
-// the end tags leading '/'.
-void MakeExpectedSpan(const vector<string>& lines,
- const string& start_tag, const string& end_tag,
- RepeatedField<int>* output) {
- string start_comment = "/*" + start_tag + "*/";
- string end_comment = "/*" + end_tag + "*/";
-
- int start_line = -1;
- int start_column = -1;
- for (int i = 0; i < lines.size(); i++) {
- string::size_type pos = lines[i].find(start_comment);
- if (pos != string::npos) {
- start_line = i;
- start_column = pos + start_comment.size();
- break;
- }
- }
- ASSERT_NE(start_line, -1)
- << "Tag \"" << start_comment << "\" not found in text.";
-
- int end_line = -1;
- int end_column = -1;
- for (int i = start_line; i < lines.size(); i++) {
- string::size_type pos = lines[i].find(end_comment);
- if (pos != string::npos) {
- end_line = i;
- end_column = pos;
- break;
- }
- }
- ASSERT_NE(end_line, -1)
- << "Tag \"" << end_comment << "\" not found in text.";
-
- output->Add(start_line);
- output->Add(start_column);
- if (end_line != start_line) output->Add(end_line);
- output->Add(end_column);
-}
-
// Check if two spans are equal.
bool CompareSpans(const RepeatedField<int>& span1,
const RepeatedField<int>& span2) {
@@ -1434,8 +1486,8 @@
// Parse the given text as a .proto file and populate the spans_ map with
// all the source location spans in its SourceCodeInfo table.
bool Parse(const char* text) {
- SetupParser(text);
- SplitLines(text, &lines_);
+ ExtractMarkers(text);
+ SetupParser(text_without_markers_.c_str());
if (!parser_->Parse(input_.get(), &file_)) {
return false;
}
@@ -1470,19 +1522,38 @@
// part of the FileDescriptorProto. (If unclear, look at the actual tests;
// it should quickly become obvious.)
- bool HasSpan(const char* start_tag, const char* end_tag,
+ bool HasSpan(char start_marker, char end_marker,
const Message& descriptor_proto) {
- return HasSpan(start_tag, end_tag, descriptor_proto, NULL, -1);
+ return HasSpanWithComment(
+ start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL);
}
- bool HasSpan(const char* start_tag, const char* end_tag,
+ bool HasSpanWithComment(char start_marker, char end_marker,
+ const Message& descriptor_proto,
+ const char* expected_leading_comments,
+ const char* expected_trailing_comments) {
+ return HasSpanWithComment(
+ start_marker, end_marker, descriptor_proto, NULL, -1,
+ expected_leading_comments, expected_trailing_comments);
+ }
+
+ bool HasSpan(char start_marker, char end_marker,
const Message& descriptor_proto, const string& field_name) {
- return HasSpan(start_tag, end_tag, descriptor_proto, field_name, -1);
+ return HasSpan(start_marker, end_marker, descriptor_proto, field_name, -1);
}
- bool HasSpan(const char* start_tag, const char* end_tag,
+ bool HasSpan(char start_marker, char end_marker,
const Message& descriptor_proto, const string& field_name,
int index) {
+ return HasSpan(start_marker, end_marker, descriptor_proto,
+ field_name, index, NULL, NULL);
+ }
+
+ bool HasSpan(char start_marker, char end_marker,
+ const Message& descriptor_proto,
+ const string& field_name, int index,
+ const char* expected_leading_comments,
+ const char* expected_trailing_comments) {
const FieldDescriptor* field =
descriptor_proto.GetDescriptor()->FindFieldByName(field_name);
if (field == NULL) {
@@ -1491,29 +1562,34 @@
return false;
}
- return HasSpan(start_tag, end_tag, descriptor_proto, field, index);
+ return HasSpanWithComment(
+ start_marker, end_marker, descriptor_proto, field, index,
+ expected_leading_comments, expected_trailing_comments);
}
bool HasSpan(const Message& descriptor_proto) {
- return HasSpan(NULL, NULL, descriptor_proto, NULL, -1);
+ return HasSpanWithComment(
+ '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL);
}
bool HasSpan(const Message& descriptor_proto, const string& field_name) {
- return HasSpan(NULL, NULL, descriptor_proto, field_name, -1);
+ return HasSpan('\0', '\0', descriptor_proto, field_name, -1);
}
bool HasSpan(const Message& descriptor_proto, const string& field_name,
int index) {
- return HasSpan(NULL, NULL, descriptor_proto, field_name, index);
+ return HasSpan('\0', '\0', descriptor_proto, field_name, index);
}
- bool HasSpan(const char* start_tag, const char* end_tag,
- const Message& descriptor_proto, const FieldDescriptor* field,
- int index) {
+ bool HasSpanWithComment(char start_marker, char end_marker,
+ const Message& descriptor_proto,
+ const FieldDescriptor* field, int index,
+ const char* expected_leading_comments,
+ const char* expected_trailing_comments) {
pair<SpanMap::iterator, SpanMap::iterator> range =
spans_.equal_range(SpanKey(descriptor_proto, field, index));
- if (start_tag == NULL) {
+ if (start_marker == '\0') {
if (range.first == range.second) {
return false;
} else {
@@ -1521,11 +1597,34 @@
return true;
}
} else {
+ pair<int, int> start_pos = FindOrDie(markers_, start_marker);
+ pair<int, int> end_pos = FindOrDie(markers_, end_marker);
+
RepeatedField<int> expected_span;
- MakeExpectedSpan(lines_, start_tag, end_tag, &expected_span);
+ expected_span.Add(start_pos.first);
+ expected_span.Add(start_pos.second);
+ if (end_pos.first != start_pos.first) {
+ expected_span.Add(end_pos.first);
+ }
+ expected_span.Add(end_pos.second);
for (SpanMap::iterator iter = range.first; iter != range.second; ++iter) {
if (CompareSpans(expected_span, iter->second->span())) {
+ if (expected_leading_comments == NULL) {
+ EXPECT_FALSE(iter->second->has_leading_comments());
+ } else {
+ EXPECT_TRUE(iter->second->has_leading_comments());
+ EXPECT_EQ(expected_leading_comments,
+ iter->second->leading_comments());
+ }
+ if (expected_trailing_comments == NULL) {
+ EXPECT_FALSE(iter->second->has_trailing_comments());
+ } else {
+ EXPECT_TRUE(iter->second->has_trailing_comments());
+ EXPECT_EQ(expected_trailing_comments,
+ iter->second->trailing_comments());
+ }
+
spans_.erase(iter);
return true;
}
@@ -1542,10 +1641,11 @@
int index;
inline SpanKey() {}
- inline SpanKey(const Message& descriptor_proto,
- const FieldDescriptor* field,
- int index)
- : descriptor_proto(&descriptor_proto), field(field), index(index) {}
+ inline SpanKey(const Message& descriptor_proto_param,
+ const FieldDescriptor* field_param,
+ int index_param)
+ : descriptor_proto(&descriptor_proto_param), field(field_param),
+ index(index_param) {}
inline bool operator<(const SpanKey& other) const {
if (descriptor_proto < other.descriptor_proto) return true;
@@ -1558,32 +1658,63 @@
typedef multimap<SpanKey, const SourceCodeInfo::Location*> SpanMap;
SpanMap spans_;
- vector<string> lines_;
+ map<char, pair<int, int> > markers_;
+ string text_without_markers_;
+
+ void ExtractMarkers(const char* text) {
+ markers_.clear();
+ text_without_markers_.clear();
+ int line = 0;
+ int column = 0;
+ while (*text != '\0') {
+ if (*text == '$') {
+ ++text;
+ GOOGLE_CHECK_NE('\0', *text);
+ if (*text == '$') {
+ text_without_markers_ += '$';
+ ++column;
+ } else {
+ markers_[*text] = make_pair(line, column);
+ ++text;
+ GOOGLE_CHECK_EQ('$', *text);
+ }
+ } else if (*text == '\n') {
+ ++line;
+ column = 0;
+ text_without_markers_ += *text;
+ } else {
+ text_without_markers_ += *text;
+ ++column;
+ }
+ ++text;
+ }
+ }
};
TEST_F(SourceInfoTest, BasicFileDecls) {
EXPECT_TRUE(Parse(
- "/*a*/syntax = \"proto2\";\n"
- "package /*b*/foo.bar/*c*/;\n"
- "import /*d*/\"baz.proto\"/*e*/;\n"
- "import /*f*/\"qux.proto\"/*g*/;/*h*/\n"
+ "$a$syntax = \"proto2\";\n"
+ "package $b$foo.bar$c$;\n"
+ "import $d$\"baz.proto\"$e$;\n"
+ "import $f$\"qux.proto\"$g$;$h$\n"
+ "\n"
"// comment ignored\n"));
- EXPECT_TRUE(HasSpan("a", "h", file_));
- EXPECT_TRUE(HasSpan("b", "c", file_, "package"));
- EXPECT_TRUE(HasSpan("d", "e", file_, "dependency", 0));
- EXPECT_TRUE(HasSpan("f", "g", file_, "dependency", 1));
+ EXPECT_TRUE(HasSpan('a', 'h', file_));
+ EXPECT_TRUE(HasSpan('b', 'c', file_, "package"));
+ EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0));
+ EXPECT_TRUE(HasSpan('f', 'g', file_, "dependency", 1));
}
TEST_F(SourceInfoTest, Messages) {
EXPECT_TRUE(Parse(
- "/*a*/message /*b*/Foo/*c*/ {}/*d*/\n"
- "/*e*/message /*f*/Bar/*g*/ {}/*h*/\n"));
+ "$a$message $b$Foo$c$ {}$d$\n"
+ "$e$message $f$Bar$g$ {}$h$\n"));
- EXPECT_TRUE(HasSpan("a", "d", file_.message_type(0)));
- EXPECT_TRUE(HasSpan("b", "c", file_.message_type(0), "name"));
- EXPECT_TRUE(HasSpan("e", "h", file_.message_type(1)));
- EXPECT_TRUE(HasSpan("f", "g", file_.message_type(1), "name"));
+ EXPECT_TRUE(HasSpan('a', 'd', file_.message_type(0)));
+ EXPECT_TRUE(HasSpan('b', 'c', file_.message_type(0), "name"));
+ EXPECT_TRUE(HasSpan('e', 'h', file_.message_type(1)));
+ EXPECT_TRUE(HasSpan('f', 'g', file_.message_type(1), "name"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -1592,24 +1723,24 @@
TEST_F(SourceInfoTest, Fields) {
EXPECT_TRUE(Parse(
"message Foo {\n"
- " /*a*/optional/*b*/ /*c*/int32/*d*/ /*e*/bar/*f*/ = /*g*/1/*h*/;/*i*/\n"
- " /*j*/repeated/*k*/ /*l*/X.Y/*m*/ /*n*/baz/*o*/ = /*p*/2/*q*/;/*r*/\n"
+ " $a$optional$b$ $c$int32$d$ $e$bar$f$ = $g$1$h$;$i$\n"
+ " $j$repeated$k$ $l$X.Y$m$ $n$baz$o$ = $p$2$q$;$r$\n"
"}\n"));
const FieldDescriptorProto& field1 = file_.message_type(0).field(0);
const FieldDescriptorProto& field2 = file_.message_type(0).field(1);
- EXPECT_TRUE(HasSpan("a", "i", field1));
- EXPECT_TRUE(HasSpan("a", "b", field1, "label"));
- EXPECT_TRUE(HasSpan("c", "d", field1, "type"));
- EXPECT_TRUE(HasSpan("e", "f", field1, "name"));
- EXPECT_TRUE(HasSpan("g", "h", field1, "number"));
+ EXPECT_TRUE(HasSpan('a', 'i', field1));
+ EXPECT_TRUE(HasSpan('a', 'b', field1, "label"));
+ EXPECT_TRUE(HasSpan('c', 'd', field1, "type"));
+ EXPECT_TRUE(HasSpan('e', 'f', field1, "name"));
+ EXPECT_TRUE(HasSpan('g', 'h', field1, "number"));
- EXPECT_TRUE(HasSpan("j", "r", field2));
- EXPECT_TRUE(HasSpan("j", "k", field2, "label"));
- EXPECT_TRUE(HasSpan("l", "m", field2, "type_name"));
- EXPECT_TRUE(HasSpan("n", "o", field2, "name"));
- EXPECT_TRUE(HasSpan("p", "q", field2, "number"));
+ EXPECT_TRUE(HasSpan('j', 'r', field2));
+ EXPECT_TRUE(HasSpan('j', 'k', field2, "label"));
+ EXPECT_TRUE(HasSpan('l', 'm', field2, "type_name"));
+ EXPECT_TRUE(HasSpan('n', 'o', field2, "name"));
+ EXPECT_TRUE(HasSpan('p', 'q', field2, "number"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -1619,31 +1750,31 @@
TEST_F(SourceInfoTest, Extensions) {
EXPECT_TRUE(Parse(
- "/*a*/extend /*b*/Foo/*c*/ {\n"
- " /*d*/optional/*e*/ int32 bar = 1;/*f*/\n"
- " /*g*/repeated/*h*/ X.Y baz = 2;/*i*/\n"
- "}/*j*/\n"
- "/*k*/extend /*l*/Bar/*m*/ {\n"
- " /*n*/optional int32 qux = 1;/*o*/\n"
- "}/*p*/\n"));
+ "$a$extend $b$Foo$c$ {\n"
+ " $d$optional$e$ int32 bar = 1;$f$\n"
+ " $g$repeated$h$ X.Y baz = 2;$i$\n"
+ "}$j$\n"
+ "$k$extend $l$Bar$m$ {\n"
+ " $n$optional int32 qux = 1;$o$\n"
+ "}$p$\n"));
const FieldDescriptorProto& field1 = file_.extension(0);
const FieldDescriptorProto& field2 = file_.extension(1);
const FieldDescriptorProto& field3 = file_.extension(2);
- EXPECT_TRUE(HasSpan("a", "j", file_, "extension"));
- EXPECT_TRUE(HasSpan("k", "p", file_, "extension"));
+ EXPECT_TRUE(HasSpan('a', 'j', file_, "extension"));
+ EXPECT_TRUE(HasSpan('k', 'p', file_, "extension"));
- EXPECT_TRUE(HasSpan("d", "f", field1));
- EXPECT_TRUE(HasSpan("d", "e", field1, "label"));
- EXPECT_TRUE(HasSpan("b", "c", field1, "extendee"));
+ EXPECT_TRUE(HasSpan('d', 'f', field1));
+ EXPECT_TRUE(HasSpan('d', 'e', field1, "label"));
+ EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee"));
- EXPECT_TRUE(HasSpan("g", "i", field2));
- EXPECT_TRUE(HasSpan("g", "h", field2, "label"));
- EXPECT_TRUE(HasSpan("b", "c", field2, "extendee"));
+ EXPECT_TRUE(HasSpan('g', 'i', field2));
+ EXPECT_TRUE(HasSpan('g', 'h', field2, "label"));
+ EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee"));
- EXPECT_TRUE(HasSpan("n", "o", field3));
- EXPECT_TRUE(HasSpan("l", "m", field3, "extendee"));
+ EXPECT_TRUE(HasSpan('n', 'o', field3));
+ EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -1662,32 +1793,32 @@
TEST_F(SourceInfoTest, NestedExtensions) {
EXPECT_TRUE(Parse(
"message Message {\n"
- " /*a*/extend /*b*/Foo/*c*/ {\n"
- " /*d*/optional/*e*/ int32 bar = 1;/*f*/\n"
- " /*g*/repeated/*h*/ X.Y baz = 2;/*i*/\n"
- " }/*j*/\n"
- " /*k*/extend /*l*/Bar/*m*/ {\n"
- " /*n*/optional int32 qux = 1;/*o*/\n"
- " }/*p*/\n"
+ " $a$extend $b$Foo$c$ {\n"
+ " $d$optional$e$ int32 bar = 1;$f$\n"
+ " $g$repeated$h$ X.Y baz = 2;$i$\n"
+ " }$j$\n"
+ " $k$extend $l$Bar$m$ {\n"
+ " $n$optional int32 qux = 1;$o$\n"
+ " }$p$\n"
"}\n"));
const FieldDescriptorProto& field1 = file_.message_type(0).extension(0);
const FieldDescriptorProto& field2 = file_.message_type(0).extension(1);
const FieldDescriptorProto& field3 = file_.message_type(0).extension(2);
- EXPECT_TRUE(HasSpan("a", "j", file_.message_type(0), "extension"));
- EXPECT_TRUE(HasSpan("k", "p", file_.message_type(0), "extension"));
+ EXPECT_TRUE(HasSpan('a', 'j', file_.message_type(0), "extension"));
+ EXPECT_TRUE(HasSpan('k', 'p', file_.message_type(0), "extension"));
- EXPECT_TRUE(HasSpan("d", "f", field1));
- EXPECT_TRUE(HasSpan("d", "e", field1, "label"));
- EXPECT_TRUE(HasSpan("b", "c", field1, "extendee"));
+ EXPECT_TRUE(HasSpan('d', 'f', field1));
+ EXPECT_TRUE(HasSpan('d', 'e', field1, "label"));
+ EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee"));
- EXPECT_TRUE(HasSpan("g", "i", field2));
- EXPECT_TRUE(HasSpan("g", "h", field2, "label"));
- EXPECT_TRUE(HasSpan("b", "c", field2, "extendee"));
+ EXPECT_TRUE(HasSpan('g', 'i', field2));
+ EXPECT_TRUE(HasSpan('g', 'h', field2, "label"));
+ EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee"));
- EXPECT_TRUE(HasSpan("n", "o", field3));
- EXPECT_TRUE(HasSpan("l", "m", field3, "extendee"));
+ EXPECT_TRUE(HasSpan('n', 'o', field3));
+ EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -1708,8 +1839,8 @@
TEST_F(SourceInfoTest, ExtensionRanges) {
EXPECT_TRUE(Parse(
"message Message {\n"
- " /*a*/extensions /*b*/1/*c*/ to /*d*/4/*e*/, /*f*/6/*g*/;/*h*/\n"
- " /*i*/extensions /*j*/8/*k*/ to /*l*/max/*m*/;/*n*/\n"
+ " $a$extensions $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n"
+ " $i$extensions $j$8$k$ to $l$max$m$;$n$\n"
"}\n"));
const DescriptorProto::ExtensionRange& range1 =
@@ -1719,20 +1850,20 @@
const DescriptorProto::ExtensionRange& range3 =
file_.message_type(0).extension_range(2);
- EXPECT_TRUE(HasSpan("a", "h", file_.message_type(0), "extension_range"));
- EXPECT_TRUE(HasSpan("i", "n", file_.message_type(0), "extension_range"));
+ EXPECT_TRUE(HasSpan('a', 'h', file_.message_type(0), "extension_range"));
+ EXPECT_TRUE(HasSpan('i', 'n', file_.message_type(0), "extension_range"));
- EXPECT_TRUE(HasSpan("b", "e", range1));
- EXPECT_TRUE(HasSpan("b", "c", range1, "start"));
- EXPECT_TRUE(HasSpan("d", "e", range1, "end"));
+ EXPECT_TRUE(HasSpan('b', 'e', range1));
+ EXPECT_TRUE(HasSpan('b', 'c', range1, "start"));
+ EXPECT_TRUE(HasSpan('d', 'e', range1, "end"));
- EXPECT_TRUE(HasSpan("f", "g", range2));
- EXPECT_TRUE(HasSpan("f", "g", range2, "start"));
- EXPECT_TRUE(HasSpan("f", "g", range2, "end"));
+ EXPECT_TRUE(HasSpan('f', 'g', range2));
+ EXPECT_TRUE(HasSpan('f', 'g', range2, "start"));
+ EXPECT_TRUE(HasSpan('f', 'g', range2, "end"));
- EXPECT_TRUE(HasSpan("j", "m", range3));
- EXPECT_TRUE(HasSpan("j", "k", range3, "start"));
- EXPECT_TRUE(HasSpan("l", "m", range3, "end"));
+ EXPECT_TRUE(HasSpan('j', 'm', range3));
+ EXPECT_TRUE(HasSpan('j', 'k', range3, "start"));
+ EXPECT_TRUE(HasSpan('l', 'm', range3, "end"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -1743,22 +1874,22 @@
TEST_F(SourceInfoTest, NestedMessages) {
EXPECT_TRUE(Parse(
"message Foo {\n"
- " /*a*/message /*b*/Bar/*c*/ {\n"
- " /*d*/message /*e*/Baz/*f*/ {}/*g*/\n"
- " }/*h*/\n"
- " /*i*/message /*j*/Qux/*k*/ {}/*l*/\n"
+ " $a$message $b$Bar$c$ {\n"
+ " $d$message $e$Baz$f$ {}$g$\n"
+ " }$h$\n"
+ " $i$message $j$Qux$k$ {}$l$\n"
"}\n"));
const DescriptorProto& bar = file_.message_type(0).nested_type(0);
const DescriptorProto& baz = bar.nested_type(0);
const DescriptorProto& qux = file_.message_type(0).nested_type(1);
- EXPECT_TRUE(HasSpan("a", "h", bar));
- EXPECT_TRUE(HasSpan("b", "c", bar, "name"));
- EXPECT_TRUE(HasSpan("d", "g", baz));
- EXPECT_TRUE(HasSpan("e", "f", baz, "name"));
- EXPECT_TRUE(HasSpan("i", "l", qux));
- EXPECT_TRUE(HasSpan("j", "k", qux, "name"));
+ EXPECT_TRUE(HasSpan('a', 'h', bar));
+ EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
+ EXPECT_TRUE(HasSpan('d', 'g', baz));
+ EXPECT_TRUE(HasSpan('e', 'f', baz, "name"));
+ EXPECT_TRUE(HasSpan('i', 'l', qux));
+ EXPECT_TRUE(HasSpan('j', 'k', qux, "name"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -1770,9 +1901,9 @@
EXPECT_TRUE(Parse(
"message Foo {\n"
" message Bar {}\n"
- " /*a*/optional/*b*/ /*c*/group/*d*/ /*e*/Baz/*f*/ = /*g*/1/*h*/ {\n"
- " /*i*/message Qux {}/*j*/\n"
- " }/*k*/\n"
+ " $a$optional$b$ $c$group$d$ $e$Baz$f$ = $g$1$h$ {\n"
+ " $i$message Qux {}$j$\n"
+ " }$k$\n"
"}\n"));
const DescriptorProto& bar = file_.message_type(0).nested_type(0);
@@ -1780,16 +1911,16 @@
const DescriptorProto& qux = baz.nested_type(0);
const FieldDescriptorProto& field = file_.message_type(0).field(0);
- EXPECT_TRUE(HasSpan("a", "k", field));
- EXPECT_TRUE(HasSpan("a", "b", field, "label"));
- EXPECT_TRUE(HasSpan("c", "d", field, "type"));
- EXPECT_TRUE(HasSpan("e", "f", field, "name"));
- EXPECT_TRUE(HasSpan("e", "f", field, "type_name"));
- EXPECT_TRUE(HasSpan("g", "h", field, "number"));
+ EXPECT_TRUE(HasSpan('a', 'k', field));
+ EXPECT_TRUE(HasSpan('a', 'b', field, "label"));
+ EXPECT_TRUE(HasSpan('c', 'd', field, "type"));
+ EXPECT_TRUE(HasSpan('e', 'f', field, "name"));
+ EXPECT_TRUE(HasSpan('e', 'f', field, "type_name"));
+ EXPECT_TRUE(HasSpan('g', 'h', field, "number"));
- EXPECT_TRUE(HasSpan("a", "k", baz));
- EXPECT_TRUE(HasSpan("e", "f", baz, "name"));
- EXPECT_TRUE(HasSpan("i", "j", qux));
+ EXPECT_TRUE(HasSpan('a', 'k', baz));
+ EXPECT_TRUE(HasSpan('e', 'f', baz, "name"));
+ EXPECT_TRUE(HasSpan('i', 'j', qux));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -1802,13 +1933,13 @@
TEST_F(SourceInfoTest, Enums) {
EXPECT_TRUE(Parse(
- "/*a*/enum /*b*/Foo/*c*/ {}/*d*/\n"
- "/*e*/enum /*f*/Bar/*g*/ {}/*h*/\n"));
+ "$a$enum $b$Foo$c$ {}$d$\n"
+ "$e$enum $f$Bar$g$ {}$h$\n"));
- EXPECT_TRUE(HasSpan("a", "d", file_.enum_type(0)));
- EXPECT_TRUE(HasSpan("b", "c", file_.enum_type(0), "name"));
- EXPECT_TRUE(HasSpan("e", "h", file_.enum_type(1)));
- EXPECT_TRUE(HasSpan("f", "g", file_.enum_type(1), "name"));
+ EXPECT_TRUE(HasSpan('a', 'd', file_.enum_type(0)));
+ EXPECT_TRUE(HasSpan('b', 'c', file_.enum_type(0), "name"));
+ EXPECT_TRUE(HasSpan('e', 'h', file_.enum_type(1)));
+ EXPECT_TRUE(HasSpan('f', 'g', file_.enum_type(1), "name"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -1817,19 +1948,19 @@
TEST_F(SourceInfoTest, EnumValues) {
EXPECT_TRUE(Parse(
"enum Foo {\n"
- " /*a*/BAR/*b*/ = /*c*/1/*d*/;/*e*/\n"
- " /*f*/BAZ/*g*/ = /*h*/2/*i*/;/*j*/\n"
+ " $a$BAR$b$ = $c$1$d$;$e$\n"
+ " $f$BAZ$g$ = $h$2$i$;$j$\n"
"}"));
const EnumValueDescriptorProto& bar = file_.enum_type(0).value(0);
const EnumValueDescriptorProto& baz = file_.enum_type(0).value(1);
- EXPECT_TRUE(HasSpan("a", "e", bar));
- EXPECT_TRUE(HasSpan("a", "b", bar, "name"));
- EXPECT_TRUE(HasSpan("c", "d", bar, "number"));
- EXPECT_TRUE(HasSpan("f", "j", baz));
- EXPECT_TRUE(HasSpan("f", "g", baz, "name"));
- EXPECT_TRUE(HasSpan("h", "i", baz, "number"));
+ EXPECT_TRUE(HasSpan('a', 'e', bar));
+ EXPECT_TRUE(HasSpan('a', 'b', bar, "name"));
+ EXPECT_TRUE(HasSpan('c', 'd', bar, "number"));
+ EXPECT_TRUE(HasSpan('f', 'j', baz));
+ EXPECT_TRUE(HasSpan('f', 'g', baz, "name"));
+ EXPECT_TRUE(HasSpan('h', 'i', baz, "number"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -1840,17 +1971,17 @@
TEST_F(SourceInfoTest, NestedEnums) {
EXPECT_TRUE(Parse(
"message Foo {\n"
- " /*a*/enum /*b*/Bar/*c*/ {}/*d*/\n"
- " /*e*/enum /*f*/Baz/*g*/ {}/*h*/\n"
+ " $a$enum $b$Bar$c$ {}$d$\n"
+ " $e$enum $f$Baz$g$ {}$h$\n"
"}\n"));
const EnumDescriptorProto& bar = file_.message_type(0).enum_type(0);
const EnumDescriptorProto& baz = file_.message_type(0).enum_type(1);
- EXPECT_TRUE(HasSpan("a", "d", bar));
- EXPECT_TRUE(HasSpan("b", "c", bar, "name"));
- EXPECT_TRUE(HasSpan("e", "h", baz));
- EXPECT_TRUE(HasSpan("f", "g", baz, "name"));
+ EXPECT_TRUE(HasSpan('a', 'd', bar));
+ EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
+ EXPECT_TRUE(HasSpan('e', 'h', baz));
+ EXPECT_TRUE(HasSpan('f', 'g', baz, "name"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -1860,37 +1991,37 @@
TEST_F(SourceInfoTest, Services) {
EXPECT_TRUE(Parse(
- "/*a*/service /*b*/Foo/*c*/ {}/*d*/\n"
- "/*e*/service /*f*/Bar/*g*/ {}/*h*/\n"));
+ "$a$service $b$Foo$c$ {}$d$\n"
+ "$e$service $f$Bar$g$ {}$h$\n"));
- EXPECT_TRUE(HasSpan("a", "d", file_.service(0)));
- EXPECT_TRUE(HasSpan("b", "c", file_.service(0), "name"));
- EXPECT_TRUE(HasSpan("e", "h", file_.service(1)));
- EXPECT_TRUE(HasSpan("f", "g", file_.service(1), "name"));
+ EXPECT_TRUE(HasSpan('a', 'd', file_.service(0)));
+ EXPECT_TRUE(HasSpan('b', 'c', file_.service(0), "name"));
+ EXPECT_TRUE(HasSpan('e', 'h', file_.service(1)));
+ EXPECT_TRUE(HasSpan('f', 'g', file_.service(1), "name"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
}
-TEST_F(SourceInfoTest, Methods) {
+TEST_F(SourceInfoTest, MethodsAndStreams) {
EXPECT_TRUE(Parse(
"service Foo {\n"
- " /*a*/rpc /*b*/Bar/*c*/(/*d*/X/*e*/) returns(/*f*/Y/*g*/);/*h*/"
- " /*i*/rpc /*j*/Baz/*k*/(/*l*/Z/*m*/) returns(/*n*/W/*o*/);/*p*/"
+ " $a$rpc $b$Bar$c$($d$X$e$) returns($f$Y$g$);$h$"
+ " $i$rpc $j$Baz$k$($l$Z$m$) returns($n$W$o$);$p$"
"}"));
const MethodDescriptorProto& bar = file_.service(0).method(0);
const MethodDescriptorProto& baz = file_.service(0).method(1);
- EXPECT_TRUE(HasSpan("a", "h", bar));
- EXPECT_TRUE(HasSpan("b", "c", bar, "name"));
- EXPECT_TRUE(HasSpan("d", "e", bar, "input_type"));
- EXPECT_TRUE(HasSpan("f", "g", bar, "output_type"));
+ EXPECT_TRUE(HasSpan('a', 'h', bar));
+ EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
+ EXPECT_TRUE(HasSpan('d', 'e', bar, "input_type"));
+ EXPECT_TRUE(HasSpan('f', 'g', bar, "output_type"));
- EXPECT_TRUE(HasSpan("i", "p", baz));
- EXPECT_TRUE(HasSpan("j", "k", baz, "name"));
- EXPECT_TRUE(HasSpan("l", "m", baz, "input_type"));
- EXPECT_TRUE(HasSpan("n", "o", baz, "output_type"));
+ EXPECT_TRUE(HasSpan('i', 'p', baz));
+ EXPECT_TRUE(HasSpan('j', 'k', baz, "name"));
+ EXPECT_TRUE(HasSpan('l', 'm', baz, "input_type"));
+ EXPECT_TRUE(HasSpan('n', 'o', baz, "output_type"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -1900,13 +2031,13 @@
TEST_F(SourceInfoTest, Options) {
EXPECT_TRUE(Parse(
- "/*a*/option /*b*/foo/*c*/./*d*/(/*e*/bar.baz/*f*/)/*g*/ = "
- "/*h*/123/*i*/;/*j*/\n"
- "/*k*/option qux = /*l*/-123/*m*/;/*n*/\n"
- "/*o*/option corge = /*p*/abc/*q*/;/*r*/\n"
- "/*s*/option grault = /*t*/'blah'/*u*/;/*v*/\n"
- "/*w*/option garply = /*x*/{ yadda yadda }/*y*/;/*z*/\n"
- "/*0*/option waldo = /*1*/123.0/*2*/;/*3*/\n"
+ "$a$option $b$foo$c$.$d$($e$bar.baz$f$)$g$ = "
+ "$h$123$i$;$j$\n"
+ "$k$option qux = $l$-123$m$;$n$\n"
+ "$o$option corge = $p$abc$q$;$r$\n"
+ "$s$option grault = $t$'blah'$u$;$v$\n"
+ "$w$option garply = $x${ yadda yadda }$y$;$z$\n"
+ "$0$option waldo = $1$123.0$2$;$3$\n"
));
const UninterpretedOption& option1 = file_.options().uninterpreted_option(0);
@@ -1916,29 +2047,29 @@
const UninterpretedOption& option5 = file_.options().uninterpreted_option(4);
const UninterpretedOption& option6 = file_.options().uninterpreted_option(5);
- EXPECT_TRUE(HasSpan("a", "j", file_.options()));
- EXPECT_TRUE(HasSpan("b", "i", option1));
- EXPECT_TRUE(HasSpan("b", "g", option1, "name"));
- EXPECT_TRUE(HasSpan("b", "c", option1.name(0)));
- EXPECT_TRUE(HasSpan("b", "c", option1.name(0), "name_part"));
- EXPECT_TRUE(HasSpan("d", "g", option1.name(1)));
- EXPECT_TRUE(HasSpan("e", "f", option1.name(1), "name_part"));
- EXPECT_TRUE(HasSpan("h", "i", option1, "positive_int_value"));
+ EXPECT_TRUE(HasSpan('a', 'j', file_.options()));
+ EXPECT_TRUE(HasSpan('a', 'j', option1));
+ EXPECT_TRUE(HasSpan('b', 'g', option1, "name"));
+ EXPECT_TRUE(HasSpan('b', 'c', option1.name(0)));
+ EXPECT_TRUE(HasSpan('b', 'c', option1.name(0), "name_part"));
+ EXPECT_TRUE(HasSpan('d', 'g', option1.name(1)));
+ EXPECT_TRUE(HasSpan('e', 'f', option1.name(1), "name_part"));
+ EXPECT_TRUE(HasSpan('h', 'i', option1, "positive_int_value"));
- EXPECT_TRUE(HasSpan("k", "n", file_.options()));
- EXPECT_TRUE(HasSpan("l", "m", option2, "negative_int_value"));
+ EXPECT_TRUE(HasSpan('k', 'n', file_.options()));
+ EXPECT_TRUE(HasSpan('l', 'm', option2, "negative_int_value"));
- EXPECT_TRUE(HasSpan("o", "r", file_.options()));
- EXPECT_TRUE(HasSpan("p", "q", option3, "identifier_value"));
+ EXPECT_TRUE(HasSpan('o', 'r', file_.options()));
+ EXPECT_TRUE(HasSpan('p', 'q', option3, "identifier_value"));
- EXPECT_TRUE(HasSpan("s", "v", file_.options()));
- EXPECT_TRUE(HasSpan("t", "u", option4, "string_value"));
+ EXPECT_TRUE(HasSpan('s', 'v', file_.options()));
+ EXPECT_TRUE(HasSpan('t', 'u', option4, "string_value"));
- EXPECT_TRUE(HasSpan("w", "z", file_.options()));
- EXPECT_TRUE(HasSpan("x", "y", option5, "aggregate_value"));
+ EXPECT_TRUE(HasSpan('w', 'z', file_.options()));
+ EXPECT_TRUE(HasSpan('x', 'y', option5, "aggregate_value"));
- EXPECT_TRUE(HasSpan("0", "3", file_.options()));
- EXPECT_TRUE(HasSpan("1", "2", option6, "double_value"));
+ EXPECT_TRUE(HasSpan('0', '3', file_.options()));
+ EXPECT_TRUE(HasSpan('1', '2', option6, "double_value"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -1967,22 +2098,22 @@
TEST_F(SourceInfoTest, ScopedOptions) {
EXPECT_TRUE(Parse(
"message Foo {\n"
- " /*a*/option mopt = 1;/*b*/\n"
+ " $a$option mopt = 1;$b$\n"
"}\n"
"enum Bar {\n"
- " /*c*/option eopt = 1;/*d*/\n"
+ " $c$option eopt = 1;$d$\n"
"}\n"
"service Baz {\n"
- " /*e*/option sopt = 1;/*f*/\n"
+ " $e$option sopt = 1;$f$\n"
" rpc M(X) returns(Y) {\n"
- " /*g*/option mopt = 1;/*h*/\n"
+ " $g$option mopt = 1;$h$\n"
" }\n"
"}\n"));
- EXPECT_TRUE(HasSpan("a", "b", file_.message_type(0).options()));
- EXPECT_TRUE(HasSpan("c", "d", file_.enum_type(0).options()));
- EXPECT_TRUE(HasSpan("e", "f", file_.service(0).options()));
- EXPECT_TRUE(HasSpan("g", "h", file_.service(0).method(0).options()));
+ EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options()));
+ EXPECT_TRUE(HasSpan('c', 'd', file_.enum_type(0).options()));
+ EXPECT_TRUE(HasSpan('e', 'f', file_.service(0).options()));
+ EXPECT_TRUE(HasSpan('g', 'h', file_.service(0).method(0).options()));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -2045,8 +2176,8 @@
EXPECT_TRUE(Parse(
"message Foo {"
" optional int32 bar = 1 "
- "/*a*/[default=/*b*/123/*c*/,/*d*/opt1=123/*e*/,"
- "/*f*/opt2='hi'/*g*/]/*h*/;"
+ "$a$[default=$b$123$c$,$d$opt1=123$e$,"
+ "$f$opt2='hi'$g$]$h$;"
"}\n"
));
@@ -2054,10 +2185,10 @@
const UninterpretedOption& option1 = field.options().uninterpreted_option(0);
const UninterpretedOption& option2 = field.options().uninterpreted_option(1);
- EXPECT_TRUE(HasSpan("a", "h", field.options()));
- EXPECT_TRUE(HasSpan("b", "c", field, "default_value"));
- EXPECT_TRUE(HasSpan("d", "e", option1));
- EXPECT_TRUE(HasSpan("f", "g", option2));
+ EXPECT_TRUE(HasSpan('a', 'h', field.options()));
+ EXPECT_TRUE(HasSpan('b', 'c', field, "default_value"));
+ EXPECT_TRUE(HasSpan('d', 'e', option1));
+ EXPECT_TRUE(HasSpan('f', 'g', option2));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -2084,7 +2215,7 @@
// syntax used for enum options is understood.
EXPECT_TRUE(Parse(
"enum Foo {"
- " BAR = 1 /*a*/[/*b*/opt1=123/*c*/,/*d*/opt2='hi'/*e*/]/*f*/;"
+ " BAR = 1 $a$[$b$opt1=123$c$,$d$opt2='hi'$e$]$f$;"
"}\n"
));
@@ -2092,9 +2223,9 @@
const UninterpretedOption& option1 = value.options().uninterpreted_option(0);
const UninterpretedOption& option2 = value.options().uninterpreted_option(1);
- EXPECT_TRUE(HasSpan("a", "f", value.options()));
- EXPECT_TRUE(HasSpan("b", "c", option1));
- EXPECT_TRUE(HasSpan("d", "e", option2));
+ EXPECT_TRUE(HasSpan('a', 'f', value.options()));
+ EXPECT_TRUE(HasSpan('b', 'c', option1));
+ EXPECT_TRUE(HasSpan('d', 'e', option2));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -2113,6 +2244,127 @@
EXPECT_TRUE(HasSpan(option2, "string_value"));
}
+TEST_F(SourceInfoTest, DocComments) {
+ EXPECT_TRUE(Parse(
+ "// Foo leading\n"
+ "// line 2\n"
+ "$a$message Foo {\n"
+ " // Foo trailing\n"
+ " // line 2\n"
+ "\n"
+ " // ignored\n"
+ "\n"
+ " // bar leading\n"
+ " $b$optional int32 bar = 1;$c$\n"
+ " // bar trailing\n"
+ "}$d$\n"
+ "// ignored\n"
+ ));
+
+ const DescriptorProto& foo = file_.message_type(0);
+ const FieldDescriptorProto& bar = foo.field(0);
+
+ EXPECT_TRUE(HasSpanWithComment('a', 'd', foo,
+ " Foo leading\n line 2\n",
+ " Foo trailing\n line 2\n"));
+ EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
+ " bar leading\n",
+ " bar trailing\n"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(foo, "name"));
+ EXPECT_TRUE(HasSpan(bar, "label"));
+ EXPECT_TRUE(HasSpan(bar, "type"));
+ EXPECT_TRUE(HasSpan(bar, "name"));
+ EXPECT_TRUE(HasSpan(bar, "number"));
+}
+
+TEST_F(SourceInfoTest, DocComments2) {
+ EXPECT_TRUE(Parse(
+ "// ignored\n"
+ "syntax = \"proto2\";\n"
+ "// Foo leading\n"
+ "// line 2\n"
+ "$a$message Foo {\n"
+ " /* Foo trailing\n"
+ " * line 2 */\n"
+ " // ignored\n"
+ " /* bar leading\n"
+ " */"
+ " $b$optional int32 bar = 1;$c$ // bar trailing\n"
+ " // ignored\n"
+ "}$d$\n"
+ "// ignored\n"
+ "\n"
+ "// option leading\n"
+ "$e$option baz = 123;$f$\n"
+ "// option trailing\n"
+ ));
+
+ const DescriptorProto& foo = file_.message_type(0);
+ const FieldDescriptorProto& bar = foo.field(0);
+ const UninterpretedOption& baz = file_.options().uninterpreted_option(0);
+
+ EXPECT_TRUE(HasSpanWithComment('a', 'd', foo,
+ " Foo leading\n line 2\n",
+ " Foo trailing\n line 2 "));
+ EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
+ " bar leading\n",
+ " bar trailing\n"));
+ EXPECT_TRUE(HasSpanWithComment('e', 'f', baz,
+ " option leading\n",
+ " option trailing\n"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(foo, "name"));
+ EXPECT_TRUE(HasSpan(bar, "label"));
+ EXPECT_TRUE(HasSpan(bar, "type"));
+ EXPECT_TRUE(HasSpan(bar, "name"));
+ EXPECT_TRUE(HasSpan(bar, "number"));
+ EXPECT_TRUE(HasSpan(file_.options()));
+ EXPECT_TRUE(HasSpan(baz, "name"));
+ EXPECT_TRUE(HasSpan(baz.name(0)));
+ EXPECT_TRUE(HasSpan(baz.name(0), "name_part"));
+ EXPECT_TRUE(HasSpan(baz, "positive_int_value"));
+}
+
+TEST_F(SourceInfoTest, DocComments3) {
+ EXPECT_TRUE(Parse(
+ "$a$message Foo {\n"
+ " // bar leading\n"
+ " $b$optional int32 bar = 1 [(baz.qux) = {}];$c$\n"
+ " // bar trailing\n"
+ "}$d$\n"
+ "// ignored\n"
+ ));
+
+ const DescriptorProto& foo = file_.message_type(0);
+ const FieldDescriptorProto& bar = foo.field(0);
+
+ EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
+ " bar leading\n",
+ " bar trailing\n"));
+
+ // Ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+ EXPECT_TRUE(HasSpan(foo));
+ EXPECT_TRUE(HasSpan(foo, "name"));
+ EXPECT_TRUE(HasSpan(bar, "label"));
+ EXPECT_TRUE(HasSpan(bar, "type"));
+ EXPECT_TRUE(HasSpan(bar, "name"));
+ EXPECT_TRUE(HasSpan(bar, "number"));
+ EXPECT_TRUE(HasSpan(bar.options()));
+ EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0)));
+ EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0), "name"));
+ EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0).name(0)));
+ EXPECT_TRUE(HasSpan(
+ bar.options().uninterpreted_option(0).name(0), "name_part"));
+ EXPECT_TRUE(HasSpan(
+ bar.options().uninterpreted_option(0), "aggregate_value"));
+}
+
// ===================================================================
} // anonymous namespace
diff --git a/third_party/protobuf/src/google/protobuf/compiler/plugin.h b/third_party/protobuf/src/google/protobuf/compiler/plugin.h
index 7c40333..6fa2de1 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/plugin.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/plugin.h
@@ -56,7 +56,6 @@
#define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
#include <google/protobuf/stubs/common.h>
-
namespace google {
namespace protobuf {
namespace compiler {
diff --git a/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.cc b/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.cc
index c956188..7b0b1f9 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.cc
@@ -1,14 +1,17 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/compiler/plugin.proto
#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
#include "google/protobuf/compiler/plugin.pb.h"
#include <algorithm>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/wire_format.h>
// @@protoc_insertion_point(includes)
@@ -124,6 +127,7 @@
if (already_here) return;
already_here = true;
GOOGLE_PROTOBUF_VERIFY_VERSION;
+
::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n%google/protobuf/compiler/plugin.proto\022"
@@ -253,7 +257,7 @@
if (input->ExpectTag(18)) goto parse_parameter;
break;
}
-
+
// optional string parameter = 2;
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -270,7 +274,7 @@
if (input->ExpectTag(122)) goto parse_proto_file;
break;
}
-
+
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
case 15: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -285,14 +289,15 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -311,7 +316,7 @@
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->file_to_generate(i), output);
}
-
+
// optional string parameter = 2;
if (has_parameter()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -320,13 +325,13 @@
::google::protobuf::internal::WireFormatLite::WriteString(
2, this->parameter(), output);
}
-
+
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
for (int i = 0; i < this->proto_file_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
15, this->proto_file(i), output);
}
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -343,7 +348,7 @@
target = ::google::protobuf::internal::WireFormatLite::
WriteStringToArray(1, this->file_to_generate(i), target);
}
-
+
// optional string parameter = 2;
if (has_parameter()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -353,14 +358,14 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
2, this->parameter(), target);
}
-
+
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
for (int i = 0; i < this->proto_file_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
15, this->proto_file(i), target);
}
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -370,7 +375,7 @@
int CodeGeneratorRequest::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
// optional string parameter = 2;
if (has_parameter()) {
@@ -378,7 +383,7 @@
::google::protobuf::internal::WireFormatLite::StringSize(
this->parameter());
}
-
+
}
// repeated string file_to_generate = 1;
total_size += 1 * this->file_to_generate_size();
@@ -386,7 +391,7 @@
total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
this->file_to_generate(i));
}
-
+
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
total_size += 1 * this->proto_file_size();
for (int i = 0; i < this->proto_file_size(); i++) {
@@ -394,7 +399,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->proto_file(i));
}
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -443,7 +448,7 @@
}
bool CodeGeneratorRequest::IsInitialized() const {
-
+
for (int i = 0; i < proto_file_size(); i++) {
if (!this->proto_file(i).IsInitialized()) return false;
}
@@ -582,7 +587,7 @@
if (input->ExpectTag(18)) goto parse_insertion_point;
break;
}
-
+
// optional string insertion_point = 2;
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -599,7 +604,7 @@
if (input->ExpectTag(122)) goto parse_content;
break;
}
-
+
// optional string content = 15;
case 15: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -616,14 +621,15 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -642,7 +648,7 @@
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->name(), output);
}
-
+
// optional string insertion_point = 2;
if (has_insertion_point()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -651,7 +657,7 @@
::google::protobuf::internal::WireFormatLite::WriteString(
2, this->insertion_point(), output);
}
-
+
// optional string content = 15;
if (has_content()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -660,7 +666,7 @@
::google::protobuf::internal::WireFormatLite::WriteString(
15, this->content(), output);
}
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -678,7 +684,7 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
}
-
+
// optional string insertion_point = 2;
if (has_insertion_point()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -688,7 +694,7 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
2, this->insertion_point(), target);
}
-
+
// optional string content = 15;
if (has_content()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -698,7 +704,7 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
15, this->content(), target);
}
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -708,7 +714,7 @@
int CodeGeneratorResponse_File::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// optional string name = 1;
if (has_name()) {
@@ -716,21 +722,21 @@
::google::protobuf::internal::WireFormatLite::StringSize(
this->name());
}
-
+
// optional string insertion_point = 2;
if (has_insertion_point()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->insertion_point());
}
-
+
// optional string content = 15;
if (has_content()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->content());
}
-
+
}
if (!unknown_fields().empty()) {
total_size +=
@@ -784,7 +790,7 @@
}
bool CodeGeneratorResponse_File::IsInitialized() const {
-
+
return true;
}
@@ -902,7 +908,7 @@
if (input->ExpectTag(122)) goto parse_file;
break;
}
-
+
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
case 15: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -917,14 +923,15 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -943,13 +950,13 @@
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->error(), output);
}
-
+
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
for (int i = 0; i < this->file_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
15, this->file(i), output);
}
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -967,14 +974,14 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->error(), target);
}
-
+
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
for (int i = 0; i < this->file_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
15, this->file(i), target);
}
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -984,7 +991,7 @@
int CodeGeneratorResponse::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// optional string error = 1;
if (has_error()) {
@@ -992,7 +999,7 @@
::google::protobuf::internal::WireFormatLite::StringSize(
this->error());
}
-
+
}
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
total_size += 1 * this->file_size();
@@ -1001,7 +1008,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->file(i));
}
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -1049,7 +1056,7 @@
}
bool CodeGeneratorResponse::IsInitialized() const {
-
+
return true;
}
diff --git a/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.h b/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.h
index 64246fc..46478c7 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/plugin.pb.h
@@ -20,10 +20,10 @@
#endif
#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/generated_message_reflection.h>
#include "google/protobuf/descriptor.pb.h"
// @@protoc_insertion_point(includes)
@@ -46,29 +46,29 @@
public:
CodeGeneratorRequest();
virtual ~CodeGeneratorRequest();
-
+
CodeGeneratorRequest(const CodeGeneratorRequest& from);
-
+
inline CodeGeneratorRequest& operator=(const CodeGeneratorRequest& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const CodeGeneratorRequest& default_instance();
-
+
void Swap(CodeGeneratorRequest* other);
-
+
// implements Message ----------------------------------------------
-
+
CodeGeneratorRequest* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -76,7 +76,7 @@
void MergeFrom(const CodeGeneratorRequest& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -89,13 +89,13 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
// repeated string file_to_generate = 1;
inline int file_to_generate_size() const;
inline void clear_file_to_generate();
@@ -111,7 +111,7 @@
inline void add_file_to_generate(const char* value, size_t size);
inline const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const;
inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate();
-
+
// optional string parameter = 2;
inline bool has_parameter() const;
inline void clear_parameter();
@@ -122,7 +122,8 @@
inline void set_parameter(const char* value, size_t size);
inline ::std::string* mutable_parameter();
inline ::std::string* release_parameter();
-
+ inline void set_allocated_parameter(::std::string* parameter);
+
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
inline int proto_file_size() const;
inline void clear_proto_file();
@@ -134,25 +135,25 @@
proto_file() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
mutable_proto_file();
-
+
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
private:
inline void set_has_parameter();
inline void clear_has_parameter();
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
::std::string* parameter_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-
+
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
-
+
void InitAsDefaultInstance();
static CodeGeneratorRequest* default_instance_;
};
@@ -162,29 +163,29 @@
public:
CodeGeneratorResponse_File();
virtual ~CodeGeneratorResponse_File();
-
+
CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from);
-
+
inline CodeGeneratorResponse_File& operator=(const CodeGeneratorResponse_File& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const CodeGeneratorResponse_File& default_instance();
-
+
void Swap(CodeGeneratorResponse_File* other);
-
+
// implements Message ----------------------------------------------
-
+
CodeGeneratorResponse_File* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -192,7 +193,7 @@
void MergeFrom(const CodeGeneratorResponse_File& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -205,13 +206,13 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
// optional string name = 1;
inline bool has_name() const;
inline void clear_name();
@@ -222,7 +223,8 @@
inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
inline ::std::string* release_name();
-
+ inline void set_allocated_name(::std::string* name);
+
// optional string insertion_point = 2;
inline bool has_insertion_point() const;
inline void clear_insertion_point();
@@ -233,7 +235,8 @@
inline void set_insertion_point(const char* value, size_t size);
inline ::std::string* mutable_insertion_point();
inline ::std::string* release_insertion_point();
-
+ inline void set_allocated_insertion_point(::std::string* insertion_point);
+
// optional string content = 15;
inline bool has_content() const;
inline void clear_content();
@@ -244,7 +247,8 @@
inline void set_content(const char* value, size_t size);
inline ::std::string* mutable_content();
inline ::std::string* release_content();
-
+ inline void set_allocated_content(::std::string* content);
+
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
private:
inline void set_has_name();
@@ -253,20 +257,20 @@
inline void clear_has_insertion_point();
inline void set_has_content();
inline void clear_has_content();
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::std::string* name_;
::std::string* insertion_point_;
::std::string* content_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-
+
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
-
+
void InitAsDefaultInstance();
static CodeGeneratorResponse_File* default_instance_;
};
@@ -276,29 +280,29 @@
public:
CodeGeneratorResponse();
virtual ~CodeGeneratorResponse();
-
+
CodeGeneratorResponse(const CodeGeneratorResponse& from);
-
+
inline CodeGeneratorResponse& operator=(const CodeGeneratorResponse& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const CodeGeneratorResponse& default_instance();
-
+
void Swap(CodeGeneratorResponse* other);
-
+
// implements Message ----------------------------------------------
-
+
CodeGeneratorResponse* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -306,7 +310,7 @@
void MergeFrom(const CodeGeneratorResponse& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -319,15 +323,15 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
typedef CodeGeneratorResponse_File File;
-
+
// accessors -------------------------------------------------------
-
+
// optional string error = 1;
inline bool has_error() const;
inline void clear_error();
@@ -338,7 +342,8 @@
inline void set_error(const char* value, size_t size);
inline ::std::string* mutable_error();
inline ::std::string* release_error();
-
+ inline void set_allocated_error(::std::string* error);
+
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
inline int file_size() const;
inline void clear_file();
@@ -350,24 +355,24 @@
file() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
mutable_file();
-
+
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
private:
inline void set_has_error();
inline void clear_has_error();
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::std::string* error_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-
+
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
-
+
void InitAsDefaultInstance();
static CodeGeneratorResponse* default_instance_;
};
@@ -479,6 +484,18 @@
return temp;
}
}
+inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
+ if (parameter_ != &::google::protobuf::internal::kEmptyString) {
+ delete parameter_;
+ }
+ if (parameter) {
+ set_has_parameter();
+ parameter_ = parameter;
+ } else {
+ clear_has_parameter();
+ parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
inline int CodeGeneratorRequest::proto_file_size() const {
@@ -566,6 +583,18 @@
return temp;
}
}
+inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
+ if (name_ != &::google::protobuf::internal::kEmptyString) {
+ delete name_;
+ }
+ if (name) {
+ set_has_name();
+ name_ = name;
+ } else {
+ clear_has_name();
+ name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// optional string insertion_point = 2;
inline bool CodeGeneratorResponse_File::has_insertion_point() const {
@@ -624,6 +653,18 @@
return temp;
}
}
+inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
+ if (insertion_point_ != &::google::protobuf::internal::kEmptyString) {
+ delete insertion_point_;
+ }
+ if (insertion_point) {
+ set_has_insertion_point();
+ insertion_point_ = insertion_point;
+ } else {
+ clear_has_insertion_point();
+ insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// optional string content = 15;
inline bool CodeGeneratorResponse_File::has_content() const {
@@ -682,6 +723,18 @@
return temp;
}
}
+inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
+ if (content_ != &::google::protobuf::internal::kEmptyString) {
+ delete content_;
+ }
+ if (content) {
+ set_has_content();
+ content_ = content;
+ } else {
+ clear_has_content();
+ content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// -------------------------------------------------------------------
@@ -744,6 +797,18 @@
return temp;
}
}
+inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
+ if (error_ != &::google::protobuf::internal::kEmptyString) {
+ delete error_;
+ }
+ if (error) {
+ set_has_error();
+ error_ = error;
+ } else {
+ clear_has_error();
+ error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
inline int CodeGeneratorResponse::file_size() const {
diff --git a/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc b/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc
index 9b10937..211ac70 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc
@@ -52,6 +52,7 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/zero_copy_stream.h>
@@ -106,6 +107,12 @@
const char kDescriptorKey[] = "DESCRIPTOR";
+// Does the file have top-level enums?
+inline bool HasTopLevelEnums(const FileDescriptor *file) {
+ return file->enum_type_count() > 0;
+}
+
+
// Should we generate generic services for this file?
inline bool HasGenericServices(const FileDescriptor *file) {
return file->service_count() > 0 &&
@@ -120,13 +127,21 @@
// TODO(robinson): Allow parameterization of Python version?
printer->Print(
"# Generated by the protocol buffer compiler. DO NOT EDIT!\n"
- "\n"
- "from google.protobuf import descriptor\n"
- "from google.protobuf import message\n"
- "from google.protobuf import reflection\n");
+ "# source: $filename$\n"
+ "\n",
+ "filename", file->name());
+ if (HasTopLevelEnums(file)) {
+ printer->Print(
+ "from google.protobuf.internal import enum_type_wrapper\n");
+ }
+ printer->Print(
+ "from google.protobuf import descriptor as _descriptor\n"
+ "from google.protobuf import message as _message\n"
+ "from google.protobuf import reflection as _reflection\n"
+ );
if (HasGenericServices(file)) {
printer->Print(
- "from google.protobuf import service\n"
+ "from google.protobuf import service as _service\n"
"from google.protobuf import service_reflection\n");
}
@@ -204,12 +219,12 @@
case FieldDescriptor::CPPTYPE_STRING:
if (field.type() == FieldDescriptor::TYPE_STRING) {
return "unicode(\"" + CEscape(field.default_value_string()) +
- "\", \"utf-8\")";
+ "\", \"utf-8\")";
} else {
return "\"" + CEscape(field.default_value_string()) + "\"";
}
- case FieldDescriptor::CPPTYPE_MESSAGE:
- return "None";
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return "None";
}
// (We could add a default case above but then we wouldn't get the nice
// compiler warning when a new type is added.)
@@ -270,6 +285,11 @@
// since they need to call static RegisterExtension() methods on these
// classes.
FixForeignFieldsInExtensions();
+ // Descriptor options may have custom extensions. These custom options
+ // can only be successfully parsed after we register corresponding
+ // extensions. Therefore we parse all options again here to recognize
+ // custom options that may be unknown when we define the descriptors.
+ FixAllDescriptorOptions();
if (HasGenericServices(file)) {
PrintServices();
}
@@ -288,6 +308,13 @@
module_name);
}
printer_->Print("\n");
+
+ // Print public imports.
+ for (int i = 0; i < file_->public_dependency_count(); ++i) {
+ string module_name = ModuleName(file_->public_dependency(i)->name());
+ printer_->Print("from $module$ import *\n", "module", module_name);
+ }
+ printer_->Print("\n");
}
// Prints the single file descriptor for this file.
@@ -297,7 +324,7 @@
m["name"] = file_->name();
m["package"] = file_->package();
const char file_descriptor_template[] =
- "$descriptor_name$ = descriptor.FileDescriptor(\n"
+ "$descriptor_name$ = _descriptor.FileDescriptor(\n"
" name='$name$',\n"
" package='$package$',\n";
printer_->Print(m, file_descriptor_template);
@@ -321,6 +348,11 @@
for (int i = 0; i < file_->enum_type_count(); ++i) {
const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
PrintEnum(enum_descriptor);
+ printer_->Print("$name$ = "
+ "enum_type_wrapper.EnumTypeWrapper($descriptor_name$)",
+ "name", enum_descriptor.name(),
+ "descriptor_name",
+ ModuleLevelDescriptorName(enum_descriptor));
printer_->Print("\n");
for (int j = 0; j < enum_descriptor.value_count(); ++j) {
@@ -355,7 +387,7 @@
m["full_name"] = enum_descriptor.full_name();
m["file"] = kDescriptorKey;
const char enum_descriptor_template[] =
- "$descriptor_name$ = descriptor.EnumDescriptor(\n"
+ "$descriptor_name$ = _descriptor.EnumDescriptor(\n"
" name='$name$',\n"
" full_name='$full_name$',\n"
" filename=None,\n"
@@ -436,7 +468,7 @@
descriptor.options().SerializeToString(&options_string);
printer_->Print(
- "$service_name$ = descriptor.ServiceDescriptor(\n",
+ "$service_name$ = _descriptor.ServiceDescriptor(\n",
"service_name", service_name);
printer_->Indent();
map<string, string> m;
@@ -459,7 +491,6 @@
printer_->Print("methods=[\n");
for (int i = 0; i < descriptor.method_count(); ++i) {
const MethodDescriptor* method = descriptor.method(i);
- string options_string;
method->options().SerializeToString(&options_string);
m.clear();
@@ -470,7 +501,7 @@
m["input_type"] = ModuleLevelDescriptorName(*(method->input_type()));
m["output_type"] = ModuleLevelDescriptorName(*(method->output_type()));
m["options_value"] = OptionsValue("MethodOptions", options_string);
- printer_->Print("descriptor.MethodDescriptor(\n");
+ printer_->Print("_descriptor.MethodDescriptor(\n");
printer_->Indent();
printer_->Print(
m,
@@ -491,7 +522,7 @@
void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const {
// Print the service.
- printer_->Print("class $class_name$(service.Service):\n",
+ printer_->Print("class $class_name$(_service.Service):\n",
"class_name", descriptor.name());
printer_->Indent();
printer_->Print(
@@ -523,7 +554,7 @@
PrintNestedDescriptors(message_descriptor);
printer_->Print("\n");
- printer_->Print("$descriptor_name$ = descriptor.Descriptor(\n",
+ printer_->Print("$descriptor_name$ = _descriptor.Descriptor(\n",
"descriptor_name",
ModuleLevelDescriptorName(message_descriptor));
printer_->Indent();
@@ -618,10 +649,10 @@
// Mutually recursive with PrintNestedMessages().
void Generator::PrintMessage(
const Descriptor& message_descriptor) const {
- printer_->Print("class $name$(message.Message):\n", "name",
+ printer_->Print("class $name$(_message.Message):\n", "name",
message_descriptor.name());
printer_->Indent();
- printer_->Print("__metaclass__ = reflection.GeneratedProtocolMessageType\n");
+ printer_->Print("__metaclass__ = _reflection.GeneratedProtocolMessageType\n");
PrintNestedMessages(message_descriptor);
map<string, string> m;
m["descriptor_key"] = kDescriptorKey;
@@ -779,6 +810,7 @@
for (int i = 0; i < file_->message_type_count(); ++i) {
FixForeignFieldsInNestedExtensions(*file_->message_type(i));
}
+ printer_->Print("\n");
}
void Generator::FixForeignFieldsInExtension(
@@ -829,7 +861,7 @@
m["options"] = OptionsValue("EnumValueOptions", options_string);
printer_->Print(
m,
- "descriptor.EnumValueDescriptor(\n"
+ "_descriptor.EnumValueDescriptor(\n"
" name='$name$', index=$index$, number=$number$,\n"
" options=$options$,\n"
" type=None)");
@@ -843,7 +875,7 @@
return "None";
} else {
string full_class_name = "descriptor_pb2." + class_name;
- return "descriptor._ParseOptions(" + full_class_name + "(), '"
+ return "_descriptor._ParseOptions(" + full_class_name + "(), '"
+ CEscape(serialized_options)+ "')";
}
}
@@ -869,7 +901,7 @@
// these fields in correctly after all referenced descriptors have been
// defined and/or imported (see FixForeignFieldsInDescriptors()).
const char field_descriptor_decl[] =
- "descriptor.FieldDescriptor(\n"
+ "_descriptor.FieldDescriptor(\n"
" name='$name$', full_name='$full_name$', index=$index$,\n"
" number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n"
" has_default_value=$has_default_value$, default_value=$default_value$,\n"
@@ -1000,6 +1032,125 @@
"serialized_end", SimpleItoa(offset + sp.size()));
}
+namespace {
+void PrintDescriptorOptionsFixingCode(const string& descriptor,
+ const string& options,
+ io::Printer* printer) {
+ // TODO(xiaofeng): I have added a method _SetOptions() to DescriptorBase
+ // in proto2 python runtime but it couldn't be used here because appengine
+ // uses a snapshot version of the library in which the new method is not
+ // yet present. After appengine has synced their runtime library, the code
+ // below should be cleaned up to use _SetOptions().
+ printer->Print(
+ "$descriptor$.has_options = True\n"
+ "$descriptor$._options = $options$\n",
+ "descriptor", descriptor, "options", options);
+}
+} // namespace
+
+// Prints expressions that set the options field of all descriptors.
+void Generator::FixAllDescriptorOptions() const {
+ // Prints an expression that sets the file descriptor's options.
+ string file_options = OptionsValue(
+ "FileOptions", file_->options().SerializeAsString());
+ if (file_options != "None") {
+ PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_);
+ }
+ // Prints expressions that set the options for all top level enums.
+ for (int i = 0; i < file_->enum_type_count(); ++i) {
+ const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
+ FixOptionsForEnum(enum_descriptor);
+ }
+ // Prints expressions that set the options for all top level extensions.
+ for (int i = 0; i < file_->extension_count(); ++i) {
+ const FieldDescriptor& field = *file_->extension(i);
+ FixOptionsForField(field);
+ }
+ // Prints expressions that set the options for all messages, nested enums,
+ // nested extensions and message fields.
+ for (int i = 0; i < file_->message_type_count(); ++i) {
+ FixOptionsForMessage(*file_->message_type(i));
+ }
+}
+
+// Prints expressions that set the options for an enum descriptor and its
+// value descriptors.
+void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const {
+ string descriptor_name = ModuleLevelDescriptorName(enum_descriptor);
+ string enum_options = OptionsValue(
+ "EnumOptions", enum_descriptor.options().SerializeAsString());
+ if (enum_options != "None") {
+ PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_);
+ }
+ for (int i = 0; i < enum_descriptor.value_count(); ++i) {
+ const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i);
+ string value_options = OptionsValue(
+ "EnumValueOptions", value_descriptor.options().SerializeAsString());
+ if (value_options != "None") {
+ PrintDescriptorOptionsFixingCode(
+ StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(),
+ value_descriptor.name().c_str()),
+ value_options, printer_);
+ }
+ }
+}
+
+// Prints expressions that set the options for field descriptors (including
+// extensions).
+void Generator::FixOptionsForField(
+ const FieldDescriptor& field) const {
+ string field_options = OptionsValue(
+ "FieldOptions", field.options().SerializeAsString());
+ if (field_options != "None") {
+ string field_name;
+ if (field.is_extension()) {
+ if (field.extension_scope() == NULL) {
+ // Top level extensions.
+ field_name = field.name();
+ } else {
+ field_name = FieldReferencingExpression(
+ field.extension_scope(), field, "extensions_by_name");
+ }
+ } else {
+ field_name = FieldReferencingExpression(
+ field.containing_type(), field, "fields_by_name");
+ }
+ PrintDescriptorOptionsFixingCode(field_name, field_options, printer_);
+ }
+}
+
+// Prints expressions that set the options for a message and all its inner
+// types (nested messages, nested enums, extensions, fields).
+void Generator::FixOptionsForMessage(const Descriptor& descriptor) const {
+ // Nested messages.
+ for (int i = 0; i < descriptor.nested_type_count(); ++i) {
+ FixOptionsForMessage(*descriptor.nested_type(i));
+ }
+ // Enums.
+ for (int i = 0; i < descriptor.enum_type_count(); ++i) {
+ FixOptionsForEnum(*descriptor.enum_type(i));
+ }
+ // Fields.
+ for (int i = 0; i < descriptor.field_count(); ++i) {
+ const FieldDescriptor& field = *descriptor.field(i);
+ FixOptionsForField(field);
+ }
+ // Extensions.
+ for (int i = 0; i < descriptor.extension_count(); ++i) {
+ const FieldDescriptor& field = *descriptor.extension(i);
+ FixOptionsForField(field);
+ }
+ // Message option for this message.
+ string message_options = OptionsValue(
+ "MessageOptions", descriptor.options().SerializeAsString());
+ if (message_options != "None") {
+ string descriptor_name = ModuleLevelDescriptorName(descriptor);
+ PrintDescriptorOptionsFixingCode(descriptor_name,
+ message_options,
+ printer_);
+ }
+}
+
} // namespace python
} // namespace compiler
} // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.h b/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.h
index 84eaf8a..a3f22ce 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.h
@@ -138,6 +138,11 @@
void PrintSerializedPbInterval(
const DescriptorT& descriptor, DescriptorProtoT& proto) const;
+ void FixAllDescriptorOptions() const;
+ void FixOptionsForField(const FieldDescriptor& field) const;
+ void FixOptionsForEnum(const EnumDescriptor& descriptor) const;
+ void FixOptionsForMessage(const Descriptor& descriptor) const;
+
// Very coarse-grained lock to ensure that Generate() is reentrant.
// Guards file_, printer_ and file_descriptor_serialized_.
mutable Mutex mutex_;
diff --git a/third_party/protobuf/src/google/protobuf/compiler/subprocess.cc b/third_party/protobuf/src/google/protobuf/compiler/subprocess.cc
index 5fb5d5c..860fc87 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/subprocess.cc
+++ b/third_party/protobuf/src/google/protobuf/compiler/subprocess.cc
@@ -33,6 +33,7 @@
#include <google/protobuf/compiler/subprocess.h>
#include <algorithm>
+#include <iostream>
#ifndef _WIN32
#include <errno.h>
diff --git a/third_party/protobuf/src/google/protobuf/compiler/subprocess.h b/third_party/protobuf/src/google/protobuf/compiler/subprocess.h
index 0056496..de9fce9 100644
--- a/third_party/protobuf/src/google/protobuf/compiler/subprocess.h
+++ b/third_party/protobuf/src/google/protobuf/compiler/subprocess.h
@@ -53,7 +53,7 @@
namespace compiler {
// Utility class for launching sub-processes.
-class LIBPROTOC_EXPORT Subprocess {
+class Subprocess {
public:
Subprocess();
~Subprocess();
diff --git a/third_party/protobuf/src/google/protobuf/descriptor.cc b/third_party/protobuf/src/google/protobuf/descriptor.cc
index 5bdd565..45293fe 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor.cc
+++ b/third_party/protobuf/src/google/protobuf/descriptor.cc
@@ -54,7 +54,7 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/stubs/map-util.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
#undef PACKAGE // autoheader #defines this. :(
@@ -108,6 +108,21 @@
"sint64", // TYPE_SINT64
};
+const char * const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = {
+ "ERROR", // 0 is reserved for errors
+
+ "int32", // CPPTYPE_INT32
+ "int64", // CPPTYPE_INT64
+ "uint32", // CPPTYPE_UINT32
+ "uint64", // CPPTYPE_UINT64
+ "double", // CPPTYPE_DOUBLE
+ "float", // CPPTYPE_FLOAT
+ "bool", // CPPTYPE_BOOL
+ "enum", // CPPTYPE_ENUM
+ "string", // CPPTYPE_STRING
+ "message", // CPPTYPE_MESSAGE
+};
+
const char * const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = {
"ERROR", // 0 is reserved for errors
@@ -221,7 +236,8 @@
struct Symbol {
enum Type {
- NULL_SYMBOL, MESSAGE, FIELD, ENUM, ENUM_VALUE, SERVICE, METHOD, PACKAGE
+ NULL_SYMBOL, MESSAGE, FIELD, ENUM, ENUM_VALUE, SERVICE, METHOD,
+ PACKAGE
};
Type type;
union {
@@ -311,17 +327,42 @@
Tables();
~Tables();
- // Checkpoint the state of the tables. Future calls to Rollback() will
- // return the Tables to this state. This is used when building files, since
- // some kinds of validation errors cannot be detected until the file's
- // descriptors have already been added to the tables. BuildFile() calls
- // Checkpoint() before it starts building and Rollback() if it encounters
- // an error.
- void Checkpoint();
+ // Record the current state of the tables to the stack of checkpoints.
+ // Each call to AddCheckpoint() must be paired with exactly one call to either
+ // ClearLastCheckpoint() or RollbackToLastCheckpoint().
+ //
+ // This is used when building files, since some kinds of validation errors
+ // cannot be detected until the file's descriptors have already been added to
+ // the tables.
+ //
+ // This supports recursive checkpoints, since building a file may trigger
+ // recursive building of other files. Note that recursive checkpoints are not
+ // normally necessary; explicit dependencies are built prior to checkpointing.
+ // So although we recursively build transitive imports, there is at most one
+ // checkpoint in the stack during dependency building.
+ //
+ // Recursive checkpoints only arise during cross-linking of the descriptors.
+ // Symbol references must be resolved, via DescriptorBuilder::FindSymbol and
+ // friends. If the pending file references an unknown symbol
+ // (e.g., it is not defined in the pending file's explicit dependencies), and
+ // the pool is using a fallback database, and that database contains a file
+ // defining that symbol, and that file has not yet been built by the pool,
+ // the pool builds the file during cross-linking, leading to another
+ // checkpoint.
+ void AddCheckpoint();
- // Roll back the Tables to the state of the last Checkpoint(), removing
- // everything that was added after that point.
- void Rollback();
+ // Mark the last checkpoint as having cleared successfully, removing it from
+ // the stack. If the stack is empty, all pending symbols will be committed.
+ //
+ // Note that this does not guarantee that the symbols added since the last
+ // checkpoint won't be rolled back: if a checkpoint gets rolled back,
+ // everything past that point gets rolled back, including symbols added after
+ // checkpoints that were pushed onto the stack after it and marked as cleared.
+ void ClearLastCheckpoint();
+
+ // Roll back the Tables to the state of the checkpoint at the top of the
+ // stack, removing everything that was added after that point.
+ void RollbackToLastCheckpoint();
// The stack of files which are currently being built. Used to detect
// cyclic dependencies when loading files from a DescriptorDatabase. Not
@@ -405,10 +446,28 @@
FilesByNameMap files_by_name_;
ExtensionsGroupedByDescriptorMap extensions_;
- int strings_before_checkpoint_;
- int messages_before_checkpoint_;
- int file_tables_before_checkpoint_;
- int allocations_before_checkpoint_;
+ struct CheckPoint {
+ explicit CheckPoint(const Tables* tables)
+ : strings_before_checkpoint(tables->strings_.size()),
+ messages_before_checkpoint(tables->messages_.size()),
+ file_tables_before_checkpoint(tables->file_tables_.size()),
+ allocations_before_checkpoint(tables->allocations_.size()),
+ pending_symbols_before_checkpoint(
+ tables->symbols_after_checkpoint_.size()),
+ pending_files_before_checkpoint(
+ tables->files_after_checkpoint_.size()),
+ pending_extensions_before_checkpoint(
+ tables->extensions_after_checkpoint_.size()) {
+ }
+ int strings_before_checkpoint;
+ int messages_before_checkpoint;
+ int file_tables_before_checkpoint;
+ int allocations_before_checkpoint;
+ int pending_symbols_before_checkpoint;
+ int pending_files_before_checkpoint;
+ int pending_extensions_before_checkpoint;
+ };
+ vector<CheckPoint> checkpoints_;
vector<const char* > symbols_after_checkpoint_;
vector<const char* > files_after_checkpoint_;
vector<DescriptorIntPair> extensions_after_checkpoint_;
@@ -481,11 +540,15 @@
};
DescriptorPool::Tables::Tables()
- : strings_before_checkpoint_(0),
- messages_before_checkpoint_(0),
- allocations_before_checkpoint_(0) {}
+ // Start some hash_map and hash_set objects with a small # of buckets
+ : known_bad_files_(3),
+ extensions_loaded_from_db_(3),
+ symbols_by_name_(3),
+ files_by_name_(3) {}
+
DescriptorPool::Tables::~Tables() {
+ GOOGLE_DCHECK(checkpoints_.empty());
// Note that the deletion order is important, since the destructors of some
// messages may refer to objects in allocations_.
STLDeleteElements(&messages_);
@@ -496,51 +559,80 @@
STLDeleteElements(&file_tables_);
}
-FileDescriptorTables::FileDescriptorTables() {}
+FileDescriptorTables::FileDescriptorTables()
+ // Initialize all the hash tables to start out with a small # of buckets
+ : symbols_by_parent_(3),
+ fields_by_lowercase_name_(3),
+ fields_by_camelcase_name_(3),
+ fields_by_number_(3),
+ enum_values_by_number_(3) {
+}
+
FileDescriptorTables::~FileDescriptorTables() {}
const FileDescriptorTables FileDescriptorTables::kEmpty;
-void DescriptorPool::Tables::Checkpoint() {
- strings_before_checkpoint_ = strings_.size();
- messages_before_checkpoint_ = messages_.size();
- file_tables_before_checkpoint_ = file_tables_.size();
- allocations_before_checkpoint_ = allocations_.size();
-
- symbols_after_checkpoint_.clear();
- files_after_checkpoint_.clear();
- extensions_after_checkpoint_.clear();
+void DescriptorPool::Tables::AddCheckpoint() {
+ checkpoints_.push_back(CheckPoint(this));
}
-void DescriptorPool::Tables::Rollback() {
- for (int i = 0; i < symbols_after_checkpoint_.size(); i++) {
+void DescriptorPool::Tables::ClearLastCheckpoint() {
+ GOOGLE_DCHECK(!checkpoints_.empty());
+ checkpoints_.pop_back();
+ if (checkpoints_.empty()) {
+ // All checkpoints have been cleared: we can now commit all of the pending
+ // data.
+ symbols_after_checkpoint_.clear();
+ files_after_checkpoint_.clear();
+ extensions_after_checkpoint_.clear();
+ }
+}
+
+void DescriptorPool::Tables::RollbackToLastCheckpoint() {
+ GOOGLE_DCHECK(!checkpoints_.empty());
+ const CheckPoint& checkpoint = checkpoints_.back();
+
+ for (int i = checkpoint.pending_symbols_before_checkpoint;
+ i < symbols_after_checkpoint_.size();
+ i++) {
symbols_by_name_.erase(symbols_after_checkpoint_[i]);
}
- for (int i = 0; i < files_after_checkpoint_.size(); i++) {
+ for (int i = checkpoint.pending_files_before_checkpoint;
+ i < files_after_checkpoint_.size();
+ i++) {
files_by_name_.erase(files_after_checkpoint_[i]);
}
- for (int i = 0; i < extensions_after_checkpoint_.size(); i++) {
+ for (int i = checkpoint.pending_extensions_before_checkpoint;
+ i < extensions_after_checkpoint_.size();
+ i++) {
extensions_.erase(extensions_after_checkpoint_[i]);
}
- symbols_after_checkpoint_.clear();
- files_after_checkpoint_.clear();
- extensions_after_checkpoint_.clear();
+ symbols_after_checkpoint_.resize(
+ checkpoint.pending_symbols_before_checkpoint);
+ files_after_checkpoint_.resize(checkpoint.pending_files_before_checkpoint);
+ extensions_after_checkpoint_.resize(
+ checkpoint.pending_extensions_before_checkpoint);
STLDeleteContainerPointers(
- strings_.begin() + strings_before_checkpoint_, strings_.end());
+ strings_.begin() + checkpoint.strings_before_checkpoint, strings_.end());
STLDeleteContainerPointers(
- messages_.begin() + messages_before_checkpoint_, messages_.end());
+ messages_.begin() + checkpoint.messages_before_checkpoint,
+ messages_.end());
STLDeleteContainerPointers(
- file_tables_.begin() + file_tables_before_checkpoint_, file_tables_.end());
- for (int i = allocations_before_checkpoint_; i < allocations_.size(); i++) {
+ file_tables_.begin() + checkpoint.file_tables_before_checkpoint,
+ file_tables_.end());
+ for (int i = checkpoint.allocations_before_checkpoint;
+ i < allocations_.size();
+ i++) {
operator delete(allocations_[i]);
}
- strings_.resize(strings_before_checkpoint_);
- messages_.resize(messages_before_checkpoint_);
- file_tables_.resize(file_tables_before_checkpoint_);
- allocations_.resize(allocations_before_checkpoint_);
+ strings_.resize(checkpoint.strings_before_checkpoint);
+ messages_.resize(checkpoint.messages_before_checkpoint);
+ file_tables_.resize(checkpoint.file_tables_before_checkpoint);
+ allocations_.resize(checkpoint.allocations_before_checkpoint);
+ checkpoints_.pop_back();
}
// -------------------------------------------------------------------
@@ -811,7 +903,7 @@
generated_pool_ = NULL;
}
-void InitGeneratedPool() {
+static void InitGeneratedPool() {
generated_database_ = new EncodedDescriptorDatabase;
generated_pool_ = new DescriptorPool(generated_database_);
@@ -874,11 +966,11 @@
const FileDescriptor* result = tables_->FindFile(name);
if (result != NULL) return result;
if (underlay_ != NULL) {
- const FileDescriptor* result = underlay_->FindFileByName(name);
+ result = underlay_->FindFileByName(name);
if (result != NULL) return result;
}
if (TryFindFileInFallbackDatabase(name)) {
- const FileDescriptor* result = tables_->FindFile(name);
+ result = tables_->FindFile(name);
if (result != NULL) return result;
}
return NULL;
@@ -890,12 +982,12 @@
Symbol result = tables_->FindSymbol(symbol_name);
if (!result.IsNull()) return result.GetFile();
if (underlay_ != NULL) {
- const FileDescriptor* result =
+ const FileDescriptor* file_result =
underlay_->FindFileContainingSymbol(symbol_name);
- if (result != NULL) return result;
+ if (file_result != NULL) return file_result;
}
if (TryFindSymbolInFallbackDatabase(symbol_name)) {
- Symbol result = tables_->FindSymbol(symbol_name);
+ result = tables_->FindSymbol(symbol_name);
if (!result.IsNull()) return result.GetFile();
}
return NULL;
@@ -962,12 +1054,11 @@
return result;
}
if (underlay_ != NULL) {
- const FieldDescriptor* result =
- underlay_->FindExtensionByNumber(extendee, number);
+ result = underlay_->FindExtensionByNumber(extendee, number);
if (result != NULL) return result;
}
if (TryFindExtensionInFallbackDatabase(extendee, number)) {
- const FieldDescriptor* result = tables_->FindExtension(extendee, number);
+ result = tables_->FindExtension(extendee, number);
if (result != NULL) {
return result;
}
@@ -1241,9 +1332,48 @@
return true;
}
+bool DescriptorPool::IsSubSymbolOfBuiltType(const string& name) const {
+ string prefix = name;
+ for (;;) {
+ string::size_type dot_pos = prefix.find_last_of('.');
+ if (dot_pos == string::npos) {
+ break;
+ }
+ prefix = prefix.substr(0, dot_pos);
+ Symbol symbol = tables_->FindSymbol(prefix);
+ // If the symbol type is anything other than PACKAGE, then its complete
+ // definition is already known.
+ if (!symbol.IsNull() && symbol.type != Symbol::PACKAGE) {
+ return true;
+ }
+ }
+ if (underlay_ != NULL) {
+ // Check to see if any prefix of this symbol exists in the underlay.
+ return underlay_->IsSubSymbolOfBuiltType(name);
+ }
+ return false;
+}
+
bool DescriptorPool::TryFindSymbolInFallbackDatabase(const string& name) const {
if (fallback_database_ == NULL) return false;
+ // We skip looking in the fallback database if the name is a sub-symbol of
+ // any descriptor that already exists in the descriptor pool (except for
+ // package descriptors). This is valid because all symbols except for
+ // packages are defined in a single file, so if the symbol exists then we
+ // should already have its definition.
+ //
+ // The other reason to do this is to support "overriding" type definitions
+ // by merging two databases that define the same type. (Yes, people do
+ // this.) The main difficulty with making this work is that
+ // FindFileContainingSymbol() is allowed to return both false positives
+ // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and false
+ // negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase). When two
+ // such databases are merged, looking up a non-existent sub-symbol of a type
+ // that already exists in the descriptor pool can result in an attempt to
+ // load multiple definitions of the same type. The check below avoids this.
+ if (IsSubSymbolOfBuiltType(name)) return false;
+
FileDescriptorProto file_proto;
if (!fallback_database_->FindFileContainingSymbol(name, &file_proto)) {
return false;
@@ -1345,6 +1475,14 @@
proto->add_dependency(dependency(i)->name());
}
+ for (int i = 0; i < public_dependency_count(); i++) {
+ proto->add_public_dependency(public_dependencies_[i]);
+ }
+
+ for (int i = 0; i < weak_dependency_count(); i++) {
+ proto->add_weak_dependency(weak_dependencies_[i]);
+ }
+
for (int i = 0; i < message_type_count(); i++) {
message_type(i)->CopyTo(proto->add_message_type());
}
@@ -1363,6 +1501,12 @@
}
}
+void FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const {
+ if (source_code_info_ != &SourceCodeInfo::default_instance()) {
+ proto->mutable_source_code_info()->CopyFrom(*source_code_info_);
+ }
+}
+
void Descriptor::CopyTo(DescriptorProto* proto) const {
proto->set_name(name());
@@ -1490,16 +1634,14 @@
namespace {
// Used by each of the option formatters.
-bool RetrieveOptions(const Message &options, vector<string> *option_entries) {
+bool RetrieveOptions(int depth,
+ const Message &options,
+ vector<string> *option_entries) {
option_entries->clear();
const Reflection* reflection = options.GetReflection();
vector<const FieldDescriptor*> fields;
reflection->ListFields(options, &fields);
for (int i = 0; i < fields.size(); i++) {
- // Doesn't make sense to have message type fields here
- if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- continue;
- }
int count = 1;
bool repeated = false;
if (fields[i]->is_repeated()) {
@@ -1508,9 +1650,27 @@
}
for (int j = 0; j < count; j++) {
string fieldval;
- TextFormat::PrintFieldValueToString(options, fields[i],
- repeated ? count : -1, &fieldval);
- option_entries->push_back(fields[i]->name() + " = " + fieldval);
+ if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ string tmp;
+ TextFormat::Printer printer;
+ printer.SetInitialIndentLevel(depth + 1);
+ printer.PrintFieldValueToString(options, fields[i],
+ repeated ? j : -1, &tmp);
+ fieldval.append("{\n");
+ fieldval.append(tmp);
+ fieldval.append(depth * 2, ' ');
+ fieldval.append("}");
+ } else {
+ TextFormat::PrintFieldValueToString(options, fields[i],
+ repeated ? j : -1, &fieldval);
+ }
+ string name;
+ if (fields[i]->is_extension()) {
+ name = "(." + fields[i]->full_name() + ")";
+ } else {
+ name = fields[i]->name();
+ }
+ option_entries->push_back(name + " = " + fieldval);
}
}
return !option_entries->empty();
@@ -1518,9 +1678,9 @@
// Formats options that all appear together in brackets. Does not include
// brackets.
-bool FormatBracketedOptions(const Message &options, string *output) {
+bool FormatBracketedOptions(int depth, const Message &options, string *output) {
vector<string> all_options;
- if (RetrieveOptions(options, &all_options)) {
+ if (RetrieveOptions(depth, options, &all_options)) {
output->append(JoinStrings(all_options, ", "));
}
return !all_options.empty();
@@ -1530,7 +1690,7 @@
bool FormatLineOptions(int depth, const Message &options, string *output) {
string prefix(depth * 2, ' ');
vector<string> all_options;
- if (RetrieveOptions(options, &all_options)) {
+ if (RetrieveOptions(depth, options, &all_options)) {
for (int i = 0; i < all_options.size(); i++) {
strings::SubstituteAndAppend(output, "$0option $1;\n",
prefix, all_options[i]);
@@ -1544,9 +1704,24 @@
string FileDescriptor::DebugString() const {
string contents = "syntax = \"proto2\";\n\n";
+ set<int> public_dependencies;
+ set<int> weak_dependencies;
+ public_dependencies.insert(public_dependencies_,
+ public_dependencies_ + public_dependency_count_);
+ weak_dependencies.insert(weak_dependencies_,
+ weak_dependencies_ + weak_dependency_count_);
+
for (int i = 0; i < dependency_count(); i++) {
- strings::SubstituteAndAppend(&contents, "import \"$0\";\n",
- dependency(i)->name());
+ if (public_dependencies.count(i) > 0) {
+ strings::SubstituteAndAppend(&contents, "import public \"$0\";\n",
+ dependency(i)->name());
+ } else if (weak_dependencies.count(i) > 0) {
+ strings::SubstituteAndAppend(&contents, "import weak \"$0\";\n",
+ dependency(i)->name());
+ } else {
+ strings::SubstituteAndAppend(&contents, "import \"$0\";\n",
+ dependency(i)->name());
+ }
}
if (!package().empty()) {
@@ -1712,7 +1887,7 @@
}
string formatted_options;
- if (FormatBracketedOptions(options(), &formatted_options)) {
+ if (FormatBracketedOptions(depth, options(), &formatted_options)) {
contents->append(bracketed ? ", " : " [");
bracketed = true;
contents->append(formatted_options);
@@ -1761,7 +1936,7 @@
prefix, name(), number());
string formatted_options;
- if (FormatBracketedOptions(options(), &formatted_options)) {
+ if (FormatBracketedOptions(depth, options(), &formatted_options)) {
strings::SubstituteAndAppend(contents, " [$0]", formatted_options);
}
contents->append(";\n");
@@ -1807,6 +1982,126 @@
contents->append(";\n");
}
}
+
+
+// Location methods ===============================================
+
+static bool PathsEqual(const vector<int>& x, const RepeatedField<int32>& y) {
+ if (x.size() != y.size()) return false;
+ for (int i = 0; i < x.size(); ++i) {
+ if (x[i] != y.Get(i)) return false;
+ }
+ return true;
+}
+
+bool FileDescriptor::GetSourceLocation(const vector<int>& path,
+ SourceLocation* out_location) const {
+ GOOGLE_CHECK_NOTNULL(out_location);
+ const SourceCodeInfo* info = source_code_info_;
+ for (int i = 0; info && i < info->location_size(); ++i) {
+ if (PathsEqual(path, info->location(i).path())) {
+ const RepeatedField<int32>& span = info->location(i).span();
+ if (span.size() == 3 || span.size() == 4) {
+ out_location->start_line = span.Get(0);
+ out_location->start_column = span.Get(1);
+ out_location->end_line = span.Get(span.size() == 3 ? 0 : 2);
+ out_location->end_column = span.Get(span.size() - 1);
+
+ out_location->leading_comments = info->location(i).leading_comments();
+ out_location->trailing_comments = info->location(i).trailing_comments();
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool FieldDescriptor::is_packed() const {
+ return is_packable() && (options_ != NULL) && options_->packed();
+}
+
+bool Descriptor::GetSourceLocation(SourceLocation* out_location) const {
+ vector<int> path;
+ GetLocationPath(&path);
+ return file()->GetSourceLocation(path, out_location);
+}
+
+bool FieldDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+ vector<int> path;
+ GetLocationPath(&path);
+ return file()->GetSourceLocation(path, out_location);
+}
+
+bool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+ vector<int> path;
+ GetLocationPath(&path);
+ return file()->GetSourceLocation(path, out_location);
+}
+
+bool MethodDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+ vector<int> path;
+ GetLocationPath(&path);
+ return service()->file()->GetSourceLocation(path, out_location);
+}
+
+bool ServiceDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+ vector<int> path;
+ GetLocationPath(&path);
+ return file()->GetSourceLocation(path, out_location);
+}
+
+bool EnumValueDescriptor::GetSourceLocation(
+ SourceLocation* out_location) const {
+ vector<int> path;
+ GetLocationPath(&path);
+ return type()->file()->GetSourceLocation(path, out_location);
+}
+
+void Descriptor::GetLocationPath(vector<int>* output) const {
+ if (containing_type()) {
+ containing_type()->GetLocationPath(output);
+ output->push_back(DescriptorProto::kNestedTypeFieldNumber);
+ output->push_back(index());
+ } else {
+ output->push_back(FileDescriptorProto::kMessageTypeFieldNumber);
+ output->push_back(index());
+ }
+}
+
+void FieldDescriptor::GetLocationPath(vector<int>* output) const {
+ containing_type()->GetLocationPath(output);
+ output->push_back(DescriptorProto::kFieldFieldNumber);
+ output->push_back(index());
+}
+
+void EnumDescriptor::GetLocationPath(vector<int>* output) const {
+ if (containing_type()) {
+ containing_type()->GetLocationPath(output);
+ output->push_back(DescriptorProto::kEnumTypeFieldNumber);
+ output->push_back(index());
+ } else {
+ output->push_back(FileDescriptorProto::kEnumTypeFieldNumber);
+ output->push_back(index());
+ }
+}
+
+void EnumValueDescriptor::GetLocationPath(vector<int>* output) const {
+ type()->GetLocationPath(output);
+ output->push_back(EnumDescriptorProto::kValueFieldNumber);
+ output->push_back(index());
+}
+
+void ServiceDescriptor::GetLocationPath(vector<int>* output) const {
+ output->push_back(FileDescriptorProto::kServiceFieldNumber);
+ output->push_back(index());
+}
+
+void MethodDescriptor::GetLocationPath(vector<int>* output) const {
+ service()->GetLocationPath(output);
+ output->push_back(ServiceDescriptorProto::kMethodFieldNumber);
+ output->push_back(index());
+}
+
// ===================================================================
namespace {
@@ -1859,6 +2154,7 @@
string filename_;
FileDescriptor* file_;
FileDescriptorTables* file_tables_;
+ set<const FileDescriptor*> dependencies_;
// If LookupSymbol() finds a symbol that is in a file which is not a declared
// dependency of this file, it will fail, but will set
@@ -1888,6 +2184,10 @@
// nested package within package_name.
bool IsInPackage(const FileDescriptor* file, const string& package_name);
+ // Helper function which finds all public dependencies of the given file, and
+ // stores the them in the dependencies_ set in the builder.
+ void RecordPublicDependencies(const FileDescriptor* file);
+
// Like tables_->FindSymbol(), but additionally:
// - Search the pool's underlay if not found in tables_.
// - Insure that the resulting Symbol is from one of the file's declared
@@ -1898,6 +2198,10 @@
// file's declared dependencies.
Symbol FindSymbolNotEnforcingDeps(const string& name);
+ // This implements the body of FindSymbolNotEnforcingDeps().
+ Symbol FindSymbolNotEnforcingDepsHelper(const DescriptorPool* pool,
+ const string& name);
+
// Like FindSymbol(), but looks up the name relative to some other symbol
// name. This first searches siblings of relative_to, then siblings of its
// parents, etc. For example, LookupSymbol("foo.bar", "baz.qux.corge") makes
@@ -2189,6 +2493,7 @@
void ValidateMapKey(FieldDescriptor* field,
const FieldDescriptorProto& proto);
+
};
const FileDescriptor* DescriptorPool::BuildFile(
@@ -2275,31 +2580,48 @@
file->package()[package_name.size()] == '.');
}
-Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const string& name) {
- Symbol result;
+void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) {
+ if (file == NULL || !dependencies_.insert(file).second) return;
+ for (int i = 0; file != NULL && i < file->public_dependency_count(); i++) {
+ RecordPublicDependencies(file->public_dependency(i));
+ }
+}
- // We need to search our pool and all its underlays.
- const DescriptorPool* pool = pool_;
- while (true) {
- // If we are looking at an underlay, we must lock its mutex_, since we are
- // accessing the underlay's tables_ dircetly.
- MutexLockMaybe lock((pool == pool_) ? NULL : pool->mutex_);
+Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper(
+ const DescriptorPool* pool, const string& name) {
+ // If we are looking at an underlay, we must lock its mutex_, since we are
+ // accessing the underlay's tables_ directly.
+ MutexLockMaybe lock((pool == pool_) ? NULL : pool->mutex_);
- // Note that we don't have to check fallback_database_ here because the
- // symbol has to be in one of its file's direct dependencies, and we have
- // already loaded those by the time we get here.
- result = pool->tables_->FindSymbol(name);
- if (!result.IsNull()) break;
- if (pool->underlay_ == NULL) return kNullSymbol;
- pool = pool->underlay_;
+ Symbol result = pool->tables_->FindSymbol(name);
+ if (result.IsNull() && pool->underlay_ != NULL) {
+ // Symbol not found; check the underlay.
+ result = FindSymbolNotEnforcingDepsHelper(pool->underlay_, name);
+ }
+
+ if (result.IsNull()) {
+ // In theory, we shouldn't need to check fallback_database_ because the
+ // symbol should be in one of its file's direct dependencies, and we have
+ // already loaded those by the time we get here. But we check anyway so
+ // that we can generate better error message when dependencies are missing
+ // (i.e., "missing dependency" rather than "type is not defined").
+ if (pool->TryFindSymbolInFallbackDatabase(name)) {
+ result = pool->tables_->FindSymbol(name);
+ }
}
return result;
}
+Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const string& name) {
+ return FindSymbolNotEnforcingDepsHelper(pool_, name);
+}
+
Symbol DescriptorBuilder::FindSymbol(const string& name) {
Symbol result = FindSymbolNotEnforcingDeps(name);
+ if (result.IsNull()) return result;
+
if (!pool_->enforce_dependencies_) {
// Hack for CompilerUpgrader.
return result;
@@ -2308,10 +2630,7 @@
// Only find symbols which were defined in this file or one of its
// dependencies.
const FileDescriptor* file = result.GetFile();
- if (file == file_) return result;
- for (int i = 0; i < file_->dependency_count(); i++) {
- if (file == file_->dependency(i)) return result;
- }
+ if (file == file_ || dependencies_.count(file) > 0) return result;
if (result.type == Symbol::PACKAGE) {
// Arg, this is overcomplicated. The symbol is a package name. It could
@@ -2322,12 +2641,10 @@
// dependency also defines the same package. We can't really rule out this
// symbol unless none of the dependencies define it.
if (IsInPackage(file_, name)) return result;
- for (int i = 0; i < file_->dependency_count(); i++) {
+ for (set<const FileDescriptor*>::const_iterator it = dependencies_.begin();
+ it != dependencies_.end(); ++it) {
// Note: A dependency may be NULL if it was not found or had errors.
- if (file_->dependency(i) != NULL &&
- IsInPackage(file_->dependency(i), name)) {
- return result;
- }
+ if (*it != NULL && IsInPackage(*it, name)) return result;
}
}
@@ -2448,6 +2765,8 @@
FileDescriptor* placeholder_file = tables_->Allocate<FileDescriptor>();
memset(placeholder_file, 0, sizeof(*placeholder_file));
+ placeholder_file->source_code_info_ = &SourceCodeInfo::default_instance();
+
placeholder_file->name_ =
tables_->AllocateString(*placeholder_full_name + ".placeholder.proto");
placeholder_file->package_ = placeholder_package;
@@ -2757,11 +3076,19 @@
}
// Checkpoint the tables so that we can roll back if something goes wrong.
- tables_->Checkpoint();
+ tables_->AddCheckpoint();
FileDescriptor* result = tables_->Allocate<FileDescriptor>();
file_ = result;
+ if (proto.has_source_code_info()) {
+ SourceCodeInfo *info = tables_->AllocateMessage<SourceCodeInfo>();
+ info->CopyFrom(proto.source_code_info());
+ result->source_code_info_ = info;
+ } else {
+ result->source_code_info_ = &SourceCodeInfo::default_instance();
+ }
+
file_tables_ = tables_->AllocateFileTables();
file_->tables_ = file_tables_;
@@ -2788,7 +3115,7 @@
"A file with this name is already in the pool.");
// Bail out early so that if this is actually the exact same file, we
// don't end up reporting that every single symbol is already defined.
- tables_->Rollback();
+ tables_->RollbackToLastCheckpoint();
return NULL;
}
if (!result->package().empty()) {
@@ -2833,6 +3160,45 @@
result->dependencies_[i] = dependency;
}
+ // Check public dependencies.
+ int public_dependency_count = 0;
+ result->public_dependencies_ = tables_->AllocateArray<int>(
+ proto.public_dependency_size());
+ for (int i = 0; i < proto.public_dependency_size(); i++) {
+ // Only put valid public dependency indexes.
+ int index = proto.public_dependency(i);
+ if (index >= 0 && index < proto.dependency_size()) {
+ result->public_dependencies_[public_dependency_count++] = index;
+ } else {
+ AddError(proto.name(), proto,
+ DescriptorPool::ErrorCollector::OTHER,
+ "Invalid public dependency index.");
+ }
+ }
+ result->public_dependency_count_ = public_dependency_count;
+
+ // Build dependency set
+ dependencies_.clear();
+ for (int i = 0; i < result->dependency_count(); i++) {
+ RecordPublicDependencies(result->dependency(i));
+ }
+
+ // Check weak dependencies.
+ int weak_dependency_count = 0;
+ result->weak_dependencies_ = tables_->AllocateArray<int>(
+ proto.weak_dependency_size());
+ for (int i = 0; i < proto.weak_dependency_size(); i++) {
+ int index = proto.weak_dependency(i);
+ if (index >= 0 && index < proto.dependency_size()) {
+ result->weak_dependencies_[weak_dependency_count++] = index;
+ } else {
+ AddError(proto.name(), proto,
+ DescriptorPool::ErrorCollector::OTHER,
+ "Invalid weak dependency index.");
+ }
+ }
+ result->weak_dependency_count_ = weak_dependency_count;
+
// Convert children.
BUILD_ARRAY(proto, result, message_type, BuildMessage , NULL);
BUILD_ARRAY(proto, result, enum_type , BuildEnum , NULL);
@@ -2870,10 +3236,10 @@
}
if (had_errors_) {
- tables_->Rollback();
+ tables_->RollbackToLastCheckpoint();
return NULL;
} else {
- tables_->Checkpoint();
+ tables_->ClearLastCheckpoint();
return result;
}
}
@@ -3065,7 +3431,7 @@
UnescapeCEscapeString(proto.default_value()));
} else {
result->default_value_string_ =
- tables_->AllocateString(proto.default_value());
+ tables_->AllocateString(proto.default_value());
}
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
@@ -3126,7 +3492,15 @@
if (result->number() <= 0) {
AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
"Field numbers must be positive integers.");
- } else if (result->number() > FieldDescriptor::kMaxNumber) {
+ } else if (!is_extension && result->number() > FieldDescriptor::kMaxNumber) {
+ // Only validate that the number is within the valid field range if it is
+ // not an extension. Since extension numbers are validated with the
+ // extendee's valid set of extension numbers, and those are in turn
+ // validated against the max allowed number, the check is unnecessary for
+ // extension fields.
+ // This avoids cross-linking issues that arise when attempting to check if
+ // the extendee is a message_set_wire_format message, which has a higher max
+ // on extension numbers.
AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
strings::Substitute("Field numbers cannot be greater than $0.",
FieldDescriptor::kMaxNumber));
@@ -3181,12 +3555,10 @@
"Extension numbers must be positive integers.");
}
- if (result->end > FieldDescriptor::kMaxNumber + 1) {
- AddError(parent->full_name(), proto,
- DescriptorPool::ErrorCollector::NUMBER,
- strings::Substitute("Extension numbers cannot be greater than $0.",
- FieldDescriptor::kMaxNumber));
- }
+ // Checking of the upper bound of the extension range is deferred until after
+ // options interpreting. This allows messages with message_set_wire_format to
+ // have extensions beyond FieldDescriptor::kMaxNumber, since the extension
+ // numbers are actually used as int32s in the message_set_wire_format.
if (result->start >= result->end) {
AddError(parent->full_name(), proto,
@@ -3681,6 +4053,20 @@
VALIDATE_OPTIONS_FROM_ARRAY(message, nested_type, Message);
VALIDATE_OPTIONS_FROM_ARRAY(message, enum_type, Enum);
VALIDATE_OPTIONS_FROM_ARRAY(message, extension, Field);
+
+ const int64 max_extension_range =
+ static_cast<int64>(message->options().message_set_wire_format() ?
+ kint32max :
+ FieldDescriptor::kMaxNumber);
+ for (int i = 0; i < message->extension_range_count(); ++i) {
+ if (message->extension_range(i)->end > max_extension_range + 1) {
+ AddError(
+ message->full_name(), proto.extension_range(i),
+ DescriptorPool::ErrorCollector::NUMBER,
+ strings::Substitute("Extension numbers cannot be greater than $0.",
+ max_extension_range));
+ }
+ }
}
void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field,
@@ -3689,6 +4075,15 @@
ValidateMapKey(field, proto);
}
+ // Only message type fields may be lazy.
+ if (field->options().lazy()) {
+ if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
+ AddError(field->full_name(), proto,
+ DescriptorPool::ErrorCollector::TYPE,
+ "[lazy = true] can only be specified for submessage fields.");
+ }
+ }
+
// Only repeated primitive fields may be packed.
if (field->options().packed() && !field->is_packable()) {
AddError(
@@ -3727,11 +4122,27 @@
"files. Note that you cannot extend a non-lite type to contain "
"a lite type, but the reverse is allowed.");
}
+
}
void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm,
const EnumDescriptorProto& proto) {
VALIDATE_OPTIONS_FROM_ARRAY(enm, value, EnumValue);
+ if (!enm->options().allow_alias()) {
+ map<int, string> used_values;
+ for (int i = 0; i < enm->value_count(); ++i) {
+ const EnumValueDescriptor* enum_value = enm->value(i);
+ if (used_values.find(enum_value->number()) != used_values.end()) {
+ AddError(enm->full_name(), proto,
+ DescriptorPool::ErrorCollector::NUMBER,
+ "\"" + enum_value->full_name() +
+ "\" uses the same enum value as \"" +
+ used_values[enum_value->number()] + "\"");
+ } else {
+ used_values[enum_value->number()] = enum_value->full_name();
+ }
+ }
+ }
}
void DescriptorBuilder::ValidateEnumValueOptions(
@@ -3811,6 +4222,7 @@
field->experimental_map_key_ = key_field;
}
+
#undef VALIDATE_OPTIONS_FROM_ARRAY
// -------------------------------------------------------------------
@@ -3901,9 +4313,11 @@
// file we're currently building. The descriptor should be there as long as
// the file we're building imported "google/protobuf/descriptors.proto".
- // Note that we use DescriptorBuilder::FindSymbol(), not
+ // Note that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
// DescriptorPool::FindMessageTypeByName() because we're already holding the
- // pool's mutex, and the latter method locks it again.
+ // pool's mutex, and the latter method locks it again. We don't use
+ // FindSymbol() because files that use custom options only need to depend on
+ // the file that defines the option, not descriptor.proto itself.
Symbol symbol = builder_->FindSymbolNotEnforcingDeps(
options->GetDescriptor()->full_name());
if (!symbol.IsNull() && symbol.type == Symbol::MESSAGE) {
@@ -3939,8 +4353,8 @@
// DescriptorPool::FindExtensionByName(), for two reasons: 1) It allows
// relative lookups, and 2) because we're already holding the pool's
// mutex, and the latter method locks it again.
- Symbol symbol = builder_->LookupSymbol(name_part,
- options_to_interpret_->name_scope);
+ symbol = builder_->LookupSymbol(name_part,
+ options_to_interpret_->name_scope);
if (!symbol.IsNull() && symbol.type == Symbol::FIELD) {
field = symbol.field_descriptor;
}
@@ -4344,14 +4758,32 @@
virtual const FieldDescriptor* FindExtension(
Message* message, const string& name) const {
assert_mutex_held(builder_->pool_);
+ const Descriptor* descriptor = message->GetDescriptor();
Symbol result = builder_->LookupSymbolNoPlaceholder(
- name, message->GetDescriptor()->full_name());
+ name, descriptor->full_name());
if (result.type == Symbol::FIELD &&
result.field_descriptor->is_extension()) {
return result.field_descriptor;
- } else {
- return NULL;
+ } else if (result.type == Symbol::MESSAGE &&
+ descriptor->options().message_set_wire_format()) {
+ const Descriptor* foreign_type = result.descriptor;
+ // The text format allows MessageSet items to be specified using
+ // the type name, rather than the extension identifier. If the symbol
+ // lookup returned a Message, and the enclosing Message has
+ // message_set_wire_format = true, then return the message set
+ // extension, if one exists.
+ for (int i = 0; i < foreign_type->extension_count(); i++) {
+ const FieldDescriptor* extension = foreign_type->extension(i);
+ if (extension->containing_type() == descriptor &&
+ extension->type() == FieldDescriptor::TYPE_MESSAGE &&
+ extension->is_optional() &&
+ extension->message_type() == foreign_type) {
+ // Found it.
+ return extension;
+ }
+ }
}
+ return NULL;
}
};
@@ -4409,7 +4841,13 @@
} else {
string serial;
dynamic->SerializeToString(&serial); // Never fails
- unknown_fields->AddLengthDelimited(option_field->number(), serial);
+ if (option_field->type() == FieldDescriptor::TYPE_MESSAGE) {
+ unknown_fields->AddLengthDelimited(option_field->number(), serial);
+ } else {
+ GOOGLE_CHECK_EQ(option_field->type(), FieldDescriptor::TYPE_GROUP);
+ UnknownFieldSet* group = unknown_fields->AddGroup(option_field->number());
+ group->ParseFromString(serial);
+ }
return true;
}
}
diff --git a/third_party/protobuf/src/google/protobuf/descriptor.h b/third_party/protobuf/src/google/protobuf/descriptor.h
index 7f87dd8..410d3ed 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor.h
+++ b/third_party/protobuf/src/google/protobuf/descriptor.h
@@ -89,6 +89,7 @@
class MethodOptions;
class FileOptions;
class UninterpretedOption;
+class SourceCodeInfo;
// Defined in message.h
class Message;
@@ -100,6 +101,20 @@
// Defined in unknown_field_set.h.
class UnknownField;
+// NB, all indices are zero-based.
+struct SourceLocation {
+ int start_line;
+ int end_line;
+ int start_column;
+ int end_column;
+
+ // Doc comments found at the source location.
+ // TODO(kenton): Maybe this struct should have been named SourceInfo or
+ // something instead. Oh well.
+ string leading_comments;
+ string trailing_comments;
+};
+
// Describes a type of protocol message, or a particular group within a
// message. To obtain the Descriptor for a given message object, call
// Message::GetDescriptor(). Generated message classes also have a
@@ -236,6 +251,13 @@
// this message type's scope.
const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const;
+ // Source Location ---------------------------------------------------
+
+ // Updates |*out_location| to the source location of the complete
+ // extent of this message declaration. Returns false and leaves
+ // |*out_location| unchanged iff location information was not available.
+ bool GetSourceLocation(SourceLocation* out_location) const;
+
private:
typedef MessageOptions OptionsType;
@@ -243,6 +265,10 @@
// correct depth
void DebugString(int depth, string *contents) const;
+ // Walks up the descriptor tree to generate the source location path
+ // to this descriptor from the file root.
+ void GetLocationPath(vector<int>* output) const;
+
const string* name_;
const string* full_name_;
const FileDescriptor* file_;
@@ -388,15 +414,19 @@
// when parsing formats which prefer to use camel-case naming style.
const string& camelcase_name() const;
- Type type() const; // Declared type of this field.
- CppType cpp_type() const; // C++ type of this field.
- Label label() const; // optional/required/repeated
+ Type type() const; // Declared type of this field.
+ const char* type_name() const; // Name of the declared type.
+ CppType cpp_type() const; // C++ type of this field.
+ const char* cpp_type_name() const; // Name of the C++ type.
+ Label label() const; // optional/required/repeated
bool is_required() const; // shorthand for label() == LABEL_REQUIRED
bool is_optional() const; // shorthand for label() == LABEL_OPTIONAL
bool is_repeated() const; // shorthand for label() == LABEL_REPEATED
bool is_packable() const; // shorthand for is_repeated() &&
// IsTypePackable(type())
+ bool is_packed() const; // shorthand for is_packable() &&
+ // options().packed()
// Index of this field within the message's field array, or the file or
// extension scope's extensions array.
@@ -479,6 +509,13 @@
// Return true iff [packed = true] is valid for fields of this type.
static inline bool IsTypePackable(Type field_type);
+ // Source Location ---------------------------------------------------
+
+ // Updates |*out_location| to the source location of the complete
+ // extent of this field declaration. Returns false and leaves
+ // |*out_location| unchanged iff location information was not available.
+ bool GetSourceLocation(SourceLocation* out_location) const;
+
private:
typedef FieldOptions OptionsType;
@@ -490,6 +527,10 @@
// types of CPPTYPE_STRING whill be surrounded by quotes and CEscaped.
string DefaultValueAsString(bool quote_string_type) const;
+ // Walks up the descriptor tree to generate the source location path
+ // to this descriptor from the file root.
+ void GetLocationPath(vector<int>* output) const;
+
const string* name_;
const string* full_name_;
const string* lowercase_name_;
@@ -527,6 +568,8 @@
static const char * const kTypeToName[MAX_TYPE + 1];
+ static const char * const kCppTypeToName[MAX_CPPTYPE + 1];
+
static const char * const kLabelToName[MAX_LABEL + 1];
// Must be constructed using DescriptorPool.
@@ -583,12 +626,23 @@
// See Descriptor::DebugString().
string DebugString() const;
+ // Source Location ---------------------------------------------------
+
+ // Updates |*out_location| to the source location of the complete
+ // extent of this enum declaration. Returns false and leaves
+ // |*out_location| unchanged iff location information was not available.
+ bool GetSourceLocation(SourceLocation* out_location) const;
+
private:
typedef EnumOptions OptionsType;
// See Descriptor::DebugString().
void DebugString(int depth, string *contents) const;
+ // Walks up the descriptor tree to generate the source location path
+ // to this descriptor from the file root.
+ void GetLocationPath(vector<int>* output) const;
+
const string* name_;
const string* full_name_;
const FileDescriptor* file_;
@@ -650,12 +704,23 @@
// See Descriptor::DebugString().
string DebugString() const;
+ // Source Location ---------------------------------------------------
+
+ // Updates |*out_location| to the source location of the complete
+ // extent of this enum value declaration. Returns false and leaves
+ // |*out_location| unchanged iff location information was not available.
+ bool GetSourceLocation(SourceLocation* out_location) const;
+
private:
typedef EnumValueOptions OptionsType;
// See Descriptor::DebugString().
void DebugString(int depth, string *contents) const;
+ // Walks up the descriptor tree to generate the source location path
+ // to this descriptor from the file root.
+ void GetLocationPath(vector<int>* output) const;
+
const string* name_;
const string* full_name_;
int number_;
@@ -703,19 +768,29 @@
// Look up a MethodDescriptor by name.
const MethodDescriptor* FindMethodByName(const string& name) const;
-
// See Descriptor::CopyTo().
void CopyTo(ServiceDescriptorProto* proto) const;
// See Descriptor::DebugString().
string DebugString() const;
+ // Source Location ---------------------------------------------------
+
+ // Updates |*out_location| to the source location of the complete
+ // extent of this service declaration. Returns false and leaves
+ // |*out_location| unchanged iff location information was not available.
+ bool GetSourceLocation(SourceLocation* out_location) const;
+
private:
typedef ServiceOptions OptionsType;
// See Descriptor::DebugString().
void DebugString(string *contents) const;
+ // Walks up the descriptor tree to generate the source location path
+ // to this descriptor from the file root.
+ void GetLocationPath(vector<int>* output) const;
+
const string* name_;
const string* full_name_;
const FileDescriptor* file_;
@@ -768,12 +843,23 @@
// See Descriptor::DebugString().
string DebugString() const;
+ // Source Location ---------------------------------------------------
+
+ // Updates |*out_location| to the source location of the complete
+ // extent of this method declaration. Returns false and leaves
+ // |*out_location| unchanged iff location information was not available.
+ bool GetSourceLocation(SourceLocation* out_location) const;
+
private:
typedef MethodOptions OptionsType;
// See Descriptor::DebugString().
void DebugString(int depth, string *contents) const;
+ // Walks up the descriptor tree to generate the source location path
+ // to this descriptor from the file root.
+ void GetLocationPath(vector<int>* output) const;
+
const string* name_;
const string* full_name_;
const ServiceDescriptor* service_;
@@ -791,6 +877,7 @@
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MethodDescriptor);
};
+
// Describes a whole .proto file. To get the FileDescriptor for a compiled-in
// file, get the descriptor for something defined in that file and call
// descriptor->file(). Use DescriptorPool to construct your own descriptors.
@@ -813,6 +900,22 @@
// These are returned in the order they were defined in the .proto file.
const FileDescriptor* dependency(int index) const;
+ // The number of files public imported by this one.
+ // The public dependency list is a subset of the dependency list.
+ int public_dependency_count() const;
+ // Gets a public imported file by index, where 0 <= index <
+ // public_dependency_count().
+ // These are returned in the order they were defined in the .proto file.
+ const FileDescriptor* public_dependency(int index) const;
+
+ // The number of files that are imported for weak fields.
+ // The weak dependency list is a subset of the dependency list.
+ int weak_dependency_count() const;
+ // Gets a weak imported file by index, where 0 <= index <
+ // weak_dependency_count().
+ // These are returned in the order they were defined in the .proto file.
+ const FileDescriptor* weak_dependency(int index) const;
+
// Number of top-level message types defined in this file. (This does not
// include nested types.)
int message_type_count() const;
@@ -866,12 +969,28 @@
const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const;
// See Descriptor::CopyTo().
+ // Notes:
+ // - This method does NOT copy source code information since it is relatively
+ // large and rarely needed. See CopySourceCodeInfoTo() below.
void CopyTo(FileDescriptorProto* proto) const;
+ // Write the source code information of this FileDescriptor into the given
+ // FileDescriptorProto. See CopyTo() above.
+ void CopySourceCodeInfoTo(FileDescriptorProto* proto) const;
// See Descriptor::DebugString().
string DebugString() const;
private:
+ // Source Location ---------------------------------------------------
+
+ // Updates |*out_location| to the source location of the complete
+ // extent of the declaration or declaration-part denoted by |path|.
+ // Returns false and leaves |*out_location| unchanged iff location
+ // information was not available. (See SourceCodeInfo for
+ // description of path encoding.)
+ bool GetSourceLocation(const vector<int>& path,
+ SourceLocation* out_location) const;
+
typedef FileOptions OptionsType;
const string* name_;
@@ -879,6 +998,10 @@
const DescriptorPool* pool_;
int dependency_count_;
const FileDescriptor** dependencies_;
+ int public_dependency_count_;
+ int* public_dependencies_;
+ int weak_dependency_count_;
+ int* weak_dependencies_;
int message_type_count_;
Descriptor* message_types_;
int enum_type_count_;
@@ -890,6 +1013,7 @@
const FileOptions* options_;
const FileDescriptorTables* tables_;
+ const SourceCodeInfo* source_code_info_;
// IMPORTANT: If you add a new field, make sure to search for all instances
// of Allocate<FileDescriptor>() and AllocateArray<FileDescriptor>() in
// descriptor.cc and update them to initialize the field.
@@ -899,6 +1023,8 @@
friend class Descriptor;
friend class FieldDescriptor;
friend class EnumDescriptor;
+ friend class EnumValueDescriptor;
+ friend class MethodDescriptor;
friend class ServiceDescriptor;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileDescriptor);
};
@@ -1106,7 +1232,7 @@
// For internal use only: Gets a non-const pointer to the generated pool.
// This is called at static-initialization time only, so thread-safety is
// not a concern. If both an underlay and a fallback database are present,
- // the fallback database takes precedence.
+ // the underlay takes precedence.
static DescriptorPool* internal_generated_pool();
// For internal use only: Changes the behavior of BuildFile() such that it
@@ -1132,6 +1258,11 @@
friend class FileDescriptor;
friend class DescriptorBuilder;
+ // Return true if the given name is a sub-symbol of any non-package
+ // descriptor that already exists in the descriptor pool. (The full
+ // definition of such types is already known.)
+ bool IsSubSymbolOfBuiltType(const string& name) const;
+
// Tries to find something in the fallback database and link in the
// corresponding proto file. Returns true if successful, in which case
// the caller should search for the thing again. These are declared
@@ -1262,11 +1393,12 @@
PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, input_type, const Descriptor*)
PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, output_type, const Descriptor*)
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(MethodDescriptor, MethodOptions);
-
PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, name)
PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, package)
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, pool, const DescriptorPool*)
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, dependency_count, int)
+PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, public_dependency_count, int)
+PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, weak_dependency_count, int)
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, message_type_count, int)
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, enum_type_count, int)
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, service_count, int)
@@ -1342,10 +1474,18 @@
return this - service_->methods_;
}
+inline const char* FieldDescriptor::type_name() const {
+ return kTypeToName[type_];
+}
+
inline FieldDescriptor::CppType FieldDescriptor::cpp_type() const {
return kTypeToCppTypeMap[type_];
}
+inline const char* FieldDescriptor::cpp_type_name() const {
+ return kCppTypeToName[kTypeToCppTypeMap[type_]];
+}
+
inline FieldDescriptor::CppType FieldDescriptor::TypeToCppType(Type type) {
return kTypeToCppTypeMap[type];
}
@@ -1361,6 +1501,16 @@
return dependencies_[index];
}
+inline const FileDescriptor* FileDescriptor::public_dependency(
+ int index) const {
+ return dependencies_[public_dependencies_[index]];
+}
+
+inline const FileDescriptor* FileDescriptor::weak_dependency(
+ int index) const {
+ return dependencies_[weak_dependencies_[index]];
+}
+
} // namespace protobuf
} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/descriptor.pb.cc b/third_party/protobuf/src/google/protobuf/descriptor.pb.cc
index 7d16080..a05414a 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor.pb.cc
+++ b/third_party/protobuf/src/google/protobuf/descriptor.pb.cc
@@ -1,14 +1,17 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/descriptor.proto
#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
#include "google/protobuf/descriptor.pb.h"
#include <algorithm>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/wire_format.h>
// @@protoc_insertion_point(includes)
@@ -108,10 +111,12 @@
::google::protobuf::MessageFactory::generated_factory(),
sizeof(FileDescriptorSet));
FileDescriptorProto_descriptor_ = file->message_type(1);
- static const int FileDescriptorProto_offsets_[9] = {
+ static const int FileDescriptorProto_offsets_[11] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, package_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, dependency_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, public_dependency_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, weak_dependency_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, message_type_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, enum_type_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, service_),
@@ -261,13 +266,14 @@
::google::protobuf::MessageFactory::generated_factory(),
sizeof(MethodDescriptorProto));
FileOptions_descriptor_ = file->message_type(8);
- static const int FileOptions_offsets_[10] = {
+ static const int FileOptions_offsets_[11] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, retain_unknown_fields_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generate_equals_and_hash_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, optimize_for_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, go_package_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_generic_services_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generic_services_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, py_generic_services_),
@@ -303,11 +309,13 @@
::google::protobuf::MessageFactory::generated_factory(),
sizeof(MessageOptions));
FieldOptions_descriptor_ = file->message_type(10);
- static const int FieldOptions_offsets_[5] = {
+ static const int FieldOptions_offsets_[7] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, packed_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, lazy_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, deprecated_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, experimental_map_key_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, weak_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, uninterpreted_option_),
};
FieldOptions_reflection_ =
@@ -323,7 +331,8 @@
sizeof(FieldOptions));
FieldOptions_CType_descriptor_ = FieldOptions_descriptor_->enum_type(0);
EnumOptions_descriptor_ = file->message_type(11);
- static const int EnumOptions_offsets_[1] = {
+ static const int EnumOptions_offsets_[2] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, allow_alias_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, uninterpreted_option_),
};
EnumOptions_reflection_ =
@@ -435,9 +444,11 @@
::google::protobuf::MessageFactory::generated_factory(),
sizeof(SourceCodeInfo));
SourceCodeInfo_Location_descriptor_ = SourceCodeInfo_descriptor_->nested_type(0);
- static const int SourceCodeInfo_Location_offsets_[2] = {
+ static const int SourceCodeInfo_Location_offsets_[4] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, span_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_comments_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, trailing_comments_),
};
SourceCodeInfo_Location_reflection_ =
new ::google::protobuf::internal::GeneratedMessageReflection(
@@ -554,107 +565,113 @@
if (already_here) return;
already_here = true;
GOOGLE_PROTOBUF_VERIFY_VERSION;
+
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n google/protobuf/descriptor.proto\022\017goog"
"le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file"
"\030\001 \003(\0132$.google.protobuf.FileDescriptorP"
- "roto\"\227\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001"
+ "roto\"\313\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001"
"(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022"
- "6\n\014message_type\030\004 \003(\0132 .google.protobuf."
- "DescriptorProto\0227\n\tenum_type\030\005 \003(\0132$.goo"
- "gle.protobuf.EnumDescriptorProto\0228\n\007serv"
- "ice\030\006 \003(\0132\'.google.protobuf.ServiceDescr"
- "iptorProto\0228\n\textension\030\007 \003(\0132%.google.p"
- "rotobuf.FieldDescriptorProto\022-\n\007options\030"
- "\010 \001(\0132\034.google.protobuf.FileOptions\0229\n\020s"
- "ource_code_info\030\t \001(\0132\037.google.protobuf."
- "SourceCodeInfo\"\251\003\n\017DescriptorProto\022\014\n\004na"
- "me\030\001 \001(\t\0224\n\005field\030\002 \003(\0132%.google.protobu"
- "f.FieldDescriptorProto\0228\n\textension\030\006 \003("
+ "\031\n\021public_dependency\030\n \003(\005\022\027\n\017weak_depen"
+ "dency\030\013 \003(\005\0226\n\014message_type\030\004 \003(\0132 .goog"
+ "le.protobuf.DescriptorProto\0227\n\tenum_type"
+ "\030\005 \003(\0132$.google.protobuf.EnumDescriptorP"
+ "roto\0228\n\007service\030\006 \003(\0132\'.google.protobuf."
+ "ServiceDescriptorProto\0228\n\textension\030\007 \003("
"\0132%.google.protobuf.FieldDescriptorProto"
- "\0225\n\013nested_type\030\003 \003(\0132 .google.protobuf."
- "DescriptorProto\0227\n\tenum_type\030\004 \003(\0132$.goo"
- "gle.protobuf.EnumDescriptorProto\022H\n\017exte"
- "nsion_range\030\005 \003(\0132/.google.protobuf.Desc"
- "riptorProto.ExtensionRange\0220\n\007options\030\007 "
- "\001(\0132\037.google.protobuf.MessageOptions\032,\n\016"
- "ExtensionRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001"
- "(\005\"\224\005\n\024FieldDescriptorProto\022\014\n\004name\030\001 \001("
- "\t\022\016\n\006number\030\003 \001(\005\022:\n\005label\030\004 \001(\0162+.googl"
- "e.protobuf.FieldDescriptorProto.Label\0228\n"
- "\004type\030\005 \001(\0162*.google.protobuf.FieldDescr"
- "iptorProto.Type\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010ex"
- "tendee\030\002 \001(\t\022\025\n\rdefault_value\030\007 \001(\t\022.\n\007o"
- "ptions\030\010 \001(\0132\035.google.protobuf.FieldOpti"
- "ons\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FL"
- "OAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016"
- "\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE"
- "_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING"
- "\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\n"
- "TYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_EN"
- "UM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rTYPE_SFIXED64"
- "\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005"
- "Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n\016LABEL_REQUI"
- "RED\020\002\022\022\n\016LABEL_REPEATED\020\003\"\214\001\n\023EnumDescri"
- "ptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002 \003(\0132)"
- ".google.protobuf.EnumValueDescriptorProt"
- "o\022-\n\007options\030\003 \001(\0132\034.google.protobuf.Enu"
- "mOptions\"l\n\030EnumValueDescriptorProto\022\014\n\004"
- "name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007options\030\003 "
- "\001(\0132!.google.protobuf.EnumValueOptions\"\220"
- "\001\n\026ServiceDescriptorProto\022\014\n\004name\030\001 \001(\t\022"
- "6\n\006method\030\002 \003(\0132&.google.protobuf.Method"
- "DescriptorProto\0220\n\007options\030\003 \001(\0132\037.googl"
- "e.protobuf.ServiceOptions\"\177\n\025MethodDescr"
- "iptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\ninput_type\030\002"
- " \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n\007options\030\004 \001"
- "(\0132\036.google.protobuf.MethodOptions\"\373\003\n\013F"
- "ileOptions\022\024\n\014java_package\030\001 \001(\t\022\034\n\024java"
- "_outer_classname\030\010 \001(\t\022\"\n\023java_multiple_"
- "files\030\n \001(\010:\005false\022$\n\025retain_unknown_fie"
- "lds\030\013 \001(\010:\005false\022,\n\035java_generate_equals"
- "_and_hash\030\024 \001(\010:\005false\022F\n\014optimize_for\030\t"
- " \001(\0162).google.protobuf.FileOptions.Optim"
- "izeMode:\005SPEED\022\"\n\023cc_generic_services\030\020 "
- "\001(\010:\005false\022$\n\025java_generic_services\030\021 \001("
- "\010:\005false\022\"\n\023py_generic_services\030\022 \001(\010:\005f"
- "alse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go"
- "ogle.protobuf.UninterpretedOption\":\n\014Opt"
- "imizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014L"
- "ITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\270\001\n\016MessageOpti"
- "ons\022&\n\027message_set_wire_format\030\001 \001(\010:\005fa"
- "lse\022.\n\037no_standard_descriptor_accessor\030\002"
- " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003"
- "(\0132$.google.protobuf.UninterpretedOption"
- "*\t\010\350\007\020\200\200\200\200\002\"\224\002\n\014FieldOptions\022:\n\005ctype\030\001 "
- "\001(\0162#.google.protobuf.FieldOptions.CType"
- ":\006STRING\022\016\n\006packed\030\002 \001(\010\022\031\n\ndeprecated\030\003"
- " \001(\010:\005false\022\034\n\024experimental_map_key\030\t \001("
- "\t\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.googl"
- "e.protobuf.UninterpretedOption\"/\n\005CType\022"
- "\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*"
- "\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022C\n\024uninterpret"
- "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint"
- "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"b\n\020EnumValueOp"
- "tions\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.g"
- "oogle.protobuf.UninterpretedOption*\t\010\350\007\020"
- "\200\200\200\200\002\"`\n\016ServiceOptions\022C\n\024uninterpreted"
- "_option\030\347\007 \003(\0132$.google.protobuf.Uninter"
- "pretedOption*\t\010\350\007\020\200\200\200\200\002\"_\n\rMethodOptions"
- "\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.google"
- ".protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002"
- "\"\236\002\n\023UninterpretedOption\022;\n\004name\030\002 \003(\0132-"
- ".google.protobuf.UninterpretedOption.Nam"
- "ePart\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022posit"
- "ive_int_value\030\004 \001(\004\022\032\n\022negative_int_valu"
- "e\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014string_"
- "value\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010"
- "NamePart\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extens"
- "ion\030\002 \002(\010\"|\n\016SourceCodeInfo\022:\n\010location\030"
- "\001 \003(\0132(.google.protobuf.SourceCodeInfo.L"
- "ocation\032.\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n"
- "\004span\030\002 \003(\005B\002\020\001B)\n\023com.google.protobufB\020"
- "DescriptorProtosH\001", 3978);
+ "\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File"
+ "Options\0229\n\020source_code_info\030\t \001(\0132\037.goog"
+ "le.protobuf.SourceCodeInfo\"\251\003\n\017Descripto"
+ "rProto\022\014\n\004name\030\001 \001(\t\0224\n\005field\030\002 \003(\0132%.go"
+ "ogle.protobuf.FieldDescriptorProto\0228\n\tex"
+ "tension\030\006 \003(\0132%.google.protobuf.FieldDes"
+ "criptorProto\0225\n\013nested_type\030\003 \003(\0132 .goog"
+ "le.protobuf.DescriptorProto\0227\n\tenum_type"
+ "\030\004 \003(\0132$.google.protobuf.EnumDescriptorP"
+ "roto\022H\n\017extension_range\030\005 \003(\0132/.google.p"
+ "rotobuf.DescriptorProto.ExtensionRange\0220"
+ "\n\007options\030\007 \001(\0132\037.google.protobuf.Messag"
+ "eOptions\032,\n\016ExtensionRange\022\r\n\005start\030\001 \001("
+ "\005\022\013\n\003end\030\002 \001(\005\"\224\005\n\024FieldDescriptorProto\022"
+ "\014\n\004name\030\001 \001(\t\022\016\n\006number\030\003 \001(\005\022:\n\005label\030\004"
+ " \001(\0162+.google.protobuf.FieldDescriptorPr"
+ "oto.Label\0228\n\004type\030\005 \001(\0162*.google.protobu"
+ "f.FieldDescriptorProto.Type\022\021\n\ttype_name"
+ "\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022\025\n\rdefault_valu"
+ "e\030\007 \001(\t\022.\n\007options\030\010 \001(\0132\035.google.protob"
+ "uf.FieldOptions\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020"
+ "\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYP"
+ "E_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED"
+ "64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n"
+ "\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_M"
+ "ESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020"
+ "\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rT"
+ "YPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_"
+ "SINT64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n"
+ "\016LABEL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\"\214\001"
+ "\n\023EnumDescriptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005v"
+ "alue\030\002 \003(\0132).google.protobuf.EnumValueDe"
+ "scriptorProto\022-\n\007options\030\003 \001(\0132\034.google."
+ "protobuf.EnumOptions\"l\n\030EnumValueDescrip"
+ "torProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222"
+ "\n\007options\030\003 \001(\0132!.google.protobuf.EnumVa"
+ "lueOptions\"\220\001\n\026ServiceDescriptorProto\022\014\n"
+ "\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.pro"
+ "tobuf.MethodDescriptorProto\0220\n\007options\030\003"
+ " \001(\0132\037.google.protobuf.ServiceOptions\"\177\n"
+ "\025MethodDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\n"
+ "input_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n"
+ "\007options\030\004 \001(\0132\036.google.protobuf.MethodO"
+ "ptions\"\217\004\n\013FileOptions\022\024\n\014java_package\030\001"
+ " \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023ja"
+ "va_multiple_files\030\n \001(\010:\005false\022$\n\025retain"
+ "_unknown_fields\030\014 \001(\010:\005false\022,\n\035java_gen"
+ "erate_equals_and_hash\030\024 \001(\010:\005false\022F\n\014op"
+ "timize_for\030\t \001(\0162).google.protobuf.FileO"
+ "ptions.OptimizeMode:\005SPEED\022\022\n\ngo_package"
+ "\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005fal"
+ "se\022$\n\025java_generic_services\030\021 \001(\010:\005false"
+ "\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022C\n\024"
+ "uninterpreted_option\030\347\007 \003(\0132$.google.pro"
+ "tobuf.UninterpretedOption\":\n\014OptimizeMod"
+ "e\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNT"
+ "IME\020\003*\t\010\350\007\020\200\200\200\200\002\"\270\001\n\016MessageOptions\022&\n\027m"
+ "essage_set_wire_format\030\001 \001(\010:\005false\022.\n\037n"
+ "o_standard_descriptor_accessor\030\002 \001(\010:\005fa"
+ "lse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo"
+ "gle.protobuf.UninterpretedOption*\t\010\350\007\020\200\200"
+ "\200\200\002\"\276\002\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#.go"
+ "ogle.protobuf.FieldOptions.CType:\006STRING"
+ "\022\016\n\006packed\030\002 \001(\010\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n"
+ "\ndeprecated\030\003 \001(\010:\005false\022\034\n\024experimental"
+ "_map_key\030\t \001(\t\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024u"
+ "ninterpreted_option\030\347\007 \003(\0132$.google.prot"
+ "obuf.UninterpretedOption\"/\n\005CType\022\n\n\006STR"
+ "ING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200"
+ "\200\200\200\002\"x\n\013EnumOptions\022\031\n\013allow_alias\030\002 \001(\010"
+ ":\004true\022C\n\024uninterpreted_option\030\347\007 \003(\0132$."
+ "google.protobuf.UninterpretedOption*\t\010\350\007"
+ "\020\200\200\200\200\002\"b\n\020EnumValueOptions\022C\n\024uninterpre"
+ "ted_option\030\347\007 \003(\0132$.google.protobuf.Unin"
+ "terpretedOption*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceOpt"
+ "ions\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go"
+ "ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200"
+ "\200\200\200\002\"_\n\rMethodOptions\022C\n\024uninterpreted_o"
+ "ption\030\347\007 \003(\0132$.google.protobuf.Uninterpr"
+ "etedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedO"
+ "ption\022;\n\004name\030\002 \003(\0132-.google.protobuf.Un"
+ "interpretedOption.NamePart\022\030\n\020identifier"
+ "_value\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004"
+ "\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014double_v"
+ "alue\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggr"
+ "egate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_pa"
+ "rt\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\261\001\n\016Sourc"
+ "eCodeInfo\022:\n\010location\030\001 \003(\0132(.google.pro"
+ "tobuf.SourceCodeInfo.Location\032c\n\010Locatio"
+ "n\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n"
+ "\020leading_comments\030\003 \001(\t\022\031\n\021trailing_comm"
+ "ents\030\004 \001(\tB)\n\023com.google.protobufB\020Descr"
+ "iptorProtosH\001", 4173);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -788,14 +805,15 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -811,7 +829,7 @@
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
1, this->file(i), output);
}
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -826,7 +844,7 @@
WriteMessageNoVirtualToArray(
1, this->file(i), target);
}
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -836,7 +854,7 @@
int FileDescriptorSet::ByteSize() const {
int total_size = 0;
-
+
// repeated .google.protobuf.FileDescriptorProto file = 1;
total_size += 1 * this->file_size();
for (int i = 0; i < this->file_size(); i++) {
@@ -844,7 +862,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->file(i));
}
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -887,7 +905,7 @@
}
bool FileDescriptorSet::IsInitialized() const {
-
+
for (int i = 0; i < file_size(); i++) {
if (!this->file(i).IsInitialized()) return false;
}
@@ -918,6 +936,8 @@
const int FileDescriptorProto::kNameFieldNumber;
const int FileDescriptorProto::kPackageFieldNumber;
const int FileDescriptorProto::kDependencyFieldNumber;
+const int FileDescriptorProto::kPublicDependencyFieldNumber;
+const int FileDescriptorProto::kWeakDependencyFieldNumber;
const int FileDescriptorProto::kMessageTypeFieldNumber;
const int FileDescriptorProto::kEnumTypeFieldNumber;
const int FileDescriptorProto::kServiceFieldNumber;
@@ -1001,16 +1021,18 @@
package_->clear();
}
}
+ }
+ if (_has_bits_[9 / 32] & (0xffu << (9 % 32))) {
if (has_options()) {
if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
}
- }
- if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
if (has_source_code_info()) {
if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
}
}
dependency_.Clear();
+ public_dependency_.Clear();
+ weak_dependency_.Clear();
message_type_.Clear();
enum_type_.Clear();
service_.Clear();
@@ -1040,7 +1062,7 @@
if (input->ExpectTag(18)) goto parse_package;
break;
}
-
+
// optional string package = 2;
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1057,7 +1079,7 @@
if (input->ExpectTag(26)) goto parse_dependency;
break;
}
-
+
// repeated string dependency = 3;
case 3: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1076,7 +1098,7 @@
if (input->ExpectTag(34)) goto parse_message_type;
break;
}
-
+
// repeated .google.protobuf.DescriptorProto message_type = 4;
case 4: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1091,7 +1113,7 @@
if (input->ExpectTag(42)) goto parse_enum_type;
break;
}
-
+
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
case 5: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1106,7 +1128,7 @@
if (input->ExpectTag(50)) goto parse_service;
break;
}
-
+
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
case 6: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1121,7 +1143,7 @@
if (input->ExpectTag(58)) goto parse_extension;
break;
}
-
+
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
case 7: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1136,7 +1158,7 @@
if (input->ExpectTag(66)) goto parse_options;
break;
}
-
+
// optional .google.protobuf.FileOptions options = 8;
case 8: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1150,7 +1172,7 @@
if (input->ExpectTag(74)) goto parse_source_code_info;
break;
}
-
+
// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
case 9: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1161,17 +1183,62 @@
} else {
goto handle_uninterpreted;
}
+ if (input->ExpectTag(80)) goto parse_public_dependency;
+ break;
+ }
+
+ // repeated int32 public_dependency = 10;
+ case 10: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_public_dependency:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ 1, 80, input, this->mutable_public_dependency())));
+ } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
+ == ::google::protobuf::internal::WireFormatLite::
+ WIRETYPE_LENGTH_DELIMITED) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, this->mutable_public_dependency())));
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(80)) goto parse_public_dependency;
+ if (input->ExpectTag(88)) goto parse_weak_dependency;
+ break;
+ }
+
+ // repeated int32 weak_dependency = 11;
+ case 11: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_weak_dependency:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ 1, 88, input, this->mutable_weak_dependency())));
+ } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
+ == ::google::protobuf::internal::WireFormatLite::
+ WIRETYPE_LENGTH_DELIMITED) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, this->mutable_weak_dependency())));
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(88)) goto parse_weak_dependency;
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -1190,7 +1257,7 @@
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->name(), output);
}
-
+
// optional string package = 2;
if (has_package()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -1199,7 +1266,7 @@
::google::protobuf::internal::WireFormatLite::WriteString(
2, this->package(), output);
}
-
+
// repeated string dependency = 3;
for (int i = 0; i < this->dependency_size(); i++) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -1208,43 +1275,55 @@
::google::protobuf::internal::WireFormatLite::WriteString(
3, this->dependency(i), output);
}
-
+
// repeated .google.protobuf.DescriptorProto message_type = 4;
for (int i = 0; i < this->message_type_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
4, this->message_type(i), output);
}
-
+
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
for (int i = 0; i < this->enum_type_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
5, this->enum_type(i), output);
}
-
+
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
for (int i = 0; i < this->service_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
6, this->service(i), output);
}
-
+
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
for (int i = 0; i < this->extension_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
7, this->extension(i), output);
}
-
+
// optional .google.protobuf.FileOptions options = 8;
if (has_options()) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
8, this->options(), output);
}
-
+
// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
if (has_source_code_info()) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
9, this->source_code_info(), output);
}
-
+
+ // repeated int32 public_dependency = 10;
+ for (int i = 0; i < this->public_dependency_size(); i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(
+ 10, this->public_dependency(i), output);
+ }
+
+ // repeated int32 weak_dependency = 11;
+ for (int i = 0; i < this->weak_dependency_size(); i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(
+ 11, this->weak_dependency(i), output);
+ }
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -1262,7 +1341,7 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
}
-
+
// optional string package = 2;
if (has_package()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -1272,7 +1351,7 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
2, this->package(), target);
}
-
+
// repeated string dependency = 3;
for (int i = 0; i < this->dependency_size(); i++) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -1281,49 +1360,61 @@
target = ::google::protobuf::internal::WireFormatLite::
WriteStringToArray(3, this->dependency(i), target);
}
-
+
// repeated .google.protobuf.DescriptorProto message_type = 4;
for (int i = 0; i < this->message_type_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
4, this->message_type(i), target);
}
-
+
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
for (int i = 0; i < this->enum_type_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
5, this->enum_type(i), target);
}
-
+
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
for (int i = 0; i < this->service_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
6, this->service(i), target);
}
-
+
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
for (int i = 0; i < this->extension_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
7, this->extension(i), target);
}
-
+
// optional .google.protobuf.FileOptions options = 8;
if (has_options()) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
8, this->options(), target);
}
-
+
// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
if (has_source_code_info()) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
9, this->source_code_info(), target);
}
-
+
+ // repeated int32 public_dependency = 10;
+ for (int i = 0; i < this->public_dependency_size(); i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteInt32ToArray(10, this->public_dependency(i), target);
+ }
+
+ // repeated int32 weak_dependency = 11;
+ for (int i = 0; i < this->weak_dependency_size(); i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteInt32ToArray(11, this->weak_dependency(i), target);
+ }
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -1333,7 +1424,7 @@
int FileDescriptorProto::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// optional string name = 1;
if (has_name()) {
@@ -1341,30 +1432,30 @@
::google::protobuf::internal::WireFormatLite::StringSize(
this->name());
}
-
+
// optional string package = 2;
if (has_package()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->package());
}
-
+
+ }
+ if (_has_bits_[9 / 32] & (0xffu << (9 % 32))) {
// optional .google.protobuf.FileOptions options = 8;
if (has_options()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->options());
}
-
- }
- if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+
// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
if (has_source_code_info()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->source_code_info());
}
-
+
}
// repeated string dependency = 3;
total_size += 1 * this->dependency_size();
@@ -1372,7 +1463,27 @@
total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
this->dependency(i));
}
-
+
+ // repeated int32 public_dependency = 10;
+ {
+ int data_size = 0;
+ for (int i = 0; i < this->public_dependency_size(); i++) {
+ data_size += ::google::protobuf::internal::WireFormatLite::
+ Int32Size(this->public_dependency(i));
+ }
+ total_size += 1 * this->public_dependency_size() + data_size;
+ }
+
+ // repeated int32 weak_dependency = 11;
+ {
+ int data_size = 0;
+ for (int i = 0; i < this->weak_dependency_size(); i++) {
+ data_size += ::google::protobuf::internal::WireFormatLite::
+ Int32Size(this->weak_dependency(i));
+ }
+ total_size += 1 * this->weak_dependency_size() + data_size;
+ }
+
// repeated .google.protobuf.DescriptorProto message_type = 4;
total_size += 1 * this->message_type_size();
for (int i = 0; i < this->message_type_size(); i++) {
@@ -1380,7 +1491,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->message_type(i));
}
-
+
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
total_size += 1 * this->enum_type_size();
for (int i = 0; i < this->enum_type_size(); i++) {
@@ -1388,7 +1499,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->enum_type(i));
}
-
+
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
total_size += 1 * this->service_size();
for (int i = 0; i < this->service_size(); i++) {
@@ -1396,7 +1507,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->service(i));
}
-
+
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
total_size += 1 * this->extension_size();
for (int i = 0; i < this->extension_size(); i++) {
@@ -1404,7 +1515,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->extension(i));
}
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -1431,6 +1542,8 @@
void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) {
GOOGLE_CHECK_NE(&from, this);
dependency_.MergeFrom(from.dependency_);
+ public_dependency_.MergeFrom(from.public_dependency_);
+ weak_dependency_.MergeFrom(from.weak_dependency_);
message_type_.MergeFrom(from.message_type_);
enum_type_.MergeFrom(from.enum_type_);
service_.MergeFrom(from.service_);
@@ -1442,11 +1555,11 @@
if (from.has_package()) {
set_package(from.package());
}
+ }
+ if (from._has_bits_[9 / 32] & (0xffu << (9 % 32))) {
if (from.has_options()) {
mutable_options()->::google::protobuf::FileOptions::MergeFrom(from.options());
}
- }
- if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
if (from.has_source_code_info()) {
mutable_source_code_info()->::google::protobuf::SourceCodeInfo::MergeFrom(from.source_code_info());
}
@@ -1467,7 +1580,7 @@
}
bool FileDescriptorProto::IsInitialized() const {
-
+
for (int i = 0; i < message_type_size(); i++) {
if (!this->message_type(i).IsInitialized()) return false;
}
@@ -1491,6 +1604,8 @@
std::swap(name_, other->name_);
std::swap(package_, other->package_);
dependency_.Swap(&other->dependency_);
+ public_dependency_.Swap(&other->public_dependency_);
+ weak_dependency_.Swap(&other->weak_dependency_);
message_type_.Swap(&other->message_type_);
enum_type_.Swap(&other->enum_type_);
service_.Swap(&other->service_);
@@ -1599,7 +1714,7 @@
if (input->ExpectTag(16)) goto parse_end;
break;
}
-
+
// optional int32 end = 2;
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1615,14 +1730,15 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -1637,12 +1753,12 @@
if (has_start()) {
::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output);
}
-
+
// optional int32 end = 2;
if (has_end()) {
::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output);
}
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -1655,12 +1771,12 @@
if (has_start()) {
target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target);
}
-
+
// optional int32 end = 2;
if (has_end()) {
target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target);
}
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -1670,7 +1786,7 @@
int DescriptorProto_ExtensionRange::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// optional int32 start = 1;
if (has_start()) {
@@ -1678,14 +1794,14 @@
::google::protobuf::internal::WireFormatLite::Int32Size(
this->start());
}
-
+
// optional int32 end = 2;
if (has_end()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::Int32Size(
this->end());
}
-
+
}
if (!unknown_fields().empty()) {
total_size +=
@@ -1736,7 +1852,7 @@
}
bool DescriptorProto_ExtensionRange::IsInitialized() const {
-
+
return true;
}
@@ -1868,7 +1984,7 @@
if (input->ExpectTag(18)) goto parse_field;
break;
}
-
+
// repeated .google.protobuf.FieldDescriptorProto field = 2;
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1883,7 +1999,7 @@
if (input->ExpectTag(26)) goto parse_nested_type;
break;
}
-
+
// repeated .google.protobuf.DescriptorProto nested_type = 3;
case 3: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1898,7 +2014,7 @@
if (input->ExpectTag(34)) goto parse_enum_type;
break;
}
-
+
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
case 4: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1913,7 +2029,7 @@
if (input->ExpectTag(42)) goto parse_extension_range;
break;
}
-
+
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
case 5: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1928,7 +2044,7 @@
if (input->ExpectTag(50)) goto parse_extension;
break;
}
-
+
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
case 6: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1943,7 +2059,7 @@
if (input->ExpectTag(58)) goto parse_options;
break;
}
-
+
// optional .google.protobuf.MessageOptions options = 7;
case 7: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -1957,14 +2073,15 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -1983,43 +2100,43 @@
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->name(), output);
}
-
+
// repeated .google.protobuf.FieldDescriptorProto field = 2;
for (int i = 0; i < this->field_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
2, this->field(i), output);
}
-
+
// repeated .google.protobuf.DescriptorProto nested_type = 3;
for (int i = 0; i < this->nested_type_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
3, this->nested_type(i), output);
}
-
+
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
for (int i = 0; i < this->enum_type_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
4, this->enum_type(i), output);
}
-
+
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
for (int i = 0; i < this->extension_range_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
5, this->extension_range(i), output);
}
-
+
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
for (int i = 0; i < this->extension_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
6, this->extension(i), output);
}
-
+
// optional .google.protobuf.MessageOptions options = 7;
if (has_options()) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
7, this->options(), output);
}
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -2037,49 +2154,49 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
}
-
+
// repeated .google.protobuf.FieldDescriptorProto field = 2;
for (int i = 0; i < this->field_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
2, this->field(i), target);
}
-
+
// repeated .google.protobuf.DescriptorProto nested_type = 3;
for (int i = 0; i < this->nested_type_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
3, this->nested_type(i), target);
}
-
+
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
for (int i = 0; i < this->enum_type_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
4, this->enum_type(i), target);
}
-
+
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
for (int i = 0; i < this->extension_range_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
5, this->extension_range(i), target);
}
-
+
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
for (int i = 0; i < this->extension_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
6, this->extension(i), target);
}
-
+
// optional .google.protobuf.MessageOptions options = 7;
if (has_options()) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
7, this->options(), target);
}
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -2089,7 +2206,7 @@
int DescriptorProto::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// optional string name = 1;
if (has_name()) {
@@ -2097,14 +2214,14 @@
::google::protobuf::internal::WireFormatLite::StringSize(
this->name());
}
-
+
// optional .google.protobuf.MessageOptions options = 7;
if (has_options()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->options());
}
-
+
}
// repeated .google.protobuf.FieldDescriptorProto field = 2;
total_size += 1 * this->field_size();
@@ -2113,7 +2230,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->field(i));
}
-
+
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
total_size += 1 * this->extension_size();
for (int i = 0; i < this->extension_size(); i++) {
@@ -2121,7 +2238,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->extension(i));
}
-
+
// repeated .google.protobuf.DescriptorProto nested_type = 3;
total_size += 1 * this->nested_type_size();
for (int i = 0; i < this->nested_type_size(); i++) {
@@ -2129,7 +2246,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->nested_type(i));
}
-
+
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
total_size += 1 * this->enum_type_size();
for (int i = 0; i < this->enum_type_size(); i++) {
@@ -2137,7 +2254,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->enum_type(i));
}
-
+
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
total_size += 1 * this->extension_range_size();
for (int i = 0; i < this->extension_range_size(); i++) {
@@ -2145,7 +2262,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->extension_range(i));
}
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -2200,7 +2317,7 @@
}
bool DescriptorProto::IsInitialized() const {
-
+
for (int i = 0; i < field_size(); i++) {
if (!this->field(i).IsInitialized()) return false;
}
@@ -2457,7 +2574,7 @@
if (input->ExpectTag(18)) goto parse_extendee;
break;
}
-
+
// optional string extendee = 2;
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -2474,7 +2591,7 @@
if (input->ExpectTag(24)) goto parse_number;
break;
}
-
+
// optional int32 number = 3;
case 3: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -2490,7 +2607,7 @@
if (input->ExpectTag(32)) goto parse_label;
break;
}
-
+
// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
case 4: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -2511,7 +2628,7 @@
if (input->ExpectTag(40)) goto parse_type;
break;
}
-
+
// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
case 5: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -2532,7 +2649,7 @@
if (input->ExpectTag(50)) goto parse_type_name;
break;
}
-
+
// optional string type_name = 6;
case 6: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -2549,7 +2666,7 @@
if (input->ExpectTag(58)) goto parse_default_value;
break;
}
-
+
// optional string default_value = 7;
case 7: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -2566,7 +2683,7 @@
if (input->ExpectTag(66)) goto parse_options;
break;
}
-
+
// optional .google.protobuf.FieldOptions options = 8;
case 8: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -2580,14 +2697,15 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -2606,7 +2724,7 @@
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->name(), output);
}
-
+
// optional string extendee = 2;
if (has_extendee()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2615,24 +2733,24 @@
::google::protobuf::internal::WireFormatLite::WriteString(
2, this->extendee(), output);
}
-
+
// optional int32 number = 3;
if (has_number()) {
::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->number(), output);
}
-
+
// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
if (has_label()) {
::google::protobuf::internal::WireFormatLite::WriteEnum(
4, this->label(), output);
}
-
+
// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
if (has_type()) {
::google::protobuf::internal::WireFormatLite::WriteEnum(
5, this->type(), output);
}
-
+
// optional string type_name = 6;
if (has_type_name()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2641,7 +2759,7 @@
::google::protobuf::internal::WireFormatLite::WriteString(
6, this->type_name(), output);
}
-
+
// optional string default_value = 7;
if (has_default_value()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2650,13 +2768,13 @@
::google::protobuf::internal::WireFormatLite::WriteString(
7, this->default_value(), output);
}
-
+
// optional .google.protobuf.FieldOptions options = 8;
if (has_options()) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
8, this->options(), output);
}
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -2674,7 +2792,7 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
}
-
+
// optional string extendee = 2;
if (has_extendee()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2684,24 +2802,24 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
2, this->extendee(), target);
}
-
+
// optional int32 number = 3;
if (has_number()) {
target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->number(), target);
}
-
+
// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
if (has_label()) {
target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
4, this->label(), target);
}
-
+
// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
if (has_type()) {
target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
5, this->type(), target);
}
-
+
// optional string type_name = 6;
if (has_type_name()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2711,7 +2829,7 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
6, this->type_name(), target);
}
-
+
// optional string default_value = 7;
if (has_default_value()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2721,14 +2839,14 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
7, this->default_value(), target);
}
-
+
// optional .google.protobuf.FieldOptions options = 8;
if (has_options()) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
8, this->options(), target);
}
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -2738,7 +2856,7 @@
int FieldDescriptorProto::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// optional string name = 1;
if (has_name()) {
@@ -2746,54 +2864,54 @@
::google::protobuf::internal::WireFormatLite::StringSize(
this->name());
}
-
+
// optional int32 number = 3;
if (has_number()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::Int32Size(
this->number());
}
-
+
// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
if (has_label()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::EnumSize(this->label());
}
-
+
// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
if (has_type()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::EnumSize(this->type());
}
-
+
// optional string type_name = 6;
if (has_type_name()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->type_name());
}
-
+
// optional string extendee = 2;
if (has_extendee()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->extendee());
}
-
+
// optional string default_value = 7;
if (has_default_value()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->default_value());
}
-
+
// optional .google.protobuf.FieldOptions options = 8;
if (has_options()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->options());
}
-
+
}
if (!unknown_fields().empty()) {
total_size +=
@@ -2862,7 +2980,7 @@
}
bool FieldDescriptorProto::IsInitialized() const {
-
+
if (has_options()) {
if (!this->options().IsInitialized()) return false;
}
@@ -2995,7 +3113,7 @@
if (input->ExpectTag(18)) goto parse_value;
break;
}
-
+
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3010,7 +3128,7 @@
if (input->ExpectTag(26)) goto parse_options;
break;
}
-
+
// optional .google.protobuf.EnumOptions options = 3;
case 3: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3024,14 +3142,15 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -3050,19 +3169,19 @@
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->name(), output);
}
-
+
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
for (int i = 0; i < this->value_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
2, this->value(i), output);
}
-
+
// optional .google.protobuf.EnumOptions options = 3;
if (has_options()) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
3, this->options(), output);
}
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -3080,21 +3199,21 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
}
-
+
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
for (int i = 0; i < this->value_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
2, this->value(i), target);
}
-
+
// optional .google.protobuf.EnumOptions options = 3;
if (has_options()) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
3, this->options(), target);
}
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -3104,7 +3223,7 @@
int EnumDescriptorProto::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// optional string name = 1;
if (has_name()) {
@@ -3112,14 +3231,14 @@
::google::protobuf::internal::WireFormatLite::StringSize(
this->name());
}
-
+
// optional .google.protobuf.EnumOptions options = 3;
if (has_options()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->options());
}
-
+
}
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
total_size += 1 * this->value_size();
@@ -3128,7 +3247,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->value(i));
}
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -3179,7 +3298,7 @@
}
bool EnumDescriptorProto::IsInitialized() const {
-
+
for (int i = 0; i < value_size(); i++) {
if (!this->value(i).IsInitialized()) return false;
}
@@ -3311,7 +3430,7 @@
if (input->ExpectTag(16)) goto parse_number;
break;
}
-
+
// optional int32 number = 2;
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3327,7 +3446,7 @@
if (input->ExpectTag(26)) goto parse_options;
break;
}
-
+
// optional .google.protobuf.EnumValueOptions options = 3;
case 3: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3341,14 +3460,15 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -3367,18 +3487,18 @@
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->name(), output);
}
-
+
// optional int32 number = 2;
if (has_number()) {
::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->number(), output);
}
-
+
// optional .google.protobuf.EnumValueOptions options = 3;
if (has_options()) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
3, this->options(), output);
}
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -3396,19 +3516,19 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
}
-
+
// optional int32 number = 2;
if (has_number()) {
target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->number(), target);
}
-
+
// optional .google.protobuf.EnumValueOptions options = 3;
if (has_options()) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
3, this->options(), target);
}
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -3418,7 +3538,7 @@
int EnumValueDescriptorProto::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// optional string name = 1;
if (has_name()) {
@@ -3426,21 +3546,21 @@
::google::protobuf::internal::WireFormatLite::StringSize(
this->name());
}
-
+
// optional int32 number = 2;
if (has_number()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::Int32Size(
this->number());
}
-
+
// optional .google.protobuf.EnumValueOptions options = 3;
if (has_options()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->options());
}
-
+
}
if (!unknown_fields().empty()) {
total_size +=
@@ -3494,7 +3614,7 @@
}
bool EnumValueDescriptorProto::IsInitialized() const {
-
+
if (has_options()) {
if (!this->options().IsInitialized()) return false;
}
@@ -3622,7 +3742,7 @@
if (input->ExpectTag(18)) goto parse_method;
break;
}
-
+
// repeated .google.protobuf.MethodDescriptorProto method = 2;
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3637,7 +3757,7 @@
if (input->ExpectTag(26)) goto parse_options;
break;
}
-
+
// optional .google.protobuf.ServiceOptions options = 3;
case 3: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3651,14 +3771,15 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -3677,19 +3798,19 @@
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->name(), output);
}
-
+
// repeated .google.protobuf.MethodDescriptorProto method = 2;
for (int i = 0; i < this->method_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
2, this->method(i), output);
}
-
+
// optional .google.protobuf.ServiceOptions options = 3;
if (has_options()) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
3, this->options(), output);
}
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -3707,21 +3828,21 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
}
-
+
// repeated .google.protobuf.MethodDescriptorProto method = 2;
for (int i = 0; i < this->method_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
2, this->method(i), target);
}
-
+
// optional .google.protobuf.ServiceOptions options = 3;
if (has_options()) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
3, this->options(), target);
}
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -3731,7 +3852,7 @@
int ServiceDescriptorProto::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// optional string name = 1;
if (has_name()) {
@@ -3739,14 +3860,14 @@
::google::protobuf::internal::WireFormatLite::StringSize(
this->name());
}
-
+
// optional .google.protobuf.ServiceOptions options = 3;
if (has_options()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->options());
}
-
+
}
// repeated .google.protobuf.MethodDescriptorProto method = 2;
total_size += 1 * this->method_size();
@@ -3755,7 +3876,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->method(i));
}
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -3806,7 +3927,7 @@
}
bool ServiceDescriptorProto::IsInitialized() const {
-
+
for (int i = 0; i < method_size(); i++) {
if (!this->method(i).IsInitialized()) return false;
}
@@ -3955,7 +4076,7 @@
if (input->ExpectTag(18)) goto parse_input_type;
break;
}
-
+
// optional string input_type = 2;
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3972,7 +4093,7 @@
if (input->ExpectTag(26)) goto parse_output_type;
break;
}
-
+
// optional string output_type = 3;
case 3: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -3989,7 +4110,7 @@
if (input->ExpectTag(34)) goto parse_options;
break;
}
-
+
// optional .google.protobuf.MethodOptions options = 4;
case 4: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4003,14 +4124,15 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -4029,7 +4151,7 @@
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->name(), output);
}
-
+
// optional string input_type = 2;
if (has_input_type()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -4038,7 +4160,7 @@
::google::protobuf::internal::WireFormatLite::WriteString(
2, this->input_type(), output);
}
-
+
// optional string output_type = 3;
if (has_output_type()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -4047,13 +4169,13 @@
::google::protobuf::internal::WireFormatLite::WriteString(
3, this->output_type(), output);
}
-
+
// optional .google.protobuf.MethodOptions options = 4;
if (has_options()) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
4, this->options(), output);
}
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -4071,7 +4193,7 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
}
-
+
// optional string input_type = 2;
if (has_input_type()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -4081,7 +4203,7 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
2, this->input_type(), target);
}
-
+
// optional string output_type = 3;
if (has_output_type()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -4091,14 +4213,14 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
3, this->output_type(), target);
}
-
+
// optional .google.protobuf.MethodOptions options = 4;
if (has_options()) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
4, this->options(), target);
}
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -4108,7 +4230,7 @@
int MethodDescriptorProto::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// optional string name = 1;
if (has_name()) {
@@ -4116,28 +4238,28 @@
::google::protobuf::internal::WireFormatLite::StringSize(
this->name());
}
-
+
// optional string input_type = 2;
if (has_input_type()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->input_type());
}
-
+
// optional string output_type = 3;
if (has_output_type()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->output_type());
}
-
+
// optional .google.protobuf.MethodOptions options = 4;
if (has_options()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->options());
}
-
+
}
if (!unknown_fields().empty()) {
total_size +=
@@ -4194,7 +4316,7 @@
}
bool MethodDescriptorProto::IsInitialized() const {
-
+
if (has_options()) {
if (!this->options().IsInitialized()) return false;
}
@@ -4254,6 +4376,7 @@
const int FileOptions::kRetainUnknownFieldsFieldNumber;
const int FileOptions::kJavaGenerateEqualsAndHashFieldNumber;
const int FileOptions::kOptimizeForFieldNumber;
+const int FileOptions::kGoPackageFieldNumber;
const int FileOptions::kCcGenericServicesFieldNumber;
const int FileOptions::kJavaGenericServicesFieldNumber;
const int FileOptions::kPyGenericServicesFieldNumber;
@@ -4282,6 +4405,7 @@
retain_unknown_fields_ = false;
java_generate_equals_and_hash_ = false;
optimize_for_ = 1;
+ go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
cc_generic_services_ = false;
java_generic_services_ = false;
py_generic_services_ = false;
@@ -4299,6 +4423,9 @@
if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) {
delete java_outer_classname_;
}
+ if (go_package_ != &::google::protobuf::internal::kEmptyString) {
+ delete go_package_;
+ }
if (this != default_instance_) {
}
}
@@ -4341,10 +4468,15 @@
retain_unknown_fields_ = false;
java_generate_equals_and_hash_ = false;
optimize_for_ = 1;
+ if (has_go_package()) {
+ if (go_package_ != &::google::protobuf::internal::kEmptyString) {
+ go_package_->clear();
+ }
+ }
cc_generic_services_ = false;
- java_generic_services_ = false;
}
if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+ java_generic_services_ = false;
py_generic_services_ = false;
}
uninterpreted_option_.Clear();
@@ -4373,7 +4505,7 @@
if (input->ExpectTag(66)) goto parse_java_outer_classname;
break;
}
-
+
// optional string java_outer_classname = 8;
case 8: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4390,7 +4522,7 @@
if (input->ExpectTag(72)) goto parse_optimize_for;
break;
}
-
+
// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
case 9: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4411,7 +4543,7 @@
if (input->ExpectTag(80)) goto parse_java_multiple_files;
break;
}
-
+
// optional bool java_multiple_files = 10 [default = false];
case 10: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4424,13 +4556,30 @@
} else {
goto handle_uninterpreted;
}
- if (input->ExpectTag(88)) goto parse_retain_unknown_fields;
+ if (input->ExpectTag(90)) goto parse_go_package;
break;
}
-
- // optional bool retain_unknown_fields = 11 [default = false];
+
+ // optional string go_package = 11;
case 11: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_go_package:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_go_package()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->go_package().data(), this->go_package().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(96)) goto parse_retain_unknown_fields;
+ break;
+ }
+
+ // optional bool retain_unknown_fields = 12 [default = false];
+ case 12: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
parse_retain_unknown_fields:
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
@@ -4443,7 +4592,7 @@
if (input->ExpectTag(128)) goto parse_cc_generic_services;
break;
}
-
+
// optional bool cc_generic_services = 16 [default = false];
case 16: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4459,7 +4608,7 @@
if (input->ExpectTag(136)) goto parse_java_generic_services;
break;
}
-
+
// optional bool java_generic_services = 17 [default = false];
case 17: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4475,7 +4624,7 @@
if (input->ExpectTag(144)) goto parse_py_generic_services;
break;
}
-
+
// optional bool py_generic_services = 18 [default = false];
case 18: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4491,7 +4640,7 @@
if (input->ExpectTag(160)) goto parse_java_generate_equals_and_hash;
break;
}
-
+
// optional bool java_generate_equals_and_hash = 20 [default = false];
case 20: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4507,7 +4656,7 @@
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
break;
}
-
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4522,7 +4671,7 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4534,7 +4683,8 @@
mutable_unknown_fields()));
continue;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -4553,7 +4703,7 @@
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->java_package(), output);
}
-
+
// optional string java_outer_classname = 8;
if (has_java_outer_classname()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -4562,53 +4712,62 @@
::google::protobuf::internal::WireFormatLite::WriteString(
8, this->java_outer_classname(), output);
}
-
+
// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
if (has_optimize_for()) {
::google::protobuf::internal::WireFormatLite::WriteEnum(
9, this->optimize_for(), output);
}
-
+
// optional bool java_multiple_files = 10 [default = false];
if (has_java_multiple_files()) {
::google::protobuf::internal::WireFormatLite::WriteBool(10, this->java_multiple_files(), output);
}
-
- // optional bool retain_unknown_fields = 11 [default = false];
- if (has_retain_unknown_fields()) {
- ::google::protobuf::internal::WireFormatLite::WriteBool(11, this->retain_unknown_fields(), output);
+
+ // optional string go_package = 11;
+ if (has_go_package()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->go_package().data(), this->go_package().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ ::google::protobuf::internal::WireFormatLite::WriteString(
+ 11, this->go_package(), output);
}
-
+
+ // optional bool retain_unknown_fields = 12 [default = false];
+ if (has_retain_unknown_fields()) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(12, this->retain_unknown_fields(), output);
+ }
+
// optional bool cc_generic_services = 16 [default = false];
if (has_cc_generic_services()) {
::google::protobuf::internal::WireFormatLite::WriteBool(16, this->cc_generic_services(), output);
}
-
+
// optional bool java_generic_services = 17 [default = false];
if (has_java_generic_services()) {
::google::protobuf::internal::WireFormatLite::WriteBool(17, this->java_generic_services(), output);
}
-
+
// optional bool py_generic_services = 18 [default = false];
if (has_py_generic_services()) {
::google::protobuf::internal::WireFormatLite::WriteBool(18, this->py_generic_services(), output);
}
-
+
// optional bool java_generate_equals_and_hash = 20 [default = false];
if (has_java_generate_equals_and_hash()) {
::google::protobuf::internal::WireFormatLite::WriteBool(20, this->java_generate_equals_and_hash(), output);
}
-
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
-
+
// Extension range [1000, 536870912)
_extensions_.SerializeWithCachedSizes(
1000, 536870912, output);
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -4626,7 +4785,7 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->java_package(), target);
}
-
+
// optional string java_outer_classname = 8;
if (has_java_outer_classname()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -4636,54 +4795,64 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
8, this->java_outer_classname(), target);
}
-
+
// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
if (has_optimize_for()) {
target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
9, this->optimize_for(), target);
}
-
+
// optional bool java_multiple_files = 10 [default = false];
if (has_java_multiple_files()) {
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->java_multiple_files(), target);
}
-
- // optional bool retain_unknown_fields = 11 [default = false];
- if (has_retain_unknown_fields()) {
- target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(11, this->retain_unknown_fields(), target);
+
+ // optional string go_package = 11;
+ if (has_go_package()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->go_package().data(), this->go_package().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 11, this->go_package(), target);
}
-
+
+ // optional bool retain_unknown_fields = 12 [default = false];
+ if (has_retain_unknown_fields()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(12, this->retain_unknown_fields(), target);
+ }
+
// optional bool cc_generic_services = 16 [default = false];
if (has_cc_generic_services()) {
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(16, this->cc_generic_services(), target);
}
-
+
// optional bool java_generic_services = 17 [default = false];
if (has_java_generic_services()) {
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(17, this->java_generic_services(), target);
}
-
+
// optional bool py_generic_services = 18 [default = false];
if (has_py_generic_services()) {
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(18, this->py_generic_services(), target);
}
-
+
// optional bool java_generate_equals_and_hash = 20 [default = false];
if (has_java_generate_equals_and_hash()) {
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(20, this->java_generate_equals_and_hash(), target);
}
-
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
999, this->uninterpreted_option(i), target);
}
-
+
// Extension range [1000, 536870912)
target = _extensions_.SerializeWithCachedSizesToArray(
1000, 536870912, target);
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -4693,7 +4862,7 @@
int FileOptions::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// optional string java_package = 1;
if (has_java_package()) {
@@ -4701,52 +4870,59 @@
::google::protobuf::internal::WireFormatLite::StringSize(
this->java_package());
}
-
+
// optional string java_outer_classname = 8;
if (has_java_outer_classname()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->java_outer_classname());
}
-
+
// optional bool java_multiple_files = 10 [default = false];
if (has_java_multiple_files()) {
total_size += 1 + 1;
}
-
- // optional bool retain_unknown_fields = 11 [default = false];
+
+ // optional bool retain_unknown_fields = 12 [default = false];
if (has_retain_unknown_fields()) {
total_size += 1 + 1;
}
-
+
// optional bool java_generate_equals_and_hash = 20 [default = false];
if (has_java_generate_equals_and_hash()) {
total_size += 2 + 1;
}
-
+
// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
if (has_optimize_for()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::EnumSize(this->optimize_for());
}
-
+
+ // optional string go_package = 11;
+ if (has_go_package()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->go_package());
+ }
+
// optional bool cc_generic_services = 16 [default = false];
if (has_cc_generic_services()) {
total_size += 2 + 1;
}
-
+
+ }
+ if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
// optional bool java_generic_services = 17 [default = false];
if (has_java_generic_services()) {
total_size += 2 + 1;
}
-
- }
- if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+
// optional bool py_generic_services = 18 [default = false];
if (has_py_generic_services()) {
total_size += 2 + 1;
}
-
+
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
total_size += 2 * this->uninterpreted_option_size();
@@ -4755,9 +4931,9 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->uninterpreted_option(i));
}
-
+
total_size += _extensions_.ByteSize();
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -4803,14 +4979,17 @@
if (from.has_optimize_for()) {
set_optimize_for(from.optimize_for());
}
+ if (from.has_go_package()) {
+ set_go_package(from.go_package());
+ }
if (from.has_cc_generic_services()) {
set_cc_generic_services(from.cc_generic_services());
}
+ }
+ if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
if (from.has_java_generic_services()) {
set_java_generic_services(from.java_generic_services());
}
- }
- if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
if (from.has_py_generic_services()) {
set_py_generic_services(from.py_generic_services());
}
@@ -4832,11 +5011,11 @@
}
bool FileOptions::IsInitialized() const {
-
+
for (int i = 0; i < uninterpreted_option_size(); i++) {
if (!this->uninterpreted_option(i).IsInitialized()) return false;
}
-
+
if (!_extensions_.IsInitialized()) return false; return true;
}
@@ -4848,6 +5027,7 @@
std::swap(retain_unknown_fields_, other->retain_unknown_fields_);
std::swap(java_generate_equals_and_hash_, other->java_generate_equals_and_hash_);
std::swap(optimize_for_, other->optimize_for_);
+ std::swap(go_package_, other->go_package_);
std::swap(cc_generic_services_, other->cc_generic_services_);
std::swap(java_generic_services_, other->java_generic_services_);
std::swap(py_generic_services_, other->py_generic_services_);
@@ -4958,7 +5138,7 @@
if (input->ExpectTag(16)) goto parse_no_standard_descriptor_accessor;
break;
}
-
+
// optional bool no_standard_descriptor_accessor = 2 [default = false];
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4974,7 +5154,7 @@
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
break;
}
-
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -4989,7 +5169,7 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5001,7 +5181,8 @@
mutable_unknown_fields()));
continue;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -5016,22 +5197,22 @@
if (has_message_set_wire_format()) {
::google::protobuf::internal::WireFormatLite::WriteBool(1, this->message_set_wire_format(), output);
}
-
+
// optional bool no_standard_descriptor_accessor = 2 [default = false];
if (has_no_standard_descriptor_accessor()) {
::google::protobuf::internal::WireFormatLite::WriteBool(2, this->no_standard_descriptor_accessor(), output);
}
-
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
-
+
// Extension range [1000, 536870912)
_extensions_.SerializeWithCachedSizes(
1000, 536870912, output);
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -5044,23 +5225,23 @@
if (has_message_set_wire_format()) {
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->message_set_wire_format(), target);
}
-
+
// optional bool no_standard_descriptor_accessor = 2 [default = false];
if (has_no_standard_descriptor_accessor()) {
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->no_standard_descriptor_accessor(), target);
}
-
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
999, this->uninterpreted_option(i), target);
}
-
+
// Extension range [1000, 536870912)
target = _extensions_.SerializeWithCachedSizesToArray(
1000, 536870912, target);
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -5070,18 +5251,18 @@
int MessageOptions::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// optional bool message_set_wire_format = 1 [default = false];
if (has_message_set_wire_format()) {
total_size += 1 + 1;
}
-
+
// optional bool no_standard_descriptor_accessor = 2 [default = false];
if (has_no_standard_descriptor_accessor()) {
total_size += 1 + 1;
}
-
+
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
total_size += 2 * this->uninterpreted_option_size();
@@ -5090,9 +5271,9 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->uninterpreted_option(i));
}
-
+
total_size += _extensions_.ByteSize();
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -5144,11 +5325,11 @@
}
bool MessageOptions::IsInitialized() const {
-
+
for (int i = 0; i < uninterpreted_option_size(); i++) {
if (!this->uninterpreted_option(i).IsInitialized()) return false;
}
-
+
if (!_extensions_.IsInitialized()) return false; return true;
}
@@ -5201,8 +5382,10 @@
#ifndef _MSC_VER
const int FieldOptions::kCtypeFieldNumber;
const int FieldOptions::kPackedFieldNumber;
+const int FieldOptions::kLazyFieldNumber;
const int FieldOptions::kDeprecatedFieldNumber;
const int FieldOptions::kExperimentalMapKeyFieldNumber;
+const int FieldOptions::kWeakFieldNumber;
const int FieldOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
@@ -5224,8 +5407,10 @@
_cached_size_ = 0;
ctype_ = 0;
packed_ = false;
+ lazy_ = false;
deprecated_ = false;
experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ weak_ = false;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -5267,12 +5452,14 @@
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
ctype_ = 0;
packed_ = false;
+ lazy_ = false;
deprecated_ = false;
if (has_experimental_map_key()) {
if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) {
experimental_map_key_->clear();
}
}
+ weak_ = false;
}
uninterpreted_option_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -5304,7 +5491,7 @@
if (input->ExpectTag(16)) goto parse_packed;
break;
}
-
+
// optional bool packed = 2;
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5320,7 +5507,7 @@
if (input->ExpectTag(24)) goto parse_deprecated;
break;
}
-
+
// optional bool deprecated = 3 [default = false];
case 3: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5333,10 +5520,26 @@
} else {
goto handle_uninterpreted;
}
+ if (input->ExpectTag(40)) goto parse_lazy;
+ break;
+ }
+
+ // optional bool lazy = 5 [default = false];
+ case 5: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_lazy:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &lazy_)));
+ set_has_lazy();
+ } else {
+ goto handle_uninterpreted;
+ }
if (input->ExpectTag(74)) goto parse_experimental_map_key;
break;
}
-
+
// optional string experimental_map_key = 9;
case 9: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5350,10 +5553,26 @@
} else {
goto handle_uninterpreted;
}
+ if (input->ExpectTag(80)) goto parse_weak;
+ break;
+ }
+
+ // optional bool weak = 10 [default = false];
+ case 10: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_weak:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &weak_)));
+ set_has_weak();
+ } else {
+ goto handle_uninterpreted;
+ }
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
break;
}
-
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5368,7 +5587,7 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5380,7 +5599,8 @@
mutable_unknown_fields()));
continue;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -5396,17 +5616,22 @@
::google::protobuf::internal::WireFormatLite::WriteEnum(
1, this->ctype(), output);
}
-
+
// optional bool packed = 2;
if (has_packed()) {
::google::protobuf::internal::WireFormatLite::WriteBool(2, this->packed(), output);
}
-
+
// optional bool deprecated = 3 [default = false];
if (has_deprecated()) {
::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output);
}
-
+
+ // optional bool lazy = 5 [default = false];
+ if (has_lazy()) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(5, this->lazy(), output);
+ }
+
// optional string experimental_map_key = 9;
if (has_experimental_map_key()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -5415,17 +5640,22 @@
::google::protobuf::internal::WireFormatLite::WriteString(
9, this->experimental_map_key(), output);
}
-
+
+ // optional bool weak = 10 [default = false];
+ if (has_weak()) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->weak(), output);
+ }
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
-
+
// Extension range [1000, 536870912)
_extensions_.SerializeWithCachedSizes(
1000, 536870912, output);
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -5439,17 +5669,22 @@
target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
1, this->ctype(), target);
}
-
+
// optional bool packed = 2;
if (has_packed()) {
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->packed(), target);
}
-
+
// optional bool deprecated = 3 [default = false];
if (has_deprecated()) {
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target);
}
-
+
+ // optional bool lazy = 5 [default = false];
+ if (has_lazy()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(5, this->lazy(), target);
+ }
+
// optional string experimental_map_key = 9;
if (has_experimental_map_key()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -5459,18 +5694,23 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
9, this->experimental_map_key(), target);
}
-
+
+ // optional bool weak = 10 [default = false];
+ if (has_weak()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->weak(), target);
+ }
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
999, this->uninterpreted_option(i), target);
}
-
+
// Extension range [1000, 536870912)
target = _extensions_.SerializeWithCachedSizesToArray(
1000, 536870912, target);
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -5480,31 +5720,41 @@
int FieldOptions::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
if (has_ctype()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::EnumSize(this->ctype());
}
-
+
// optional bool packed = 2;
if (has_packed()) {
total_size += 1 + 1;
}
-
+
+ // optional bool lazy = 5 [default = false];
+ if (has_lazy()) {
+ total_size += 1 + 1;
+ }
+
// optional bool deprecated = 3 [default = false];
if (has_deprecated()) {
total_size += 1 + 1;
}
-
+
// optional string experimental_map_key = 9;
if (has_experimental_map_key()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->experimental_map_key());
}
-
+
+ // optional bool weak = 10 [default = false];
+ if (has_weak()) {
+ total_size += 1 + 1;
+ }
+
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
total_size += 2 * this->uninterpreted_option_size();
@@ -5513,9 +5763,9 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->uninterpreted_option(i));
}
-
+
total_size += _extensions_.ByteSize();
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -5549,12 +5799,18 @@
if (from.has_packed()) {
set_packed(from.packed());
}
+ if (from.has_lazy()) {
+ set_lazy(from.lazy());
+ }
if (from.has_deprecated()) {
set_deprecated(from.deprecated());
}
if (from.has_experimental_map_key()) {
set_experimental_map_key(from.experimental_map_key());
}
+ if (from.has_weak()) {
+ set_weak(from.weak());
+ }
}
_extensions_.MergeFrom(from._extensions_);
mutable_unknown_fields()->MergeFrom(from.unknown_fields());
@@ -5573,11 +5829,11 @@
}
bool FieldOptions::IsInitialized() const {
-
+
for (int i = 0; i < uninterpreted_option_size(); i++) {
if (!this->uninterpreted_option(i).IsInitialized()) return false;
}
-
+
if (!_extensions_.IsInitialized()) return false; return true;
}
@@ -5585,8 +5841,10 @@
if (other != this) {
std::swap(ctype_, other->ctype_);
std::swap(packed_, other->packed_);
+ std::swap(lazy_, other->lazy_);
std::swap(deprecated_, other->deprecated_);
std::swap(experimental_map_key_, other->experimental_map_key_);
+ std::swap(weak_, other->weak_);
uninterpreted_option_.Swap(&other->uninterpreted_option_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_unknown_fields_.Swap(&other->_unknown_fields_);
@@ -5607,6 +5865,7 @@
// ===================================================================
#ifndef _MSC_VER
+const int EnumOptions::kAllowAliasFieldNumber;
const int EnumOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
@@ -5626,6 +5885,7 @@
void EnumOptions::SharedCtor() {
_cached_size_ = 0;
+ allow_alias_ = true;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -5661,6 +5921,9 @@
void EnumOptions::Clear() {
_extensions_.Clear();
+ if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ allow_alias_ = true;
+ }
uninterpreted_option_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
mutable_unknown_fields()->Clear();
@@ -5672,6 +5935,21 @@
::google::protobuf::uint32 tag;
while ((tag = input->ReadTag()) != 0) {
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional bool allow_alias = 2 [default = true];
+ case 2: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &allow_alias_)));
+ set_has_allow_alias();
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+ break;
+ }
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5686,7 +5964,7 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5698,7 +5976,8 @@
mutable_unknown_fields()));
continue;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -5709,16 +5988,21 @@
void EnumOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
+ // optional bool allow_alias = 2 [default = true];
+ if (has_allow_alias()) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->allow_alias(), output);
+ }
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
-
+
// Extension range [1000, 536870912)
_extensions_.SerializeWithCachedSizes(
1000, 536870912, output);
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -5727,17 +6011,22 @@
::google::protobuf::uint8* EnumOptions::SerializeWithCachedSizesToArray(
::google::protobuf::uint8* target) const {
+ // optional bool allow_alias = 2 [default = true];
+ if (has_allow_alias()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->allow_alias(), target);
+ }
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
999, this->uninterpreted_option(i), target);
}
-
+
// Extension range [1000, 536870912)
target = _extensions_.SerializeWithCachedSizesToArray(
1000, 536870912, target);
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -5747,7 +6036,14 @@
int EnumOptions::ByteSize() const {
int total_size = 0;
-
+
+ if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ // optional bool allow_alias = 2 [default = true];
+ if (has_allow_alias()) {
+ total_size += 1 + 1;
+ }
+
+ }
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
total_size += 2 * this->uninterpreted_option_size();
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
@@ -5755,9 +6051,9 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->uninterpreted_option(i));
}
-
+
total_size += _extensions_.ByteSize();
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -5784,6 +6080,11 @@
void EnumOptions::MergeFrom(const EnumOptions& from) {
GOOGLE_CHECK_NE(&from, this);
uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
+ if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (from.has_allow_alias()) {
+ set_allow_alias(from.allow_alias());
+ }
+ }
_extensions_.MergeFrom(from._extensions_);
mutable_unknown_fields()->MergeFrom(from.unknown_fields());
}
@@ -5801,16 +6102,17 @@
}
bool EnumOptions::IsInitialized() const {
-
+
for (int i = 0; i < uninterpreted_option_size(); i++) {
if (!this->uninterpreted_option(i).IsInitialized()) return false;
}
-
+
if (!_extensions_.IsInitialized()) return false; return true;
}
void EnumOptions::Swap(EnumOptions* other) {
if (other != this) {
+ std::swap(allow_alias_, other->allow_alias_);
uninterpreted_option_.Swap(&other->uninterpreted_option_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_unknown_fields_.Swap(&other->_unknown_fields_);
@@ -5910,7 +6212,7 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -5922,7 +6224,8 @@
mutable_unknown_fields()));
continue;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -5938,11 +6241,11 @@
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
-
+
// Extension range [1000, 536870912)
_extensions_.SerializeWithCachedSizes(
1000, 536870912, output);
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -5957,11 +6260,11 @@
WriteMessageNoVirtualToArray(
999, this->uninterpreted_option(i), target);
}
-
+
// Extension range [1000, 536870912)
target = _extensions_.SerializeWithCachedSizesToArray(
1000, 536870912, target);
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -5971,7 +6274,7 @@
int EnumValueOptions::ByteSize() const {
int total_size = 0;
-
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
total_size += 2 * this->uninterpreted_option_size();
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
@@ -5979,9 +6282,9 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->uninterpreted_option(i));
}
-
+
total_size += _extensions_.ByteSize();
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -6025,11 +6328,11 @@
}
bool EnumValueOptions::IsInitialized() const {
-
+
for (int i = 0; i < uninterpreted_option_size(); i++) {
if (!this->uninterpreted_option(i).IsInitialized()) return false;
}
-
+
if (!_extensions_.IsInitialized()) return false; return true;
}
@@ -6134,7 +6437,7 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6146,7 +6449,8 @@
mutable_unknown_fields()));
continue;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -6162,11 +6466,11 @@
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
-
+
// Extension range [1000, 536870912)
_extensions_.SerializeWithCachedSizes(
1000, 536870912, output);
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -6181,11 +6485,11 @@
WriteMessageNoVirtualToArray(
999, this->uninterpreted_option(i), target);
}
-
+
// Extension range [1000, 536870912)
target = _extensions_.SerializeWithCachedSizesToArray(
1000, 536870912, target);
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -6195,7 +6499,7 @@
int ServiceOptions::ByteSize() const {
int total_size = 0;
-
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
total_size += 2 * this->uninterpreted_option_size();
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
@@ -6203,9 +6507,9 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->uninterpreted_option(i));
}
-
+
total_size += _extensions_.ByteSize();
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -6249,11 +6553,11 @@
}
bool ServiceOptions::IsInitialized() const {
-
+
for (int i = 0; i < uninterpreted_option_size(); i++) {
if (!this->uninterpreted_option(i).IsInitialized()) return false;
}
-
+
if (!_extensions_.IsInitialized()) return false; return true;
}
@@ -6358,7 +6662,7 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6370,7 +6674,8 @@
mutable_unknown_fields()));
continue;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -6386,11 +6691,11 @@
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
-
+
// Extension range [1000, 536870912)
_extensions_.SerializeWithCachedSizes(
1000, 536870912, output);
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -6405,11 +6710,11 @@
WriteMessageNoVirtualToArray(
999, this->uninterpreted_option(i), target);
}
-
+
// Extension range [1000, 536870912)
target = _extensions_.SerializeWithCachedSizesToArray(
1000, 536870912, target);
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -6419,7 +6724,7 @@
int MethodOptions::ByteSize() const {
int total_size = 0;
-
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
total_size += 2 * this->uninterpreted_option_size();
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
@@ -6427,9 +6732,9 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->uninterpreted_option(i));
}
-
+
total_size += _extensions_.ByteSize();
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -6473,11 +6778,11 @@
}
bool MethodOptions::IsInitialized() const {
-
+
for (int i = 0; i < uninterpreted_option_size(); i++) {
if (!this->uninterpreted_option(i).IsInitialized()) return false;
}
-
+
if (!_extensions_.IsInitialized()) return false; return true;
}
@@ -6595,7 +6900,7 @@
if (input->ExpectTag(16)) goto parse_is_extension;
break;
}
-
+
// required bool is_extension = 2;
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6611,14 +6916,15 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -6637,12 +6943,12 @@
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->name_part(), output);
}
-
+
// required bool is_extension = 2;
if (has_is_extension()) {
::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_extension(), output);
}
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -6660,12 +6966,12 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name_part(), target);
}
-
+
// required bool is_extension = 2;
if (has_is_extension()) {
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_extension(), target);
}
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -6675,7 +6981,7 @@
int UninterpretedOption_NamePart::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// required string name_part = 1;
if (has_name_part()) {
@@ -6683,12 +6989,12 @@
::google::protobuf::internal::WireFormatLite::StringSize(
this->name_part());
}
-
+
// required bool is_extension = 2;
if (has_is_extension()) {
total_size += 1 + 1;
}
-
+
}
if (!unknown_fields().empty()) {
total_size +=
@@ -6740,7 +7046,7 @@
bool UninterpretedOption_NamePart::IsInitialized() const {
if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false;
-
+
return true;
}
@@ -6885,7 +7191,7 @@
if (input->ExpectTag(26)) goto parse_identifier_value;
break;
}
-
+
// optional string identifier_value = 3;
case 3: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6902,7 +7208,7 @@
if (input->ExpectTag(32)) goto parse_positive_int_value;
break;
}
-
+
// optional uint64 positive_int_value = 4;
case 4: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6918,7 +7224,7 @@
if (input->ExpectTag(40)) goto parse_negative_int_value;
break;
}
-
+
// optional int64 negative_int_value = 5;
case 5: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6934,7 +7240,7 @@
if (input->ExpectTag(49)) goto parse_double_value;
break;
}
-
+
// optional double double_value = 6;
case 6: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6950,7 +7256,7 @@
if (input->ExpectTag(58)) goto parse_string_value;
break;
}
-
+
// optional bytes string_value = 7;
case 7: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6964,7 +7270,7 @@
if (input->ExpectTag(66)) goto parse_aggregate_value;
break;
}
-
+
// optional string aggregate_value = 8;
case 8: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -6981,14 +7287,15 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -7004,7 +7311,7 @@
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
2, this->name(i), output);
}
-
+
// optional string identifier_value = 3;
if (has_identifier_value()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -7013,28 +7320,28 @@
::google::protobuf::internal::WireFormatLite::WriteString(
3, this->identifier_value(), output);
}
-
+
// optional uint64 positive_int_value = 4;
if (has_positive_int_value()) {
::google::protobuf::internal::WireFormatLite::WriteUInt64(4, this->positive_int_value(), output);
}
-
+
// optional int64 negative_int_value = 5;
if (has_negative_int_value()) {
::google::protobuf::internal::WireFormatLite::WriteInt64(5, this->negative_int_value(), output);
}
-
+
// optional double double_value = 6;
if (has_double_value()) {
::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->double_value(), output);
}
-
+
// optional bytes string_value = 7;
if (has_string_value()) {
::google::protobuf::internal::WireFormatLite::WriteBytes(
7, this->string_value(), output);
}
-
+
// optional string aggregate_value = 8;
if (has_aggregate_value()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -7043,7 +7350,7 @@
::google::protobuf::internal::WireFormatLite::WriteString(
8, this->aggregate_value(), output);
}
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -7058,7 +7365,7 @@
WriteMessageNoVirtualToArray(
2, this->name(i), target);
}
-
+
// optional string identifier_value = 3;
if (has_identifier_value()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -7068,29 +7375,29 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
3, this->identifier_value(), target);
}
-
+
// optional uint64 positive_int_value = 4;
if (has_positive_int_value()) {
target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(4, this->positive_int_value(), target);
}
-
+
// optional int64 negative_int_value = 5;
if (has_negative_int_value()) {
target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(5, this->negative_int_value(), target);
}
-
+
// optional double double_value = 6;
if (has_double_value()) {
target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->double_value(), target);
}
-
+
// optional bytes string_value = 7;
if (has_string_value()) {
target =
::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
7, this->string_value(), target);
}
-
+
// optional string aggregate_value = 8;
if (has_aggregate_value()) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -7100,7 +7407,7 @@
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
8, this->aggregate_value(), target);
}
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -7110,7 +7417,7 @@
int UninterpretedOption::ByteSize() const {
int total_size = 0;
-
+
if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
// optional string identifier_value = 3;
if (has_identifier_value()) {
@@ -7118,40 +7425,40 @@
::google::protobuf::internal::WireFormatLite::StringSize(
this->identifier_value());
}
-
+
// optional uint64 positive_int_value = 4;
if (has_positive_int_value()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::UInt64Size(
this->positive_int_value());
}
-
+
// optional int64 negative_int_value = 5;
if (has_negative_int_value()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::Int64Size(
this->negative_int_value());
}
-
+
// optional double double_value = 6;
if (has_double_value()) {
total_size += 1 + 8;
}
-
+
// optional bytes string_value = 7;
if (has_string_value()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::BytesSize(
this->string_value());
}
-
+
// optional string aggregate_value = 8;
if (has_aggregate_value()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->aggregate_value());
}
-
+
}
// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
total_size += 1 * this->name_size();
@@ -7160,7 +7467,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->name(i));
}
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -7223,7 +7530,7 @@
}
bool UninterpretedOption::IsInitialized() const {
-
+
for (int i = 0; i < name_size(); i++) {
if (!this->name(i).IsInitialized()) return false;
}
@@ -7259,6 +7566,8 @@
#ifndef _MSC_VER
const int SourceCodeInfo_Location::kPathFieldNumber;
const int SourceCodeInfo_Location::kSpanFieldNumber;
+const int SourceCodeInfo_Location::kLeadingCommentsFieldNumber;
+const int SourceCodeInfo_Location::kTrailingCommentsFieldNumber;
#endif // !_MSC_VER
SourceCodeInfo_Location::SourceCodeInfo_Location()
@@ -7277,6 +7586,8 @@
void SourceCodeInfo_Location::SharedCtor() {
_cached_size_ = 0;
+ leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -7285,6 +7596,12 @@
}
void SourceCodeInfo_Location::SharedDtor() {
+ if (leading_comments_ != &::google::protobuf::internal::kEmptyString) {
+ delete leading_comments_;
+ }
+ if (trailing_comments_ != &::google::protobuf::internal::kEmptyString) {
+ delete trailing_comments_;
+ }
if (this != default_instance_) {
}
}
@@ -7311,6 +7628,18 @@
}
void SourceCodeInfo_Location::Clear() {
+ if (_has_bits_[2 / 32] & (0xffu << (2 % 32))) {
+ if (has_leading_comments()) {
+ if (leading_comments_ != &::google::protobuf::internal::kEmptyString) {
+ leading_comments_->clear();
+ }
+ }
+ if (has_trailing_comments()) {
+ if (trailing_comments_ != &::google::protobuf::internal::kEmptyString) {
+ trailing_comments_->clear();
+ }
+ }
+ }
path_.Clear();
span_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -7342,7 +7671,7 @@
if (input->ExpectTag(18)) goto parse_span;
break;
}
-
+
// repeated int32 span = 2 [packed = true];
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
@@ -7360,17 +7689,52 @@
} else {
goto handle_uninterpreted;
}
+ if (input->ExpectTag(26)) goto parse_leading_comments;
+ break;
+ }
+
+ // optional string leading_comments = 3;
+ case 3: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_leading_comments:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_leading_comments()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->leading_comments().data(), this->leading_comments().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(34)) goto parse_trailing_comments;
+ break;
+ }
+
+ // optional string trailing_comments = 4;
+ case 4: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_trailing_comments:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_trailing_comments()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->trailing_comments().data(), this->trailing_comments().length(),
+ ::google::protobuf::internal::WireFormat::PARSE);
+ } else {
+ goto handle_uninterpreted;
+ }
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -7390,7 +7754,7 @@
::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
this->path(i), output);
}
-
+
// repeated int32 span = 2 [packed = true];
if (this->span_size() > 0) {
::google::protobuf::internal::WireFormatLite::WriteTag(2, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
@@ -7400,7 +7764,25 @@
::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
this->span(i), output);
}
-
+
+ // optional string leading_comments = 3;
+ if (has_leading_comments()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->leading_comments().data(), this->leading_comments().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ ::google::protobuf::internal::WireFormatLite::WriteString(
+ 3, this->leading_comments(), output);
+ }
+
+ // optional string trailing_comments = 4;
+ if (has_trailing_comments()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->trailing_comments().data(), this->trailing_comments().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ ::google::protobuf::internal::WireFormatLite::WriteString(
+ 4, this->trailing_comments(), output);
+ }
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -7422,7 +7804,7 @@
target = ::google::protobuf::internal::WireFormatLite::
WriteInt32NoTagToArray(this->path(i), target);
}
-
+
// repeated int32 span = 2 [packed = true];
if (this->span_size() > 0) {
target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(
@@ -7436,7 +7818,27 @@
target = ::google::protobuf::internal::WireFormatLite::
WriteInt32NoTagToArray(this->span(i), target);
}
-
+
+ // optional string leading_comments = 3;
+ if (has_leading_comments()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->leading_comments().data(), this->leading_comments().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 3, this->leading_comments(), target);
+ }
+
+ // optional string trailing_comments = 4;
+ if (has_trailing_comments()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ this->trailing_comments().data(), this->trailing_comments().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE);
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 4, this->trailing_comments(), target);
+ }
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -7446,7 +7848,23 @@
int SourceCodeInfo_Location::ByteSize() const {
int total_size = 0;
-
+
+ if (_has_bits_[2 / 32] & (0xffu << (2 % 32))) {
+ // optional string leading_comments = 3;
+ if (has_leading_comments()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->leading_comments());
+ }
+
+ // optional string trailing_comments = 4;
+ if (has_trailing_comments()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->trailing_comments());
+ }
+
+ }
// repeated int32 path = 1 [packed = true];
{
int data_size = 0;
@@ -7458,10 +7876,12 @@
total_size += 1 +
::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_path_cached_byte_size_ = data_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
total_size += data_size;
}
-
+
// repeated int32 span = 2 [packed = true];
{
int data_size = 0;
@@ -7473,10 +7893,12 @@
total_size += 1 +
::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_span_cached_byte_size_ = data_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
total_size += data_size;
}
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -7504,6 +7926,14 @@
GOOGLE_CHECK_NE(&from, this);
path_.MergeFrom(from.path_);
span_.MergeFrom(from.span_);
+ if (from._has_bits_[2 / 32] & (0xffu << (2 % 32))) {
+ if (from.has_leading_comments()) {
+ set_leading_comments(from.leading_comments());
+ }
+ if (from.has_trailing_comments()) {
+ set_trailing_comments(from.trailing_comments());
+ }
+ }
mutable_unknown_fields()->MergeFrom(from.unknown_fields());
}
@@ -7520,7 +7950,7 @@
}
bool SourceCodeInfo_Location::IsInitialized() const {
-
+
return true;
}
@@ -7528,6 +7958,8 @@
if (other != this) {
path_.Swap(&other->path_);
span_.Swap(&other->span_);
+ std::swap(leading_comments_, other->leading_comments_);
+ std::swap(trailing_comments_, other->trailing_comments_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_unknown_fields_.Swap(&other->_unknown_fields_);
std::swap(_cached_size_, other->_cached_size_);
@@ -7624,14 +8056,15 @@
if (input->ExpectAtEnd()) return true;
break;
}
-
+
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
- DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag, mutable_unknown_fields()));
+ DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+ input, tag, mutable_unknown_fields()));
break;
}
}
@@ -7647,7 +8080,7 @@
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
1, this->location(i), output);
}
-
+
if (!unknown_fields().empty()) {
::google::protobuf::internal::WireFormatLite::SerializeUnknownFields(
unknown_fields(), output);
@@ -7662,7 +8095,7 @@
WriteMessageNoVirtualToArray(
1, this->location(i), target);
}
-
+
if (!unknown_fields().empty()) {
target = ::google::protobuf::internal::WireFormatLite::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -7672,7 +8105,7 @@
int SourceCodeInfo::ByteSize() const {
int total_size = 0;
-
+
// repeated .google.protobuf.SourceCodeInfo.Location location = 1;
total_size += 1 * this->location_size();
for (int i = 0; i < this->location_size(); i++) {
@@ -7680,7 +8113,7 @@
::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
this->location(i));
}
-
+
if (!unknown_fields().empty()) {
total_size +=
::google::protobuf::internal::WireFormatLite::ComputeUnknownFieldsSize(
@@ -7723,7 +8156,7 @@
}
bool SourceCodeInfo::IsInitialized() const {
-
+
return true;
}
diff --git a/third_party/protobuf/src/google/protobuf/descriptor.pb.h b/third_party/protobuf/src/google/protobuf/descriptor.pb.h
index 1f91d79..5c1175c 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor.pb.h
+++ b/third_party/protobuf/src/google/protobuf/descriptor.pb.h
@@ -20,10 +20,11 @@
#endif
#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_enum_reflection.h>
#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/generated_message_reflection.h>
// @@protoc_insertion_point(includes)
namespace google {
@@ -156,29 +157,29 @@
public:
FileDescriptorSet();
virtual ~FileDescriptorSet();
-
+
FileDescriptorSet(const FileDescriptorSet& from);
-
+
inline FileDescriptorSet& operator=(const FileDescriptorSet& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const FileDescriptorSet& default_instance();
-
+
void Swap(FileDescriptorSet* other);
-
+
// implements Message ----------------------------------------------
-
+
FileDescriptorSet* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -186,7 +187,7 @@
void MergeFrom(const FileDescriptorSet& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -199,13 +200,13 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
// repeated .google.protobuf.FileDescriptorProto file = 1;
inline int file_size() const;
inline void clear_file();
@@ -217,21 +218,21 @@
file() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
mutable_file();
-
+
// @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet)
private:
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static FileDescriptorSet* default_instance_;
};
@@ -241,29 +242,29 @@
public:
FileDescriptorProto();
virtual ~FileDescriptorProto();
-
+
FileDescriptorProto(const FileDescriptorProto& from);
-
+
inline FileDescriptorProto& operator=(const FileDescriptorProto& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const FileDescriptorProto& default_instance();
-
+
void Swap(FileDescriptorProto* other);
-
+
// implements Message ----------------------------------------------
-
+
FileDescriptorProto* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -271,7 +272,7 @@
void MergeFrom(const FileDescriptorProto& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -284,13 +285,13 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
// optional string name = 1;
inline bool has_name() const;
inline void clear_name();
@@ -301,7 +302,8 @@
inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
inline ::std::string* release_name();
-
+ inline void set_allocated_name(::std::string* name);
+
// optional string package = 2;
inline bool has_package() const;
inline void clear_package();
@@ -312,7 +314,8 @@
inline void set_package(const char* value, size_t size);
inline ::std::string* mutable_package();
inline ::std::string* release_package();
-
+ inline void set_allocated_package(::std::string* package);
+
// repeated string dependency = 3;
inline int dependency_size() const;
inline void clear_dependency();
@@ -328,7 +331,31 @@
inline void add_dependency(const char* value, size_t size);
inline const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const;
inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency();
-
+
+ // repeated int32 public_dependency = 10;
+ inline int public_dependency_size() const;
+ inline void clear_public_dependency();
+ static const int kPublicDependencyFieldNumber = 10;
+ inline ::google::protobuf::int32 public_dependency(int index) const;
+ inline void set_public_dependency(int index, ::google::protobuf::int32 value);
+ inline void add_public_dependency(::google::protobuf::int32 value);
+ inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+ public_dependency() const;
+ inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+ mutable_public_dependency();
+
+ // repeated int32 weak_dependency = 11;
+ inline int weak_dependency_size() const;
+ inline void clear_weak_dependency();
+ static const int kWeakDependencyFieldNumber = 11;
+ inline ::google::protobuf::int32 weak_dependency(int index) const;
+ inline void set_weak_dependency(int index, ::google::protobuf::int32 value);
+ inline void add_weak_dependency(::google::protobuf::int32 value);
+ inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+ weak_dependency() const;
+ inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+ mutable_weak_dependency();
+
// repeated .google.protobuf.DescriptorProto message_type = 4;
inline int message_type_size() const;
inline void clear_message_type();
@@ -340,7 +367,7 @@
message_type() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
mutable_message_type();
-
+
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
inline int enum_type_size() const;
inline void clear_enum_type();
@@ -352,7 +379,7 @@
enum_type() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
mutable_enum_type();
-
+
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
inline int service_size() const;
inline void clear_service();
@@ -364,7 +391,7 @@
service() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
mutable_service();
-
+
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
inline int extension_size() const;
inline void clear_extension();
@@ -376,7 +403,7 @@
extension() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
mutable_extension();
-
+
// optional .google.protobuf.FileOptions options = 8;
inline bool has_options() const;
inline void clear_options();
@@ -384,7 +411,8 @@
inline const ::google::protobuf::FileOptions& options() const;
inline ::google::protobuf::FileOptions* mutable_options();
inline ::google::protobuf::FileOptions* release_options();
-
+ inline void set_allocated_options(::google::protobuf::FileOptions* options);
+
// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
inline bool has_source_code_info() const;
inline void clear_source_code_info();
@@ -392,7 +420,8 @@
inline const ::google::protobuf::SourceCodeInfo& source_code_info() const;
inline ::google::protobuf::SourceCodeInfo* mutable_source_code_info();
inline ::google::protobuf::SourceCodeInfo* release_source_code_info();
-
+ inline void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info);
+
// @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto)
private:
inline void set_has_name();
@@ -403,26 +432,28 @@
inline void clear_has_options();
inline void set_has_source_code_info();
inline void clear_has_source_code_info();
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::std::string* name_;
::std::string* package_;
::google::protobuf::RepeatedPtrField< ::std::string> dependency_;
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 > public_dependency_;
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 > weak_dependency_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > message_type_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto > service_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_;
::google::protobuf::FileOptions* options_;
::google::protobuf::SourceCodeInfo* source_code_info_;
-
+
mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(9 + 31) / 32];
-
+ ::google::protobuf::uint32 _has_bits_[(11 + 31) / 32];
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static FileDescriptorProto* default_instance_;
};
@@ -432,29 +463,29 @@
public:
DescriptorProto_ExtensionRange();
virtual ~DescriptorProto_ExtensionRange();
-
+
DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from);
-
+
inline DescriptorProto_ExtensionRange& operator=(const DescriptorProto_ExtensionRange& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const DescriptorProto_ExtensionRange& default_instance();
-
+
void Swap(DescriptorProto_ExtensionRange* other);
-
+
// implements Message ----------------------------------------------
-
+
DescriptorProto_ExtensionRange* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -462,7 +493,7 @@
void MergeFrom(const DescriptorProto_ExtensionRange& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -475,46 +506,46 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
// optional int32 start = 1;
inline bool has_start() const;
inline void clear_start();
static const int kStartFieldNumber = 1;
inline ::google::protobuf::int32 start() const;
inline void set_start(::google::protobuf::int32 value);
-
+
// optional int32 end = 2;
inline bool has_end() const;
inline void clear_end();
static const int kEndFieldNumber = 2;
inline ::google::protobuf::int32 end() const;
inline void set_end(::google::protobuf::int32 value);
-
+
// @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange)
private:
inline void set_has_start();
inline void clear_has_start();
inline void set_has_end();
inline void clear_has_end();
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::google::protobuf::int32 start_;
::google::protobuf::int32 end_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static DescriptorProto_ExtensionRange* default_instance_;
};
@@ -524,29 +555,29 @@
public:
DescriptorProto();
virtual ~DescriptorProto();
-
+
DescriptorProto(const DescriptorProto& from);
-
+
inline DescriptorProto& operator=(const DescriptorProto& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const DescriptorProto& default_instance();
-
+
void Swap(DescriptorProto* other);
-
+
// implements Message ----------------------------------------------
-
+
DescriptorProto* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -554,7 +585,7 @@
void MergeFrom(const DescriptorProto& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -567,15 +598,15 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
typedef DescriptorProto_ExtensionRange ExtensionRange;
-
+
// accessors -------------------------------------------------------
-
+
// optional string name = 1;
inline bool has_name() const;
inline void clear_name();
@@ -586,7 +617,8 @@
inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
inline ::std::string* release_name();
-
+ inline void set_allocated_name(::std::string* name);
+
// repeated .google.protobuf.FieldDescriptorProto field = 2;
inline int field_size() const;
inline void clear_field();
@@ -598,7 +630,7 @@
field() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
mutable_field();
-
+
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
inline int extension_size() const;
inline void clear_extension();
@@ -610,7 +642,7 @@
extension() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
mutable_extension();
-
+
// repeated .google.protobuf.DescriptorProto nested_type = 3;
inline int nested_type_size() const;
inline void clear_nested_type();
@@ -622,7 +654,7 @@
nested_type() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
mutable_nested_type();
-
+
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
inline int enum_type_size() const;
inline void clear_enum_type();
@@ -634,7 +666,7 @@
enum_type() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
mutable_enum_type();
-
+
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
inline int extension_range_size() const;
inline void clear_extension_range();
@@ -646,7 +678,7 @@
extension_range() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
mutable_extension_range();
-
+
// optional .google.protobuf.MessageOptions options = 7;
inline bool has_options() const;
inline void clear_options();
@@ -654,16 +686,17 @@
inline const ::google::protobuf::MessageOptions& options() const;
inline ::google::protobuf::MessageOptions* mutable_options();
inline ::google::protobuf::MessageOptions* release_options();
-
+ inline void set_allocated_options(::google::protobuf::MessageOptions* options);
+
// @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto)
private:
inline void set_has_name();
inline void clear_has_name();
inline void set_has_options();
inline void clear_has_options();
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::std::string* name_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > field_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_;
@@ -671,14 +704,14 @@
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange > extension_range_;
::google::protobuf::MessageOptions* options_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
-
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static DescriptorProto* default_instance_;
};
@@ -688,29 +721,29 @@
public:
FieldDescriptorProto();
virtual ~FieldDescriptorProto();
-
+
FieldDescriptorProto(const FieldDescriptorProto& from);
-
+
inline FieldDescriptorProto& operator=(const FieldDescriptorProto& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const FieldDescriptorProto& default_instance();
-
+
void Swap(FieldDescriptorProto* other);
-
+
// implements Message ----------------------------------------------
-
+
FieldDescriptorProto* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -718,7 +751,7 @@
void MergeFrom(const FieldDescriptorProto& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -731,11 +764,11 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
typedef FieldDescriptorProto_Type Type;
static const Type TYPE_DOUBLE = FieldDescriptorProto_Type_TYPE_DOUBLE;
static const Type TYPE_FLOAT = FieldDescriptorProto_Type_TYPE_FLOAT;
@@ -775,7 +808,7 @@
Type* value) {
return FieldDescriptorProto_Type_Parse(name, value);
}
-
+
typedef FieldDescriptorProto_Label Label;
static const Label LABEL_OPTIONAL = FieldDescriptorProto_Label_LABEL_OPTIONAL;
static const Label LABEL_REQUIRED = FieldDescriptorProto_Label_LABEL_REQUIRED;
@@ -800,9 +833,9 @@
Label* value) {
return FieldDescriptorProto_Label_Parse(name, value);
}
-
+
// accessors -------------------------------------------------------
-
+
// optional string name = 1;
inline bool has_name() const;
inline void clear_name();
@@ -813,28 +846,29 @@
inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
inline ::std::string* release_name();
-
+ inline void set_allocated_name(::std::string* name);
+
// optional int32 number = 3;
inline bool has_number() const;
inline void clear_number();
static const int kNumberFieldNumber = 3;
inline ::google::protobuf::int32 number() const;
inline void set_number(::google::protobuf::int32 value);
-
+
// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
inline bool has_label() const;
inline void clear_label();
static const int kLabelFieldNumber = 4;
inline ::google::protobuf::FieldDescriptorProto_Label label() const;
inline void set_label(::google::protobuf::FieldDescriptorProto_Label value);
-
+
// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
inline bool has_type() const;
inline void clear_type();
static const int kTypeFieldNumber = 5;
inline ::google::protobuf::FieldDescriptorProto_Type type() const;
inline void set_type(::google::protobuf::FieldDescriptorProto_Type value);
-
+
// optional string type_name = 6;
inline bool has_type_name() const;
inline void clear_type_name();
@@ -845,7 +879,8 @@
inline void set_type_name(const char* value, size_t size);
inline ::std::string* mutable_type_name();
inline ::std::string* release_type_name();
-
+ inline void set_allocated_type_name(::std::string* type_name);
+
// optional string extendee = 2;
inline bool has_extendee() const;
inline void clear_extendee();
@@ -856,7 +891,8 @@
inline void set_extendee(const char* value, size_t size);
inline ::std::string* mutable_extendee();
inline ::std::string* release_extendee();
-
+ inline void set_allocated_extendee(::std::string* extendee);
+
// optional string default_value = 7;
inline bool has_default_value() const;
inline void clear_default_value();
@@ -867,7 +903,8 @@
inline void set_default_value(const char* value, size_t size);
inline ::std::string* mutable_default_value();
inline ::std::string* release_default_value();
-
+ inline void set_allocated_default_value(::std::string* default_value);
+
// optional .google.protobuf.FieldOptions options = 8;
inline bool has_options() const;
inline void clear_options();
@@ -875,7 +912,8 @@
inline const ::google::protobuf::FieldOptions& options() const;
inline ::google::protobuf::FieldOptions* mutable_options();
inline ::google::protobuf::FieldOptions* release_options();
-
+ inline void set_allocated_options(::google::protobuf::FieldOptions* options);
+
// @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto)
private:
inline void set_has_name();
@@ -894,9 +932,9 @@
inline void clear_has_default_value();
inline void set_has_options();
inline void clear_has_options();
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::std::string* name_;
::google::protobuf::int32 number_;
int label_;
@@ -905,14 +943,14 @@
::std::string* default_value_;
::google::protobuf::FieldOptions* options_;
int type_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
-
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static FieldDescriptorProto* default_instance_;
};
@@ -922,29 +960,29 @@
public:
EnumDescriptorProto();
virtual ~EnumDescriptorProto();
-
+
EnumDescriptorProto(const EnumDescriptorProto& from);
-
+
inline EnumDescriptorProto& operator=(const EnumDescriptorProto& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const EnumDescriptorProto& default_instance();
-
+
void Swap(EnumDescriptorProto* other);
-
+
// implements Message ----------------------------------------------
-
+
EnumDescriptorProto* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -952,7 +990,7 @@
void MergeFrom(const EnumDescriptorProto& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -965,13 +1003,13 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
// optional string name = 1;
inline bool has_name() const;
inline void clear_name();
@@ -982,7 +1020,8 @@
inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
inline ::std::string* release_name();
-
+ inline void set_allocated_name(::std::string* name);
+
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
inline int value_size() const;
inline void clear_value();
@@ -994,7 +1033,7 @@
value() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
mutable_value();
-
+
// optional .google.protobuf.EnumOptions options = 3;
inline bool has_options() const;
inline void clear_options();
@@ -1002,27 +1041,28 @@
inline const ::google::protobuf::EnumOptions& options() const;
inline ::google::protobuf::EnumOptions* mutable_options();
inline ::google::protobuf::EnumOptions* release_options();
-
+ inline void set_allocated_options(::google::protobuf::EnumOptions* options);
+
// @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto)
private:
inline void set_has_name();
inline void clear_has_name();
inline void set_has_options();
inline void clear_has_options();
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::std::string* name_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto > value_;
::google::protobuf::EnumOptions* options_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static EnumDescriptorProto* default_instance_;
};
@@ -1032,29 +1072,29 @@
public:
EnumValueDescriptorProto();
virtual ~EnumValueDescriptorProto();
-
+
EnumValueDescriptorProto(const EnumValueDescriptorProto& from);
-
+
inline EnumValueDescriptorProto& operator=(const EnumValueDescriptorProto& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const EnumValueDescriptorProto& default_instance();
-
+
void Swap(EnumValueDescriptorProto* other);
-
+
// implements Message ----------------------------------------------
-
+
EnumValueDescriptorProto* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -1062,7 +1102,7 @@
void MergeFrom(const EnumValueDescriptorProto& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -1075,13 +1115,13 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
// optional string name = 1;
inline bool has_name() const;
inline void clear_name();
@@ -1092,14 +1132,15 @@
inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
inline ::std::string* release_name();
-
+ inline void set_allocated_name(::std::string* name);
+
// optional int32 number = 2;
inline bool has_number() const;
inline void clear_number();
static const int kNumberFieldNumber = 2;
inline ::google::protobuf::int32 number() const;
inline void set_number(::google::protobuf::int32 value);
-
+
// optional .google.protobuf.EnumValueOptions options = 3;
inline bool has_options() const;
inline void clear_options();
@@ -1107,7 +1148,8 @@
inline const ::google::protobuf::EnumValueOptions& options() const;
inline ::google::protobuf::EnumValueOptions* mutable_options();
inline ::google::protobuf::EnumValueOptions* release_options();
-
+ inline void set_allocated_options(::google::protobuf::EnumValueOptions* options);
+
// @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto)
private:
inline void set_has_name();
@@ -1116,20 +1158,20 @@
inline void clear_has_number();
inline void set_has_options();
inline void clear_has_options();
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::std::string* name_;
::google::protobuf::EnumValueOptions* options_;
::google::protobuf::int32 number_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static EnumValueDescriptorProto* default_instance_;
};
@@ -1139,29 +1181,29 @@
public:
ServiceDescriptorProto();
virtual ~ServiceDescriptorProto();
-
+
ServiceDescriptorProto(const ServiceDescriptorProto& from);
-
+
inline ServiceDescriptorProto& operator=(const ServiceDescriptorProto& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const ServiceDescriptorProto& default_instance();
-
+
void Swap(ServiceDescriptorProto* other);
-
+
// implements Message ----------------------------------------------
-
+
ServiceDescriptorProto* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -1169,7 +1211,7 @@
void MergeFrom(const ServiceDescriptorProto& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -1182,13 +1224,13 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
// optional string name = 1;
inline bool has_name() const;
inline void clear_name();
@@ -1199,7 +1241,8 @@
inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
inline ::std::string* release_name();
-
+ inline void set_allocated_name(::std::string* name);
+
// repeated .google.protobuf.MethodDescriptorProto method = 2;
inline int method_size() const;
inline void clear_method();
@@ -1211,7 +1254,7 @@
method() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
mutable_method();
-
+
// optional .google.protobuf.ServiceOptions options = 3;
inline bool has_options() const;
inline void clear_options();
@@ -1219,27 +1262,28 @@
inline const ::google::protobuf::ServiceOptions& options() const;
inline ::google::protobuf::ServiceOptions* mutable_options();
inline ::google::protobuf::ServiceOptions* release_options();
-
+ inline void set_allocated_options(::google::protobuf::ServiceOptions* options);
+
// @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto)
private:
inline void set_has_name();
inline void clear_has_name();
inline void set_has_options();
inline void clear_has_options();
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::std::string* name_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto > method_;
::google::protobuf::ServiceOptions* options_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static ServiceDescriptorProto* default_instance_;
};
@@ -1249,29 +1293,29 @@
public:
MethodDescriptorProto();
virtual ~MethodDescriptorProto();
-
+
MethodDescriptorProto(const MethodDescriptorProto& from);
-
+
inline MethodDescriptorProto& operator=(const MethodDescriptorProto& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const MethodDescriptorProto& default_instance();
-
+
void Swap(MethodDescriptorProto* other);
-
+
// implements Message ----------------------------------------------
-
+
MethodDescriptorProto* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -1279,7 +1323,7 @@
void MergeFrom(const MethodDescriptorProto& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -1292,13 +1336,13 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
// optional string name = 1;
inline bool has_name() const;
inline void clear_name();
@@ -1309,7 +1353,8 @@
inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
inline ::std::string* release_name();
-
+ inline void set_allocated_name(::std::string* name);
+
// optional string input_type = 2;
inline bool has_input_type() const;
inline void clear_input_type();
@@ -1320,7 +1365,8 @@
inline void set_input_type(const char* value, size_t size);
inline ::std::string* mutable_input_type();
inline ::std::string* release_input_type();
-
+ inline void set_allocated_input_type(::std::string* input_type);
+
// optional string output_type = 3;
inline bool has_output_type() const;
inline void clear_output_type();
@@ -1331,7 +1377,8 @@
inline void set_output_type(const char* value, size_t size);
inline ::std::string* mutable_output_type();
inline ::std::string* release_output_type();
-
+ inline void set_allocated_output_type(::std::string* output_type);
+
// optional .google.protobuf.MethodOptions options = 4;
inline bool has_options() const;
inline void clear_options();
@@ -1339,7 +1386,8 @@
inline const ::google::protobuf::MethodOptions& options() const;
inline ::google::protobuf::MethodOptions* mutable_options();
inline ::google::protobuf::MethodOptions* release_options();
-
+ inline void set_allocated_options(::google::protobuf::MethodOptions* options);
+
// @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto)
private:
inline void set_has_name();
@@ -1350,21 +1398,21 @@
inline void clear_has_output_type();
inline void set_has_options();
inline void clear_has_options();
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::std::string* name_;
::std::string* input_type_;
::std::string* output_type_;
::google::protobuf::MethodOptions* options_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
-
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static MethodDescriptorProto* default_instance_;
};
@@ -1374,29 +1422,29 @@
public:
FileOptions();
virtual ~FileOptions();
-
+
FileOptions(const FileOptions& from);
-
+
inline FileOptions& operator=(const FileOptions& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const FileOptions& default_instance();
-
+
void Swap(FileOptions* other);
-
+
// implements Message ----------------------------------------------
-
+
FileOptions* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -1404,7 +1452,7 @@
void MergeFrom(const FileOptions& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -1417,11 +1465,11 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
typedef FileOptions_OptimizeMode OptimizeMode;
static const OptimizeMode SPEED = FileOptions_OptimizeMode_SPEED;
static const OptimizeMode CODE_SIZE = FileOptions_OptimizeMode_CODE_SIZE;
@@ -1446,9 +1494,9 @@
OptimizeMode* value) {
return FileOptions_OptimizeMode_Parse(name, value);
}
-
+
// accessors -------------------------------------------------------
-
+
// optional string java_package = 1;
inline bool has_java_package() const;
inline void clear_java_package();
@@ -1459,7 +1507,8 @@
inline void set_java_package(const char* value, size_t size);
inline ::std::string* mutable_java_package();
inline ::std::string* release_java_package();
-
+ inline void set_allocated_java_package(::std::string* java_package);
+
// optional string java_outer_classname = 8;
inline bool has_java_outer_classname() const;
inline void clear_java_outer_classname();
@@ -1470,56 +1519,69 @@
inline void set_java_outer_classname(const char* value, size_t size);
inline ::std::string* mutable_java_outer_classname();
inline ::std::string* release_java_outer_classname();
-
+ inline void set_allocated_java_outer_classname(::std::string* java_outer_classname);
+
// optional bool java_multiple_files = 10 [default = false];
inline bool has_java_multiple_files() const;
inline void clear_java_multiple_files();
static const int kJavaMultipleFilesFieldNumber = 10;
inline bool java_multiple_files() const;
inline void set_java_multiple_files(bool value);
-
- // optional bool retain_unknown_fields = 11 [default = false];
+
+ // optional bool retain_unknown_fields = 12 [default = false];
inline bool has_retain_unknown_fields() const;
inline void clear_retain_unknown_fields();
- static const int kRetainUnknownFieldsFieldNumber = 11;
+ static const int kRetainUnknownFieldsFieldNumber = 12;
inline bool retain_unknown_fields() const;
inline void set_retain_unknown_fields(bool value);
-
+
// optional bool java_generate_equals_and_hash = 20 [default = false];
inline bool has_java_generate_equals_and_hash() const;
inline void clear_java_generate_equals_and_hash();
static const int kJavaGenerateEqualsAndHashFieldNumber = 20;
inline bool java_generate_equals_and_hash() const;
inline void set_java_generate_equals_and_hash(bool value);
-
+
// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
inline bool has_optimize_for() const;
inline void clear_optimize_for();
static const int kOptimizeForFieldNumber = 9;
inline ::google::protobuf::FileOptions_OptimizeMode optimize_for() const;
inline void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value);
-
+
+ // optional string go_package = 11;
+ inline bool has_go_package() const;
+ inline void clear_go_package();
+ static const int kGoPackageFieldNumber = 11;
+ inline const ::std::string& go_package() const;
+ inline void set_go_package(const ::std::string& value);
+ inline void set_go_package(const char* value);
+ inline void set_go_package(const char* value, size_t size);
+ inline ::std::string* mutable_go_package();
+ inline ::std::string* release_go_package();
+ inline void set_allocated_go_package(::std::string* go_package);
+
// optional bool cc_generic_services = 16 [default = false];
inline bool has_cc_generic_services() const;
inline void clear_cc_generic_services();
static const int kCcGenericServicesFieldNumber = 16;
inline bool cc_generic_services() const;
inline void set_cc_generic_services(bool value);
-
+
// optional bool java_generic_services = 17 [default = false];
inline bool has_java_generic_services() const;
inline void clear_java_generic_services();
static const int kJavaGenericServicesFieldNumber = 17;
inline bool java_generic_services() const;
inline void set_java_generic_services(bool value);
-
+
// optional bool py_generic_services = 18 [default = false];
inline bool has_py_generic_services() const;
inline void clear_py_generic_services();
static const int kPyGenericServicesFieldNumber = 18;
inline bool py_generic_services() const;
inline void set_py_generic_services(bool value);
-
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
@@ -1531,7 +1593,7 @@
uninterpreted_option() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
-
+
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.FileOptions)
private:
@@ -1547,17 +1609,19 @@
inline void clear_has_java_generate_equals_and_hash();
inline void set_has_optimize_for();
inline void clear_has_optimize_for();
+ inline void set_has_go_package();
+ inline void clear_has_go_package();
inline void set_has_cc_generic_services();
inline void clear_has_cc_generic_services();
inline void set_has_java_generic_services();
inline void clear_has_java_generic_services();
inline void set_has_py_generic_services();
inline void clear_has_py_generic_services();
-
+
::google::protobuf::internal::ExtensionSet _extensions_;
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::std::string* java_package_;
::std::string* java_outer_classname_;
bool java_multiple_files_;
@@ -1565,17 +1629,18 @@
bool java_generate_equals_and_hash_;
bool cc_generic_services_;
int optimize_for_;
+ ::std::string* go_package_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
bool java_generic_services_;
bool py_generic_services_;
-
+
mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(10 + 31) / 32];
-
+ ::google::protobuf::uint32 _has_bits_[(11 + 31) / 32];
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static FileOptions* default_instance_;
};
@@ -1585,29 +1650,29 @@
public:
MessageOptions();
virtual ~MessageOptions();
-
+
MessageOptions(const MessageOptions& from);
-
+
inline MessageOptions& operator=(const MessageOptions& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const MessageOptions& default_instance();
-
+
void Swap(MessageOptions* other);
-
+
// implements Message ----------------------------------------------
-
+
MessageOptions* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -1615,7 +1680,7 @@
void MergeFrom(const MessageOptions& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -1628,27 +1693,27 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
// optional bool message_set_wire_format = 1 [default = false];
inline bool has_message_set_wire_format() const;
inline void clear_message_set_wire_format();
static const int kMessageSetWireFormatFieldNumber = 1;
inline bool message_set_wire_format() const;
inline void set_message_set_wire_format(bool value);
-
+
// optional bool no_standard_descriptor_accessor = 2 [default = false];
inline bool has_no_standard_descriptor_accessor() const;
inline void clear_no_standard_descriptor_accessor();
static const int kNoStandardDescriptorAccessorFieldNumber = 2;
inline bool no_standard_descriptor_accessor() const;
inline void set_no_standard_descriptor_accessor(bool value);
-
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
@@ -1660,7 +1725,7 @@
uninterpreted_option() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
-
+
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions)
private:
@@ -1668,22 +1733,22 @@
inline void clear_has_message_set_wire_format();
inline void set_has_no_standard_descriptor_accessor();
inline void clear_has_no_standard_descriptor_accessor();
-
+
::google::protobuf::internal::ExtensionSet _extensions_;
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
bool message_set_wire_format_;
bool no_standard_descriptor_accessor_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static MessageOptions* default_instance_;
};
@@ -1693,29 +1758,29 @@
public:
FieldOptions();
virtual ~FieldOptions();
-
+
FieldOptions(const FieldOptions& from);
-
+
inline FieldOptions& operator=(const FieldOptions& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const FieldOptions& default_instance();
-
+
void Swap(FieldOptions* other);
-
+
// implements Message ----------------------------------------------
-
+
FieldOptions* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -1723,7 +1788,7 @@
void MergeFrom(const FieldOptions& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -1736,11 +1801,11 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
typedef FieldOptions_CType CType;
static const CType STRING = FieldOptions_CType_STRING;
static const CType CORD = FieldOptions_CType_CORD;
@@ -1765,30 +1830,37 @@
CType* value) {
return FieldOptions_CType_Parse(name, value);
}
-
+
// accessors -------------------------------------------------------
-
+
// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
inline bool has_ctype() const;
inline void clear_ctype();
static const int kCtypeFieldNumber = 1;
inline ::google::protobuf::FieldOptions_CType ctype() const;
inline void set_ctype(::google::protobuf::FieldOptions_CType value);
-
+
// optional bool packed = 2;
inline bool has_packed() const;
inline void clear_packed();
static const int kPackedFieldNumber = 2;
inline bool packed() const;
inline void set_packed(bool value);
-
+
+ // optional bool lazy = 5 [default = false];
+ inline bool has_lazy() const;
+ inline void clear_lazy();
+ static const int kLazyFieldNumber = 5;
+ inline bool lazy() const;
+ inline void set_lazy(bool value);
+
// optional bool deprecated = 3 [default = false];
inline bool has_deprecated() const;
inline void clear_deprecated();
static const int kDeprecatedFieldNumber = 3;
inline bool deprecated() const;
inline void set_deprecated(bool value);
-
+
// optional string experimental_map_key = 9;
inline bool has_experimental_map_key() const;
inline void clear_experimental_map_key();
@@ -1799,7 +1871,15 @@
inline void set_experimental_map_key(const char* value, size_t size);
inline ::std::string* mutable_experimental_map_key();
inline ::std::string* release_experimental_map_key();
-
+ inline void set_allocated_experimental_map_key(::std::string* experimental_map_key);
+
+ // optional bool weak = 10 [default = false];
+ inline bool has_weak() const;
+ inline void clear_weak();
+ static const int kWeakFieldNumber = 10;
+ inline bool weak() const;
+ inline void set_weak(bool value);
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
@@ -1811,7 +1891,7 @@
uninterpreted_option() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
-
+
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions)
private:
@@ -1819,28 +1899,34 @@
inline void clear_has_ctype();
inline void set_has_packed();
inline void clear_has_packed();
+ inline void set_has_lazy();
+ inline void clear_has_lazy();
inline void set_has_deprecated();
inline void clear_has_deprecated();
inline void set_has_experimental_map_key();
inline void clear_has_experimental_map_key();
-
+ inline void set_has_weak();
+ inline void clear_has_weak();
+
::google::protobuf::internal::ExtensionSet _extensions_;
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
int ctype_;
bool packed_;
+ bool lazy_;
bool deprecated_;
+ bool weak_;
::std::string* experimental_map_key_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
-
+
mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
-
+ ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static FieldOptions* default_instance_;
};
@@ -1850,29 +1936,29 @@
public:
EnumOptions();
virtual ~EnumOptions();
-
+
EnumOptions(const EnumOptions& from);
-
+
inline EnumOptions& operator=(const EnumOptions& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const EnumOptions& default_instance();
-
+
void Swap(EnumOptions* other);
-
+
// implements Message ----------------------------------------------
-
+
EnumOptions* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -1880,7 +1966,7 @@
void MergeFrom(const EnumOptions& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -1893,13 +1979,20 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
+ // optional bool allow_alias = 2 [default = true];
+ inline bool has_allow_alias() const;
+ inline void clear_allow_alias();
+ static const int kAllowAliasFieldNumber = 2;
+ inline bool allow_alias() const;
+ inline void set_allow_alias(bool value);
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
@@ -1911,24 +2004,27 @@
uninterpreted_option() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
-
+
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions)
private:
-
+ inline void set_has_allow_alias();
+ inline void clear_has_allow_alias();
+
::google::protobuf::internal::ExtensionSet _extensions_;
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
-
+ bool allow_alias_;
+
mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-
+ ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static EnumOptions* default_instance_;
};
@@ -1938,29 +2034,29 @@
public:
EnumValueOptions();
virtual ~EnumValueOptions();
-
+
EnumValueOptions(const EnumValueOptions& from);
-
+
inline EnumValueOptions& operator=(const EnumValueOptions& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const EnumValueOptions& default_instance();
-
+
void Swap(EnumValueOptions* other);
-
+
// implements Message ----------------------------------------------
-
+
EnumValueOptions* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -1968,7 +2064,7 @@
void MergeFrom(const EnumValueOptions& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -1981,13 +2077,13 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
@@ -1999,24 +2095,24 @@
uninterpreted_option() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
-
+
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions)
private:
-
+
::google::protobuf::internal::ExtensionSet _extensions_;
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static EnumValueOptions* default_instance_;
};
@@ -2026,29 +2122,29 @@
public:
ServiceOptions();
virtual ~ServiceOptions();
-
+
ServiceOptions(const ServiceOptions& from);
-
+
inline ServiceOptions& operator=(const ServiceOptions& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const ServiceOptions& default_instance();
-
+
void Swap(ServiceOptions* other);
-
+
// implements Message ----------------------------------------------
-
+
ServiceOptions* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -2056,7 +2152,7 @@
void MergeFrom(const ServiceOptions& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -2069,13 +2165,13 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
@@ -2087,24 +2183,24 @@
uninterpreted_option() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
-
+
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions)
private:
-
+
::google::protobuf::internal::ExtensionSet _extensions_;
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static ServiceOptions* default_instance_;
};
@@ -2114,29 +2210,29 @@
public:
MethodOptions();
virtual ~MethodOptions();
-
+
MethodOptions(const MethodOptions& from);
-
+
inline MethodOptions& operator=(const MethodOptions& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const MethodOptions& default_instance();
-
+
void Swap(MethodOptions* other);
-
+
// implements Message ----------------------------------------------
-
+
MethodOptions* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -2144,7 +2240,7 @@
void MergeFrom(const MethodOptions& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -2157,13 +2253,13 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
@@ -2175,24 +2271,24 @@
uninterpreted_option() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
-
+
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions)
private:
-
+
::google::protobuf::internal::ExtensionSet _extensions_;
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static MethodOptions* default_instance_;
};
@@ -2202,29 +2298,29 @@
public:
UninterpretedOption_NamePart();
virtual ~UninterpretedOption_NamePart();
-
+
UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from);
-
+
inline UninterpretedOption_NamePart& operator=(const UninterpretedOption_NamePart& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const UninterpretedOption_NamePart& default_instance();
-
+
void Swap(UninterpretedOption_NamePart* other);
-
+
// implements Message ----------------------------------------------
-
+
UninterpretedOption_NamePart* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -2232,7 +2328,7 @@
void MergeFrom(const UninterpretedOption_NamePart& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -2245,13 +2341,13 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
// required string name_part = 1;
inline bool has_name_part() const;
inline void clear_name_part();
@@ -2262,33 +2358,34 @@
inline void set_name_part(const char* value, size_t size);
inline ::std::string* mutable_name_part();
inline ::std::string* release_name_part();
-
+ inline void set_allocated_name_part(::std::string* name_part);
+
// required bool is_extension = 2;
inline bool has_is_extension() const;
inline void clear_is_extension();
static const int kIsExtensionFieldNumber = 2;
inline bool is_extension() const;
inline void set_is_extension(bool value);
-
+
// @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart)
private:
inline void set_has_name_part();
inline void clear_has_name_part();
inline void set_has_is_extension();
inline void clear_has_is_extension();
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::std::string* name_part_;
bool is_extension_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static UninterpretedOption_NamePart* default_instance_;
};
@@ -2298,29 +2395,29 @@
public:
UninterpretedOption();
virtual ~UninterpretedOption();
-
+
UninterpretedOption(const UninterpretedOption& from);
-
+
inline UninterpretedOption& operator=(const UninterpretedOption& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const UninterpretedOption& default_instance();
-
+
void Swap(UninterpretedOption* other);
-
+
// implements Message ----------------------------------------------
-
+
UninterpretedOption* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -2328,7 +2425,7 @@
void MergeFrom(const UninterpretedOption& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -2341,15 +2438,15 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
typedef UninterpretedOption_NamePart NamePart;
-
+
// accessors -------------------------------------------------------
-
+
// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
inline int name_size() const;
inline void clear_name();
@@ -2361,7 +2458,7 @@
name() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
mutable_name();
-
+
// optional string identifier_value = 3;
inline bool has_identifier_value() const;
inline void clear_identifier_value();
@@ -2372,28 +2469,29 @@
inline void set_identifier_value(const char* value, size_t size);
inline ::std::string* mutable_identifier_value();
inline ::std::string* release_identifier_value();
-
+ inline void set_allocated_identifier_value(::std::string* identifier_value);
+
// optional uint64 positive_int_value = 4;
inline bool has_positive_int_value() const;
inline void clear_positive_int_value();
static const int kPositiveIntValueFieldNumber = 4;
inline ::google::protobuf::uint64 positive_int_value() const;
inline void set_positive_int_value(::google::protobuf::uint64 value);
-
+
// optional int64 negative_int_value = 5;
inline bool has_negative_int_value() const;
inline void clear_negative_int_value();
static const int kNegativeIntValueFieldNumber = 5;
inline ::google::protobuf::int64 negative_int_value() const;
inline void set_negative_int_value(::google::protobuf::int64 value);
-
+
// optional double double_value = 6;
inline bool has_double_value() const;
inline void clear_double_value();
static const int kDoubleValueFieldNumber = 6;
inline double double_value() const;
inline void set_double_value(double value);
-
+
// optional bytes string_value = 7;
inline bool has_string_value() const;
inline void clear_string_value();
@@ -2404,7 +2502,8 @@
inline void set_string_value(const void* value, size_t size);
inline ::std::string* mutable_string_value();
inline ::std::string* release_string_value();
-
+ inline void set_allocated_string_value(::std::string* string_value);
+
// optional string aggregate_value = 8;
inline bool has_aggregate_value() const;
inline void clear_aggregate_value();
@@ -2415,7 +2514,8 @@
inline void set_aggregate_value(const char* value, size_t size);
inline ::std::string* mutable_aggregate_value();
inline ::std::string* release_aggregate_value();
-
+ inline void set_allocated_aggregate_value(::std::string* aggregate_value);
+
// @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption)
private:
inline void set_has_identifier_value();
@@ -2430,9 +2530,9 @@
inline void clear_has_string_value();
inline void set_has_aggregate_value();
inline void clear_has_aggregate_value();
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart > name_;
::std::string* identifier_value_;
::google::protobuf::uint64 positive_int_value_;
@@ -2440,14 +2540,14 @@
double double_value_;
::std::string* string_value_;
::std::string* aggregate_value_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
-
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static UninterpretedOption* default_instance_;
};
@@ -2457,29 +2557,29 @@
public:
SourceCodeInfo_Location();
virtual ~SourceCodeInfo_Location();
-
+
SourceCodeInfo_Location(const SourceCodeInfo_Location& from);
-
+
inline SourceCodeInfo_Location& operator=(const SourceCodeInfo_Location& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const SourceCodeInfo_Location& default_instance();
-
+
void Swap(SourceCodeInfo_Location* other);
-
+
// implements Message ----------------------------------------------
-
+
SourceCodeInfo_Location* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -2487,7 +2587,7 @@
void MergeFrom(const SourceCodeInfo_Location& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -2500,13 +2600,13 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
// accessors -------------------------------------------------------
-
+
// repeated int32 path = 1 [packed = true];
inline int path_size() const;
inline void clear_path();
@@ -2518,7 +2618,7 @@
path() const;
inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
mutable_path();
-
+
// repeated int32 span = 2 [packed = true];
inline int span_size() const;
inline void clear_span();
@@ -2530,24 +2630,54 @@
span() const;
inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
mutable_span();
-
+
+ // optional string leading_comments = 3;
+ inline bool has_leading_comments() const;
+ inline void clear_leading_comments();
+ static const int kLeadingCommentsFieldNumber = 3;
+ inline const ::std::string& leading_comments() const;
+ inline void set_leading_comments(const ::std::string& value);
+ inline void set_leading_comments(const char* value);
+ inline void set_leading_comments(const char* value, size_t size);
+ inline ::std::string* mutable_leading_comments();
+ inline ::std::string* release_leading_comments();
+ inline void set_allocated_leading_comments(::std::string* leading_comments);
+
+ // optional string trailing_comments = 4;
+ inline bool has_trailing_comments() const;
+ inline void clear_trailing_comments();
+ static const int kTrailingCommentsFieldNumber = 4;
+ inline const ::std::string& trailing_comments() const;
+ inline void set_trailing_comments(const ::std::string& value);
+ inline void set_trailing_comments(const char* value);
+ inline void set_trailing_comments(const char* value, size_t size);
+ inline ::std::string* mutable_trailing_comments();
+ inline ::std::string* release_trailing_comments();
+ inline void set_allocated_trailing_comments(::std::string* trailing_comments);
+
// @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location)
private:
-
+ inline void set_has_leading_comments();
+ inline void clear_has_leading_comments();
+ inline void set_has_trailing_comments();
+ inline void clear_has_trailing_comments();
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::google::protobuf::RepeatedField< ::google::protobuf::int32 > path_;
mutable int _path_cached_byte_size_;
::google::protobuf::RepeatedField< ::google::protobuf::int32 > span_;
mutable int _span_cached_byte_size_;
-
+ ::std::string* leading_comments_;
+ ::std::string* trailing_comments_;
+
mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-
+ ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static SourceCodeInfo_Location* default_instance_;
};
@@ -2557,29 +2687,29 @@
public:
SourceCodeInfo();
virtual ~SourceCodeInfo();
-
+
SourceCodeInfo(const SourceCodeInfo& from);
-
+
inline SourceCodeInfo& operator=(const SourceCodeInfo& from) {
CopyFrom(from);
return *this;
}
-
+
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
return _unknown_fields_;
}
-
+
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
return &_unknown_fields_;
}
-
+
static const ::google::protobuf::Descriptor* descriptor();
static const SourceCodeInfo& default_instance();
-
+
void Swap(SourceCodeInfo* other);
-
+
// implements Message ----------------------------------------------
-
+
SourceCodeInfo* New() const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
@@ -2587,7 +2717,7 @@
void MergeFrom(const SourceCodeInfo& from);
void Clear();
bool IsInitialized() const;
-
+
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
@@ -2600,15 +2730,15 @@
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
+
::google::protobuf::Metadata GetMetadata() const;
-
+
// nested types ----------------------------------------------------
-
+
typedef SourceCodeInfo_Location Location;
-
+
// accessors -------------------------------------------------------
-
+
// repeated .google.protobuf.SourceCodeInfo.Location location = 1;
inline int location_size() const;
inline void clear_location();
@@ -2620,21 +2750,21 @@
location() const;
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
mutable_location();
-
+
// @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo)
private:
-
+
::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+
::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location > location_;
-
+
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-
+
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-
+
void InitAsDefaultInstance();
static SourceCodeInfo* default_instance_;
};
@@ -2731,6 +2861,18 @@
return temp;
}
}
+inline void FileDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name_ != &::google::protobuf::internal::kEmptyString) {
+ delete name_;
+ }
+ if (name) {
+ set_has_name();
+ name_ = name;
+ } else {
+ clear_has_name();
+ name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// optional string package = 2;
inline bool FileDescriptorProto::has_package() const {
@@ -2789,6 +2931,18 @@
return temp;
}
}
+inline void FileDescriptorProto::set_allocated_package(::std::string* package) {
+ if (package_ != &::google::protobuf::internal::kEmptyString) {
+ delete package_;
+ }
+ if (package) {
+ set_has_package();
+ package_ = package;
+ } else {
+ clear_has_package();
+ package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// repeated string dependency = 3;
inline int FileDescriptorProto::dependency_size() const {
@@ -2834,6 +2988,56 @@
return &dependency_;
}
+// repeated int32 public_dependency = 10;
+inline int FileDescriptorProto::public_dependency_size() const {
+ return public_dependency_.size();
+}
+inline void FileDescriptorProto::clear_public_dependency() {
+ public_dependency_.Clear();
+}
+inline ::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const {
+ return public_dependency_.Get(index);
+}
+inline void FileDescriptorProto::set_public_dependency(int index, ::google::protobuf::int32 value) {
+ public_dependency_.Set(index, value);
+}
+inline void FileDescriptorProto::add_public_dependency(::google::protobuf::int32 value) {
+ public_dependency_.Add(value);
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+FileDescriptorProto::public_dependency() const {
+ return public_dependency_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+FileDescriptorProto::mutable_public_dependency() {
+ return &public_dependency_;
+}
+
+// repeated int32 weak_dependency = 11;
+inline int FileDescriptorProto::weak_dependency_size() const {
+ return weak_dependency_.size();
+}
+inline void FileDescriptorProto::clear_weak_dependency() {
+ weak_dependency_.Clear();
+}
+inline ::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const {
+ return weak_dependency_.Get(index);
+}
+inline void FileDescriptorProto::set_weak_dependency(int index, ::google::protobuf::int32 value) {
+ weak_dependency_.Set(index, value);
+}
+inline void FileDescriptorProto::add_weak_dependency(::google::protobuf::int32 value) {
+ weak_dependency_.Add(value);
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+FileDescriptorProto::weak_dependency() const {
+ return weak_dependency_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+FileDescriptorProto::mutable_weak_dependency() {
+ return &weak_dependency_;
+}
+
// repeated .google.protobuf.DescriptorProto message_type = 4;
inline int FileDescriptorProto::message_type_size() const {
return message_type_.size();
@@ -2936,13 +3140,13 @@
// optional .google.protobuf.FileOptions options = 8;
inline bool FileDescriptorProto::has_options() const {
- return (_has_bits_[0] & 0x00000080u) != 0;
+ return (_has_bits_[0] & 0x00000200u) != 0;
}
inline void FileDescriptorProto::set_has_options() {
- _has_bits_[0] |= 0x00000080u;
+ _has_bits_[0] |= 0x00000200u;
}
inline void FileDescriptorProto::clear_has_options() {
- _has_bits_[0] &= ~0x00000080u;
+ _has_bits_[0] &= ~0x00000200u;
}
inline void FileDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
@@ -2962,16 +3166,25 @@
options_ = NULL;
return temp;
}
+inline void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+}
// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
inline bool FileDescriptorProto::has_source_code_info() const {
- return (_has_bits_[0] & 0x00000100u) != 0;
+ return (_has_bits_[0] & 0x00000400u) != 0;
}
inline void FileDescriptorProto::set_has_source_code_info() {
- _has_bits_[0] |= 0x00000100u;
+ _has_bits_[0] |= 0x00000400u;
}
inline void FileDescriptorProto::clear_has_source_code_info() {
- _has_bits_[0] &= ~0x00000100u;
+ _has_bits_[0] &= ~0x00000400u;
}
inline void FileDescriptorProto::clear_source_code_info() {
if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
@@ -2991,6 +3204,15 @@
source_code_info_ = NULL;
return temp;
}
+inline void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) {
+ delete source_code_info_;
+ source_code_info_ = source_code_info;
+ if (source_code_info) {
+ set_has_source_code_info();
+ } else {
+ clear_has_source_code_info();
+ }
+}
// -------------------------------------------------------------------
@@ -3101,6 +3323,18 @@
return temp;
}
}
+inline void DescriptorProto::set_allocated_name(::std::string* name) {
+ if (name_ != &::google::protobuf::internal::kEmptyString) {
+ delete name_;
+ }
+ if (name) {
+ set_has_name();
+ name_ = name;
+ } else {
+ clear_has_name();
+ name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// repeated .google.protobuf.FieldDescriptorProto field = 2;
inline int DescriptorProto::field_size() const {
@@ -3255,6 +3489,15 @@
options_ = NULL;
return temp;
}
+inline void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+}
// -------------------------------------------------------------------
@@ -3317,6 +3560,18 @@
return temp;
}
}
+inline void FieldDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name_ != &::google::protobuf::internal::kEmptyString) {
+ delete name_;
+ }
+ if (name) {
+ set_has_name();
+ name_ = name;
+ } else {
+ clear_has_name();
+ name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// optional int32 number = 3;
inline bool FieldDescriptorProto::has_number() const {
@@ -3358,7 +3613,7 @@
return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_);
}
inline void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) {
- GOOGLE_DCHECK(::google::protobuf::FieldDescriptorProto_Label_IsValid(value));
+ assert(::google::protobuf::FieldDescriptorProto_Label_IsValid(value));
set_has_label();
label_ = value;
}
@@ -3381,7 +3636,7 @@
return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_);
}
inline void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) {
- GOOGLE_DCHECK(::google::protobuf::FieldDescriptorProto_Type_IsValid(value));
+ assert(::google::protobuf::FieldDescriptorProto_Type_IsValid(value));
set_has_type();
type_ = value;
}
@@ -3443,6 +3698,18 @@
return temp;
}
}
+inline void FieldDescriptorProto::set_allocated_type_name(::std::string* type_name) {
+ if (type_name_ != &::google::protobuf::internal::kEmptyString) {
+ delete type_name_;
+ }
+ if (type_name) {
+ set_has_type_name();
+ type_name_ = type_name;
+ } else {
+ clear_has_type_name();
+ type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// optional string extendee = 2;
inline bool FieldDescriptorProto::has_extendee() const {
@@ -3501,6 +3768,18 @@
return temp;
}
}
+inline void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee) {
+ if (extendee_ != &::google::protobuf::internal::kEmptyString) {
+ delete extendee_;
+ }
+ if (extendee) {
+ set_has_extendee();
+ extendee_ = extendee;
+ } else {
+ clear_has_extendee();
+ extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// optional string default_value = 7;
inline bool FieldDescriptorProto::has_default_value() const {
@@ -3559,6 +3838,18 @@
return temp;
}
}
+inline void FieldDescriptorProto::set_allocated_default_value(::std::string* default_value) {
+ if (default_value_ != &::google::protobuf::internal::kEmptyString) {
+ delete default_value_;
+ }
+ if (default_value) {
+ set_has_default_value();
+ default_value_ = default_value;
+ } else {
+ clear_has_default_value();
+ default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// optional .google.protobuf.FieldOptions options = 8;
inline bool FieldDescriptorProto::has_options() const {
@@ -3588,6 +3879,15 @@
options_ = NULL;
return temp;
}
+inline void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+}
// -------------------------------------------------------------------
@@ -3650,6 +3950,18 @@
return temp;
}
}
+inline void EnumDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name_ != &::google::protobuf::internal::kEmptyString) {
+ delete name_;
+ }
+ if (name) {
+ set_has_name();
+ name_ = name;
+ } else {
+ clear_has_name();
+ name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
inline int EnumDescriptorProto::value_size() const {
@@ -3704,6 +4016,15 @@
options_ = NULL;
return temp;
}
+inline void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+}
// -------------------------------------------------------------------
@@ -3766,6 +4087,18 @@
return temp;
}
}
+inline void EnumValueDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name_ != &::google::protobuf::internal::kEmptyString) {
+ delete name_;
+ }
+ if (name) {
+ set_has_name();
+ name_ = name;
+ } else {
+ clear_has_name();
+ name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// optional int32 number = 2;
inline bool EnumValueDescriptorProto::has_number() const {
@@ -3817,6 +4150,15 @@
options_ = NULL;
return temp;
}
+inline void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+}
// -------------------------------------------------------------------
@@ -3879,6 +4221,18 @@
return temp;
}
}
+inline void ServiceDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name_ != &::google::protobuf::internal::kEmptyString) {
+ delete name_;
+ }
+ if (name) {
+ set_has_name();
+ name_ = name;
+ } else {
+ clear_has_name();
+ name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// repeated .google.protobuf.MethodDescriptorProto method = 2;
inline int ServiceDescriptorProto::method_size() const {
@@ -3933,6 +4287,15 @@
options_ = NULL;
return temp;
}
+inline void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+}
// -------------------------------------------------------------------
@@ -3995,6 +4358,18 @@
return temp;
}
}
+inline void MethodDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name_ != &::google::protobuf::internal::kEmptyString) {
+ delete name_;
+ }
+ if (name) {
+ set_has_name();
+ name_ = name;
+ } else {
+ clear_has_name();
+ name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// optional string input_type = 2;
inline bool MethodDescriptorProto::has_input_type() const {
@@ -4053,6 +4428,18 @@
return temp;
}
}
+inline void MethodDescriptorProto::set_allocated_input_type(::std::string* input_type) {
+ if (input_type_ != &::google::protobuf::internal::kEmptyString) {
+ delete input_type_;
+ }
+ if (input_type) {
+ set_has_input_type();
+ input_type_ = input_type;
+ } else {
+ clear_has_input_type();
+ input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// optional string output_type = 3;
inline bool MethodDescriptorProto::has_output_type() const {
@@ -4111,6 +4498,18 @@
return temp;
}
}
+inline void MethodDescriptorProto::set_allocated_output_type(::std::string* output_type) {
+ if (output_type_ != &::google::protobuf::internal::kEmptyString) {
+ delete output_type_;
+ }
+ if (output_type) {
+ set_has_output_type();
+ output_type_ = output_type;
+ } else {
+ clear_has_output_type();
+ output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// optional .google.protobuf.MethodOptions options = 4;
inline bool MethodDescriptorProto::has_options() const {
@@ -4140,6 +4539,15 @@
options_ = NULL;
return temp;
}
+inline void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+}
// -------------------------------------------------------------------
@@ -4202,6 +4610,18 @@
return temp;
}
}
+inline void FileOptions::set_allocated_java_package(::std::string* java_package) {
+ if (java_package_ != &::google::protobuf::internal::kEmptyString) {
+ delete java_package_;
+ }
+ if (java_package) {
+ set_has_java_package();
+ java_package_ = java_package;
+ } else {
+ clear_has_java_package();
+ java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// optional string java_outer_classname = 8;
inline bool FileOptions::has_java_outer_classname() const {
@@ -4260,6 +4680,18 @@
return temp;
}
}
+inline void FileOptions::set_allocated_java_outer_classname(::std::string* java_outer_classname) {
+ if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) {
+ delete java_outer_classname_;
+ }
+ if (java_outer_classname) {
+ set_has_java_outer_classname();
+ java_outer_classname_ = java_outer_classname;
+ } else {
+ clear_has_java_outer_classname();
+ java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// optional bool java_multiple_files = 10 [default = false];
inline bool FileOptions::has_java_multiple_files() const {
@@ -4283,7 +4715,7 @@
java_multiple_files_ = value;
}
-// optional bool retain_unknown_fields = 11 [default = false];
+// optional bool retain_unknown_fields = 12 [default = false];
inline bool FileOptions::has_retain_unknown_fields() const {
return (_has_bits_[0] & 0x00000008u) != 0;
}
@@ -4345,21 +4777,91 @@
return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_);
}
inline void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) {
- GOOGLE_DCHECK(::google::protobuf::FileOptions_OptimizeMode_IsValid(value));
+ assert(::google::protobuf::FileOptions_OptimizeMode_IsValid(value));
set_has_optimize_for();
optimize_for_ = value;
}
-// optional bool cc_generic_services = 16 [default = false];
-inline bool FileOptions::has_cc_generic_services() const {
+// optional string go_package = 11;
+inline bool FileOptions::has_go_package() const {
return (_has_bits_[0] & 0x00000040u) != 0;
}
-inline void FileOptions::set_has_cc_generic_services() {
+inline void FileOptions::set_has_go_package() {
_has_bits_[0] |= 0x00000040u;
}
-inline void FileOptions::clear_has_cc_generic_services() {
+inline void FileOptions::clear_has_go_package() {
_has_bits_[0] &= ~0x00000040u;
}
+inline void FileOptions::clear_go_package() {
+ if (go_package_ != &::google::protobuf::internal::kEmptyString) {
+ go_package_->clear();
+ }
+ clear_has_go_package();
+}
+inline const ::std::string& FileOptions::go_package() const {
+ return *go_package_;
+}
+inline void FileOptions::set_go_package(const ::std::string& value) {
+ set_has_go_package();
+ if (go_package_ == &::google::protobuf::internal::kEmptyString) {
+ go_package_ = new ::std::string;
+ }
+ go_package_->assign(value);
+}
+inline void FileOptions::set_go_package(const char* value) {
+ set_has_go_package();
+ if (go_package_ == &::google::protobuf::internal::kEmptyString) {
+ go_package_ = new ::std::string;
+ }
+ go_package_->assign(value);
+}
+inline void FileOptions::set_go_package(const char* value, size_t size) {
+ set_has_go_package();
+ if (go_package_ == &::google::protobuf::internal::kEmptyString) {
+ go_package_ = new ::std::string;
+ }
+ go_package_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* FileOptions::mutable_go_package() {
+ set_has_go_package();
+ if (go_package_ == &::google::protobuf::internal::kEmptyString) {
+ go_package_ = new ::std::string;
+ }
+ return go_package_;
+}
+inline ::std::string* FileOptions::release_go_package() {
+ clear_has_go_package();
+ if (go_package_ == &::google::protobuf::internal::kEmptyString) {
+ return NULL;
+ } else {
+ ::std::string* temp = go_package_;
+ go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ return temp;
+ }
+}
+inline void FileOptions::set_allocated_go_package(::std::string* go_package) {
+ if (go_package_ != &::google::protobuf::internal::kEmptyString) {
+ delete go_package_;
+ }
+ if (go_package) {
+ set_has_go_package();
+ go_package_ = go_package;
+ } else {
+ clear_has_go_package();
+ go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
+
+// optional bool cc_generic_services = 16 [default = false];
+inline bool FileOptions::has_cc_generic_services() const {
+ return (_has_bits_[0] & 0x00000080u) != 0;
+}
+inline void FileOptions::set_has_cc_generic_services() {
+ _has_bits_[0] |= 0x00000080u;
+}
+inline void FileOptions::clear_has_cc_generic_services() {
+ _has_bits_[0] &= ~0x00000080u;
+}
inline void FileOptions::clear_cc_generic_services() {
cc_generic_services_ = false;
clear_has_cc_generic_services();
@@ -4374,13 +4876,13 @@
// optional bool java_generic_services = 17 [default = false];
inline bool FileOptions::has_java_generic_services() const {
- return (_has_bits_[0] & 0x00000080u) != 0;
+ return (_has_bits_[0] & 0x00000100u) != 0;
}
inline void FileOptions::set_has_java_generic_services() {
- _has_bits_[0] |= 0x00000080u;
+ _has_bits_[0] |= 0x00000100u;
}
inline void FileOptions::clear_has_java_generic_services() {
- _has_bits_[0] &= ~0x00000080u;
+ _has_bits_[0] &= ~0x00000100u;
}
inline void FileOptions::clear_java_generic_services() {
java_generic_services_ = false;
@@ -4396,13 +4898,13 @@
// optional bool py_generic_services = 18 [default = false];
inline bool FileOptions::has_py_generic_services() const {
- return (_has_bits_[0] & 0x00000100u) != 0;
+ return (_has_bits_[0] & 0x00000200u) != 0;
}
inline void FileOptions::set_has_py_generic_services() {
- _has_bits_[0] |= 0x00000100u;
+ _has_bits_[0] |= 0x00000200u;
}
inline void FileOptions::clear_has_py_generic_services() {
- _has_bits_[0] &= ~0x00000100u;
+ _has_bits_[0] &= ~0x00000200u;
}
inline void FileOptions::clear_py_generic_services() {
py_generic_services_ = false;
@@ -4536,7 +5038,7 @@
return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_);
}
inline void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) {
- GOOGLE_DCHECK(::google::protobuf::FieldOptions_CType_IsValid(value));
+ assert(::google::protobuf::FieldOptions_CType_IsValid(value));
set_has_ctype();
ctype_ = value;
}
@@ -4563,16 +5065,38 @@
packed_ = value;
}
-// optional bool deprecated = 3 [default = false];
-inline bool FieldOptions::has_deprecated() const {
+// optional bool lazy = 5 [default = false];
+inline bool FieldOptions::has_lazy() const {
return (_has_bits_[0] & 0x00000004u) != 0;
}
-inline void FieldOptions::set_has_deprecated() {
+inline void FieldOptions::set_has_lazy() {
_has_bits_[0] |= 0x00000004u;
}
-inline void FieldOptions::clear_has_deprecated() {
+inline void FieldOptions::clear_has_lazy() {
_has_bits_[0] &= ~0x00000004u;
}
+inline void FieldOptions::clear_lazy() {
+ lazy_ = false;
+ clear_has_lazy();
+}
+inline bool FieldOptions::lazy() const {
+ return lazy_;
+}
+inline void FieldOptions::set_lazy(bool value) {
+ set_has_lazy();
+ lazy_ = value;
+}
+
+// optional bool deprecated = 3 [default = false];
+inline bool FieldOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void FieldOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000008u;
+}
+inline void FieldOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000008u;
+}
inline void FieldOptions::clear_deprecated() {
deprecated_ = false;
clear_has_deprecated();
@@ -4587,13 +5111,13 @@
// optional string experimental_map_key = 9;
inline bool FieldOptions::has_experimental_map_key() const {
- return (_has_bits_[0] & 0x00000008u) != 0;
+ return (_has_bits_[0] & 0x00000010u) != 0;
}
inline void FieldOptions::set_has_experimental_map_key() {
- _has_bits_[0] |= 0x00000008u;
+ _has_bits_[0] |= 0x00000010u;
}
inline void FieldOptions::clear_has_experimental_map_key() {
- _has_bits_[0] &= ~0x00000008u;
+ _has_bits_[0] &= ~0x00000010u;
}
inline void FieldOptions::clear_experimental_map_key() {
if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) {
@@ -4642,6 +5166,40 @@
return temp;
}
}
+inline void FieldOptions::set_allocated_experimental_map_key(::std::string* experimental_map_key) {
+ if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) {
+ delete experimental_map_key_;
+ }
+ if (experimental_map_key) {
+ set_has_experimental_map_key();
+ experimental_map_key_ = experimental_map_key;
+ } else {
+ clear_has_experimental_map_key();
+ experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
+
+// optional bool weak = 10 [default = false];
+inline bool FieldOptions::has_weak() const {
+ return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void FieldOptions::set_has_weak() {
+ _has_bits_[0] |= 0x00000020u;
+}
+inline void FieldOptions::clear_has_weak() {
+ _has_bits_[0] &= ~0x00000020u;
+}
+inline void FieldOptions::clear_weak() {
+ weak_ = false;
+ clear_has_weak();
+}
+inline bool FieldOptions::weak() const {
+ return weak_;
+}
+inline void FieldOptions::set_weak(bool value) {
+ set_has_weak();
+ weak_ = value;
+}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int FieldOptions::uninterpreted_option_size() const {
@@ -4672,6 +5230,28 @@
// EnumOptions
+// optional bool allow_alias = 2 [default = true];
+inline bool EnumOptions::has_allow_alias() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void EnumOptions::set_has_allow_alias() {
+ _has_bits_[0] |= 0x00000001u;
+}
+inline void EnumOptions::clear_has_allow_alias() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+inline void EnumOptions::clear_allow_alias() {
+ allow_alias_ = true;
+ clear_has_allow_alias();
+}
+inline bool EnumOptions::allow_alias() const {
+ return allow_alias_;
+}
+inline void EnumOptions::set_allow_alias(bool value) {
+ set_has_allow_alias();
+ allow_alias_ = value;
+}
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int EnumOptions::uninterpreted_option_size() const {
return uninterpreted_option_.size();
@@ -4845,6 +5425,18 @@
return temp;
}
}
+inline void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part) {
+ if (name_part_ != &::google::protobuf::internal::kEmptyString) {
+ delete name_part_;
+ }
+ if (name_part) {
+ set_has_name_part();
+ name_part_ = name_part;
+ } else {
+ clear_has_name_part();
+ name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// required bool is_extension = 2;
inline bool UninterpretedOption_NamePart::has_is_extension() const {
@@ -4954,6 +5546,18 @@
return temp;
}
}
+inline void UninterpretedOption::set_allocated_identifier_value(::std::string* identifier_value) {
+ if (identifier_value_ != &::google::protobuf::internal::kEmptyString) {
+ delete identifier_value_;
+ }
+ if (identifier_value) {
+ set_has_identifier_value();
+ identifier_value_ = identifier_value;
+ } else {
+ clear_has_identifier_value();
+ identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// optional uint64 positive_int_value = 4;
inline bool UninterpretedOption::has_positive_int_value() const {
@@ -5078,6 +5682,18 @@
return temp;
}
}
+inline void UninterpretedOption::set_allocated_string_value(::std::string* string_value) {
+ if (string_value_ != &::google::protobuf::internal::kEmptyString) {
+ delete string_value_;
+ }
+ if (string_value) {
+ set_has_string_value();
+ string_value_ = string_value;
+ } else {
+ clear_has_string_value();
+ string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// optional string aggregate_value = 8;
inline bool UninterpretedOption::has_aggregate_value() const {
@@ -5136,6 +5752,18 @@
return temp;
}
}
+inline void UninterpretedOption::set_allocated_aggregate_value(::std::string* aggregate_value) {
+ if (aggregate_value_ != &::google::protobuf::internal::kEmptyString) {
+ delete aggregate_value_;
+ }
+ if (aggregate_value) {
+ set_has_aggregate_value();
+ aggregate_value_ = aggregate_value;
+ } else {
+ clear_has_aggregate_value();
+ aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
// -------------------------------------------------------------------
@@ -5191,6 +5819,146 @@
return &span_;
}
+// optional string leading_comments = 3;
+inline bool SourceCodeInfo_Location::has_leading_comments() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void SourceCodeInfo_Location::set_has_leading_comments() {
+ _has_bits_[0] |= 0x00000004u;
+}
+inline void SourceCodeInfo_Location::clear_has_leading_comments() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+inline void SourceCodeInfo_Location::clear_leading_comments() {
+ if (leading_comments_ != &::google::protobuf::internal::kEmptyString) {
+ leading_comments_->clear();
+ }
+ clear_has_leading_comments();
+}
+inline const ::std::string& SourceCodeInfo_Location::leading_comments() const {
+ return *leading_comments_;
+}
+inline void SourceCodeInfo_Location::set_leading_comments(const ::std::string& value) {
+ set_has_leading_comments();
+ if (leading_comments_ == &::google::protobuf::internal::kEmptyString) {
+ leading_comments_ = new ::std::string;
+ }
+ leading_comments_->assign(value);
+}
+inline void SourceCodeInfo_Location::set_leading_comments(const char* value) {
+ set_has_leading_comments();
+ if (leading_comments_ == &::google::protobuf::internal::kEmptyString) {
+ leading_comments_ = new ::std::string;
+ }
+ leading_comments_->assign(value);
+}
+inline void SourceCodeInfo_Location::set_leading_comments(const char* value, size_t size) {
+ set_has_leading_comments();
+ if (leading_comments_ == &::google::protobuf::internal::kEmptyString) {
+ leading_comments_ = new ::std::string;
+ }
+ leading_comments_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* SourceCodeInfo_Location::mutable_leading_comments() {
+ set_has_leading_comments();
+ if (leading_comments_ == &::google::protobuf::internal::kEmptyString) {
+ leading_comments_ = new ::std::string;
+ }
+ return leading_comments_;
+}
+inline ::std::string* SourceCodeInfo_Location::release_leading_comments() {
+ clear_has_leading_comments();
+ if (leading_comments_ == &::google::protobuf::internal::kEmptyString) {
+ return NULL;
+ } else {
+ ::std::string* temp = leading_comments_;
+ leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ return temp;
+ }
+}
+inline void SourceCodeInfo_Location::set_allocated_leading_comments(::std::string* leading_comments) {
+ if (leading_comments_ != &::google::protobuf::internal::kEmptyString) {
+ delete leading_comments_;
+ }
+ if (leading_comments) {
+ set_has_leading_comments();
+ leading_comments_ = leading_comments;
+ } else {
+ clear_has_leading_comments();
+ leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
+
+// optional string trailing_comments = 4;
+inline bool SourceCodeInfo_Location::has_trailing_comments() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void SourceCodeInfo_Location::set_has_trailing_comments() {
+ _has_bits_[0] |= 0x00000008u;
+}
+inline void SourceCodeInfo_Location::clear_has_trailing_comments() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+inline void SourceCodeInfo_Location::clear_trailing_comments() {
+ if (trailing_comments_ != &::google::protobuf::internal::kEmptyString) {
+ trailing_comments_->clear();
+ }
+ clear_has_trailing_comments();
+}
+inline const ::std::string& SourceCodeInfo_Location::trailing_comments() const {
+ return *trailing_comments_;
+}
+inline void SourceCodeInfo_Location::set_trailing_comments(const ::std::string& value) {
+ set_has_trailing_comments();
+ if (trailing_comments_ == &::google::protobuf::internal::kEmptyString) {
+ trailing_comments_ = new ::std::string;
+ }
+ trailing_comments_->assign(value);
+}
+inline void SourceCodeInfo_Location::set_trailing_comments(const char* value) {
+ set_has_trailing_comments();
+ if (trailing_comments_ == &::google::protobuf::internal::kEmptyString) {
+ trailing_comments_ = new ::std::string;
+ }
+ trailing_comments_->assign(value);
+}
+inline void SourceCodeInfo_Location::set_trailing_comments(const char* value, size_t size) {
+ set_has_trailing_comments();
+ if (trailing_comments_ == &::google::protobuf::internal::kEmptyString) {
+ trailing_comments_ = new ::std::string;
+ }
+ trailing_comments_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() {
+ set_has_trailing_comments();
+ if (trailing_comments_ == &::google::protobuf::internal::kEmptyString) {
+ trailing_comments_ = new ::std::string;
+ }
+ return trailing_comments_;
+}
+inline ::std::string* SourceCodeInfo_Location::release_trailing_comments() {
+ clear_has_trailing_comments();
+ if (trailing_comments_ == &::google::protobuf::internal::kEmptyString) {
+ return NULL;
+ } else {
+ ::std::string* temp = trailing_comments_;
+ trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ return temp;
+ }
+}
+inline void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::string* trailing_comments) {
+ if (trailing_comments_ != &::google::protobuf::internal::kEmptyString) {
+ delete trailing_comments_;
+ }
+ if (trailing_comments) {
+ set_has_trailing_comments();
+ trailing_comments_ = trailing_comments;
+ } else {
+ clear_has_trailing_comments();
+ trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString);
+ }
+}
+
// -------------------------------------------------------------------
// SourceCodeInfo
diff --git a/third_party/protobuf/src/google/protobuf/descriptor.proto b/third_party/protobuf/src/google/protobuf/descriptor.proto
index bd3cb96..ef9eb65 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor.proto
+++ b/third_party/protobuf/src/google/protobuf/descriptor.proto
@@ -59,6 +59,11 @@
// Names of files imported by this file.
repeated string dependency = 3;
+ // Indexes of the public imported files in the dependency list above.
+ repeated int32 public_dependency = 10;
+ // Indexes of the weak imported files in the dependency list.
+ // For Google-internal migration only. Do not use.
+ repeated int32 weak_dependency = 11;
// All top-level definitions in this file.
repeated DescriptorProto message_type = 4;
@@ -101,13 +106,13 @@
// Order is weird for historical reasons.
TYPE_DOUBLE = 1;
TYPE_FLOAT = 2;
- TYPE_INT64 = 3; // Not ZigZag encoded. Negative numbers
- // take 10 bytes. Use TYPE_SINT64 if negative
- // values are likely.
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if
+ // negative values are likely.
+ TYPE_INT64 = 3;
TYPE_UINT64 = 4;
- TYPE_INT32 = 5; // Not ZigZag encoded. Negative numbers
- // take 10 bytes. Use TYPE_SINT32 if negative
- // values are likely.
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if
+ // negative values are likely.
+ TYPE_INT32 = 5;
TYPE_FIXED64 = 6;
TYPE_FIXED32 = 7;
TYPE_BOOL = 8;
@@ -199,6 +204,7 @@
optional MethodOptions options = 4;
}
+
// ===================================================================
// Options
@@ -260,7 +266,7 @@
// reserializing a message will retain them. This is the default behaviour
// unless LITE_RUNTIME is specified. Therefore, this option only makes sense
// when LITE_RUNTIME is in use.
- optional bool retain_unknown_fields = 11 [default=false];
+ optional bool retain_unknown_fields = 12 [default=false];
// If set true, then the Java code generator will generate equals() and
// hashCode() methods for all messages defined in the .proto file. This is
@@ -277,6 +283,9 @@
}
optional OptimizeMode optimize_for = 9 [default=SPEED];
+ // Sets the Go package where structs generated from this .proto will be
+ // placed. There is no default.
+ optional string go_package = 11;
@@ -355,6 +364,37 @@
optional bool packed = 2;
+
+ // Should this field be parsed lazily? Lazy applies only to message-type
+ // fields. It means that when the outer message is initially parsed, the
+ // inner message's contents will not be parsed but instead stored in encoded
+ // form. The inner message will actually be parsed when it is first accessed.
+ //
+ // This is only a hint. Implementations are free to choose whether to use
+ // eager or lazy parsing regardless of the value of this option. However,
+ // setting this option true suggests that the protocol author believes that
+ // using lazy parsing on this field is worth the additional bookkeeping
+ // overhead typically needed to implement it.
+ //
+ // This option does not affect the public interface of any generated code;
+ // all method signatures remain the same. Furthermore, thread-safety of the
+ // interface is not affected by this option; const methods remain safe to
+ // call from multiple threads concurrently, while non-const methods continue
+ // to require exclusive access.
+ //
+ //
+ // Note that implementations may choose not to check required fields within
+ // a lazy sub-message. That is, calling IsInitialized() on the outher message
+ // may return true even if the inner message has missing required fields.
+ // This is necessary because otherwise the inner message would have to be
+ // parsed in order to perform the check, defeating the purpose of lazy
+ // parsing. An implementation which chooses not to check required fields
+ // must be consistent about it. That is, for any particular sub-message, the
+ // implementation must either *always* check its required fields, or *never*
+ // check its required fields, regardless of whether or not the message has
+ // been parsed.
+ optional bool lazy = 5 [default=false];
+
// Is this field deprecated?
// Depending on the target platform, this can emit Deprecated annotations
// for accessors, or it will be completely ignored; in the very least, this
@@ -375,6 +415,9 @@
// TODO: Fully-implement this, then remove the "experimental_" prefix.
optional string experimental_map_key = 9;
+ // For Google-internal migration only. Do not use.
+ optional bool weak = 10 [default=false];
+
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
@@ -384,6 +427,10 @@
message EnumOptions {
+ // Set this option to false to disallow mapping different tag names to a same
+ // value.
+ optional bool allow_alias = 2 [default=true];
+
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
@@ -427,6 +474,7 @@
extensions 1000 to max;
}
+
// A message representing a option the parser does not recognize. This only
// appears in options protos created by the compiler::Parser class.
// DescriptorPool resolves these when building Descriptor objects. Therefore,
@@ -538,7 +586,41 @@
// 1 to each before displaying to a user.
repeated int32 span = 2 [packed=true];
- // TODO(kenton): Record comments appearing before and after the
- // declaration.
+ // If this SourceCodeInfo represents a complete declaration, these are any
+ // comments appearing before and after the declaration which appear to be
+ // attached to the declaration.
+ //
+ // A series of line comments appearing on consecutive lines, with no other
+ // tokens appearing on those lines, will be treated as a single comment.
+ //
+ // Only the comment content is provided; comment markers (e.g. //) are
+ // stripped out. For block comments, leading whitespace and an asterisk
+ // will be stripped from the beginning of each line other than the first.
+ // Newlines are included in the output.
+ //
+ // Examples:
+ //
+ // optional int32 foo = 1; // Comment attached to foo.
+ // // Comment attached to bar.
+ // optional int32 bar = 2;
+ //
+ // optional string baz = 3;
+ // // Comment attached to baz.
+ // // Another line attached to baz.
+ //
+ // // Comment attached to qux.
+ // //
+ // // Another line attached to qux.
+ // optional double qux = 4;
+ //
+ // optional string corge = 5;
+ // /* Block comment attached
+ // * to corge. Leading asterisks
+ // * will be removed. */
+ // /* Block comment attached to
+ // * grault. */
+ // optional int32 grault = 6;
+ optional string leading_comments = 3;
+ optional string trailing_comments = 4;
}
}
diff --git a/third_party/protobuf/src/google/protobuf/descriptor_database.cc b/third_party/protobuf/src/google/protobuf/descriptor_database.cc
index 23e48a6..35e459d 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor_database.cc
+++ b/third_party/protobuf/src/google/protobuf/descriptor_database.cc
@@ -39,7 +39,7 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
#include <google/protobuf/stubs/map-util.h>
namespace google {
diff --git a/third_party/protobuf/src/google/protobuf/descriptor_database.h b/third_party/protobuf/src/google/protobuf/descriptor_database.h
index f32b1db..2ccb145 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor_database.h
+++ b/third_party/protobuf/src/google/protobuf/descriptor_database.h
@@ -41,6 +41,7 @@
#include <string>
#include <utility>
#include <vector>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
namespace google {
diff --git a/third_party/protobuf/src/google/protobuf/descriptor_unittest.cc b/third_party/protobuf/src/google/protobuf/descriptor_unittest.cc
index 55aebfd..3503f13 100644
--- a/third_party/protobuf/src/google/protobuf/descriptor_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/descriptor_unittest.cc
@@ -36,13 +36,15 @@
#include <vector>
+#include <google/protobuf/compiler/importer.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_custom_options.pb.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor_database.h>
#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/text_format.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_custom_options.pb.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
@@ -1518,9 +1520,8 @@
class MiscTest : public testing::Test {
protected:
- // Function which makes a field of the given type just to find out what its
- // cpp_type is.
- FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) {
+ // Function which makes a field descriptor of the given type.
+ const FieldDescriptor* GetFieldDescriptorOfType(FieldDescriptor::Type type) {
FileDescriptorProto file_proto;
file_proto.set_name("foo.proto");
AddEmptyEnum(&file_proto, "DummyEnum");
@@ -1538,19 +1539,62 @@
}
// Build the descriptors and get the pointers.
- DescriptorPool pool;
- const FileDescriptor* file = pool.BuildFile(file_proto);
+ pool_.reset(new DescriptorPool());
+ const FileDescriptor* file = pool_->BuildFile(file_proto);
if (file != NULL &&
file->message_type_count() == 1 &&
file->message_type(0)->field_count() == 1) {
- return file->message_type(0)->field(0)->cpp_type();
+ return file->message_type(0)->field(0);
} else {
- return static_cast<FieldDescriptor::CppType>(0);
+ return NULL;
}
}
+
+ const char* GetTypeNameForFieldType(FieldDescriptor::Type type) {
+ const FieldDescriptor* field = GetFieldDescriptorOfType(type);
+ return field != NULL ? field->type_name() : "";
+ }
+
+ FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) {
+ const FieldDescriptor* field = GetFieldDescriptorOfType(type);
+ return field != NULL ? field->cpp_type() :
+ static_cast<FieldDescriptor::CppType>(0);
+ }
+
+ const char* GetCppTypeNameForFieldType(FieldDescriptor::Type type) {
+ const FieldDescriptor* field = GetFieldDescriptorOfType(type);
+ return field != NULL ? field->cpp_type_name() : "";
+ }
+
+ scoped_ptr<DescriptorPool> pool_;
};
+TEST_F(MiscTest, TypeNames) {
+ // Test that correct type names are returned.
+
+ typedef FieldDescriptor FD; // avoid ugly line wrapping
+
+ EXPECT_STREQ("double" , GetTypeNameForFieldType(FD::TYPE_DOUBLE ));
+ EXPECT_STREQ("float" , GetTypeNameForFieldType(FD::TYPE_FLOAT ));
+ EXPECT_STREQ("int64" , GetTypeNameForFieldType(FD::TYPE_INT64 ));
+ EXPECT_STREQ("uint64" , GetTypeNameForFieldType(FD::TYPE_UINT64 ));
+ EXPECT_STREQ("int32" , GetTypeNameForFieldType(FD::TYPE_INT32 ));
+ EXPECT_STREQ("fixed64" , GetTypeNameForFieldType(FD::TYPE_FIXED64 ));
+ EXPECT_STREQ("fixed32" , GetTypeNameForFieldType(FD::TYPE_FIXED32 ));
+ EXPECT_STREQ("bool" , GetTypeNameForFieldType(FD::TYPE_BOOL ));
+ EXPECT_STREQ("string" , GetTypeNameForFieldType(FD::TYPE_STRING ));
+ EXPECT_STREQ("group" , GetTypeNameForFieldType(FD::TYPE_GROUP ));
+ EXPECT_STREQ("message" , GetTypeNameForFieldType(FD::TYPE_MESSAGE ));
+ EXPECT_STREQ("bytes" , GetTypeNameForFieldType(FD::TYPE_BYTES ));
+ EXPECT_STREQ("uint32" , GetTypeNameForFieldType(FD::TYPE_UINT32 ));
+ EXPECT_STREQ("enum" , GetTypeNameForFieldType(FD::TYPE_ENUM ));
+ EXPECT_STREQ("sfixed32", GetTypeNameForFieldType(FD::TYPE_SFIXED32));
+ EXPECT_STREQ("sfixed64", GetTypeNameForFieldType(FD::TYPE_SFIXED64));
+ EXPECT_STREQ("sint32" , GetTypeNameForFieldType(FD::TYPE_SINT32 ));
+ EXPECT_STREQ("sint64" , GetTypeNameForFieldType(FD::TYPE_SINT64 ));
+}
+
TEST_F(MiscTest, CppTypes) {
// Test that CPP types are assigned correctly.
@@ -1576,6 +1620,31 @@
EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_SINT64 ));
}
+TEST_F(MiscTest, CppTypeNames) {
+ // Test that correct CPP type names are returned.
+
+ typedef FieldDescriptor FD; // avoid ugly line wrapping
+
+ EXPECT_STREQ("double" , GetCppTypeNameForFieldType(FD::TYPE_DOUBLE ));
+ EXPECT_STREQ("float" , GetCppTypeNameForFieldType(FD::TYPE_FLOAT ));
+ EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_INT64 ));
+ EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_UINT64 ));
+ EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_INT32 ));
+ EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_FIXED64 ));
+ EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_FIXED32 ));
+ EXPECT_STREQ("bool" , GetCppTypeNameForFieldType(FD::TYPE_BOOL ));
+ EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_STRING ));
+ EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_GROUP ));
+ EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_MESSAGE ));
+ EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_BYTES ));
+ EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_UINT32 ));
+ EXPECT_STREQ("enum" , GetCppTypeNameForFieldType(FD::TYPE_ENUM ));
+ EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED32));
+ EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED64));
+ EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SINT32 ));
+ EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SINT64 ));
+}
+
TEST_F(MiscTest, DefaultValues) {
// Test that setting default values works.
FileDescriptorProto file_proto;
@@ -1739,13 +1808,31 @@
}
// ===================================================================
+enum DescriptorPoolMode {
+ NO_DATABASE,
+ FALLBACK_DATABASE
+};
-class AllowUnknownDependenciesTest : public testing::Test {
+class AllowUnknownDependenciesTest
+ : public testing::TestWithParam<DescriptorPoolMode> {
protected:
+ DescriptorPoolMode mode() {
+ return GetParam();
+ }
+
virtual void SetUp() {
FileDescriptorProto foo_proto, bar_proto;
- pool_.AllowUnknownDependencies();
+ switch (mode()) {
+ case NO_DATABASE:
+ pool_.reset(new DescriptorPool);
+ break;
+ case FALLBACK_DATABASE:
+ pool_.reset(new DescriptorPool(&db_));
+ break;
+ }
+
+ pool_->AllowUnknownDependencies();
ASSERT_TRUE(TextFormat::ParseFromString(
"name: 'foo.proto'"
@@ -1776,13 +1863,13 @@
&bar_proto));
// Collect pointers to stuff.
- bar_file_ = pool_.BuildFile(bar_proto);
+ bar_file_ = BuildFile(bar_proto);
ASSERT_TRUE(bar_file_ != NULL);
ASSERT_EQ(1, bar_file_->message_type_count());
bar_type_ = bar_file_->message_type(0);
- foo_file_ = pool_.BuildFile(foo_proto);
+ foo_file_ = BuildFile(foo_proto);
ASSERT_TRUE(foo_file_ != NULL);
ASSERT_EQ(1, foo_file_->message_type_count());
@@ -1794,6 +1881,20 @@
qux_field_ = foo_type_->field(2);
}
+ const FileDescriptor* BuildFile(const FileDescriptorProto& proto) {
+ switch (mode()) {
+ case NO_DATABASE:
+ return pool_->BuildFile(proto);
+ break;
+ case FALLBACK_DATABASE: {
+ EXPECT_TRUE(db_.Add(proto));
+ return pool_->FindFileByName(proto.name());
+ }
+ }
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+ }
+
const FileDescriptor* bar_file_;
const Descriptor* bar_type_;
const FileDescriptor* foo_file_;
@@ -1802,10 +1903,11 @@
const FieldDescriptor* baz_field_;
const FieldDescriptor* qux_field_;
- DescriptorPool pool_;
+ SimpleDescriptorDatabase db_; // used if in FALLBACK_DATABASE mode.
+ scoped_ptr<DescriptorPool> pool_;
};
-TEST_F(AllowUnknownDependenciesTest, PlaceholderFile) {
+TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) {
ASSERT_EQ(2, foo_file_->dependency_count());
EXPECT_EQ(bar_file_, foo_file_->dependency(0));
@@ -1814,11 +1916,11 @@
EXPECT_EQ(0, baz_file->message_type_count());
// Placeholder files should not be findable.
- EXPECT_EQ(bar_file_, pool_.FindFileByName(bar_file_->name()));
- EXPECT_TRUE(pool_.FindFileByName(baz_file->name()) == NULL);
+ EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name()));
+ EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == NULL);
}
-TEST_F(AllowUnknownDependenciesTest, PlaceholderTypes) {
+TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) {
ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type());
EXPECT_EQ(bar_type_, bar_field_->message_type());
@@ -1836,12 +1938,12 @@
EXPECT_EQ("corge.Qux.placeholder.proto", qux_type->file()->name());
// Placeholder types should not be findable.
- EXPECT_EQ(bar_type_, pool_.FindMessageTypeByName(bar_type_->full_name()));
- EXPECT_TRUE(pool_.FindMessageTypeByName(baz_type->full_name()) == NULL);
- EXPECT_TRUE(pool_.FindEnumTypeByName(qux_type->full_name()) == NULL);
+ EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name()));
+ EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == NULL);
+ EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == NULL);
}
-TEST_F(AllowUnknownDependenciesTest, CopyTo) {
+TEST_P(AllowUnknownDependenciesTest, CopyTo) {
// FieldDescriptor::CopyTo() should write non-fully-qualified type names
// for placeholder types which were not originally fully-qualified.
FieldDescriptorProto proto;
@@ -1864,7 +1966,7 @@
EXPECT_EQ(FieldDescriptorProto::TYPE_ENUM, proto.type());
}
-TEST_F(AllowUnknownDependenciesTest, CustomOptions) {
+TEST_P(AllowUnknownDependenciesTest, CustomOptions) {
// Qux should still have the uninterpreted option attached.
ASSERT_EQ(1, qux_field_->options().uninterpreted_option_size());
const UninterpretedOption& option =
@@ -1873,7 +1975,7 @@
EXPECT_EQ("grault", option.name(0).name_part());
}
-TEST_F(AllowUnknownDependenciesTest, UnknownExtendee) {
+TEST_P(AllowUnknownDependenciesTest, UnknownExtendee) {
// Test that we can extend an unknown type. This is slightly tricky because
// it means that the placeholder type must have an extension range.
@@ -1884,7 +1986,7 @@
"extension { extendee: 'UnknownType' name:'some_extension' number:123"
" label:LABEL_OPTIONAL type:TYPE_INT32 }",
&extension_proto));
- const FileDescriptor* file = pool_.BuildFile(extension_proto);
+ const FileDescriptor* file = BuildFile(extension_proto);
ASSERT_TRUE(file != NULL);
@@ -1896,7 +1998,7 @@
EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end);
}
-TEST_F(AllowUnknownDependenciesTest, CustomOption) {
+TEST_P(AllowUnknownDependenciesTest, CustomOption) {
// Test that we can use a custom option without having parsed
// descriptor.proto.
@@ -1937,7 +2039,7 @@
"}",
&option_proto));
- const FileDescriptor* file = pool_.BuildFile(option_proto);
+ const FileDescriptor* file = BuildFile(option_proto);
ASSERT_TRUE(file != NULL);
// Verify that no extension options were set, but they were left as
@@ -1949,6 +2051,81 @@
EXPECT_EQ(2, file->options().uninterpreted_option_size());
}
+TEST_P(AllowUnknownDependenciesTest,
+ UndeclaredDependencyTriggersBuildOfDependency) {
+ // Crazy case: suppose foo.proto refers to a symbol without declaring the
+ // dependency that finds it. In the event that the pool is backed by a
+ // DescriptorDatabase, the pool will attempt to find the symbol in the
+ // database. If successful, it will build the undeclared dependency to verify
+ // that the file does indeed contain the symbol. If that file fails to build,
+ // then its descriptors must be rolled back. However, we still want foo.proto
+ // to build successfully, since we are allowing unknown dependencies.
+
+ FileDescriptorProto undeclared_dep_proto;
+ // We make this file fail to build by giving it two fields with tag 1.
+ ASSERT_TRUE(TextFormat::ParseFromString(
+ "name: \"invalid_file_as_undeclared_dep.proto\" "
+ "package: \"undeclared\" "
+ "message_type: { "
+ " name: \"Quux\" "
+ " field { "
+ " name:'qux' number:1 label:LABEL_OPTIONAL type: TYPE_INT32 "
+ " }"
+ " field { "
+ " name:'quux' number:1 label:LABEL_OPTIONAL type: TYPE_INT64 "
+ " }"
+ "}",
+ &undeclared_dep_proto));
+ // We can't use the BuildFile() helper because we don't actually want to build
+ // it into the descriptor pool in the fallback database case: it just needs to
+ // be sitting in the database so that it gets built during the building of
+ // test.proto below.
+ switch (mode()) {
+ case NO_DATABASE: {
+ ASSERT_TRUE(pool_->BuildFile(undeclared_dep_proto) == NULL);
+ break;
+ }
+ case FALLBACK_DATABASE: {
+ ASSERT_TRUE(db_.Add(undeclared_dep_proto));
+ }
+ }
+
+ FileDescriptorProto test_proto;
+ ASSERT_TRUE(TextFormat::ParseFromString(
+ "name: \"test.proto\" "
+ "message_type: { "
+ " name: \"Corge\" "
+ " field { "
+ " name:'quux' number:1 label: LABEL_OPTIONAL "
+ " type_name:'undeclared.Quux' type: TYPE_MESSAGE "
+ " }"
+ "}",
+ &test_proto));
+
+ const FileDescriptor* file = BuildFile(test_proto);
+ ASSERT_TRUE(file != NULL);
+ GOOGLE_LOG(INFO) << file->DebugString();
+
+ EXPECT_EQ(0, file->dependency_count());
+ ASSERT_EQ(1, file->message_type_count());
+ const Descriptor* corge_desc = file->message_type(0);
+ ASSERT_EQ("Corge", corge_desc->name());
+ ASSERT_EQ(1, corge_desc->field_count());
+
+ const FieldDescriptor* quux_field = corge_desc->field(0);
+ ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, quux_field->type());
+ ASSERT_EQ("Quux", quux_field->message_type()->name());
+ ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name());
+ EXPECT_EQ("undeclared.Quux.placeholder.proto",
+ quux_field->message_type()->file()->name());
+ // The place holder type should not be findable.
+ ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL);
+}
+
+INSTANTIATE_TEST_CASE_P(DatabaseSource,
+ AllowUnknownDependenciesTest,
+ testing::Values(NO_DATABASE, FALLBACK_DATABASE));
+
// ===================================================================
TEST(CustomOptions, OptionLocations) {
@@ -2451,6 +2628,15 @@
"bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n");
}
+TEST_F(ValidationErrorTest, InvalidPublicDependencyIndex) {
+ BuildFile("name: \"foo.proto\"");
+ BuildFileWithErrors(
+ "name: \"bar.proto\" "
+ "dependency: \"foo.proto\" "
+ "public_dependency: 1",
+ "bar.proto: bar.proto: OTHER: Invalid public dependency index.\n");
+}
+
TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) {
// Used to crash: If we depend on a non-existent file and then refer to a
// package defined in a file that we didn't import, and that package is
@@ -2829,6 +3015,164 @@
"necessary import.\n");
}
+TEST_F(ValidationErrorTest, FieldTypeDefinedInIndirectDependency) {
+ // Test for hidden dependencies.
+ //
+ // // bar.proto
+ // message Bar{}
+ //
+ // // forward.proto
+ // import "bar.proto"
+ //
+ // // foo.proto
+ // import "forward.proto"
+ // message Foo {
+ // optional Bar foo = 1; // Error, needs to import bar.proto explicitly.
+ // }
+ //
+ BuildFile(
+ "name: \"bar.proto\" "
+ "message_type { name: \"Bar\" }");
+
+ BuildFile(
+ "name: \"forward.proto\""
+ "dependency: \"bar.proto\"");
+
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "dependency: \"forward.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+ "}",
+ "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
+ "which is not imported by \"foo.proto\". To use it here, please add the "
+ "necessary import.\n");
+}
+
+TEST_F(ValidationErrorTest, FieldTypeDefinedInPublicDependency) {
+ // Test for public dependencies.
+ //
+ // // bar.proto
+ // message Bar{}
+ //
+ // // forward.proto
+ // import public "bar.proto"
+ //
+ // // foo.proto
+ // import "forward.proto"
+ // message Foo {
+ // optional Bar foo = 1; // Correct. "bar.proto" is public imported into
+ // // forward.proto, so when "foo.proto" imports
+ // // "forward.proto", it imports "bar.proto" too.
+ // }
+ //
+ BuildFile(
+ "name: \"bar.proto\" "
+ "message_type { name: \"Bar\" }");
+
+ BuildFile(
+ "name: \"forward.proto\""
+ "dependency: \"bar.proto\" "
+ "public_dependency: 0");
+
+ BuildFile(
+ "name: \"foo.proto\" "
+ "dependency: \"forward.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+ "}");
+}
+
+TEST_F(ValidationErrorTest, FieldTypeDefinedInTransitivePublicDependency) {
+ // Test for public dependencies.
+ //
+ // // bar.proto
+ // message Bar{}
+ //
+ // // forward.proto
+ // import public "bar.proto"
+ //
+ // // forward2.proto
+ // import public "forward.proto"
+ //
+ // // foo.proto
+ // import "forward2.proto"
+ // message Foo {
+ // optional Bar foo = 1; // Correct, public imports are transitive.
+ // }
+ //
+ BuildFile(
+ "name: \"bar.proto\" "
+ "message_type { name: \"Bar\" }");
+
+ BuildFile(
+ "name: \"forward.proto\""
+ "dependency: \"bar.proto\" "
+ "public_dependency: 0");
+
+ BuildFile(
+ "name: \"forward2.proto\""
+ "dependency: \"forward.proto\" "
+ "public_dependency: 0");
+
+ BuildFile(
+ "name: \"foo.proto\" "
+ "dependency: \"forward2.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+ "}");
+}
+
+TEST_F(ValidationErrorTest,
+ FieldTypeDefinedInPrivateDependencyOfPublicDependency) {
+ // Test for public dependencies.
+ //
+ // // bar.proto
+ // message Bar{}
+ //
+ // // forward.proto
+ // import "bar.proto"
+ //
+ // // forward2.proto
+ // import public "forward.proto"
+ //
+ // // foo.proto
+ // import "forward2.proto"
+ // message Foo {
+ // optional Bar foo = 1; // Error, the "bar.proto" is not public imported
+ // // into "forward.proto", so will not be imported
+ // // into either "forward2.proto" or "foo.proto".
+ // }
+ //
+ BuildFile(
+ "name: \"bar.proto\" "
+ "message_type { name: \"Bar\" }");
+
+ BuildFile(
+ "name: \"forward.proto\""
+ "dependency: \"bar.proto\"");
+
+ BuildFile(
+ "name: \"forward2.proto\""
+ "dependency: \"forward.proto\" "
+ "public_dependency: 0");
+
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "dependency: \"forward2.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+ "}",
+ "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", "
+ "which is not imported by \"foo.proto\". To use it here, please add the "
+ "necessary import.\n");
+}
+
+
TEST_F(ValidationErrorTest, SearchMostLocalFirst) {
// The following should produce an error that Bar.Baz is not defined:
// message Bar { message Baz {} }
@@ -3031,7 +3375,8 @@
" method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
"}",
- "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n");
+ "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n"
+ );
}
TEST_F(ValidationErrorTest, InputTypeNotAMessage) {
@@ -3044,7 +3389,8 @@
" method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
"}",
- "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n");
+ "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n"
+ );
}
TEST_F(ValidationErrorTest, OutputTypeNotDefined) {
@@ -3056,7 +3402,8 @@
" method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
"}",
- "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n");
+ "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n"
+ );
}
TEST_F(ValidationErrorTest, OutputTypeNotAMessage) {
@@ -3069,9 +3416,11 @@
" method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
"}",
- "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n");
+ "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n"
+ );
}
+
TEST_F(ValidationErrorTest, IllegalPackedField) {
BuildFileWithErrors(
"name: \"foo.proto\" "
@@ -3592,7 +3941,8 @@
" }"
"}",
- "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n");
+ "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n"
+ );
// Make sure that if we build the same file again with the error fixed,
// it works. If the above rollback was incomplete, then some symbols will
@@ -3641,6 +3991,19 @@
EXPECT_EQ(" Foo: \"Foo\" is already defined.", errors[1]);
}
+TEST_F(ValidationErrorTest, DisallowEnumAlias) {
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "enum_type {"
+ " name: \"Bar\""
+ " value { name:\"ENUM_A\" number:0 }"
+ " value { name:\"ENUM_B\" number:0 }"
+ " options { allow_alias: false }"
+ "}",
+ "foo.proto: Bar: NUMBER: "
+ "\"ENUM_B\" uses the same enum value as \"ENUM_A\"\n");
+}
+
// ===================================================================
// DescriptorDatabase
@@ -3659,16 +4022,23 @@
virtual void SetUp() {
AddToDatabase(&database_,
- "name: \"foo.proto\" "
- "message_type { name:\"Foo\" extension_range { start: 1 end: 100 } } "
- "enum_type { name:\"TestEnum\" value { name:\"DUMMY\" number:0 } } "
- "service { name:\"TestService\" } ");
+ "name: 'foo.proto' "
+ "message_type { name:'Foo' extension_range { start: 1 end: 100 } } "
+ "enum_type { name:'TestEnum' value { name:'DUMMY' number:0 } } "
+ "service { name:'TestService' } ");
AddToDatabase(&database_,
- "name: \"bar.proto\" "
- "dependency: \"foo.proto\" "
- "message_type { name:\"Bar\" } "
- "extension { name:\"foo_ext\" extendee: \".Foo\" number:5 "
+ "name: 'bar.proto' "
+ "dependency: 'foo.proto' "
+ "message_type { name:'Bar' } "
+ "extension { name:'foo_ext' extendee: '.Foo' number:5 "
" label:LABEL_OPTIONAL type:TYPE_INT32 } ");
+ // Baz has an undeclared dependency on Foo.
+ AddToDatabase(&database_,
+ "name: 'baz.proto' "
+ "message_type { "
+ " name:'Baz' "
+ " field { name:'foo' number:1 label:LABEL_OPTIONAL type_name:'Foo' } "
+ "}");
}
// We can't inject a file containing errors into a DescriptorPool, so we
@@ -3907,6 +4277,33 @@
error_collector.text_);
}
+TEST_F(DatabaseBackedPoolTest, UndeclaredDependencyOnUnbuiltType) {
+ // Check that we find and report undeclared dependencies on types that exist
+ // in the descriptor database but that have not not been built yet.
+ MockErrorCollector error_collector;
+ DescriptorPool pool(&database_, &error_collector);
+ EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
+ EXPECT_EQ(
+ "baz.proto: Baz.foo: TYPE: \"Foo\" seems to be defined in \"foo.proto\", "
+ "which is not imported by \"baz.proto\". To use it here, please add "
+ "the necessary import.\n",
+ error_collector.text_);
+}
+
+TEST_F(DatabaseBackedPoolTest, RollbackAfterError) {
+ // Make sure that all traces of bad types are removed from the pool. This used
+ // to be b/4529436, due to the fact that a symbol resolution failure could
+ // potentially cause another file to be recursively built, which would trigger
+ // a checkpoint _past_ possibly invalid symbols.
+ // Baz is defined in the database, but the file is invalid because it is
+ // missing a necessary import.
+ DescriptorPool pool(&database_);
+ EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
+ // Make sure that searching again for the file or the type fails.
+ EXPECT_TRUE(pool.FindFileByName("baz.proto") == NULL);
+ EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
+}
+
TEST_F(DatabaseBackedPoolTest, UnittestProto) {
// Try to load all of unittest.proto from a DescriptorDatabase. This should
// thoroughly test all paths through DescriptorBuilder to insure that there
@@ -3963,6 +4360,16 @@
EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == NULL);
EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == NULL);
+
+ EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == NULL);
+ EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == NULL);
+ EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == NULL);
+ EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == NULL);
+ EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == NULL);
+ EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == NULL);
+ EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == NULL);
+ EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == NULL);
+
EXPECT_EQ(0, call_counter.call_count_);
}
@@ -4028,6 +4435,219 @@
// ===================================================================
+class AbortingErrorCollector : public DescriptorPool::ErrorCollector {
+ public:
+ AbortingErrorCollector() {}
+
+ virtual void AddError(
+ const string &filename,
+ const string &element_name,
+ const Message *message,
+ ErrorLocation location,
+ const string &error_message) {
+ GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << ": "
+ << error_message;
+ }
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector);
+};
+
+// A source tree containing only one file.
+class SingletonSourceTree : public compiler::SourceTree {
+ public:
+ SingletonSourceTree(const string& filename, const string& contents)
+ : filename_(filename), contents_(contents) {}
+
+ virtual io::ZeroCopyInputStream* Open(const string& filename) {
+ return filename == filename_ ?
+ new io::ArrayInputStream(contents_.data(), contents_.size()) : NULL;
+ }
+
+ private:
+ const string filename_;
+ const string contents_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingletonSourceTree);
+};
+
+const char *const kSourceLocationTestInput =
+ "syntax = \"proto2\";\n"
+ "message A {\n"
+ " optional int32 a = 1;\n"
+ " message B {\n"
+ " required double b = 1;\n"
+ " }\n"
+ "}\n"
+ "enum Indecision {\n"
+ " YES = 1;\n"
+ " NO = 2;\n"
+ " MAYBE = 3;\n"
+ "}\n"
+ "service S {\n"
+ " rpc Method(A) returns (A.B);\n"
+ // Put an empty line here to make the source location range match.
+ "\n"
+ "}\n";
+
+class SourceLocationTest : public testing::Test {
+ public:
+ SourceLocationTest()
+ : source_tree_("/test/test.proto", kSourceLocationTestInput),
+ db_(&source_tree_),
+ pool_(&db_, &collector_) {}
+
+ static string PrintSourceLocation(const SourceLocation &loc) {
+ return strings::Substitute("$0:$1-$2:$3",
+ 1 + loc.start_line,
+ 1 + loc.start_column,
+ 1 + loc.end_line,
+ 1 + loc.end_column);
+ }
+
+ private:
+ AbortingErrorCollector collector_;
+ SingletonSourceTree source_tree_;
+ compiler::SourceTreeDescriptorDatabase db_;
+
+ protected:
+ DescriptorPool pool_;
+};
+
+// TODO(adonovan): implement support for option fields and for
+// subparts of declarations.
+
+TEST_F(SourceLocationTest, GetSourceLocation) {
+ SourceLocation loc;
+
+ const FileDescriptor *file_desc =
+ GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+
+ const Descriptor *a_desc = file_desc->FindMessageTypeByName("A");
+ EXPECT_TRUE(a_desc->GetSourceLocation(&loc));
+ EXPECT_EQ("2:1-7:2", PrintSourceLocation(loc));
+
+ const Descriptor *a_b_desc = a_desc->FindNestedTypeByName("B");
+ EXPECT_TRUE(a_b_desc->GetSourceLocation(&loc));
+ EXPECT_EQ("4:3-6:4", PrintSourceLocation(loc));
+
+ const EnumDescriptor *e_desc = file_desc->FindEnumTypeByName("Indecision");
+ EXPECT_TRUE(e_desc->GetSourceLocation(&loc));
+ EXPECT_EQ("8:1-12:2", PrintSourceLocation(loc));
+
+ const EnumValueDescriptor *yes_desc = e_desc->FindValueByName("YES");
+ EXPECT_TRUE(yes_desc->GetSourceLocation(&loc));
+ EXPECT_EQ("9:3-9:13", PrintSourceLocation(loc));
+
+ const ServiceDescriptor *s_desc = file_desc->FindServiceByName("S");
+ EXPECT_TRUE(s_desc->GetSourceLocation(&loc));
+ EXPECT_EQ("13:1-16:2", PrintSourceLocation(loc));
+
+ const MethodDescriptor *m_desc = s_desc->FindMethodByName("Method");
+ EXPECT_TRUE(m_desc->GetSourceLocation(&loc));
+ EXPECT_EQ("14:3-14:31", PrintSourceLocation(loc));
+
+}
+
+// Missing SourceCodeInfo doesn't cause crash:
+TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) {
+ SourceLocation loc;
+
+ const FileDescriptor *file_desc =
+ GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+
+ FileDescriptorProto proto;
+ file_desc->CopyTo(&proto); // Note, this discards the SourceCodeInfo.
+ EXPECT_FALSE(proto.has_source_code_info());
+
+ DescriptorPool bad1_pool(&pool_);
+ const FileDescriptor* bad1_file_desc =
+ GOOGLE_CHECK_NOTNULL(bad1_pool.BuildFile(proto));
+ const Descriptor *bad1_a_desc = bad1_file_desc->FindMessageTypeByName("A");
+ EXPECT_FALSE(bad1_a_desc->GetSourceLocation(&loc));
+}
+
+// Corrupt SourceCodeInfo doesn't cause crash:
+TEST_F(SourceLocationTest, GetSourceLocation_BogusSourceCodeInfo) {
+ SourceLocation loc;
+
+ const FileDescriptor *file_desc =
+ GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+
+ FileDescriptorProto proto;
+ file_desc->CopyTo(&proto); // Note, this discards the SourceCodeInfo.
+ EXPECT_FALSE(proto.has_source_code_info());
+ SourceCodeInfo_Location *loc_msg =
+ proto.mutable_source_code_info()->add_location();
+ loc_msg->add_path(1);
+ loc_msg->add_path(2);
+ loc_msg->add_path(3);
+ loc_msg->add_span(4);
+ loc_msg->add_span(5);
+ loc_msg->add_span(6);
+
+ DescriptorPool bad2_pool(&pool_);
+ const FileDescriptor* bad2_file_desc =
+ GOOGLE_CHECK_NOTNULL(bad2_pool.BuildFile(proto));
+ const Descriptor *bad2_a_desc = bad2_file_desc->FindMessageTypeByName("A");
+ EXPECT_FALSE(bad2_a_desc->GetSourceLocation(&loc));
+}
+
+// ===================================================================
+
+const char* const kCopySourceCodeInfoToTestInput =
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n";
+
+// Required since source code information is not preserved by
+// FileDescriptorTest.
+class CopySourceCodeInfoToTest : public testing::Test {
+ public:
+ CopySourceCodeInfoToTest()
+ : source_tree_("/test/test.proto", kCopySourceCodeInfoToTestInput),
+ db_(&source_tree_),
+ pool_(&db_, &collector_) {}
+
+ private:
+ AbortingErrorCollector collector_;
+ SingletonSourceTree source_tree_;
+ compiler::SourceTreeDescriptorDatabase db_;
+
+ protected:
+ DescriptorPool pool_;
+};
+
+TEST_F(CopySourceCodeInfoToTest, CopyTo_DoesNotCopySourceCodeInfo) {
+ const FileDescriptor* file_desc =
+ GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+ FileDescriptorProto file_desc_proto;
+ ASSERT_FALSE(file_desc_proto.has_source_code_info());
+
+ file_desc->CopyTo(&file_desc_proto);
+ EXPECT_FALSE(file_desc_proto.has_source_code_info());
+}
+
+TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) {
+ const FileDescriptor* file_desc =
+ GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto"));
+ FileDescriptorProto file_desc_proto;
+ ASSERT_FALSE(file_desc_proto.has_source_code_info());
+
+ file_desc->CopySourceCodeInfoTo(&file_desc_proto);
+ const SourceCodeInfo& info = file_desc_proto.source_code_info();
+ ASSERT_EQ(3, info.location_size());
+ // Get the Foo message location
+ const SourceCodeInfo_Location& foo_location = info.location(1);
+ ASSERT_EQ(2, foo_location.path_size());
+ EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0));
+ EXPECT_EQ(0, foo_location.path(1)); // Foo is the first message defined
+ ASSERT_EQ(3, foo_location.span_size()); // Foo spans one line
+ EXPECT_EQ(1, foo_location.span(0)); // Foo is declared on line 1
+ EXPECT_EQ(0, foo_location.span(1)); // Foo starts at column 0
+ EXPECT_EQ(14, foo_location.span(2)); // Foo ends on column 14
+}
+
+// ===================================================================
+
} // namespace descriptor_unittest
} // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/dynamic_message.cc b/third_party/protobuf/src/google/protobuf/dynamic_message.cc
index c711a2d..e4bebb2 100644
--- a/third_party/protobuf/src/google/protobuf/dynamic_message.cc
+++ b/third_party/protobuf/src/google/protobuf/dynamic_message.cc
@@ -123,7 +123,9 @@
case FD::CPPTYPE_FLOAT : return sizeof(float );
case FD::CPPTYPE_BOOL : return sizeof(bool );
case FD::CPPTYPE_ENUM : return sizeof(int );
- case FD::CPPTYPE_MESSAGE: return sizeof(Message*);
+
+ case FD::CPPTYPE_MESSAGE:
+ return sizeof(Message*);
case FD::CPPTYPE_STRING:
switch (field->options().ctype()) {
@@ -178,7 +180,17 @@
// important (the prototype must be deleted *before* the offsets).
scoped_array<int> offsets;
scoped_ptr<const GeneratedMessageReflection> reflection;
- scoped_ptr<const DynamicMessage> prototype;
+ // Don't use a scoped_ptr to hold the prototype: the destructor for
+ // DynamicMessage needs to know whether it is the prototype, and does so by
+ // looking back at this field. This would assume details about the
+ // implementation of scoped_ptr.
+ const DynamicMessage* prototype;
+
+ TypeInfo() : prototype(NULL) {}
+
+ ~TypeInfo() {
+ delete prototype;
+ }
};
DynamicMessage(const TypeInfo* type_info);
@@ -196,6 +208,14 @@
Metadata GetMetadata() const;
+ // We actually allocate more memory than sizeof(*this) when this
+ // class's memory is allocated via the global operator new. Thus, we need to
+ // manually call the global operator delete. Calling the destructor is taken
+ // care of for us.
+ static void operator delete(void* ptr) {
+ ::operator delete(ptr);
+ }
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
@@ -368,11 +388,12 @@
break;
}
}
- } else if ((field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) &&
- !is_prototype()) {
- Message* message = *reinterpret_cast<Message**>(field_ptr);
- if (message != NULL) {
- delete message;
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (!is_prototype()) {
+ Message* message = *reinterpret_cast<Message**>(field_ptr);
+ if (message != NULL) {
+ delete message;
+ }
}
}
}
@@ -403,7 +424,7 @@
}
Message* DynamicMessage::New() const {
- void* new_base = reinterpret_cast<uint8*>(operator new(type_info_->size));
+ void* new_base = operator new(type_info_->size);
memset(new_base, 0, type_info_->size);
return new(new_base) DynamicMessage(type_info_);
}
@@ -465,7 +486,7 @@
const DynamicMessage::TypeInfo** target = &prototypes_->map_[type];
if (*target != NULL) {
// Already exists.
- return (*target)->prototype.get();
+ return (*target)->prototype;
}
DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo;
@@ -533,13 +554,13 @@
void* base = operator new(size);
memset(base, 0, size);
DynamicMessage* prototype = new(base) DynamicMessage(type_info);
- type_info->prototype.reset(prototype);
+ type_info->prototype = prototype;
// Construct the reflection object.
type_info->reflection.reset(
new GeneratedMessageReflection(
type_info->type,
- type_info->prototype.get(),
+ type_info->prototype,
type_info->offsets.get(),
type_info->has_bits_offset,
type_info->unknown_fields_offset,
diff --git a/third_party/protobuf/src/google/protobuf/dynamic_message.h b/third_party/protobuf/src/google/protobuf/dynamic_message.h
index 81dd2c6..b3d1e5d 100644
--- a/third_party/protobuf/src/google/protobuf/dynamic_message.h
+++ b/third_party/protobuf/src/google/protobuf/dynamic_message.h
@@ -68,7 +68,7 @@
class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
public:
// Construct a DynamicMessageFactory that will search for extensions in
- // the DescriptorPool in which the exendee is defined.
+ // the DescriptorPool in which the extendee is defined.
DynamicMessageFactory();
// Construct a DynamicMessageFactory that will search for extensions in
@@ -102,7 +102,7 @@
// object. The returned object remains property of the factory and will
// be destroyed when the factory is destroyed. Also, any objects created
// by calling the prototype's New() method share some data with the
- // prototype, so these must be destoyed before the DynamicMessageFactory
+ // prototype, so these must be destroyed before the DynamicMessageFactory
// is destroyed.
//
// The given descriptor must outlive the returned message, and hence must
diff --git a/third_party/protobuf/src/google/protobuf/dynamic_message_unittest.cc b/third_party/protobuf/src/google/protobuf/dynamic_message_unittest.cc
index 41b89ab..e461597 100644
--- a/third_party/protobuf/src/google/protobuf/dynamic_message_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/dynamic_message_unittest.cc
@@ -73,11 +73,15 @@
// unittest_import.proto.
FileDescriptorProto unittest_file;
FileDescriptorProto unittest_import_file;
+ FileDescriptorProto unittest_import_public_file;
unittest::TestAllTypes::descriptor()->file()->CopyTo(&unittest_file);
unittest_import::ImportMessage::descriptor()->file()->CopyTo(
&unittest_import_file);
+ unittest_import::PublicImportMessage::descriptor()->file()->CopyTo(
+ &unittest_import_public_file);
+ ASSERT_TRUE(pool_.BuildFile(unittest_import_public_file) != NULL);
ASSERT_TRUE(pool_.BuildFile(unittest_import_file) != NULL);
ASSERT_TRUE(pool_.BuildFile(unittest_file) != NULL);
diff --git a/third_party/protobuf/src/google/protobuf/extension_set.cc b/third_party/protobuf/src/google/protobuf/extension_set.cc
index dbb0915..418e068 100644
--- a/third_party/protobuf/src/google/protobuf/extension_set.cc
+++ b/third_party/protobuf/src/google/protobuf/extension_set.cc
@@ -71,7 +71,7 @@
void InitRegistry() {
registry_ = new ExtensionRegistry;
- internal::OnShutdown(&DeleteRegistry);
+ OnShutdown(&DeleteRegistry);
}
// This function is only called at startup, so there is no need for thread-
@@ -180,6 +180,17 @@
return !iter->second.is_cleared;
}
+int ExtensionSet::NumExtensions() const {
+ int result = 0;
+ for (map<int, Extension>::const_iterator iter = extensions_.begin();
+ iter != extensions_.end(); ++iter) {
+ if (!iter->second.is_cleared) {
+ ++result;
+ }
+ }
+ return result;
+}
+
int ExtensionSet::ExtensionSize(int number) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
if (iter == extensions_.end()) return false;
@@ -293,6 +304,14 @@
#undef PRIMITIVE_ACCESSORS
+void* ExtensionSet::MutableRawRepeatedField(int number) {
+ // We assume that all the RepeatedField<>* pointers have the same
+ // size and alignment within the anonymous union in Extension.
+ map<int, Extension>::const_iterator iter = extensions_.find(number);
+ GOOGLE_CHECK(iter != extensions_.end()) << "no extension numbered " << number;
+ return iter->second.repeated_int32_value;
+}
+
// -------------------------------------------------------------------
// Enums
@@ -422,7 +441,11 @@
return default_value;
} else {
GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
- return *iter->second.message_value;
+ if (iter->second.is_lazy) {
+ return iter->second.lazymessage_value->GetMessage(default_value);
+ } else {
+ return *iter->second.message_value;
+ }
}
}
@@ -439,12 +462,19 @@
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
extension->is_repeated = false;
+ extension->is_lazy = false;
extension->message_value = prototype.New();
+ extension->is_cleared = false;
+ return extension->message_value;
} else {
GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
+ extension->is_cleared = false;
+ if (extension->is_lazy) {
+ return extension->lazymessage_value->MutableMessage(prototype);
+ } else {
+ return extension->message_value;
+ }
}
- extension->is_cleared = false;
- return extension->message_value;
}
// Defined in extension_set_heavy.cc.
@@ -452,6 +482,56 @@
// const Descriptor* message_type,
// MessageFactory* factory)
+void ExtensionSet::SetAllocatedMessage(int number, FieldType type,
+ const FieldDescriptor* descriptor,
+ MessageLite* message) {
+ if (message == NULL) {
+ ClearExtension(number);
+ return;
+ }
+ Extension* extension;
+ if (MaybeNewExtension(number, descriptor, &extension)) {
+ extension->type = type;
+ GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
+ extension->is_repeated = false;
+ extension->is_lazy = false;
+ extension->message_value = message;
+ } else {
+ GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
+ if (extension->is_lazy) {
+ extension->lazymessage_value->SetAllocatedMessage(message);
+ } else {
+ delete extension->message_value;
+ extension->message_value = message;
+ }
+ }
+ extension->is_cleared = false;
+}
+
+MessageLite* ExtensionSet::ReleaseMessage(int number,
+ const MessageLite& prototype) {
+ map<int, Extension>::iterator iter = extensions_.find(number);
+ if (iter == extensions_.end()) {
+ // Not present. Return NULL.
+ return NULL;
+ } else {
+ GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
+ MessageLite* ret = NULL;
+ if (iter->second.is_lazy) {
+ ret = iter->second.lazymessage_value->ReleaseMessage(prototype);
+ delete iter->second.lazymessage_value;
+ } else {
+ ret = iter->second.message_value;
+ }
+ extensions_.erase(number);
+ return ret;
+ }
+}
+
+// Defined in extension_set_heavy.cc.
+// MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
+// MessageFactory* factory);
+
const MessageLite& ExtensionSet::GetRepeatedMessage(
int number, int index) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
@@ -484,7 +564,7 @@
// RepeatedPtrField<MessageLite> does not know how to Add() since it cannot
// allocate an abstract object, so we have to be tricky.
MessageLite* result = extension->repeated_message_value
- ->AddFromCleared<internal::GenericTypeHandler<MessageLite> >();
+ ->AddFromCleared<GenericTypeHandler<MessageLite> >();
if (result == NULL) {
result = prototype.New();
extension->repeated_message_value->AddAllocated(result);
@@ -540,6 +620,16 @@
}
}
+MessageLite* ExtensionSet::ReleaseLast(int number) {
+ map<int, Extension>::iterator iter = extensions_.find(number);
+ GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
+
+ Extension* extension = &iter->second;
+ GOOGLE_DCHECK(extension->is_repeated);
+ GOOGLE_DCHECK(cpp_type(extension->type) == WireFormatLite::CPPTYPE_MESSAGE);
+ return extension->repeated_message_value->ReleaseLast();
+}
+
void ExtensionSet::SwapElements(int number, int index1, int index2) {
map<int, Extension>::iterator iter = extensions_.find(number);
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
@@ -602,9 +692,11 @@
if (is_new) {
// Extension did not already exist in set.
extension->type = other_extension.type;
+ extension->is_packed = other_extension.is_packed;
extension->is_repeated = true;
} else {
GOOGLE_DCHECK_EQ(extension->type, other_extension.type);
+ GOOGLE_DCHECK_EQ(extension->is_packed, other_extension.is_packed);
GOOGLE_DCHECK(extension->is_repeated);
}
@@ -675,12 +767,55 @@
*other_extension.string_value,
other_extension.descriptor);
break;
- case WireFormatLite::CPPTYPE_MESSAGE:
- MutableMessage(iter->first, other_extension.type,
- *other_extension.message_value,
- other_extension.descriptor)
- ->CheckTypeAndMergeFrom(*other_extension.message_value);
+ case WireFormatLite::CPPTYPE_MESSAGE: {
+ Extension* extension;
+ bool is_new = MaybeNewExtension(iter->first,
+ other_extension.descriptor,
+ &extension);
+ if (is_new) {
+ extension->type = other_extension.type;
+ extension->is_packed = other_extension.is_packed;
+ extension->is_repeated = false;
+ if (other_extension.is_lazy) {
+ extension->is_lazy = true;
+ extension->lazymessage_value =
+ other_extension.lazymessage_value->New();
+ extension->lazymessage_value->MergeFrom(
+ *other_extension.lazymessage_value);
+ } else {
+ extension->is_lazy = false;
+ extension->message_value =
+ other_extension.message_value->New();
+ extension->message_value->CheckTypeAndMergeFrom(
+ *other_extension.message_value);
+ }
+ } else {
+ GOOGLE_DCHECK_EQ(extension->type, other_extension.type);
+ GOOGLE_DCHECK_EQ(extension->is_packed,other_extension.is_packed);
+ GOOGLE_DCHECK(!extension->is_repeated);
+ if (other_extension.is_lazy) {
+ if (extension->is_lazy) {
+ extension->lazymessage_value->MergeFrom(
+ *other_extension.lazymessage_value);
+ } else {
+ extension->message_value->CheckTypeAndMergeFrom(
+ other_extension.lazymessage_value->GetMessage(
+ *extension->message_value));
+ }
+ } else {
+ if (extension->is_lazy) {
+ extension->lazymessage_value->MutableMessage(
+ *other_extension.message_value)->CheckTypeAndMergeFrom(
+ *other_extension.message_value);
+ } else {
+ extension->message_value->CheckTypeAndMergeFrom(
+ *other_extension.message_value);
+ }
+ }
+ }
+ extension->is_cleared = false;
break;
+ }
}
}
}
@@ -706,7 +841,11 @@
}
} else {
if (!extension.is_cleared) {
- if (!extension.message_value->IsInitialized()) return false;
+ if (extension.is_lazy) {
+ if (!extension.lazymessage_value->IsInitialized()) return false;
+ } else {
+ if (!extension.message_value->IsInitialized()) return false;
+ }
}
}
}
@@ -715,27 +854,42 @@
return true;
}
-bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
- ExtensionFinder* extension_finder,
- FieldSkipper* field_skipper) {
- int number = WireFormatLite::GetTagFieldNumber(tag);
+bool ExtensionSet::FindExtensionInfoFromTag(
+ uint32 tag, ExtensionFinder* extension_finder,
+ int* field_number, ExtensionInfo* extension) {
+ *field_number = WireFormatLite::GetTagFieldNumber(tag);
WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
- ExtensionInfo extension;
bool is_unknown;
- if (!extension_finder->Find(number, &extension)) {
+ if (!extension_finder->Find(*field_number, extension)) {
is_unknown = true;
- } else if (extension.is_packed) {
+ } else if (extension->is_packed) {
is_unknown = (wire_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
} else {
WireFormatLite::WireType expected_wire_type =
- WireFormatLite::WireTypeForFieldType(real_type(extension.type));
+ WireFormatLite::WireTypeForFieldType(real_type(extension->type));
is_unknown = (wire_type != expected_wire_type);
}
+ return !is_unknown;
+}
- if (is_unknown) {
- field_skipper->SkipField(input, tag);
- } else if (extension.is_packed) {
+bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
+ ExtensionFinder* extension_finder,
+ FieldSkipper* field_skipper) {
+ int number;
+ ExtensionInfo extension;
+ if (!FindExtensionInfoFromTag(tag, extension_finder, &number, &extension)) {
+ return field_skipper->SkipField(input, tag);
+ } else {
+ return ParseFieldWithExtensionInfo(number, extension, input, field_skipper);
+ }
+}
+
+bool ExtensionSet::ParseFieldWithExtensionInfo(
+ int number, const ExtensionInfo& extension,
+ io::CodedInputStream* input,
+ FieldSkipper* field_skipper) {
+ if (extension.is_packed) {
uint32 size;
if (!input->ReadVarint32(&size)) return false;
io::CodedInputStream::Limit limit = input->PushLimit(size);
@@ -852,8 +1006,8 @@
case WireFormatLite::TYPE_BYTES: {
string* value = extension.is_repeated ?
- AddString(number, WireFormatLite::TYPE_STRING, extension.descriptor) :
- MutableString(number, WireFormatLite::TYPE_STRING,
+ AddString(number, WireFormatLite::TYPE_BYTES, extension.descriptor) :
+ MutableString(number, WireFormatLite::TYPE_BYTES,
extension.descriptor);
if (!WireFormatLite::ReadBytes(input, value)) return false;
break;
@@ -897,121 +1051,11 @@
// const Message* containing_type,
// UnknownFieldSet* unknown_fields)
-bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
- ExtensionFinder* extension_finder,
- FieldSkipper* field_skipper) {
- while (true) {
- uint32 tag = input->ReadTag();
- switch (tag) {
- case 0:
- return true;
- case WireFormatLite::kMessageSetItemStartTag:
- if (!ParseMessageSetItem(input, extension_finder, field_skipper)) {
- return false;
- }
- break;
- default:
- if (!ParseField(tag, input, extension_finder, field_skipper)) {
- return false;
- }
- break;
- }
- }
-}
-
-bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
- const MessageLite* containing_type,
- UnknownFieldSet* unknown_fields) {
- FieldSkipper skipper(unknown_fields);
- GeneratedExtensionFinder finder(containing_type);
- return ParseMessageSet(input, &finder, &skipper);
-}
-
// Defined in extension_set_heavy.cc.
// bool ExtensionSet::ParseMessageSetHeavy(io::CodedInputStream* input,
// const Message* containing_type,
// UnknownFieldSet* unknown_fields);
-bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
- ExtensionFinder* extension_finder,
- FieldSkipper* field_skipper) {
- // TODO(kenton): It would be nice to share code between this and
- // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the
- // differences would be hard to factor out.
-
- // This method parses a group which should contain two fields:
- // required int32 type_id = 2;
- // required data message = 3;
-
- // Once we see a type_id, we'll construct a fake tag for this extension
- // which is the tag it would have had under the proto2 extensions wire
- // format.
- uint32 fake_tag = 0;
-
- // If we see message data before the type_id, we'll append it to this so
- // we can parse it later. This will probably never happen in practice,
- // as no MessageSet encoder I know of writes the message before the type ID.
- // But, it's technically valid so we should allow it.
- // TODO(kenton): Use a Cord instead? Do I care?
- string message_data;
-
- while (true) {
- uint32 tag = input->ReadTag();
- if (tag == 0) return false;
-
- switch (tag) {
- case WireFormatLite::kMessageSetTypeIdTag: {
- uint32 type_id;
- if (!input->ReadVarint32(&type_id)) return false;
- fake_tag = WireFormatLite::MakeTag(type_id,
- WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
-
- if (!message_data.empty()) {
- // We saw some message data before the type_id. Have to parse it
- // now.
- io::CodedInputStream sub_input(
- reinterpret_cast<const uint8*>(message_data.data()),
- message_data.size());
- if (!ParseField(fake_tag, &sub_input,
- extension_finder, field_skipper)) {
- return false;
- }
- message_data.clear();
- }
-
- break;
- }
-
- case WireFormatLite::kMessageSetMessageTag: {
- if (fake_tag == 0) {
- // We haven't seen a type_id yet. Append this data to message_data.
- string temp;
- uint32 length;
- if (!input->ReadVarint32(&length)) return false;
- if (!input->ReadString(&temp, length)) return false;
- message_data.append(temp);
- } else {
- // Already saw type_id, so we can parse this directly.
- if (!ParseField(fake_tag, input,
- extension_finder, field_skipper)) {
- return false;
- }
- }
-
- break;
- }
-
- case WireFormatLite::kMessageSetItemEndTag: {
- return true;
- }
-
- default: {
- if (!field_skipper->SkipField(input, tag)) return false;
- }
- }
- }
-}
-
void ExtensionSet::SerializeWithCachedSizes(
int start_field_number, int end_field_number,
io::CodedOutputStream* output) const {
@@ -1023,14 +1067,6 @@
}
}
-void ExtensionSet::SerializeMessageSetWithCachedSizes(
- io::CodedOutputStream* output) const {
- map<int, Extension>::const_iterator iter;
- for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
- iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output);
- }
-}
-
int ExtensionSet::ByteSize() const {
int total_size = 0;
@@ -1042,17 +1078,6 @@
return total_size;
}
-int ExtensionSet::MessageSetByteSize() const {
- int total_size = 0;
-
- for (map<int, Extension>::const_iterator iter = extensions_.begin();
- iter != extensions_.end(); ++iter) {
- total_size += iter->second.MessageSetItemByteSize(iter->first);
- }
-
- return total_size;
-}
-
// Defined in extension_set_heavy.cc.
// int ExtensionSet::SpaceUsedExcludingSelf() const
@@ -1096,7 +1121,11 @@
string_value->clear();
break;
case WireFormatLite::CPPTYPE_MESSAGE:
- message_value->Clear();
+ if (is_lazy) {
+ lazymessage_value->Clear();
+ } else {
+ message_value->Clear();
+ }
break;
default:
// No need to do anything. Get*() will return the default value
@@ -1208,40 +1237,18 @@
HANDLE_TYPE( BYTES, Bytes, *string_value);
HANDLE_TYPE( ENUM, Enum, enum_value);
HANDLE_TYPE( GROUP, Group, *message_value);
- HANDLE_TYPE( MESSAGE, Message, *message_value);
#undef HANDLE_TYPE
+ case WireFormatLite::TYPE_MESSAGE:
+ if (is_lazy) {
+ lazymessage_value->WriteMessage(number, output);
+ } else {
+ WireFormatLite::WriteMessage(number, *message_value, output);
+ }
+ break;
}
}
}
-void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes(
- int number,
- io::CodedOutputStream* output) const {
- if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
- // Not a valid MessageSet extension, but serialize it the normal way.
- SerializeFieldWithCachedSizes(number, output);
- return;
- }
-
- if (is_cleared) return;
-
- // Start group.
- output->WriteTag(WireFormatLite::kMessageSetItemStartTag);
-
- // Write type ID.
- WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber,
- number,
- output);
- // Write message.
- WireFormatLite::WriteMessageMaybeToArray(
- WireFormatLite::kMessageSetMessageNumber,
- *message_value,
- output);
-
- // End group.
- output->WriteTag(WireFormatLite::kMessageSetItemEndTag);
-}
-
int ExtensionSet::Extension::ByteSize(int number) const {
int result = 0;
@@ -1355,8 +1362,16 @@
HANDLE_TYPE( BYTES, Bytes, *string_value);
HANDLE_TYPE( ENUM, Enum, enum_value);
HANDLE_TYPE( GROUP, Group, *message_value);
- HANDLE_TYPE( MESSAGE, Message, *message_value);
#undef HANDLE_TYPE
+ case WireFormatLite::TYPE_MESSAGE: {
+ if (is_lazy) {
+ int size = lazymessage_value->ByteSize();
+ result += io::CodedOutputStream::VarintSize32(size) + size;
+ } else {
+ result += WireFormatLite::MessageSize(*message_value);
+ }
+ break;
+ }
// Stuff with fixed size.
#define HANDLE_TYPE(UPPERCASE, CAMELCASE) \
@@ -1377,29 +1392,6 @@
return result;
}
-int ExtensionSet::Extension::MessageSetItemByteSize(int number) const {
- if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
- // Not a valid MessageSet extension, but compute the byte size for it the
- // normal way.
- return ByteSize(number);
- }
-
- if (is_cleared) return 0;
-
- int our_size = WireFormatLite::kMessageSetItemTagsSize;
-
- // type_id
- our_size += io::CodedOutputStream::VarintSize32(number);
-
- // message
- int message_size = message_value->ByteSize();
-
- our_size += io::CodedOutputStream::VarintSize32(message_size);
- our_size += message_size;
-
- return our_size;
-}
-
int ExtensionSet::Extension::GetSize() const {
GOOGLE_DCHECK(is_repeated);
switch (cpp_type(type)) {
@@ -1450,7 +1442,11 @@
delete string_value;
break;
case WireFormatLite::CPPTYPE_MESSAGE:
- delete message_value;
+ if (is_lazy) {
+ delete lazymessage_value;
+ } else {
+ delete message_value;
+ }
break;
default:
break;
diff --git a/third_party/protobuf/src/google/protobuf/extension_set.h b/third_party/protobuf/src/google/protobuf/extension_set.h
index a1b6f35..f3935fb 100644
--- a/third_party/protobuf/src/google/protobuf/extension_set.h
+++ b/third_party/protobuf/src/google/protobuf/extension_set.h
@@ -89,8 +89,8 @@
// Information about a registered extension.
struct ExtensionInfo {
inline ExtensionInfo() {}
- inline ExtensionInfo(FieldType type, bool is_repeated, bool is_packed)
- : type(type), is_repeated(is_repeated), is_packed(is_packed),
+ inline ExtensionInfo(FieldType type_param, bool isrepeated, bool ispacked)
+ : type(type_param), is_repeated(isrepeated), is_packed(ispacked),
descriptor(NULL) {}
FieldType type;
@@ -214,6 +214,7 @@
bool Has(int number) const;
int ExtensionSize(int number) const; // Size of a repeated extension.
+ int NumExtensions() const; // The number of extensions
FieldType ExtensionType(int number) const;
void ClearExtension(int number);
@@ -251,10 +252,21 @@
const MessageLite& prototype, desc);
MessageLite* MutableMessage(const FieldDescriptor* decsriptor,
MessageFactory* factory);
+ // Adds the given message to the ExtensionSet, taking ownership of the
+ // message object. Existing message with the same number will be deleted.
+ // If "message" is NULL, this is equivalent to "ClearExtension(number)".
+ void SetAllocatedMessage(int number, FieldType type,
+ const FieldDescriptor* descriptor,
+ MessageLite* message);
+ MessageLite* ReleaseMessage(int number, const MessageLite& prototype);
+ MessageLite* ReleaseMessage(const FieldDescriptor* descriptor,
+ MessageFactory* factory);
#undef desc
// repeated fields -------------------------------------------------
+ void* MutableRawRepeatedField(int number);
+
int32 GetRepeatedInt32 (int number, int index) const;
int64 GetRepeatedInt64 (int number, int index) const;
uint32 GetRepeatedUInt32(int number, int index) const;
@@ -296,6 +308,7 @@
#undef desc
void RemoveLast(int number);
+ MessageLite* ReleaseLast(int number);
void SwapElements(int number, int index1, int index2);
// -----------------------------------------------------------------
@@ -312,18 +325,18 @@
void Swap(ExtensionSet* other);
bool IsInitialized() const;
- // Parses a single extension from the input. The input should start out
- // positioned immediately after the tag. |containing_type| is the default
- // instance for the containing message; it is used only to look up the
- // extension by number. See RegisterExtension(), above. Unlike the other
- // methods of ExtensionSet, this only works for generated message types --
- // it looks up extensions registered using RegisterExtension().
+ // Parses a single extension from the input. The input should start out
+ // positioned immediately after the tag.
bool ParseField(uint32 tag, io::CodedInputStream* input,
ExtensionFinder* extension_finder,
FieldSkipper* field_skipper);
// Specific versions for lite or full messages (constructs the appropriate
- // FieldSkipper automatically).
+ // FieldSkipper automatically). |containing_type| is the default
+ // instance for the containing message; it is used only to look up the
+ // extension by number. See RegisterExtension(), above. Unlike the other
+ // methods of ExtensionSet, this only works for generated message types --
+ // it looks up extensions registered using RegisterExtension().
bool ParseField(uint32 tag, io::CodedInputStream* input,
const MessageLite* containing_type,
UnknownFieldSet* unknown_fields);
@@ -384,18 +397,49 @@
private:
+ // Interface of a lazily parsed singular message extension.
+ class LIBPROTOBUF_EXPORT LazyMessageExtension {
+ public:
+ LazyMessageExtension() {}
+ virtual ~LazyMessageExtension() {}
+
+ virtual LazyMessageExtension* New() const = 0;
+ virtual const MessageLite& GetMessage(
+ const MessageLite& prototype) const = 0;
+ virtual MessageLite* MutableMessage(const MessageLite& prototype) = 0;
+ virtual void SetAllocatedMessage(MessageLite *message) = 0;
+ virtual MessageLite* ReleaseMessage(const MessageLite& prototype) = 0;
+
+ virtual bool IsInitialized() const = 0;
+ virtual int ByteSize() const = 0;
+ virtual int SpaceUsed() const = 0;
+
+ virtual void MergeFrom(const LazyMessageExtension& other) = 0;
+ virtual void Clear() = 0;
+
+ virtual bool ReadMessage(const MessageLite& prototype,
+ io::CodedInputStream* input) = 0;
+ virtual void WriteMessage(int number,
+ io::CodedOutputStream* output) const = 0;
+ virtual uint8* WriteMessageToArray(int number, uint8* target) const = 0;
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LazyMessageExtension);
+ };
struct Extension {
+ // The order of these fields packs Extension into 24 bytes when using 8
+ // byte alignment. Consider this when adding or removing fields here.
union {
- int32 int32_value;
- int64 int64_value;
- uint32 uint32_value;
- uint64 uint64_value;
- float float_value;
- double double_value;
- bool bool_value;
- int enum_value;
- string* string_value;
- MessageLite* message_value;
+ int32 int32_value;
+ int64 int64_value;
+ uint32 uint32_value;
+ uint64 uint64_value;
+ float float_value;
+ double double_value;
+ bool bool_value;
+ int enum_value;
+ string* string_value;
+ MessageLite* message_value;
+ LazyMessageExtension* lazymessage_value;
RepeatedField <int32 >* repeated_int32_value;
RepeatedField <int64 >* repeated_int64_value;
@@ -418,21 +462,28 @@
// removing it from the map, we just set is_cleared = true. This has no
// meaning for repeated types; for those, the size of the RepeatedField
// simply becomes zero when cleared.
- bool is_cleared;
+ bool is_cleared : 4;
+
+ // For singular message types, indicates whether lazy parsing is enabled
+ // for this extension. This field is only valid when type == TYPE_MESSAGE
+ // and !is_repeated because we only support lazy parsing for singular
+ // message types currently. If is_lazy = true, the extension is stored in
+ // lazymessage_value. Otherwise, the extension will be message_value.
+ bool is_lazy : 4;
// For repeated types, this indicates if the [packed=true] option is set.
bool is_packed;
- // The descriptor for this extension, if one exists and is known. May be
- // NULL. Must not be NULL if the descriptor for the extension does not
- // live in the same pool as the descriptor for the containing type.
- const FieldDescriptor* descriptor;
-
// For packed fields, the size of the packed data is recorded here when
// ByteSize() is called then used during serialization.
// TODO(kenton): Use atomic<int> when C++ supports it.
mutable int cached_size;
+ // The descriptor for this extension, if one exists and is known. May be
+ // NULL. Must not be NULL if the descriptor for the extension does not
+ // live in the same pool as the descriptor for the containing type.
+ const FieldDescriptor* descriptor;
+
// Some helper methods for operations on a single Extension.
void SerializeFieldWithCachedSizes(
int number,
@@ -455,6 +506,25 @@
};
+ // Returns true and fills field_number and extension if extension is found.
+ bool FindExtensionInfoFromTag(uint32 tag, ExtensionFinder* extension_finder,
+ int* field_number, ExtensionInfo* extension);
+
+ // Parses a single extension from the input. The input should start out
+ // positioned immediately after the wire tag. This method is called in
+ // ParseField() after field number is extracted from the wire tag and
+ // ExtensionInfo is found by the field number.
+ bool ParseFieldWithExtensionInfo(int field_number,
+ const ExtensionInfo& extension,
+ io::CodedInputStream* input,
+ FieldSkipper* field_skipper);
+
+ // Like ParseField(), but this method may parse singular message extensions
+ // lazily depending on the value of FLAGS_eagerly_parse_message_sets.
+ bool ParseFieldMaybeLazily(uint32 tag, io::CodedInputStream* input,
+ ExtensionFinder* extension_finder,
+ FieldSkipper* field_skipper);
+
// Gets the extension with the given number, creating it if it does not
// already exist. Returns true if the extension did not already exist.
bool MaybeNewExtension(int number, const FieldDescriptor* descriptor,
@@ -722,6 +792,15 @@
return static_cast<Type*>(
set->MutableMessage(number, field_type, Type::default_instance(), NULL));
}
+ static inline void SetAllocated(int number, FieldType field_type,
+ MutableType message, ExtensionSet* set) {
+ set->SetAllocatedMessage(number, field_type, NULL, message);
+ }
+ static inline MutableType Release(int number, FieldType field_type,
+ ExtensionSet* set) {
+ return static_cast<Type*>(set->ReleaseMessage(
+ number, Type::default_instance()));
+ }
};
template <typename Type>
@@ -789,113 +868,137 @@
// causes problems if the class has a nested message or enum type with that
// name and "_TypeTraits" is technically reserved for the C++ library since
// it starts with an underscore followed by a capital letter.
+//
+// For similar reason, we use "_field_type" and "_is_packed" as parameter names
+// below, so that "field_type" and "is_packed" can be used as field names.
#define GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(CLASSNAME) \
/* Has, Size, Clear */ \
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline bool HasExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \
return _extensions_.Has(id.number()); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline void ClearExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \
_extensions_.ClearExtension(id.number()); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline int ExtensionSize( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \
return _extensions_.ExtensionSize(id.number()); \
} \
\
/* Singular accessors */ \
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline typename _proto_TypeTraits::ConstType GetExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \
return _proto_TypeTraits::Get(id.number(), _extensions_, \
id.default_value()); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline typename _proto_TypeTraits::MutableType MutableExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \
- return _proto_TypeTraits::Mutable(id.number(), field_type, &_extensions_);\
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \
+ return _proto_TypeTraits::Mutable(id.number(), _field_type, \
+ &_extensions_); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline void SetExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
typename _proto_TypeTraits::ConstType value) { \
- _proto_TypeTraits::Set(id.number(), field_type, value, &_extensions_); \
+ _proto_TypeTraits::Set(id.number(), _field_type, value, &_extensions_); \
+ } \
+ \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
+ inline void SetAllocatedExtension( \
+ const ::google::protobuf::internal::ExtensionIdentifier< \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
+ typename _proto_TypeTraits::MutableType value) { \
+ _proto_TypeTraits::SetAllocated(id.number(), _field_type, \
+ value, &_extensions_); \
+ } \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
+ inline typename _proto_TypeTraits::MutableType ReleaseExtension( \
+ const ::google::protobuf::internal::ExtensionIdentifier< \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \
+ return _proto_TypeTraits::Release(id.number(), _field_type, \
+ &_extensions_); \
} \
\
/* Repeated accessors */ \
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline typename _proto_TypeTraits::ConstType GetExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
int index) const { \
return _proto_TypeTraits::Get(id.number(), _extensions_, index); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline typename _proto_TypeTraits::MutableType MutableExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
int index) { \
return _proto_TypeTraits::Mutable(id.number(), index, &_extensions_); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline void SetExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
int index, typename _proto_TypeTraits::ConstType value) { \
_proto_TypeTraits::Set(id.number(), index, value, &_extensions_); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline typename _proto_TypeTraits::MutableType AddExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \
- return _proto_TypeTraits::Add(id.number(), field_type, &_extensions_); \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \
+ return _proto_TypeTraits::Add(id.number(), _field_type, &_extensions_); \
} \
\
template <typename _proto_TypeTraits, \
- ::google::protobuf::internal::FieldType field_type, \
- bool is_packed> \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
inline void AddExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
- CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
+ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
typename _proto_TypeTraits::ConstType value) { \
- _proto_TypeTraits::Add(id.number(), field_type, is_packed, \
+ _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, \
value, &_extensions_); \
}
diff --git a/third_party/protobuf/src/google/protobuf/extension_set_heavy.cc b/third_party/protobuf/src/google/protobuf/extension_set_heavy.cc
index e00fd4d..01b9490 100644
--- a/third_party/protobuf/src/google/protobuf/extension_set_heavy.cc
+++ b/third_party/protobuf/src/google/protobuf/extension_set_heavy.cc
@@ -35,17 +35,20 @@
// Contains methods defined in extension_set.h which cannot be part of the
// lite library because they use descriptors or reflection.
-#include <google/protobuf/extension_set.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/extension_set.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/wire_format_lite_inl.h>
namespace google {
+
namespace protobuf {
namespace internal {
+
// Implementation of ExtensionFinder which finds extensions in a given
// DescriptorPool, using the given MessageFactory to construct sub-objects.
// This class is implemented in extension_set_heavy.cc.
@@ -103,6 +106,11 @@
static_cast<FieldDescriptor::Type>(type));
}
+inline WireFormatLite::FieldType field_type(FieldType type) {
+ GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE);
+ return static_cast<WireFormatLite::FieldType>(type);
+}
+
#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \
GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \
: FieldDescriptor::LABEL_OPTIONAL, \
@@ -118,7 +126,12 @@
return *factory->GetPrototype(message_type);
} else {
GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
- return *iter->second.message_value;
+ if (iter->second.is_lazy) {
+ return iter->second.lazymessage_value->GetMessage(
+ *factory->GetPrototype(message_type));
+ } else {
+ return *iter->second.message_value;
+ }
}
}
@@ -132,13 +145,41 @@
extension->is_packed = false;
const MessageLite* prototype =
factory->GetPrototype(descriptor->message_type());
- GOOGLE_CHECK(prototype != NULL);
+ extension->is_lazy = false;
extension->message_value = prototype->New();
+ extension->is_cleared = false;
+ return extension->message_value;
} else {
GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
+ extension->is_cleared = false;
+ if (extension->is_lazy) {
+ return extension->lazymessage_value->MutableMessage(
+ *factory->GetPrototype(descriptor->message_type()));
+ } else {
+ return extension->message_value;
+ }
}
- extension->is_cleared = false;
- return extension->message_value;
+}
+
+MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
+ MessageFactory* factory) {
+ map<int, Extension>::iterator iter = extensions_.find(descriptor->number());
+ if (iter == extensions_.end()) {
+ // Not present. Return NULL.
+ return NULL;
+ } else {
+ GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
+ MessageLite* ret = NULL;
+ if (iter->second.is_lazy) {
+ ret = iter->second.lazymessage_value->ReleaseMessage(
+ *factory->GetPrototype(descriptor->message_type()));
+ delete iter->second.lazymessage_value;
+ } else {
+ ret = iter->second.message_value;
+ }
+ extensions_.erase(descriptor->number());
+ return ret;
+ }
}
MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
@@ -157,7 +198,7 @@
// RepeatedPtrField<Message> does not know how to Add() since it cannot
// allocate an abstract object, so we have to be tricky.
MessageLite* result = extension->repeated_message_value
- ->AddFromCleared<internal::GenericTypeHandler<MessageLite> >();
+ ->AddFromCleared<GenericTypeHandler<MessageLite> >();
if (result == NULL) {
const MessageLite* prototype;
if (extension->repeated_message_value->size() == 0) {
@@ -286,7 +327,11 @@
StringSpaceUsedExcludingSelf(*string_value);
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
- total_size += down_cast<Message*>(message_value)->SpaceUsed();
+ if (is_lazy) {
+ total_size += lazymessage_value->SpaceUsed();
+ } else {
+ total_size += down_cast<Message*>(message_value)->SpaceUsed();
+ }
break;
default:
// No extra storage costs for primitive types.
@@ -419,8 +464,15 @@
HANDLE_TYPE( BYTES, Bytes, *string_value);
HANDLE_TYPE( ENUM, Enum, enum_value);
HANDLE_TYPE( GROUP, Group, *message_value);
- HANDLE_TYPE( MESSAGE, Message, *message_value);
#undef HANDLE_TYPE
+ case FieldDescriptor::TYPE_MESSAGE:
+ if (is_lazy) {
+ target = lazymessage_value->WriteMessageToArray(number, target);
+ } else {
+ target = WireFormatLite::WriteMessageToArray(
+ number, *message_value, target);
+ }
+ break;
}
}
return target;
@@ -444,14 +496,217 @@
target = WireFormatLite::WriteUInt32ToArray(
WireFormatLite::kMessageSetTypeIdNumber, number, target);
// Write message.
- target = WireFormatLite::WriteMessageToArray(
- WireFormatLite::kMessageSetMessageNumber, *message_value, target);
+ if (is_lazy) {
+ target = lazymessage_value->WriteMessageToArray(
+ WireFormatLite::kMessageSetMessageNumber, target);
+ } else {
+ target = WireFormatLite::WriteMessageToArray(
+ WireFormatLite::kMessageSetMessageNumber, *message_value, target);
+ }
// End group.
target = io::CodedOutputStream::WriteTagToArray(
WireFormatLite::kMessageSetItemEndTag, target);
return target;
}
+
+bool ExtensionSet::ParseFieldMaybeLazily(
+ uint32 tag, io::CodedInputStream* input,
+ ExtensionFinder* extension_finder,
+ FieldSkipper* field_skipper) {
+ return ParseField(tag, input, extension_finder, field_skipper);
+}
+
+bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
+ ExtensionFinder* extension_finder,
+ FieldSkipper* field_skipper) {
+ while (true) {
+ uint32 tag = input->ReadTag();
+ switch (tag) {
+ case 0:
+ return true;
+ case WireFormatLite::kMessageSetItemStartTag:
+ if (!ParseMessageSetItem(input, extension_finder, field_skipper)) {
+ return false;
+ }
+ break;
+ default:
+ if (!ParseField(tag, input, extension_finder, field_skipper)) {
+ return false;
+ }
+ break;
+ }
+ }
+}
+
+bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
+ const MessageLite* containing_type,
+ UnknownFieldSet* unknown_fields) {
+ FieldSkipper skipper(unknown_fields);
+ GeneratedExtensionFinder finder(containing_type);
+ return ParseMessageSet(input, &finder, &skipper);
+}
+
+bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
+ ExtensionFinder* extension_finder,
+ FieldSkipper* field_skipper) {
+ // TODO(kenton): It would be nice to share code between this and
+ // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the
+ // differences would be hard to factor out.
+
+ // This method parses a group which should contain two fields:
+ // required int32 type_id = 2;
+ // required data message = 3;
+
+ // Once we see a type_id, we'll construct a fake tag for this extension
+ // which is the tag it would have had under the proto2 extensions wire
+ // format.
+ uint32 fake_tag = 0;
+
+ // If we see message data before the type_id, we'll append it to this so
+ // we can parse it later.
+ string message_data;
+
+ while (true) {
+ uint32 tag = input->ReadTag();
+ if (tag == 0) return false;
+
+ switch (tag) {
+ case WireFormatLite::kMessageSetTypeIdTag: {
+ uint32 type_id;
+ if (!input->ReadVarint32(&type_id)) return false;
+ fake_tag = WireFormatLite::MakeTag(type_id,
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+
+ if (!message_data.empty()) {
+ // We saw some message data before the type_id. Have to parse it
+ // now.
+ io::CodedInputStream sub_input(
+ reinterpret_cast<const uint8*>(message_data.data()),
+ message_data.size());
+ if (!ParseFieldMaybeLazily(fake_tag, &sub_input,
+ extension_finder, field_skipper)) {
+ return false;
+ }
+ message_data.clear();
+ }
+
+ break;
+ }
+
+ case WireFormatLite::kMessageSetMessageTag: {
+ if (fake_tag == 0) {
+ // We haven't seen a type_id yet. Append this data to message_data.
+ string temp;
+ uint32 length;
+ if (!input->ReadVarint32(&length)) return false;
+ if (!input->ReadString(&temp, length)) return false;
+ io::StringOutputStream output_stream(&message_data);
+ io::CodedOutputStream coded_output(&output_stream);
+ coded_output.WriteVarint32(length);
+ coded_output.WriteString(temp);
+ } else {
+ // Already saw type_id, so we can parse this directly.
+ if (!ParseFieldMaybeLazily(fake_tag, input,
+ extension_finder, field_skipper)) {
+ return false;
+ }
+ }
+
+ break;
+ }
+
+ case WireFormatLite::kMessageSetItemEndTag: {
+ return true;
+ }
+
+ default: {
+ if (!field_skipper->SkipField(input, tag)) return false;
+ }
+ }
+ }
+}
+
+void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes(
+ int number,
+ io::CodedOutputStream* output) const {
+ if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
+ // Not a valid MessageSet extension, but serialize it the normal way.
+ SerializeFieldWithCachedSizes(number, output);
+ return;
+ }
+
+ if (is_cleared) return;
+
+ // Start group.
+ output->WriteTag(WireFormatLite::kMessageSetItemStartTag);
+
+ // Write type ID.
+ WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber,
+ number,
+ output);
+ // Write message.
+ if (is_lazy) {
+ lazymessage_value->WriteMessage(
+ WireFormatLite::kMessageSetMessageNumber, output);
+ } else {
+ WireFormatLite::WriteMessageMaybeToArray(
+ WireFormatLite::kMessageSetMessageNumber,
+ *message_value,
+ output);
+ }
+
+ // End group.
+ output->WriteTag(WireFormatLite::kMessageSetItemEndTag);
+}
+
+int ExtensionSet::Extension::MessageSetItemByteSize(int number) const {
+ if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
+ // Not a valid MessageSet extension, but compute the byte size for it the
+ // normal way.
+ return ByteSize(number);
+ }
+
+ if (is_cleared) return 0;
+
+ int our_size = WireFormatLite::kMessageSetItemTagsSize;
+
+ // type_id
+ our_size += io::CodedOutputStream::VarintSize32(number);
+
+ // message
+ int message_size = 0;
+ if (is_lazy) {
+ message_size = lazymessage_value->ByteSize();
+ } else {
+ message_size = message_value->ByteSize();
+ }
+
+ our_size += io::CodedOutputStream::VarintSize32(message_size);
+ our_size += message_size;
+
+ return our_size;
+}
+
+void ExtensionSet::SerializeMessageSetWithCachedSizes(
+ io::CodedOutputStream* output) const {
+ map<int, Extension>::const_iterator iter;
+ for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
+ iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output);
+ }
+}
+
+int ExtensionSet::MessageSetByteSize() const {
+ int total_size = 0;
+
+ for (map<int, Extension>::const_iterator iter = extensions_.begin();
+ iter != extensions_.end(); ++iter) {
+ total_size += iter->second.MessageSetItemByteSize(iter->first);
+ }
+
+ return total_size;
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/extension_set_unittest.cc b/third_party/protobuf/src/google/protobuf/extension_set_unittest.cc
index 000f846..1e7c5a5 100644
--- a/third_party/protobuf/src/google/protobuf/extension_set_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/extension_set_unittest.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/extension_set.h>
#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_mset.pb.h>
#include <google/protobuf/test_util.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
@@ -46,9 +47,10 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
+
namespace protobuf {
namespace internal {
namespace {
@@ -140,23 +142,98 @@
TestUtil::ExpectAllExtensionsSet(message);
}
+TEST(ExtensionSetTest, SetAllocatedExtensin) {
+ unittest::TestAllExtensions message;
+ EXPECT_FALSE(message.HasExtension(
+ unittest::optional_foreign_message_extension));
+ // Add a extension using SetAllocatedExtension
+ unittest::ForeignMessage* foreign_message = new unittest::ForeignMessage();
+ message.SetAllocatedExtension(unittest::optional_foreign_message_extension,
+ foreign_message);
+ EXPECT_TRUE(message.HasExtension(
+ unittest::optional_foreign_message_extension));
+ EXPECT_EQ(foreign_message,
+ message.MutableExtension(
+ unittest::optional_foreign_message_extension));
+ EXPECT_EQ(foreign_message,
+ &message.GetExtension(
+ unittest::optional_foreign_message_extension));
+
+ // SetAllocatedExtension should delete the previously existing extension.
+ // (We reply on unittest to check memory leaks for this case)
+ message.SetAllocatedExtension(unittest::optional_foreign_message_extension,
+ new unittest::ForeignMessage());
+
+ // SetAllocatedExtension with a NULL parameter is equivalent to ClearExtenion.
+ message.SetAllocatedExtension(unittest::optional_foreign_message_extension,
+ NULL);
+ EXPECT_FALSE(message.HasExtension(
+ unittest::optional_foreign_message_extension));
+}
+
+TEST(ExtensionSetTest, ReleaseExtension) {
+ unittest::TestMessageSet message;
+ EXPECT_FALSE(message.HasExtension(
+ unittest::TestMessageSetExtension1::message_set_extension));
+ // Add a extension using SetAllocatedExtension
+ unittest::TestMessageSetExtension1* extension =
+ new unittest::TestMessageSetExtension1();
+ message.SetAllocatedExtension(
+ unittest::TestMessageSetExtension1::message_set_extension,
+ extension);
+ EXPECT_TRUE(message.HasExtension(
+ unittest::TestMessageSetExtension1::message_set_extension));
+ // Release the extension using ReleaseExtension
+ unittest::TestMessageSetExtension1* released_extension =
+ message.ReleaseExtension(
+ unittest::TestMessageSetExtension1::message_set_extension);
+ EXPECT_EQ(extension, released_extension);
+ EXPECT_FALSE(message.HasExtension(
+ unittest::TestMessageSetExtension1::message_set_extension));
+ // ReleaseExtension will return the underlying object even after
+ // ClearExtension is called.
+ message.SetAllocatedExtension(
+ unittest::TestMessageSetExtension1::message_set_extension,
+ extension);
+ message.ClearExtension(
+ unittest::TestMessageSetExtension1::message_set_extension);
+ released_extension = message.ReleaseExtension(
+ unittest::TestMessageSetExtension1::message_set_extension);
+ EXPECT_TRUE(released_extension != NULL);
+ delete released_extension;
+}
+
+
TEST(ExtensionSetTest, CopyFrom) {
unittest::TestAllExtensions message1, message2;
- string data;
TestUtil::SetAllExtensions(&message1);
message2.CopyFrom(message1);
TestUtil::ExpectAllExtensionsSet(message2);
+ message2.CopyFrom(message1); // exercise copy when fields already exist
+ TestUtil::ExpectAllExtensionsSet(message2);
+}
+
+TEST(ExtensioSetTest, CopyFromPacked) {
+ unittest::TestPackedExtensions message1, message2;
+
+ TestUtil::SetPackedExtensions(&message1);
+ message2.CopyFrom(message1);
+ TestUtil::ExpectPackedExtensionsSet(message2);
+ message2.CopyFrom(message1); // exercise copy when fields already exist
+ TestUtil::ExpectPackedExtensionsSet(message2);
}
TEST(ExtensionSetTest, CopyFromUpcasted) {
unittest::TestAllExtensions message1, message2;
- string data;
const Message& upcasted_message = message1;
TestUtil::SetAllExtensions(&message1);
message2.CopyFrom(upcasted_message);
TestUtil::ExpectAllExtensionsSet(message2);
+ // exercise copy when fields already exist
+ message2.CopyFrom(upcasted_message);
+ TestUtil::ExpectAllExtensionsSet(message2);
}
TEST(ExtensionSetTest, SwapWithEmpty) {
@@ -418,7 +495,8 @@
for (int i = 0; i < 16; ++i) { \
message.AddExtension(unittest::repeated_##type##_extension, value); \
} \
- int expected_size = sizeof(cpptype) * 16 + empty_repeated_field_size; \
+ int expected_size = sizeof(cpptype) * (16 - \
+ kMinRepeatedFieldAllocationSize) + empty_repeated_field_size; \
EXPECT_EQ(expected_size, message.SpaceUsed()) << #type; \
} while (0)
@@ -450,7 +528,8 @@
for (int i = 0; i < 16; ++i) {
message.AddExtension(unittest::repeated_string_extension, value);
}
- min_expected_size += (sizeof(value) + value.size()) * 16;
+ min_expected_size += (sizeof(value) + value.size()) *
+ (16 - kMinRepeatedFieldAllocationSize);
EXPECT_LE(min_expected_size, message.SpaceUsed());
}
// Repeated messages
@@ -465,7 +544,8 @@
message.AddExtension(unittest::repeated_foreign_message_extension)->
CopyFrom(prototype);
}
- min_expected_size += 16 * prototype.SpaceUsed();
+ min_expected_size +=
+ (16 - kMinRepeatedFieldAllocationSize) * prototype.SpaceUsed();
EXPECT_LE(min_expected_size, message.SpaceUsed());
}
}
diff --git a/third_party/protobuf/src/google/protobuf/generated_enum_reflection.h b/third_party/protobuf/src/google/protobuf/generated_enum_reflection.h
new file mode 100644
index 0000000..a09a540
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/generated_enum_reflection.h
@@ -0,0 +1,85 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: jasonh@google.com (Jason Hsueh)
+//
+// This header is logically internal, but is made public because it is used
+// from protocol-compiler-generated code, which may reside in other components.
+// It provides reflection support for generated enums, and is included in
+// generated .pb.h files and should have minimal dependencies. The methods are
+// implemented in generated_message_reflection.cc.
+
+#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
+#define GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
+
+#include <string>
+
+namespace google {
+namespace protobuf {
+ class EnumDescriptor;
+} // namespace protobuf
+
+namespace protobuf {
+
+// Returns the EnumDescriptor for enum type E, which must be a
+// proto-declared enum type. Code generated by the protocol compiler
+// will include specializations of this template for each enum type declared.
+template <typename E>
+const EnumDescriptor* GetEnumDescriptor();
+
+namespace internal {
+
+// Helper for EnumType_Parse functions: try to parse the string 'name' as an
+// enum name of the given type, returning true and filling in value on success,
+// or returning false and leaving value unchanged on failure.
+LIBPROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor,
+ const string& name,
+ int* value);
+
+template<typename EnumType>
+bool ParseNamedEnum(const EnumDescriptor* descriptor,
+ const string& name,
+ EnumType* value) {
+ int tmp;
+ if (!ParseNamedEnum(descriptor, name, &tmp)) return false;
+ *value = static_cast<EnumType>(tmp);
+ return true;
+}
+
+// Just a wrapper around printing the name of a value. The main point of this
+// function is not to be inlined, so that you can do this without including
+// descriptor.h.
+LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value);
+
+} // namespace internal
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
diff --git a/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc b/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc
index 226e951..09b0699 100644
--- a/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc
+++ b/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc
@@ -33,9 +33,9 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <algorithm>
+#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/generated_message_util.h>
@@ -309,7 +309,7 @@
"descriptor.";
GOOGLE_CHECK_EQ(message2->GetReflection(), this)
<< "Second argument to Swap() (of type \""
- << message1->GetDescriptor()->full_name()
+ << message2->GetDescriptor()->full_name()
<< "\") is not compatible with this reflection object (which is for type \""
<< descriptor_->full_name()
<< "\"). Note that the exact same class is required; not just the same "
@@ -368,8 +368,11 @@
SWAP_VALUES(DOUBLE, double);
SWAP_VALUES(BOOL , bool );
SWAP_VALUES(ENUM , int );
- SWAP_VALUES(MESSAGE, Message*);
#undef SWAP_VALUES
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ std::swap(*MutableRaw<Message*>(message1, field),
+ *MutableRaw<Message*>(message2, field));
+ break;
case FieldDescriptor::CPPTYPE_STRING:
switch (field->options().ctype()) {
@@ -576,6 +579,20 @@
}
}
+Message* GeneratedMessageReflection::ReleaseLast(
+ Message* message,
+ const FieldDescriptor* field) const {
+ USAGE_CHECK_ALL(ReleaseLast, REPEATED, MESSAGE);
+
+ if (field->is_extension()) {
+ return static_cast<Message*>(
+ MutableExtensionSet(message)->ReleaseLast(field->number()));
+ } else {
+ return MutableRaw<RepeatedPtrFieldBase>(message, field)
+ ->ReleaseLast<GenericTypeHandler<Message> >();
+ }
+}
+
void GeneratedMessageReflection::SwapElements(
Message* message,
const FieldDescriptor* field,
@@ -877,7 +894,9 @@
}
const EnumValueDescriptor* result =
field->enum_type()->FindValueByNumber(value);
- GOOGLE_CHECK(result != NULL);
+ GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field "
+ << field->full_name() << " of type "
+ << field->enum_type()->full_name() << ".";
return result;
}
@@ -907,7 +926,9 @@
}
const EnumValueDescriptor* result =
field->enum_type()->FindValueByNumber(value);
- GOOGLE_CHECK(result != NULL);
+ GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field "
+ << field->full_name() << " of type "
+ << field->enum_type()->full_name() << ".";
return result;
}
@@ -948,13 +969,15 @@
MessageFactory* factory) const {
USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
+ if (factory == NULL) factory = message_factory_;
+
if (field->is_extension()) {
return static_cast<const Message&>(
GetExtensionSet(message).GetMessage(
- field->number(), field->message_type(),
- factory == NULL ? message_factory_ : factory));
+ field->number(), field->message_type(), factory));
} else {
- const Message* result = GetRaw<const Message*>(message, field);
+ const Message* result;
+ result = GetRaw<const Message*>(message, field);
if (result == NULL) {
result = DefaultRaw<const Message*>(field);
}
@@ -967,17 +990,40 @@
MessageFactory* factory) const {
USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
+ if (factory == NULL) factory = message_factory_;
+
if (field->is_extension()) {
return static_cast<Message*>(
- MutableExtensionSet(message)->MutableMessage(field,
- factory == NULL ? message_factory_ : factory));
+ MutableExtensionSet(message)->MutableMessage(field, factory));
} else {
- Message** result = MutableField<Message*>(message, field);
- if (*result == NULL) {
+ Message* result;
+ Message** result_holder = MutableField<Message*>(message, field);
+ if (*result_holder == NULL) {
const Message* default_message = DefaultRaw<const Message*>(field);
- *result = default_message->New();
+ *result_holder = default_message->New();
}
- return *result;
+ result = *result_holder;
+ return result;
+ }
+}
+
+Message* GeneratedMessageReflection::ReleaseMessage(
+ Message* message,
+ const FieldDescriptor* field,
+ MessageFactory* factory) const {
+ USAGE_CHECK_ALL(ReleaseMessage, SINGULAR, MESSAGE);
+
+ if (factory == NULL) factory = message_factory_;
+
+ if (field->is_extension()) {
+ return static_cast<Message*>(
+ MutableExtensionSet(message)->ReleaseMessage(field, factory));
+ } else {
+ ClearBit(message, field);
+ Message** result = MutableRaw<Message*>(message, field);
+ Message* ret = *result;
+ *result = NULL;
+ return ret;
}
}
@@ -1022,7 +1068,7 @@
// We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
// know how to allocate one.
RepeatedPtrFieldBase* repeated =
- MutableRaw<RepeatedPtrFieldBase>(message, field);
+ MutableRaw<RepeatedPtrFieldBase>(message, field);
Message* result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
if (result == NULL) {
// We must allocate a new object.
@@ -1039,7 +1085,26 @@
}
}
-// -------------------------------------------------------------------
+void* GeneratedMessageReflection::MutableRawRepeatedField(
+ Message* message, const FieldDescriptor* field,
+ FieldDescriptor::CppType cpptype,
+ int ctype, const Descriptor* desc) const {
+ USAGE_CHECK_REPEATED("MutableRawRepeatedField");
+ if (field->cpp_type() != cpptype)
+ ReportReflectionUsageTypeError(descriptor_,
+ field, "MutableRawRepeatedField", cpptype);
+ if (ctype >= 0)
+ GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
+ if (desc != NULL)
+ GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
+ if (field->is_extension())
+ return MutableExtensionSet(message)->MutableRawRepeatedField(
+ field->number());
+ else
+ return reinterpret_cast<uint8*>(message) + offsets_[field->index()];
+}
+
+// -----------------------------------------------------------------------------
const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName(
const string& name) const {
diff --git a/third_party/protobuf/src/google/protobuf/generated_message_reflection.h b/third_party/protobuf/src/google/protobuf/generated_message_reflection.h
index b545fa1..e6670ae 100644
--- a/third_party/protobuf/src/google/protobuf/generated_message_reflection.h
+++ b/third_party/protobuf/src/google/protobuf/generated_message_reflection.h
@@ -40,17 +40,23 @@
#include <string>
#include <vector>
+#include <google/protobuf/stubs/common.h>
+// TODO(jasonh): Remove this once the compiler change to directly include this
+// is released to components.
+#include <google/protobuf/generated_enum_reflection.h>
#include <google/protobuf/message.h>
#include <google/protobuf/unknown_field_set.h>
namespace google {
+namespace upb {
+namespace proto2_bridge_opensource {
+class FieldAccessor;
+} // namespace protobuf_bridge_google3
+} // namespace upb
+
namespace protobuf {
class DescriptorPool;
- // Generated code needs these to have been forward-declared. Easier to do it
- // here than to print them inside every .pb.h file.
- class FileDescriptor;
- class EnumDescriptor;
}
namespace protobuf {
@@ -141,6 +147,7 @@
int FieldSize(const Message& message, const FieldDescriptor* field) const;
void ClearField(Message* message, const FieldDescriptor* field) const;
void RemoveLast(Message* message, const FieldDescriptor* field) const;
+ Message* ReleaseLast(Message* message, const FieldDescriptor* field) const;
void Swap(Message* message1, Message* message2) const;
void SwapElements(Message* message, const FieldDescriptor* field,
int index1, int index2) const;
@@ -193,6 +200,8 @@
const EnumValueDescriptor* value) const;
Message* MutableMessage(Message* message, const FieldDescriptor* field,
MessageFactory* factory = NULL) const;
+ Message* ReleaseMessage(Message* message, const FieldDescriptor* field,
+ MessageFactory* factory = NULL) const;
int32 GetRepeatedInt32 (const Message& message,
const FieldDescriptor* field, int index) const;
@@ -270,9 +279,18 @@
const FieldDescriptor* FindKnownExtensionByName(const string& name) const;
const FieldDescriptor* FindKnownExtensionByNumber(int number) const;
+ protected:
+ virtual void* MutableRawRepeatedField(
+ Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
+ int ctype, const Descriptor* desc) const;
+
private:
friend class GeneratedMessage;
+ // To parse directly into a proto2 generated class, FieldAccessor needs
+ // access to member offsets and hasbits.
+ friend class LIBPROTOBUF_EXPORT upb::proto2_bridge_opensource::FieldAccessor;
+
const Descriptor* descriptor_;
const Message* default_instance_;
const int* offsets_;
@@ -293,7 +311,6 @@
const FieldDescriptor* field) const;
template <typename Type>
inline const Type& DefaultRaw(const FieldDescriptor* field) const;
- inline const Message* GetMessagePrototype(const FieldDescriptor* field) const;
inline const uint32* GetHasBits(const Message& message) const;
inline uint32* MutableHasBits(Message* message) const;
@@ -395,28 +412,6 @@
#endif
}
-// Helper for EnumType_Parse functions: try to parse the string 'name' as an
-// enum name of the given type, returning true and filling in value on success,
-// or returning false and leaving value unchanged on failure.
-LIBPROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor,
- const string& name,
- int* value);
-
-template<typename EnumType>
-bool ParseNamedEnum(const EnumDescriptor* descriptor,
- const string& name,
- EnumType* value) {
- int tmp;
- if (!ParseNamedEnum(descriptor, name, &tmp)) return false;
- *value = static_cast<EnumType>(tmp);
- return true;
-}
-
-// Just a wrapper around printing the name of a value. The main point of this
-// function is not to be inlined, so that you can do this without including
-// descriptor.h.
-LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value);
-
} // namespace internal
} // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/generated_message_reflection_unittest.cc b/third_party/protobuf/src/google/protobuf/generated_message_reflection_unittest.cc
index a03bcdb..f60e430 100644
--- a/third_party/protobuf/src/google/protobuf/generated_message_reflection_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/generated_message_reflection_unittest.cc
@@ -225,11 +225,59 @@
unittest::TestAllExtensions::descriptor());
TestUtil::SetAllExtensions(&message);
+
reflection_tester.RemoveLastRepeatedsViaReflection(&message);
TestUtil::ExpectLastRepeatedExtensionsRemoved(message);
}
+TEST(GeneratedMessageReflectionTest, ReleaseLast) {
+ unittest::TestAllTypes message;
+ const Descriptor* descriptor = message.GetDescriptor();
+ TestUtil::ReflectionTester reflection_tester(descriptor);
+
+ TestUtil::SetAllFields(&message);
+
+ reflection_tester.ReleaseLastRepeatedsViaReflection(&message, false);
+
+ TestUtil::ExpectLastRepeatedsReleased(message);
+
+ // Now test that we actually release the right message.
+ message.Clear();
+ TestUtil::SetAllFields(&message);
+ ASSERT_EQ(2, message.repeated_foreign_message_size());
+ const protobuf_unittest::ForeignMessage* expected =
+ message.mutable_repeated_foreign_message(1);
+ scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
+ &message, descriptor->FindFieldByName("repeated_foreign_message")));
+ EXPECT_EQ(expected, released.get());
+}
+
+TEST(GeneratedMessageReflectionTest, ReleaseLastExtensions) {
+ unittest::TestAllExtensions message;
+ const Descriptor* descriptor = message.GetDescriptor();
+ TestUtil::ReflectionTester reflection_tester(descriptor);
+
+ TestUtil::SetAllExtensions(&message);
+
+ reflection_tester.ReleaseLastRepeatedsViaReflection(&message, true);
+
+ TestUtil::ExpectLastRepeatedExtensionsReleased(message);
+
+ // Now test that we actually release the right message.
+ message.Clear();
+ TestUtil::SetAllExtensions(&message);
+ ASSERT_EQ(2, message.ExtensionSize(
+ unittest::repeated_foreign_message_extension));
+ const protobuf_unittest::ForeignMessage* expected = message.MutableExtension(
+ unittest::repeated_foreign_message_extension, 1);
+ scoped_ptr<Message> released(message.GetReflection()->ReleaseLast(
+ &message, descriptor->file()->FindExtensionByName(
+ "repeated_foreign_message_extension")));
+ EXPECT_EQ(expected, released.get());
+
+}
+
TEST(GeneratedMessageReflectionTest, SwapRepeatedElements) {
unittest::TestAllTypes message;
TestUtil::ReflectionTester reflection_tester(
@@ -327,6 +375,58 @@
FindKnownExtensionByName(extension1->full_name()) == NULL);
}
+TEST(GeneratedMessageReflectionTest, ReleaseMessageTest) {
+ unittest::TestAllTypes message;
+ TestUtil::ReflectionTester reflection_tester(
+ unittest::TestAllTypes::descriptor());
+
+ // When nothing is set, we expect all released messages to be NULL.
+ reflection_tester.ExpectMessagesReleasedViaReflection(
+ &message, TestUtil::ReflectionTester::IS_NULL);
+
+ // After fields are set we should get non-NULL releases.
+ reflection_tester.SetAllFieldsViaReflection(&message);
+ reflection_tester.ExpectMessagesReleasedViaReflection(
+ &message, TestUtil::ReflectionTester::NOT_NULL);
+
+ // After Clear() we may or may not get a message from ReleaseMessage().
+ // This is implementation specific.
+ reflection_tester.SetAllFieldsViaReflection(&message);
+ message.Clear();
+ reflection_tester.ExpectMessagesReleasedViaReflection(
+ &message, TestUtil::ReflectionTester::CAN_BE_NULL);
+
+ // Test a different code path for setting after releasing.
+ TestUtil::SetAllFields(&message);
+ TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(GeneratedMessageReflectionTest, ReleaseExtensionMessageTest) {
+ unittest::TestAllExtensions message;
+ TestUtil::ReflectionTester reflection_tester(
+ unittest::TestAllExtensions::descriptor());
+
+ // When nothing is set, we expect all released messages to be NULL.
+ reflection_tester.ExpectMessagesReleasedViaReflection(
+ &message, TestUtil::ReflectionTester::IS_NULL);
+
+ // After fields are set we should get non-NULL releases.
+ reflection_tester.SetAllFieldsViaReflection(&message);
+ reflection_tester.ExpectMessagesReleasedViaReflection(
+ &message, TestUtil::ReflectionTester::NOT_NULL);
+
+ // After Clear() we may or may not get a message from ReleaseMessage().
+ // This is implementation specific.
+ reflection_tester.SetAllFieldsViaReflection(&message);
+ message.Clear();
+ reflection_tester.ExpectMessagesReleasedViaReflection(
+ &message, TestUtil::ReflectionTester::CAN_BE_NULL);
+
+ // Test a different code path for setting after releasing.
+ TestUtil::SetAllExtensions(&message);
+ TestUtil::ExpectAllExtensionsSet(message);
+}
+
#ifdef GTEST_HAS_DEATH_TEST
TEST(GeneratedMessageReflectionTest, UsageErrors) {
diff --git a/third_party/protobuf/src/google/protobuf/generated_message_util.cc b/third_party/protobuf/src/google/protobuf/generated_message_util.cc
index 76e547b..ac32150 100644
--- a/third_party/protobuf/src/google/protobuf/generated_message_util.cc
+++ b/third_party/protobuf/src/google/protobuf/generated_message_util.cc
@@ -49,7 +49,6 @@
const ::std::string kEmptyString;
-
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/generated_message_util.h b/third_party/protobuf/src/google/protobuf/generated_message_util.h
index 77ae106..b2fb8f0 100644
--- a/third_party/protobuf/src/google/protobuf/generated_message_util.h
+++ b/third_party/protobuf/src/google/protobuf/generated_message_util.h
@@ -41,16 +41,8 @@
#include <string>
#include <google/protobuf/stubs/common.h>
-
-
namespace google {
namespace protobuf {
- namespace io {
- class CodedInputStream; // coded_stream.h
- }
-}
-
-namespace protobuf {
namespace internal {
// Annotation for the compiler to emit a deprecation message if a field marked
@@ -60,11 +52,7 @@
// For internal use in the pb.cc files, deprecation warnings are suppressed
// there.
#undef DEPRECATED_PROTOBUF_FIELD
-#if !defined(INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION)
-# define PROTOBUF_DEPRECATED GOOGLE_ATTRIBUTE_DEPRECATED
-#else
-# define PROTOBUF_DEPRECATED
-#endif
+#define PROTOBUF_DEPRECATED
// Constants for special floating point values.
@@ -74,6 +62,13 @@
// Constant used for empty default strings.
LIBPROTOBUF_EXPORT extern const ::std::string kEmptyString;
+// Defined in generated_message_reflection.cc -- not actually part of the lite
+// library.
+//
+// TODO(jasonh): The various callers get this declaration from a variety of
+// places: probably in most cases repeated_field.h. Clean these up so they all
+// get the declaration from this file.
+LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
} // namespace internal
} // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/io/coded_stream.cc b/third_party/protobuf/src/google/protobuf/io/coded_stream.cc
index 402a3ad..36add8c 100644
--- a/third_party/protobuf/src/google/protobuf/io/coded_stream.cc
+++ b/third_party/protobuf/src/google/protobuf/io/coded_stream.cc
@@ -43,7 +43,7 @@
#include <limits.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
@@ -69,6 +69,19 @@
// CodedInputStream ==================================================
+CodedInputStream::~CodedInputStream() {
+ if (input_ != NULL) {
+ BackUpInputToCurrentPosition();
+ }
+
+ if (total_bytes_warning_threshold_ == -2) {
+ GOOGLE_LOG(WARNING) << "The total number of bytes read was " << total_bytes_read_;
+ }
+}
+
+// Static.
+int CodedInputStream::default_recursion_limit_ = 100;
+
void CodedInputStream::BackUpInputToCurrentPosition() {
int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_;
@@ -98,8 +111,7 @@
CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
// Current position relative to the beginning of the stream.
- int current_position = total_bytes_read_ -
- (BufferSize() + buffer_size_after_limit_);
+ int current_position = CurrentPosition();
Limit old_limit = current_limit_;
@@ -133,10 +145,9 @@
legitimate_message_end_ = false;
}
-int CodedInputStream::BytesUntilLimit() {
+int CodedInputStream::BytesUntilLimit() const {
if (current_limit_ == INT_MAX) return -1;
- int current_position = total_bytes_read_ -
- (BufferSize() + buffer_size_after_limit_);
+ int current_position = CurrentPosition();
return current_limit_ - current_position;
}
@@ -145,10 +156,14 @@
int total_bytes_limit, int warning_threshold) {
// Make sure the limit isn't already past, since this could confuse other
// code.
- int current_position = total_bytes_read_ -
- (BufferSize() + buffer_size_after_limit_);
+ int current_position = CurrentPosition();
total_bytes_limit_ = max(current_position, total_bytes_limit);
- total_bytes_warning_threshold_ = warning_threshold;
+ if (warning_threshold >= 0) {
+ total_bytes_warning_threshold_ = warning_threshold;
+ } else {
+ // warning_threshold is negative
+ total_bytes_warning_threshold_ = -1;
+ }
RecomputeBufferLimits();
}
@@ -368,16 +383,17 @@
// For the slow path, just do a 64-bit read. Try to optimize for one-byte tags
// again, since we have now refreshed the buffer.
- uint64 result;
+ uint64 result = 0;
if (!ReadVarint64(&result)) return 0;
return static_cast<uint32>(result);
}
uint32 CodedInputStream::ReadTagFallback() {
- if (BufferSize() >= kMaxVarintBytes ||
+ const int buf_size = BufferSize();
+ if (buf_size >= kMaxVarintBytes ||
// Optimization: If the varint ends at exactly the end of the buffer,
// we can detect that and still use the fast path.
- (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
+ (buf_size > 0 && !(buffer_end_[-1] & 0x80))) {
uint32 tag;
const uint8* end = ReadVarint32FromArray(buffer_, &tag);
if (end == NULL) {
@@ -388,7 +404,9 @@
} else {
// We are commonly at a limit when attempting to read tags. Try to quickly
// detect this case without making another function call.
- if (buffer_ == buffer_end_ && buffer_size_after_limit_ > 0 &&
+ if ((buf_size == 0) &&
+ ((buffer_size_after_limit_ > 0) ||
+ (total_bytes_read_ == current_limit_)) &&
// Make sure that the limit we hit is not total_bytes_limit_, since
// in that case we still need to call Refresh() so that it prints an
// error.
@@ -492,8 +510,8 @@
"CodedInputStream::SetTotalBytesLimit() in "
"google/protobuf/io/coded_stream.h.";
- // Don't warn again for this stream.
- total_bytes_warning_threshold_ = -1;
+ // Don't warn again for this stream, and print total size at the end.
+ total_bytes_warning_threshold_ = -2;
}
const void* void_buffer;
diff --git a/third_party/protobuf/src/google/protobuf/io/coded_stream.h b/third_party/protobuf/src/google/protobuf/io/coded_stream.h
index 97ac507..66cbee0 100644
--- a/third_party/protobuf/src/google/protobuf/io/coded_stream.h
+++ b/third_party/protobuf/src/google/protobuf/io/coded_stream.h
@@ -170,6 +170,9 @@
// successfully and the stream's byte limit.
~CodedInputStream();
+ // Return true if this CodedInputStream reads from a flat array instead of
+ // a ZeroCopyInputStream.
+ inline bool IsFlat() const;
// Skips a number of bytes. Returns false if an underlying read error
// occurs.
@@ -311,7 +314,10 @@
// Returns the number of bytes left until the nearest limit on the
// stack is hit, or -1 if no limits are in place.
- int BytesUntilLimit();
+ int BytesUntilLimit() const;
+
+ // Returns current position relative to the beginning of the input stream.
+ int CurrentPosition() const;
// Total Bytes Limit -----------------------------------------------
// To prevent malicious users from sending excessively large messages
@@ -327,8 +333,9 @@
// cause integer overflows is 512MB. The default limit is 64MB. Apps
// should set shorter limits if possible. If warning_threshold is not -1,
// a warning will be printed to stderr after warning_threshold bytes are
- // read. An error will always be printed to stderr if the limit is
- // reached.
+ // read. For backwards compatibility all negative values get squached to -1,
+ // as other negative values might have special internal meanings.
+ // An error will always be printed to stderr if the limit is reached.
//
// This is unrelated to PushLimit()/PopLimit().
//
@@ -355,9 +362,10 @@
// messages and groups. CodedInputStream keeps track of this because it
// is the only object that is passed down the stack during parsing.
- // Sets the maximum recursion depth. The default is 64.
+ // Sets the maximum recursion depth. The default is 100.
void SetRecursionLimit(int limit);
+
// Increments the current recursion depth. Returns true if the depth is
// under the limit, false if it has gone over.
bool IncrementRecursionDepth();
@@ -433,7 +441,8 @@
//
// Note that this feature is ignored when parsing "lite" messages as they do
// not have descriptors.
- void SetExtensionRegistry(DescriptorPool* pool, MessageFactory* factory);
+ void SetExtensionRegistry(const DescriptorPool* pool,
+ MessageFactory* factory);
// Get the DescriptorPool set via SetExtensionRegistry(), or NULL if no pool
// has been provided.
@@ -482,6 +491,11 @@
// Maximum number of bytes to read, period. This is unrelated to
// current_limit_. Set using SetTotalBytesLimit().
int total_bytes_limit_;
+
+ // If positive/0: Limit for bytes read after which a warning due to size
+ // should be logged.
+ // If -1: Printing of warning disabled. Can be set by client.
+ // If -2: Internal: Limit has been reached, print full size when destructing.
int total_bytes_warning_threshold_;
// Current recursion depth, controlled by IncrementRecursionDepth() and
@@ -539,7 +553,8 @@
static const int kDefaultTotalBytesLimit = 64 << 20; // 64MB
static const int kDefaultTotalBytesWarningThreshold = 32 << 20; // 32MB
- static const int kDefaultRecursionLimit = 64;
+
+ static int default_recursion_limit_; // 100 by default.
};
// Class which encodes and writes binary data which is composed of varint-
@@ -891,7 +906,9 @@
// If we are at a limit we know no more bytes can be read. Otherwise, it's
// hard to say without calling Refresh(), and we'd rather not do that.
- if (buffer_ == buffer_end_ && buffer_size_after_limit_ != 0) {
+ if (buffer_ == buffer_end_ &&
+ ((buffer_size_after_limit_ != 0) ||
+ (total_bytes_read_ == current_limit_))) {
last_tag_ = 0; // Pretend we called ReadTag()...
legitimate_message_end_ = true; // ... and it hit EOF.
return true;
@@ -900,6 +917,10 @@
}
}
+inline int CodedInputStream::CurrentPosition() const {
+ return total_bytes_read_ - (BufferSize() + buffer_size_after_limit_);
+}
+
inline uint8* CodedOutputStream::GetDirectBufferForNBytesAndAdvance(int size) {
if (buffer_size_ < size) {
return NULL;
@@ -1039,7 +1060,7 @@
if (recursion_depth_ > 0) --recursion_depth_;
}
-inline void CodedInputStream::SetExtensionRegistry(DescriptorPool* pool,
+inline void CodedInputStream::SetExtensionRegistry(const DescriptorPool* pool,
MessageFactory* factory) {
extension_pool_ = pool;
extension_factory_ = factory;
@@ -1071,7 +1092,7 @@
total_bytes_limit_(kDefaultTotalBytesLimit),
total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
recursion_depth_(0),
- recursion_limit_(kDefaultRecursionLimit),
+ recursion_limit_(default_recursion_limit_),
extension_pool_(NULL),
extension_factory_(NULL) {
// Eagerly Refresh() so buffer space is immediately available.
@@ -1092,17 +1113,15 @@
total_bytes_limit_(kDefaultTotalBytesLimit),
total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
recursion_depth_(0),
- recursion_limit_(kDefaultRecursionLimit),
+ recursion_limit_(default_recursion_limit_),
extension_pool_(NULL),
extension_factory_(NULL) {
// Note that setting current_limit_ == size is important to prevent some
// code paths from trying to access input_ and segfaulting.
}
-inline CodedInputStream::~CodedInputStream() {
- if (input_ != NULL) {
- BackUpInputToCurrentPosition();
- }
+inline bool CodedInputStream::IsFlat() const {
+ return input_ == NULL;
}
} // namespace io
diff --git a/third_party/protobuf/src/google/protobuf/io/coded_stream_inl.h b/third_party/protobuf/src/google/protobuf/io/coded_stream_inl.h
index 8156602..144f44f 100644
--- a/third_party/protobuf/src/google/protobuf/io/coded_stream_inl.h
+++ b/third_party/protobuf/src/google/protobuf/io/coded_stream_inl.h
@@ -38,7 +38,7 @@
#include <google/protobuf/io/coded_stream.h>
#include <string>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
diff --git a/third_party/protobuf/src/google/protobuf/io/coded_stream_unittest.cc b/third_party/protobuf/src/google/protobuf/io/coded_stream_unittest.cc
index ff268ab..2daab19 100644
--- a/third_party/protobuf/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/io/coded_stream_unittest.cc
@@ -44,7 +44,6 @@
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/strutil.h>
// This declares an unsigned long long integer literal in a portable way.
@@ -125,6 +124,13 @@
class CodedStreamTest : public testing::Test {
protected:
+ // Helper method used by tests for bytes warning. See implementation comment
+ // for further information.
+ static void SetupTotalBytesLimitWarningTest(
+ int total_bytes_limit, int warning_threshold,
+ vector<string>* out_errors, vector<string>* out_warnings);
+
+ // Buffer used during most of the tests. This assumes tests run sequentially.
static const int kBufferSize = 1024 * 64;
static uint8 buffer_[kBufferSize];
};
@@ -1022,6 +1028,59 @@
EXPECT_FALSE(coded_input.ConsumedEntireMessage());
}
+// This method is used by the tests below.
+// It constructs a CodedInputStream with the given limits and tries to read 2KiB
+// of data from it. Then it returns the logged errors and warnings in the given
+// vectors.
+void CodedStreamTest::SetupTotalBytesLimitWarningTest(
+ int total_bytes_limit, int warning_threshold,
+ vector<string>* out_errors, vector<string>* out_warnings) {
+ ArrayInputStream raw_input(buffer_, sizeof(buffer_), 128);
+
+ ScopedMemoryLog scoped_log;
+ {
+ CodedInputStream input(&raw_input);
+ input.SetTotalBytesLimit(total_bytes_limit, warning_threshold);
+ string str;
+ EXPECT_TRUE(input.ReadString(&str, 2048));
+ }
+
+ *out_errors = scoped_log.GetMessages(ERROR);
+ *out_warnings = scoped_log.GetMessages(WARNING);
+}
+
+TEST_F(CodedStreamTest, TotalBytesLimitWarning) {
+ vector<string> errors;
+ vector<string> warnings;
+ SetupTotalBytesLimitWarningTest(10240, 1024, &errors, &warnings);
+
+ EXPECT_EQ(0, errors.size());
+
+ ASSERT_EQ(2, warnings.size());
+ EXPECT_PRED_FORMAT2(testing::IsSubstring,
+ "Reading dangerously large protocol message. If the message turns out to "
+ "be larger than 10240 bytes, parsing will be halted for security reasons.",
+ warnings[0]);
+ EXPECT_PRED_FORMAT2(testing::IsSubstring,
+ "The total number of bytes read was 2048",
+ warnings[1]);
+}
+
+TEST_F(CodedStreamTest, TotalBytesLimitWarningDisabled) {
+ vector<string> errors;
+ vector<string> warnings;
+
+ // Test with -1
+ SetupTotalBytesLimitWarningTest(10240, -1, &errors, &warnings);
+ EXPECT_EQ(0, errors.size());
+ EXPECT_EQ(0, warnings.size());
+
+ // Test again with -2, expecting the same result
+ SetupTotalBytesLimitWarningTest(10240, -2, &errors, &warnings);
+ EXPECT_EQ(0, errors.size());
+ EXPECT_EQ(0, warnings.size());
+}
+
TEST_F(CodedStreamTest, RecursionLimit) {
ArrayInputStream input(buffer_, sizeof(buffer_));
@@ -1060,6 +1119,7 @@
EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 7
}
+
class ReallyBigInputStream : public ZeroCopyInputStream {
public:
ReallyBigInputStream() : backup_amount_(0), buffer_count_(0) {}
diff --git a/third_party/protobuf/src/google/protobuf/io/gzip_stream.cc b/third_party/protobuf/src/google/protobuf/io/gzip_stream.cc
index 0f1ff87..fe1f331 100644
--- a/third_party/protobuf/src/google/protobuf/io/gzip_stream.cc
+++ b/third_party/protobuf/src/google/protobuf/io/gzip_stream.cc
@@ -199,16 +199,6 @@
Init(sub_stream, options);
}
-GzipOutputStream::GzipOutputStream(
- ZeroCopyOutputStream* sub_stream, Format format, int buffer_size) {
- Options options;
- options.format = format;
- if (buffer_size != -1) {
- options.buffer_size = buffer_size;
- }
- Init(sub_stream, options);
-}
-
void GzipOutputStream::Init(ZeroCopyOutputStream* sub_stream,
const Options& options) {
sub_stream_ = sub_stream;
@@ -309,10 +299,11 @@
}
bool GzipOutputStream::Flush() {
- do {
- zerror_ = Deflate(Z_FULL_FLUSH);
- } while (zerror_ == Z_OK);
- return zerror_ == Z_OK;
+ zerror_ = Deflate(Z_FULL_FLUSH);
+ // Return true if the flush succeeded or if it was a no-op.
+ return (zerror_ == Z_OK) ||
+ (zerror_ == Z_BUF_ERROR && zcontext_.avail_in == 0 &&
+ zcontext_.avail_out != 0);
}
bool GzipOutputStream::Close() {
diff --git a/third_party/protobuf/src/google/protobuf/io/gzip_stream.h b/third_party/protobuf/src/google/protobuf/io/gzip_stream.h
index 65dbc5b..7ee24bc 100644
--- a/third_party/protobuf/src/google/protobuf/io/gzip_stream.h
+++ b/third_party/protobuf/src/google/protobuf/io/gzip_stream.h
@@ -45,6 +45,7 @@
#include <zlib.h>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/zero_copy_stream.h>
namespace google {
@@ -144,12 +145,6 @@
ZeroCopyOutputStream* sub_stream,
const Options& options);
- // DEPRECATED: Use one of the above constructors instead.
- GzipOutputStream(
- ZeroCopyOutputStream* sub_stream,
- Format format,
- int buffer_size = -1) GOOGLE_ATTRIBUTE_DEPRECATED;
-
virtual ~GzipOutputStream();
// Return last error message or NULL if no error.
@@ -165,6 +160,13 @@
// necessary.
// Compression may be less efficient stopping and starting around flushes.
// Returns true if no error.
+ //
+ // Please ensure that block size is > 6. Here is an excerpt from the zlib
+ // doc that explains why:
+ //
+ // In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out
+ // is greater than six to avoid repeated flush markers due to
+ // avail_out == 0 on return.
bool Flush();
// Writes out all data and closes the gzip stream.
diff --git a/third_party/protobuf/src/google/protobuf/io/printer.cc b/third_party/protobuf/src/google/protobuf/io/printer.cc
index 9ab90de..d2bf3f5 100644
--- a/third_party/protobuf/src/google/protobuf/io/printer.cc
+++ b/third_party/protobuf/src/google/protobuf/io/printer.cc
@@ -35,7 +35,6 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
@@ -51,8 +50,8 @@
}
Printer::~Printer() {
- // Only BackUp() if we're sure we've successfully called Next() at least once.
- if (buffer_size_ > 0) {
+ // Only BackUp() if we have called Next() at least once and never failed.
+ if (buffer_size_ > 0 && !failed_) {
output_->BackUp(buffer_size_);
}
}
@@ -169,7 +168,7 @@
if (failed_) return;
if (size == 0) return;
- if (at_start_of_line_) {
+ if (at_start_of_line_ && (size > 0) && (data[0] != '\n')) {
// Insert an indent.
at_start_of_line_ = false;
WriteRaw(indent_.data(), indent_.size());
diff --git a/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc b/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc
index 580a53d..399395c 100644
--- a/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc
@@ -233,7 +233,31 @@
}
#endif // GTEST_HAS_DEATH_TEST
-TEST(Printer, WriteFailure) {
+TEST(Printer, WriteFailurePartial) {
+ char buffer[17];
+
+ ArrayOutputStream output(buffer, sizeof(buffer));
+ Printer printer(&output, '$');
+
+ // Print 16 bytes to almost fill the buffer (should not fail).
+ printer.Print("0123456789abcdef");
+ EXPECT_FALSE(printer.failed());
+
+ // Try to print 2 chars. Only one fits.
+ printer.Print("<>");
+ EXPECT_TRUE(printer.failed());
+
+ // Anything else should fail too.
+ printer.Print(" ");
+ EXPECT_TRUE(printer.failed());
+ printer.Print("blah");
+ EXPECT_TRUE(printer.failed());
+
+ // Buffer should contain the first 17 bytes written.
+ EXPECT_EQ("0123456789abcdef<", string(buffer, sizeof(buffer)));
+}
+
+TEST(Printer, WriteFailureExact) {
char buffer[16];
ArrayOutputStream output(buffer, sizeof(buffer));
diff --git a/third_party/protobuf/src/google/protobuf/io/tokenizer.cc b/third_party/protobuf/src/google/protobuf/io/tokenizer.cc
index 513831d..a022b71 100644
--- a/third_party/protobuf/src/google/protobuf/io/tokenizer.cc
+++ b/third_party/protobuf/src/google/protobuf/io/tokenizer.cc
@@ -89,8 +89,11 @@
// exactly pretty.
#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
@@ -118,6 +121,8 @@
CHARACTER_CLASS(Whitespace, c == ' ' || c == '\n' || c == '\t' ||
c == '\r' || c == '\v' || c == '\f');
+CHARACTER_CLASS(WhitespaceNoNewline, c == ' ' || c == '\t' ||
+ c == '\r' || c == '\v' || c == '\f');
CHARACTER_CLASS(Unprintable, c < ' ' && c > '\0');
@@ -187,7 +192,8 @@
read_error_(false),
line_(0),
column_(0),
- token_start_(-1),
+ record_target_(NULL),
+ record_start_(-1),
allow_f_after_float_(false),
comment_style_(CPP_COMMENT_STYLE) {
@@ -238,9 +244,9 @@
}
// If we're in a token, append the rest of the buffer to it.
- if (token_start_ >= 0 && token_start_ < buffer_size_) {
- current_.text.append(buffer_ + token_start_, buffer_size_ - token_start_);
- token_start_ = 0;
+ if (record_target_ != NULL && record_start_ < buffer_size_) {
+ record_target_->append(buffer_ + record_start_, buffer_size_ - record_start_);
+ record_start_ = 0;
}
const void* data = NULL;
@@ -261,23 +267,33 @@
current_char_ = buffer_[0];
}
-inline void Tokenizer::StartToken() {
- token_start_ = buffer_pos_;
- current_.type = TYPE_START; // Just for the sake of initializing it.
- current_.text.clear();
- current_.line = line_;
- current_.column = column_;
+inline void Tokenizer::RecordTo(string* target) {
+ record_target_ = target;
+ record_start_ = buffer_pos_;
}
-inline void Tokenizer::EndToken() {
+inline void Tokenizer::StopRecording() {
// Note: The if() is necessary because some STL implementations crash when
// you call string::append(NULL, 0), presumably because they are trying to
// be helpful by detecting the NULL pointer, even though there's nothing
// wrong with reading zero bytes from NULL.
- if (buffer_pos_ != token_start_) {
- current_.text.append(buffer_ + token_start_, buffer_pos_ - token_start_);
+ if (buffer_pos_ != record_start_) {
+ record_target_->append(buffer_ + record_start_, buffer_pos_ - record_start_);
}
- token_start_ = -1;
+ record_target_ = NULL;
+ record_start_ = -1;
+}
+
+inline void Tokenizer::StartToken() {
+ current_.type = TYPE_START; // Just for the sake of initializing it.
+ current_.text.clear();
+ current_.line = line_;
+ current_.column = column_;
+ RecordTo(¤t_.text);
+}
+
+inline void Tokenizer::EndToken() {
+ StopRecording();
current_.end_column = column_;
}
@@ -353,6 +369,27 @@
AddError("Expected hex digits for escape sequence.");
}
// Possibly followed by another hex digit, but again we don't care.
+ } else if (TryConsume('u')) {
+ if (!TryConsumeOne<HexDigit>() ||
+ !TryConsumeOne<HexDigit>() ||
+ !TryConsumeOne<HexDigit>() ||
+ !TryConsumeOne<HexDigit>()) {
+ AddError("Expected four hex digits for \\u escape sequence.");
+ }
+ } else if (TryConsume('U')) {
+ // We expect 8 hex digits; but only the range up to 0x10ffff is
+ // legal.
+ if (!TryConsume('0') ||
+ !TryConsume('0') ||
+ !(TryConsume('0') || TryConsume('1')) ||
+ !TryConsumeOne<HexDigit>() ||
+ !TryConsumeOne<HexDigit>() ||
+ !TryConsumeOne<HexDigit>() ||
+ !TryConsumeOne<HexDigit>() ||
+ !TryConsumeOne<HexDigit>()) {
+ AddError("Expected eight hex digits up to 10ffff for \\U escape "
+ "sequence");
+ }
} else {
AddError("Invalid escape sequence in string literal.");
}
@@ -426,26 +463,51 @@
return is_float ? TYPE_FLOAT : TYPE_INTEGER;
}
-void Tokenizer::ConsumeLineComment() {
+void Tokenizer::ConsumeLineComment(string* content) {
+ if (content != NULL) RecordTo(content);
+
while (current_char_ != '\0' && current_char_ != '\n') {
NextChar();
}
TryConsume('\n');
+
+ if (content != NULL) StopRecording();
}
-void Tokenizer::ConsumeBlockComment() {
+void Tokenizer::ConsumeBlockComment(string* content) {
int start_line = line_;
int start_column = column_ - 2;
+ if (content != NULL) RecordTo(content);
+
while (true) {
while (current_char_ != '\0' &&
current_char_ != '*' &&
- current_char_ != '/') {
+ current_char_ != '/' &&
+ current_char_ != '\n') {
NextChar();
}
- if (TryConsume('*') && TryConsume('/')) {
+ if (TryConsume('\n')) {
+ if (content != NULL) StopRecording();
+
+ // Consume leading whitespace and asterisk;
+ ConsumeZeroOrMore<WhitespaceNoNewline>();
+ if (TryConsume('*')) {
+ if (TryConsume('/')) {
+ // End of comment.
+ break;
+ }
+ }
+
+ if (content != NULL) RecordTo(content);
+ } else if (TryConsume('*') && TryConsume('/')) {
// End of comment.
+ if (content != NULL) {
+ StopRecording();
+ // Strip trailing "*/".
+ content->erase(content->size() - 2);
+ }
break;
} else if (TryConsume('/') && current_char_ == '*') {
// Note: We didn't consume the '*' because if there is a '/' after it
@@ -456,42 +518,59 @@
AddError("End-of-file inside block comment.");
error_collector_->AddError(
start_line, start_column, " Comment started here.");
+ if (content != NULL) StopRecording();
break;
}
}
}
+Tokenizer::NextCommentStatus Tokenizer::TryConsumeCommentStart() {
+ if (comment_style_ == CPP_COMMENT_STYLE && TryConsume('/')) {
+ if (TryConsume('/')) {
+ return LINE_COMMENT;
+ } else if (TryConsume('*')) {
+ return BLOCK_COMMENT;
+ } else {
+ // Oops, it was just a slash. Return it.
+ current_.type = TYPE_SYMBOL;
+ current_.text = "/";
+ current_.line = line_;
+ current_.column = column_ - 1;
+ current_.end_column = column_;
+ return SLASH_NOT_COMMENT;
+ }
+ } else if (comment_style_ == SH_COMMENT_STYLE && TryConsume('#')) {
+ return LINE_COMMENT;
+ } else {
+ return NO_COMMENT;
+ }
+}
+
// -------------------------------------------------------------------
bool Tokenizer::Next() {
previous_ = current_;
- // Did we skip any characters after the last token?
- bool skipped_stuff = false;
-
while (!read_error_) {
- if (TryConsumeOne<Whitespace>()) {
- ConsumeZeroOrMore<Whitespace>();
+ ConsumeZeroOrMore<Whitespace>();
- } else if (comment_style_ == CPP_COMMENT_STYLE && TryConsume('/')) {
- // Starting a comment?
- if (TryConsume('/')) {
- ConsumeLineComment();
- } else if (TryConsume('*')) {
- ConsumeBlockComment();
- } else {
- // Oops, it was just a slash. Return it.
- current_.type = TYPE_SYMBOL;
- current_.text = "/";
- current_.line = line_;
- current_.column = column_ - 1;
+ switch (TryConsumeCommentStart()) {
+ case LINE_COMMENT:
+ ConsumeLineComment(NULL);
+ continue;
+ case BLOCK_COMMENT:
+ ConsumeBlockComment(NULL);
+ continue;
+ case SLASH_NOT_COMMENT:
return true;
- }
+ case NO_COMMENT:
+ break;
+ }
- } else if (comment_style_ == SH_COMMENT_STYLE && TryConsume('#')) {
- ConsumeLineComment();
+ // Check for EOF before continuing.
+ if (read_error_) break;
- } else if (LookingAt<Unprintable>() || current_char_ == '\0') {
+ if (LookingAt<Unprintable>() || current_char_ == '\0') {
AddError("Invalid control characters encountered in text.");
NextChar();
// Skip more unprintable characters, too. But, remember that '\0' is
@@ -519,7 +598,9 @@
if (TryConsumeOne<Digit>()) {
// It's a floating-point number.
- if (previous_.type == TYPE_IDENTIFIER && !skipped_stuff) {
+ if (previous_.type == TYPE_IDENTIFIER &&
+ current_.line == previous_.line &&
+ current_.column == previous_.end_column) {
// We don't accept syntax like "blah.123".
error_collector_->AddError(line_, column_ - 2,
"Need space between identifier and decimal point.");
@@ -544,8 +625,6 @@
EndToken();
return true;
}
-
- skipped_stuff = true;
}
// EOF
@@ -557,6 +636,195 @@
return false;
}
+namespace {
+
+// Helper class for collecting comments and putting them in the right places.
+//
+// This basically just buffers the most recent comment until it can be decided
+// exactly where that comment should be placed. When Flush() is called, the
+// current comment goes into either prev_trailing_comments or detached_comments.
+// When the CommentCollector is destroyed, the last buffered comment goes into
+// next_leading_comments.
+class CommentCollector {
+ public:
+ CommentCollector(string* prev_trailing_comments,
+ vector<string>* detached_comments,
+ string* next_leading_comments)
+ : prev_trailing_comments_(prev_trailing_comments),
+ detached_comments_(detached_comments),
+ next_leading_comments_(next_leading_comments),
+ has_comment_(false),
+ is_line_comment_(false),
+ can_attach_to_prev_(true) {
+ if (prev_trailing_comments != NULL) prev_trailing_comments->clear();
+ if (detached_comments != NULL) detached_comments->clear();
+ if (next_leading_comments != NULL) next_leading_comments->clear();
+ }
+
+ ~CommentCollector() {
+ // Whatever is in the buffer is a leading comment.
+ if (next_leading_comments_ != NULL && has_comment_) {
+ comment_buffer_.swap(*next_leading_comments_);
+ }
+ }
+
+ // About to read a line comment. Get the comment buffer pointer in order to
+ // read into it.
+ string* GetBufferForLineComment() {
+ // We want to combine with previous line comments, but not block comments.
+ if (has_comment_ && !is_line_comment_) {
+ Flush();
+ }
+ has_comment_ = true;
+ is_line_comment_ = true;
+ return &comment_buffer_;
+ }
+
+ // About to read a block comment. Get the comment buffer pointer in order to
+ // read into it.
+ string* GetBufferForBlockComment() {
+ if (has_comment_) {
+ Flush();
+ }
+ has_comment_ = true;
+ is_line_comment_ = false;
+ return &comment_buffer_;
+ }
+
+ void ClearBuffer() {
+ comment_buffer_.clear();
+ has_comment_ = false;
+ }
+
+ // Called once we know that the comment buffer is complete and is *not*
+ // connected to the next token.
+ void Flush() {
+ if (has_comment_) {
+ if (can_attach_to_prev_) {
+ if (prev_trailing_comments_ != NULL) {
+ prev_trailing_comments_->append(comment_buffer_);
+ }
+ can_attach_to_prev_ = false;
+ } else {
+ if (detached_comments_ != NULL) {
+ detached_comments_->push_back(comment_buffer_);
+ }
+ }
+ ClearBuffer();
+ }
+ }
+
+ void DetachFromPrev() {
+ can_attach_to_prev_ = false;
+ }
+
+ private:
+ string* prev_trailing_comments_;
+ vector<string>* detached_comments_;
+ string* next_leading_comments_;
+
+ string comment_buffer_;
+
+ // True if any comments were read into comment_buffer_. This can be true even
+ // if comment_buffer_ is empty, namely if the comment was "/**/".
+ bool has_comment_;
+
+ // Is the comment in the comment buffer a line comment?
+ bool is_line_comment_;
+
+ // Is it still possible that we could be reading a comment attached to the
+ // previous token?
+ bool can_attach_to_prev_;
+};
+
+} // namespace
+
+bool Tokenizer::NextWithComments(string* prev_trailing_comments,
+ vector<string>* detached_comments,
+ string* next_leading_comments) {
+ CommentCollector collector(prev_trailing_comments, detached_comments,
+ next_leading_comments);
+
+ if (current_.type == TYPE_START) {
+ collector.DetachFromPrev();
+ } else {
+ // A comment appearing on the same line must be attached to the previous
+ // declaration.
+ ConsumeZeroOrMore<WhitespaceNoNewline>();
+ switch (TryConsumeCommentStart()) {
+ case LINE_COMMENT:
+ ConsumeLineComment(collector.GetBufferForLineComment());
+
+ // Don't allow comments on subsequent lines to be attached to a trailing
+ // comment.
+ collector.Flush();
+ break;
+ case BLOCK_COMMENT:
+ ConsumeBlockComment(collector.GetBufferForBlockComment());
+
+ ConsumeZeroOrMore<WhitespaceNoNewline>();
+ if (!TryConsume('\n')) {
+ // Oops, the next token is on the same line. If we recorded a comment
+ // we really have no idea which token it should be attached to.
+ collector.ClearBuffer();
+ return Next();
+ }
+
+ // Don't allow comments on subsequent lines to be attached to a trailing
+ // comment.
+ collector.Flush();
+ break;
+ case SLASH_NOT_COMMENT:
+ return true;
+ case NO_COMMENT:
+ if (!TryConsume('\n')) {
+ // The next token is on the same line. There are no comments.
+ return Next();
+ }
+ break;
+ }
+ }
+
+ // OK, we are now on the line *after* the previous token.
+ while (true) {
+ ConsumeZeroOrMore<WhitespaceNoNewline>();
+
+ switch (TryConsumeCommentStart()) {
+ case LINE_COMMENT:
+ ConsumeLineComment(collector.GetBufferForLineComment());
+ break;
+ case BLOCK_COMMENT:
+ ConsumeBlockComment(collector.GetBufferForBlockComment());
+
+ // Consume the rest of the line so that we don't interpret it as a
+ // blank line the next time around the loop.
+ ConsumeZeroOrMore<WhitespaceNoNewline>();
+ TryConsume('\n');
+ break;
+ case SLASH_NOT_COMMENT:
+ return true;
+ case NO_COMMENT:
+ if (TryConsume('\n')) {
+ // Completely blank line.
+ collector.Flush();
+ collector.DetachFromPrev();
+ } else {
+ bool result = Next();
+ if (!result ||
+ current_.text == "}" ||
+ current_.text == "]" ||
+ current_.text == ")") {
+ // It looks like we're at the end of a scope. In this case it
+ // makes no sense to attach a comment to the following token.
+ collector.Flush();
+ }
+ return result;
+ }
+ break;
+ }
+ }
+}
+
// -------------------------------------------------------------------
// Token-parsing helpers. Remember that these don't need to report
// errors since any errors should already have been reported while
@@ -626,17 +894,138 @@
return result;
}
+// Helper to append a Unicode code point to a string as UTF8, without bringing
+// in any external dependencies.
+static void AppendUTF8(uint32 code_point, string* output) {
+ uint32 tmp = 0;
+ int len = 0;
+ if (code_point <= 0x7f) {
+ tmp = code_point;
+ len = 1;
+ } else if (code_point <= 0x07ff) {
+ tmp = 0x0000c080 |
+ ((code_point & 0x07c0) << 2) |
+ (code_point & 0x003f);
+ len = 2;
+ } else if (code_point <= 0xffff) {
+ tmp = 0x00e08080 |
+ ((code_point & 0xf000) << 4) |
+ ((code_point & 0x0fc0) << 2) |
+ (code_point & 0x003f);
+ len = 3;
+ } else if (code_point <= 0x1fffff) {
+ tmp = 0xf0808080 |
+ ((code_point & 0x1c0000) << 6) |
+ ((code_point & 0x03f000) << 4) |
+ ((code_point & 0x000fc0) << 2) |
+ (code_point & 0x003f);
+ len = 4;
+ } else {
+ // UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is
+ // normally only defined up to there as well.
+ StringAppendF(output, "\\U%08x", code_point);
+ return;
+ }
+ tmp = ghtonl(tmp);
+ output->append(reinterpret_cast<const char*>(&tmp) + sizeof(tmp) - len, len);
+}
+
+// Try to read <len> hex digits from ptr, and stuff the numeric result into
+// *result. Returns true if that many digits were successfully consumed.
+static bool ReadHexDigits(const char* ptr, int len, uint32* result) {
+ *result = 0;
+ if (len == 0) return false;
+ for (const char* end = ptr + len; ptr < end; ++ptr) {
+ if (*ptr == '\0') return false;
+ *result = (*result << 4) + DigitValue(*ptr);
+ }
+ return true;
+}
+
+// Handling UTF-16 surrogate pairs. UTF-16 encodes code points in the range
+// 0x10000...0x10ffff as a pair of numbers, a head surrogate followed by a trail
+// surrogate. These numbers are in a reserved range of Unicode code points, so
+// if we encounter such a pair we know how to parse it and convert it into a
+// single code point.
+static const uint32 kMinHeadSurrogate = 0xd800;
+static const uint32 kMaxHeadSurrogate = 0xdc00;
+static const uint32 kMinTrailSurrogate = 0xdc00;
+static const uint32 kMaxTrailSurrogate = 0xe000;
+
+static inline bool IsHeadSurrogate(uint32 code_point) {
+ return (code_point >= kMinHeadSurrogate) && (code_point < kMaxHeadSurrogate);
+}
+
+static inline bool IsTrailSurrogate(uint32 code_point) {
+ return (code_point >= kMinTrailSurrogate) &&
+ (code_point < kMaxTrailSurrogate);
+}
+
+// Combine a head and trail surrogate into a single Unicode code point.
+static uint32 AssembleUTF16(uint32 head_surrogate, uint32 trail_surrogate) {
+ GOOGLE_DCHECK(IsHeadSurrogate(head_surrogate));
+ GOOGLE_DCHECK(IsTrailSurrogate(trail_surrogate));
+ return 0x10000 + (((head_surrogate - kMinHeadSurrogate) << 10) |
+ (trail_surrogate - kMinTrailSurrogate));
+}
+
+// Convert the escape sequence parameter to a number of expected hex digits.
+static inline int UnicodeLength(char key) {
+ if (key == 'u') return 4;
+ if (key == 'U') return 8;
+ return 0;
+}
+
+// Given a pointer to the 'u' or 'U' starting a Unicode escape sequence, attempt
+// to parse that sequence. On success, returns a pointer to the first char
+// beyond that sequence, and fills in *code_point. On failure, returns ptr
+// itself.
+static const char* FetchUnicodePoint(const char* ptr, uint32* code_point) {
+ const char* p = ptr;
+ // Fetch the code point.
+ const int len = UnicodeLength(*p++);
+ if (!ReadHexDigits(p, len, code_point))
+ return ptr;
+ p += len;
+
+ // Check if the code point we read is a "head surrogate." If so, then we
+ // expect it to be immediately followed by another code point which is a valid
+ // "trail surrogate," and together they form a UTF-16 pair which decodes into
+ // a single Unicode point. Trail surrogates may only use \u, not \U.
+ if (IsHeadSurrogate(*code_point) && *p == '\\' && *(p + 1) == 'u') {
+ uint32 trail_surrogate;
+ if (ReadHexDigits(p + 2, 4, &trail_surrogate) &&
+ IsTrailSurrogate(trail_surrogate)) {
+ *code_point = AssembleUTF16(*code_point, trail_surrogate);
+ p += 6;
+ }
+ // If this failed, then we just emit the head surrogate as a code point.
+ // It's bogus, but so is the string.
+ }
+
+ return p;
+}
+
+// The text string must begin and end with single or double quote
+// characters.
void Tokenizer::ParseStringAppend(const string& text, string* output) {
- // Reminder: text[0] is always the quote character. (If text is
- // empty, it's invalid, so we'll just return.)
- if (text.empty()) {
+ // Reminder: text[0] is always a quote character. (If text is
+ // empty, it's invalid, so we'll just return).
+ const size_t text_size = text.size();
+ if (text_size == 0) {
GOOGLE_LOG(DFATAL)
<< " Tokenizer::ParseStringAppend() passed text that could not"
" have been tokenized as a string: " << CEscape(text);
return;
}
- output->reserve(output->size() + text.size());
+ // Reserve room for new string. The branch is necessary because if
+ // there is already space available the reserve() call might
+ // downsize the output.
+ const size_t new_len = text_size + output->size();
+ if (new_len > output->capacity()) {
+ output->reserve(new_len);
+ }
// Loop through the string copying characters to "output" and
// interpreting escape sequences. Note that any invalid escape
@@ -674,19 +1063,27 @@
}
output->push_back(static_cast<char>(code));
+ } else if (*ptr == 'u' || *ptr == 'U') {
+ uint32 unicode;
+ const char* end = FetchUnicodePoint(ptr, &unicode);
+ if (end == ptr) {
+ // Failure: Just dump out what we saw, don't try to parse it.
+ output->push_back(*ptr);
+ } else {
+ AppendUTF8(unicode, output);
+ ptr = end - 1; // Because we're about to ++ptr.
+ }
} else {
// Some other escape code.
output->push_back(TranslateEscape(*ptr));
}
- } else if (*ptr == text[0]) {
- // Ignore quote matching the starting quote.
+ } else if (*ptr == text[0] && ptr[1] == '\0') {
+ // Ignore final quote matching the starting quote.
} else {
output->push_back(*ptr);
}
}
-
- return;
}
} // namespace io
diff --git a/third_party/protobuf/src/google/protobuf/io/tokenizer.h b/third_party/protobuf/src/google/protobuf/io/tokenizer.h
index 8f759ab..d85b82f 100644
--- a/third_party/protobuf/src/google/protobuf/io/tokenizer.h
+++ b/third_party/protobuf/src/google/protobuf/io/tokenizer.h
@@ -38,6 +38,7 @@
#define GOOGLE_PROTOBUF_IO_TOKENIZER_H__
#include <string>
+#include <vector>
#include <google/protobuf/stubs/common.h>
namespace google {
@@ -137,6 +138,53 @@
// reached.
bool Next();
+ // Like Next(), but also collects comments which appear between the previous
+ // and next tokens.
+ //
+ // Comments which appear to be attached to the previous token are stored
+ // in *prev_tailing_comments. Comments which appear to be attached to the
+ // next token are stored in *next_leading_comments. Comments appearing in
+ // between which do not appear to be attached to either will be added to
+ // detached_comments. Any of these parameters can be NULL to simply discard
+ // the comments.
+ //
+ // A series of line comments appearing on consecutive lines, with no other
+ // tokens appearing on those lines, will be treated as a single comment.
+ //
+ // Only the comment content is returned; comment markers (e.g. //) are
+ // stripped out. For block comments, leading whitespace and an asterisk will
+ // be stripped from the beginning of each line other than the first. Newlines
+ // are included in the output.
+ //
+ // Examples:
+ //
+ // optional int32 foo = 1; // Comment attached to foo.
+ // // Comment attached to bar.
+ // optional int32 bar = 2;
+ //
+ // optional string baz = 3;
+ // // Comment attached to baz.
+ // // Another line attached to baz.
+ //
+ // // Comment attached to qux.
+ // //
+ // // Another line attached to qux.
+ // optional double qux = 4;
+ //
+ // // Detached comment. This is not attached to qux or corge
+ // // because there are blank lines separating it from both.
+ //
+ // optional string corge = 5;
+ // /* Block comment attached
+ // * to corge. Leading asterisks
+ // * will be removed. */
+ // /* Block comment attached to
+ // * grault. */
+ // optional int32 grault = 6;
+ bool NextWithComments(string* prev_trailing_comments,
+ vector<string>* detached_comments,
+ string* next_leading_comments);
+
// Parse helpers ---------------------------------------------------
// Parses a TYPE_FLOAT token. This never fails, so long as the text actually
@@ -200,11 +248,12 @@
int line_;
int column_;
- // Position in buffer_ where StartToken() was called. If the token
- // started in the previous buffer, this is zero, and current_.text already
- // contains the part of the token from the previous buffer. If not
- // currently parsing a token, this is -1.
- int token_start_;
+ // String to which text should be appended as we advance through it.
+ // Call RecordTo(&str) to start recording and StopRecording() to stop.
+ // E.g. StartToken() calls RecordTo(¤t_.text). record_start_ is the
+ // position within the current buffer where recording started.
+ string* record_target_;
+ int record_start_;
// Options.
bool allow_f_after_float_;
@@ -223,6 +272,9 @@
// Read a new buffer from the input.
void Refresh();
+ inline void RecordTo(string* target);
+ inline void StopRecording();
+
// Called when the current character is the first character of a new
// token (not including whitespace or comments).
inline void StartToken();
@@ -255,9 +307,28 @@
TokenType ConsumeNumber(bool started_with_zero, bool started_with_dot);
// Consume the rest of a line.
- void ConsumeLineComment();
+ void ConsumeLineComment(string* content);
// Consume until "*/".
- void ConsumeBlockComment();
+ void ConsumeBlockComment(string* content);
+
+ enum NextCommentStatus {
+ // Started a line comment.
+ LINE_COMMENT,
+
+ // Started a block comment.
+ BLOCK_COMMENT,
+
+ // Consumed a slash, then realized it wasn't a comment. current_ has
+ // been filled in with a slash token. The caller should return it.
+ SLASH_NOT_COMMENT,
+
+ // We do not appear to be starting a comment here.
+ NO_COMMENT
+ };
+
+ // If we're at the start of a new comment, consume it and return what kind
+ // of comment it is.
+ NextCommentStatus TryConsumeCommentStart();
// -----------------------------------------------------------------
// These helper methods make the parsing code more readable. The
diff --git a/third_party/protobuf/src/google/protobuf/io/tokenizer_unittest.cc b/third_party/protobuf/src/google/protobuf/io/tokenizer_unittest.cc
index 106d080..8de4393 100644
--- a/third_party/protobuf/src/google/protobuf/io/tokenizer_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/io/tokenizer_unittest.cc
@@ -32,9 +32,10 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <vector>
-#include <math.h>
#include <limits.h>
+#include <math.h>
+
+#include <vector>
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
@@ -514,6 +515,217 @@
// -------------------------------------------------------------------
+// In each case, the input is expected to have two tokens named "prev" and
+// "next" with comments in between.
+struct DocCommentCase {
+ string input;
+
+ const char* prev_trailing_comments;
+ const char* detached_comments[10];
+ const char* next_leading_comments;
+};
+
+inline ostream& operator<<(ostream& out,
+ const DocCommentCase& test_case) {
+ return out << CEscape(test_case.input);
+}
+
+DocCommentCase kDocCommentCases[] = {
+ {
+ "prev next",
+
+ "",
+ {},
+ ""
+ },
+
+ {
+ "prev /* ignored */ next",
+
+ "",
+ {},
+ ""
+ },
+
+ {
+ "prev // trailing comment\n"
+ "next",
+
+ " trailing comment\n",
+ {},
+ ""
+ },
+
+ {
+ "prev\n"
+ "// leading comment\n"
+ "// line 2\n"
+ "next",
+
+ "",
+ {},
+ " leading comment\n"
+ " line 2\n"
+ },
+
+ {
+ "prev\n"
+ "// trailing comment\n"
+ "// line 2\n"
+ "\n"
+ "next",
+
+ " trailing comment\n"
+ " line 2\n",
+ {},
+ ""
+ },
+
+ {
+ "prev // trailing comment\n"
+ "// leading comment\n"
+ "// line 2\n"
+ "next",
+
+ " trailing comment\n",
+ {},
+ " leading comment\n"
+ " line 2\n"
+ },
+
+ {
+ "prev /* trailing block comment */\n"
+ "/* leading block comment\n"
+ " * line 2\n"
+ " * line 3 */"
+ "next",
+
+ " trailing block comment ",
+ {},
+ " leading block comment\n"
+ " line 2\n"
+ " line 3 "
+ },
+
+ {
+ "prev\n"
+ "/* trailing block comment\n"
+ " * line 2\n"
+ " * line 3\n"
+ " */\n"
+ "/* leading block comment\n"
+ " * line 2\n"
+ " * line 3 */"
+ "next",
+
+ " trailing block comment\n"
+ " line 2\n"
+ " line 3\n",
+ {},
+ " leading block comment\n"
+ " line 2\n"
+ " line 3 "
+ },
+
+ {
+ "prev\n"
+ "// trailing comment\n"
+ "\n"
+ "// detached comment\n"
+ "// line 2\n"
+ "\n"
+ "// second detached comment\n"
+ "/* third detached comment\n"
+ " * line 2 */\n"
+ "// leading comment\n"
+ "next",
+
+ " trailing comment\n",
+ {
+ " detached comment\n"
+ " line 2\n",
+ " second detached comment\n",
+ " third detached comment\n"
+ " line 2 "
+ },
+ " leading comment\n"
+ },
+
+ {
+ "prev /**/\n"
+ "\n"
+ "// detached comment\n"
+ "\n"
+ "// leading comment\n"
+ "next",
+
+ "",
+ {
+ " detached comment\n"
+ },
+ " leading comment\n"
+ },
+
+ {
+ "prev /**/\n"
+ "// leading comment\n"
+ "next",
+
+ "",
+ {},
+ " leading comment\n"
+ },
+ };
+
+TEST_2D(TokenizerTest, DocComments, kDocCommentCases, kBlockSizes) {
+ // Set up the tokenizer.
+ TestInputStream input(kDocCommentCases_case.input.data(),
+ kDocCommentCases_case.input.size(),
+ kBlockSizes_case);
+ TestErrorCollector error_collector;
+ Tokenizer tokenizer(&input, &error_collector);
+
+ // Set up a second tokenizer where we'll pass all NULLs to NextWithComments().
+ TestInputStream input2(kDocCommentCases_case.input.data(),
+ kDocCommentCases_case.input.size(),
+ kBlockSizes_case);
+ Tokenizer tokenizer2(&input2, &error_collector);
+
+ tokenizer.Next();
+ tokenizer2.Next();
+
+ EXPECT_EQ("prev", tokenizer.current().text);
+ EXPECT_EQ("prev", tokenizer2.current().text);
+
+ string prev_trailing_comments;
+ vector<string> detached_comments;
+ string next_leading_comments;
+ tokenizer.NextWithComments(&prev_trailing_comments, &detached_comments,
+ &next_leading_comments);
+ tokenizer2.NextWithComments(NULL, NULL, NULL);
+ EXPECT_EQ("next", tokenizer.current().text);
+ EXPECT_EQ("next", tokenizer2.current().text);
+
+ EXPECT_EQ(kDocCommentCases_case.prev_trailing_comments,
+ prev_trailing_comments);
+
+ for (int i = 0; i < detached_comments.size(); i++) {
+ ASSERT_LT(i, GOOGLE_ARRAYSIZE(kDocCommentCases));
+ ASSERT_TRUE(kDocCommentCases_case.detached_comments[i] != NULL);
+ EXPECT_EQ(kDocCommentCases_case.detached_comments[i],
+ detached_comments[i]);
+ }
+
+ // Verify that we matched all the detached comments.
+ EXPECT_EQ(NULL,
+ kDocCommentCases_case.detached_comments[detached_comments.size()]);
+
+ EXPECT_EQ(kDocCommentCases_case.next_leading_comments,
+ next_leading_comments);
+}
+
+// -------------------------------------------------------------------
+
// Test parse helpers. It's not really worth setting up a full data-driven
// test here.
TEST_F(TokenizerTest, ParseInteger) {
@@ -614,6 +826,22 @@
Tokenizer::ParseString("'\\", &output);
EXPECT_EQ("\\", output);
+ // Experiment with Unicode escapes. Here are one-, two- and three-byte Unicode
+ // characters.
+ Tokenizer::ParseString("'\\u0024\\u00a2\\u20ac\\U00024b62XX'", &output);
+ EXPECT_EQ("$¢€𤭢XX", output);
+ // Same thing encoded using UTF16.
+ Tokenizer::ParseString("'\\u0024\\u00a2\\u20ac\\ud852\\udf62XX'", &output);
+ EXPECT_EQ("$¢€𤭢XX", output);
+ // Here's some broken UTF16; there's a head surrogate with no tail surrogate.
+ // We just output this as if it were UTF8; it's not a defined code point, but
+ // it has a defined encoding.
+ Tokenizer::ParseString("'\\ud852XX'", &output);
+ EXPECT_EQ("\xed\xa1\x92XX", output);
+ // Malformed escape: Demons may fly out of the nose.
+ Tokenizer::ParseString("\\u0", &output);
+ EXPECT_EQ("u0", output);
+
// Test invalid strings that will never be tokenized as strings.
#ifdef GTEST_HAS_DEATH_TEST // death tests do not work on Windows yet
EXPECT_DEBUG_DEATH(Tokenizer::ParseString("", &output),
@@ -658,6 +886,12 @@
"0:4: String literals cannot cross line boundaries.\n" },
{ "'bar\nfoo", true,
"0:4: String literals cannot cross line boundaries.\n" },
+ { "'\\u01' foo", true,
+ "0:5: Expected four hex digits for \\u escape sequence.\n" },
+ { "'\\u01' foo", true,
+ "0:5: Expected four hex digits for \\u escape sequence.\n" },
+ { "'\\uXYZ' foo", true,
+ "0:3: Expected four hex digits for \\u escape sequence.\n" },
// Integer errors.
{ "123foo", true,
@@ -734,7 +968,7 @@
}
// Check that the errors match what was expected.
- EXPECT_EQ(error_collector.text_, kErrorCases_case.errors);
+ EXPECT_EQ(kErrorCases_case.errors, error_collector.text_);
// If the error was recoverable, make sure we saw "foo" after it.
if (kErrorCases_case.recoverable) {
@@ -760,6 +994,7 @@
EXPECT_EQ(strlen("foo"), input.ByteCount());
}
+
} // namespace
} // namespace io
} // namespace protobuf
diff --git a/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc b/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc
index 1384c74..9fcbb62 100644
--- a/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc
+++ b/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc
@@ -46,7 +46,8 @@
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
+
namespace google {
namespace protobuf {
diff --git a/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
index e801251..f552e1f 100644
--- a/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+++ b/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
@@ -32,9 +32,9 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
diff --git a/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_unittest.cc b/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_unittest.cc
index 5196d90..6f155df 100644
--- a/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -370,6 +370,100 @@
delete [] buffer;
}
+TEST_F(IoTest, GzipIoWithFlush) {
+ const int kBufferSize = 2*1024;
+ uint8* buffer = new uint8[kBufferSize];
+ // We start with i = 4 as we want a block size > 6. With block size <= 6
+ // Flush() fills up the entire 2K buffer with flush markers and the test
+ // fails. See documentation for Flush() for more detail.
+ for (int i = 4; i < kBlockSizeCount; i++) {
+ for (int j = 0; j < kBlockSizeCount; j++) {
+ for (int z = 0; z < kBlockSizeCount; z++) {
+ int gzip_buffer_size = kBlockSizes[z];
+ int size;
+ {
+ ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]);
+ GzipOutputStream::Options options;
+ options.format = GzipOutputStream::GZIP;
+ if (gzip_buffer_size != -1) {
+ options.buffer_size = gzip_buffer_size;
+ }
+ GzipOutputStream gzout(&output, options);
+ WriteStuff(&gzout);
+ EXPECT_TRUE(gzout.Flush());
+ gzout.Close();
+ size = output.ByteCount();
+ }
+ {
+ ArrayInputStream input(buffer, size, kBlockSizes[j]);
+ GzipInputStream gzin(
+ &input, GzipInputStream::GZIP, gzip_buffer_size);
+ ReadStuff(&gzin);
+ }
+ }
+ }
+ }
+ delete [] buffer;
+}
+
+TEST_F(IoTest, GzipIoContiguousFlushes) {
+ const int kBufferSize = 2*1024;
+ uint8* buffer = new uint8[kBufferSize];
+
+ int block_size = kBlockSizes[4];
+ int gzip_buffer_size = block_size;
+ int size;
+
+ ArrayOutputStream output(buffer, kBufferSize, block_size);
+ GzipOutputStream::Options options;
+ options.format = GzipOutputStream::GZIP;
+ if (gzip_buffer_size != -1) {
+ options.buffer_size = gzip_buffer_size;
+ }
+ GzipOutputStream gzout(&output, options);
+ WriteStuff(&gzout);
+ EXPECT_TRUE(gzout.Flush());
+ EXPECT_TRUE(gzout.Flush());
+ gzout.Close();
+ size = output.ByteCount();
+
+ ArrayInputStream input(buffer, size, block_size);
+ GzipInputStream gzin(
+ &input, GzipInputStream::GZIP, gzip_buffer_size);
+ ReadStuff(&gzin);
+
+ delete [] buffer;
+}
+
+TEST_F(IoTest, GzipIoReadAfterFlush) {
+ const int kBufferSize = 2*1024;
+ uint8* buffer = new uint8[kBufferSize];
+
+ int block_size = kBlockSizes[4];
+ int gzip_buffer_size = block_size;
+ int size;
+ ArrayOutputStream output(buffer, kBufferSize, block_size);
+ GzipOutputStream::Options options;
+ options.format = GzipOutputStream::GZIP;
+ if (gzip_buffer_size != -1) {
+ options.buffer_size = gzip_buffer_size;
+ }
+
+ GzipOutputStream gzout(&output, options);
+ WriteStuff(&gzout);
+ EXPECT_TRUE(gzout.Flush());
+ size = output.ByteCount();
+
+ ArrayInputStream input(buffer, size, block_size);
+ GzipInputStream gzin(
+ &input, GzipInputStream::GZIP, gzip_buffer_size);
+ ReadStuff(&gzin);
+
+ gzout.Close();
+
+ delete [] buffer;
+}
+
TEST_F(IoTest, ZlibIo) {
const int kBufferSize = 2*1024;
uint8* buffer = new uint8[kBufferSize];
diff --git a/third_party/protobuf/src/google/protobuf/lite_unittest.cc b/third_party/protobuf/src/google/protobuf/lite_unittest.cc
index ffeec3c..7a0a57b 100644
--- a/third_party/protobuf/src/google/protobuf/lite_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/lite_unittest.cc
@@ -33,11 +33,32 @@
#include <string>
#include <iostream>
-#include <google/protobuf/test_util_lite.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/test_util_lite.h>
+#include <google/protobuf/unittest_lite.pb.h>
using namespace std;
+namespace {
+// Helper methods to test parsing merge behavior.
+void ExpectMessageMerged(const google::protobuf::unittest::TestAllTypesLite& message) {
+ GOOGLE_CHECK(message.optional_int32() == 3);
+ GOOGLE_CHECK(message.optional_int64() == 2);
+ GOOGLE_CHECK(message.optional_string() == "hello");
+}
+
+void AssignParsingMergeMessages(
+ google::protobuf::unittest::TestAllTypesLite* msg1,
+ google::protobuf::unittest::TestAllTypesLite* msg2,
+ google::protobuf::unittest::TestAllTypesLite* msg3) {
+ msg1->set_optional_int32(1);
+ msg2->set_optional_int64(2);
+ msg3->set_optional_int32(3);
+ msg3->set_optional_string("hello");
+}
+
+} // namespace
+
int main(int argc, char* argv[]) {
string data, packed_data;
@@ -107,6 +128,58 @@
google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message);
}
+ {
+ // Test that if an optional or required message/group field appears multiple
+ // times in the input, they need to be merged.
+ google::protobuf::unittest::TestParsingMergeLite::RepeatedFieldsGenerator generator;
+ google::protobuf::unittest::TestAllTypesLite* msg1;
+ google::protobuf::unittest::TestAllTypesLite* msg2;
+ google::protobuf::unittest::TestAllTypesLite* msg3;
+
+#define ASSIGN_REPEATED_FIELD(FIELD) \
+ msg1 = generator.add_##FIELD(); \
+ msg2 = generator.add_##FIELD(); \
+ msg3 = generator.add_##FIELD(); \
+ AssignParsingMergeMessages(msg1, msg2, msg3)
+
+ ASSIGN_REPEATED_FIELD(field1);
+ ASSIGN_REPEATED_FIELD(field2);
+ ASSIGN_REPEATED_FIELD(field3);
+ ASSIGN_REPEATED_FIELD(ext1);
+ ASSIGN_REPEATED_FIELD(ext2);
+
+#undef ASSIGN_REPEATED_FIELD
+#define ASSIGN_REPEATED_GROUP(FIELD) \
+ msg1 = generator.add_##FIELD()->mutable_field1(); \
+ msg2 = generator.add_##FIELD()->mutable_field1(); \
+ msg3 = generator.add_##FIELD()->mutable_field1(); \
+ AssignParsingMergeMessages(msg1, msg2, msg3)
+
+ ASSIGN_REPEATED_GROUP(group1);
+ ASSIGN_REPEATED_GROUP(group2);
+
+#undef ASSIGN_REPEATED_GROUP
+
+ string buffer;
+ generator.SerializeToString(&buffer);
+ google::protobuf::unittest::TestParsingMergeLite parsing_merge;
+ parsing_merge.ParseFromString(buffer);
+
+ // Required and optional fields should be merged.
+ ExpectMessageMerged(parsing_merge.required_all_types());
+ ExpectMessageMerged(parsing_merge.optional_all_types());
+ ExpectMessageMerged(
+ parsing_merge.optionalgroup().optional_group_all_types());
+ ExpectMessageMerged(parsing_merge.GetExtension(
+ google::protobuf::unittest::TestParsingMergeLite::optional_ext));
+
+ // Repeated fields should not be merged.
+ GOOGLE_CHECK(parsing_merge.repeated_all_types_size() == 3);
+ GOOGLE_CHECK(parsing_merge.repeatedgroup_size() == 3);
+ GOOGLE_CHECK(parsing_merge.ExtensionSize(
+ google::protobuf::unittest::TestParsingMergeLite::repeated_ext) == 3);
+ }
+
cout << "PASS" << endl;
return 0;
}
diff --git a/third_party/protobuf/src/google/protobuf/message.cc b/third_party/protobuf/src/google/protobuf/message.cc
index 0409a94..ab7efa9 100644
--- a/third_party/protobuf/src/google/protobuf/message.cc
+++ b/third_party/protobuf/src/google/protobuf/message.cc
@@ -44,11 +44,12 @@
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/map-util.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
@@ -182,9 +183,46 @@
}
+// =============================================================================
+// Reflection and associated Template Specializations
+
Reflection::~Reflection() {}
-// ===================================================================
+#define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE) \
+template<> \
+const RepeatedField<TYPE>& Reflection::GetRepeatedField<TYPE>( \
+ const Message& message, const FieldDescriptor* field) const { \
+ return *static_cast<RepeatedField<TYPE>* >( \
+ MutableRawRepeatedField(const_cast<Message*>(&message), \
+ field, CPPTYPE, CTYPE, NULL)); \
+} \
+ \
+template<> \
+RepeatedField<TYPE>* Reflection::MutableRepeatedField<TYPE>( \
+ Message* message, const FieldDescriptor* field) const { \
+ return static_cast<RepeatedField<TYPE>* >( \
+ MutableRawRepeatedField(message, field, CPPTYPE, CTYPE, NULL)); \
+}
+
+HANDLE_TYPE(int32, FieldDescriptor::CPPTYPE_INT32, -1);
+HANDLE_TYPE(int64, FieldDescriptor::CPPTYPE_INT64, -1);
+HANDLE_TYPE(uint32, FieldDescriptor::CPPTYPE_UINT32, -1);
+HANDLE_TYPE(uint64, FieldDescriptor::CPPTYPE_UINT64, -1);
+HANDLE_TYPE(float, FieldDescriptor::CPPTYPE_FLOAT, -1);
+HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1);
+HANDLE_TYPE(bool, FieldDescriptor::CPPTYPE_BOOL, -1);
+
+
+#undef HANDLE_TYPE
+
+void* Reflection::MutableRawRepeatedString(
+ Message* message, const FieldDescriptor* field, bool is_string) const {
+ return MutableRawRepeatedField(message, field,
+ FieldDescriptor::CPPTYPE_STRING, FieldOptions::STRING, NULL);
+}
+
+
+// =============================================================================
// MessageFactory
MessageFactory::~MessageFactory() {}
@@ -258,6 +296,7 @@
}
}
+
const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) {
{
ReaderMutexLock lock(&mutex_);
diff --git a/third_party/protobuf/src/google/protobuf/message.h b/third_party/protobuf/src/google/protobuf/message.h
index 4bbc641..77faa9a 100644
--- a/third_party/protobuf/src/google/protobuf/message.h
+++ b/third_party/protobuf/src/google/protobuf/message.h
@@ -79,18 +79,19 @@
// // Same as the last block, but do it dynamically via the Message
// // reflection interface.
// Message* foo = new Foo;
-// Descriptor* descriptor = foo->GetDescriptor();
+// const Descriptor* descriptor = foo->GetDescriptor();
//
// // Get the descriptors for the fields we're interested in and verify
// // their types.
-// FieldDescriptor* text_field = descriptor->FindFieldByName("text");
+// const FieldDescriptor* text_field = descriptor->FindFieldByName("text");
// assert(text_field != NULL);
// assert(text_field->type() == FieldDescriptor::TYPE_STRING);
-// assert(text_field->label() == FieldDescriptor::TYPE_OPTIONAL);
-// FieldDescriptor* numbers_field = descriptor->FindFieldByName("numbers");
+// assert(text_field->label() == FieldDescriptor::LABEL_OPTIONAL);
+// const FieldDescriptor* numbers_field = descriptor->
+// FindFieldByName("numbers");
// assert(numbers_field != NULL);
// assert(numbers_field->type() == FieldDescriptor::TYPE_INT32);
-// assert(numbers_field->label() == FieldDescriptor::TYPE_REPEATED);
+// assert(numbers_field->label() == FieldDescriptor::LABEL_REPEATED);
//
// // Parse the message.
// foo->ParseFromString(data);
@@ -122,6 +123,7 @@
#include <google/protobuf/message_lite.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
namespace google {
@@ -133,17 +135,20 @@
class MessageFactory;
// Defined in other files.
-class Descriptor; // descriptor.h
-class FieldDescriptor; // descriptor.h
-class EnumDescriptor; // descriptor.h
-class EnumValueDescriptor; // descriptor.h
+class UnknownFieldSet; // unknown_field_set.h
namespace io {
class ZeroCopyInputStream; // zero_copy_stream.h
class ZeroCopyOutputStream; // zero_copy_stream.h
class CodedInputStream; // coded_stream.h
class CodedOutputStream; // coded_stream.h
}
-class UnknownFieldSet; // unknown_field_set.h
+
+
+template<typename T>
+class RepeatedField; // repeated_field.h
+
+template<typename T>
+class RepeatedPtrField; // repeated_field.h
// A container to hold message metadata.
struct Metadata {
@@ -151,12 +156,6 @@
const Reflection* reflection;
};
-// Returns the EnumDescriptor for enum type E, which must be a
-// proto-declared enum type. Code generated by the protocol compiler
-// will include specializations of this template for each enum type declared.
-template <typename E>
-const EnumDescriptor* GetEnumDescriptor();
-
// Abstract interface for protocol messages.
//
// See also MessageLite, which contains most every-day operations. Message
@@ -360,7 +359,6 @@
// write fields from a Reflection without paying attention to the type.
class LIBPROTOBUF_EXPORT Reflection {
public:
- // TODO(kenton): Remove parameter.
inline Reflection() {}
virtual ~Reflection();
@@ -390,7 +388,7 @@
virtual void ClearField(Message* message,
const FieldDescriptor* field) const = 0;
- // Remove the last element of a repeated field.
+ // Removes the last element of a repeated field.
// We don't provide a way to remove any element other than the last
// because it invites inefficient use, such as O(n^2) filtering loops
// that should have been O(n). If you want to remove an element other
@@ -399,6 +397,10 @@
// call RemoveLast().
virtual void RemoveLast(Message* message,
const FieldDescriptor* field) const = 0;
+ // Removes the last element of a repeated message field, and returns the
+ // pointer to the caller. Caller takes ownership of the returned pointer.
+ virtual Message* ReleaseLast(Message* message,
+ const FieldDescriptor* field) const = 0;
// Swap the complete contents of two messages.
virtual void Swap(Message* message1, Message* message2) const = 0;
@@ -500,6 +502,16 @@
virtual Message* MutableMessage(Message* message,
const FieldDescriptor* field,
MessageFactory* factory = NULL) const = 0;
+ // Releases the message specified by 'field' and returns the pointer,
+ // ReleaseMessage() will return the message the message object if it exists.
+ // Otherwise, it may or may not return NULL. In any case, if the return value
+ // is non-NULL, the caller takes ownership of the pointer.
+ // If the field existed (HasField() is true), then the returned pointer will
+ // be the same as the pointer returned by MutableMessage().
+ // This function has the same effect as ClearField().
+ virtual Message* ReleaseMessage(Message* message,
+ const FieldDescriptor* field,
+ MessageFactory* factory = NULL) const = 0;
// Repeated field getters ------------------------------------------
@@ -607,7 +619,39 @@
MessageFactory* factory = NULL) const = 0;
- // Extensions ------------------------------------------------------
+ // Repeated field accessors -------------------------------------------------
+ // The methods above, e.g. GetRepeatedInt32(msg, fd, index), provide singular
+ // access to the data in a RepeatedField. The methods below provide aggregate
+ // access by exposing the RepeatedField object itself with the Message.
+ // Applying these templates to inappropriate types will lead to an undefined
+ // reference at link time (e.g. GetRepeatedField<***double>), or possibly a
+ // template matching error at compile time (e.g. GetRepeatedPtrField<File>).
+ //
+ // Usage example: my_doubs = refl->GetRepeatedField<double>(msg, fd);
+
+ // for T = Cord and all protobuf scalar types except enums.
+ template<typename T>
+ const RepeatedField<T>& GetRepeatedField(
+ const Message&, const FieldDescriptor*) const;
+
+ // for T = Cord and all protobuf scalar types except enums.
+ template<typename T>
+ RepeatedField<T>* MutableRepeatedField(
+ Message*, const FieldDescriptor*) const;
+
+ // for T = string, google::protobuf::internal::StringPieceField
+ // google::protobuf::Message & descendants.
+ template<typename T>
+ const RepeatedPtrField<T>& GetRepeatedPtrField(
+ const Message&, const FieldDescriptor*) const;
+
+ // for T = string, google::protobuf::internal::StringPieceField
+ // google::protobuf::Message & descendants.
+ template<typename T>
+ RepeatedPtrField<T>* MutableRepeatedPtrField(
+ Message*, const FieldDescriptor*) const;
+
+ // Extensions ----------------------------------------------------------------
// Try to find an extension of this message type by fully-qualified field
// name. Returns NULL if no extension is known for this name or number.
@@ -619,7 +663,26 @@
virtual const FieldDescriptor* FindKnownExtensionByNumber(
int number) const = 0;
+ // ---------------------------------------------------------------------------
+
+ protected:
+ // Obtain a pointer to a Repeated Field Structure and do some type checking:
+ // on field->cpp_type(),
+ // on field->field_option().ctype() (if ctype >= 0)
+ // of field->message_type() (if message_type != NULL).
+ // We use 1 routine rather than 4 (const vs mutable) x (scalar vs pointer).
+ virtual void* MutableRawRepeatedField(
+ Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
+ int ctype, const Descriptor* message_type) const = 0;
+
private:
+ // Special version for specialized implementations of string. We can't call
+ // MutableRawRepeatedField directly here because we don't have access to
+ // FieldOptions::* which are defined in descriptor.pb.h. Including that
+ // file here is not possible because it would cause a circular include cycle.
+ void* MutableRawRepeatedString(
+ Message* message, const FieldDescriptor* field, bool is_string) const;
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reflection);
};
@@ -682,10 +745,71 @@
static void InternalRegisterGeneratedMessage(const Descriptor* descriptor,
const Message* prototype);
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFactory);
};
+// =============================================================================
+// Implementation details for {Get,Mutable}RawRepeatedPtrField. We provide
+// specializations for <string>, <StringPieceField> and <Message> and handle
+// everything else with the default template which will match any type having
+// a method with signature "static const google::protobuf::Descriptor* descriptor()".
+// Such a type presumably is a descendant of google::protobuf::Message.
+
+template<>
+inline const RepeatedPtrField<string>& Reflection::GetRepeatedPtrField<string>(
+ const Message& message, const FieldDescriptor* field) const {
+ return *static_cast<RepeatedPtrField<string>* >(
+ MutableRawRepeatedString(const_cast<Message*>(&message), field, true));
+}
+
+template<>
+inline RepeatedPtrField<string>* Reflection::MutableRepeatedPtrField<string>(
+ Message* message, const FieldDescriptor* field) const {
+ return static_cast<RepeatedPtrField<string>* >(
+ MutableRawRepeatedString(message, field, true));
+}
+
+
+// -----
+
+template<>
+inline const RepeatedPtrField<Message>& Reflection::GetRepeatedPtrField(
+ const Message& message, const FieldDescriptor* field) const {
+ return *static_cast<RepeatedPtrField<Message>* >(
+ MutableRawRepeatedField(const_cast<Message*>(&message), field,
+ FieldDescriptor::CPPTYPE_MESSAGE, -1,
+ NULL));
+}
+
+template<>
+inline RepeatedPtrField<Message>* Reflection::MutableRepeatedPtrField(
+ Message* message, const FieldDescriptor* field) const {
+ return static_cast<RepeatedPtrField<Message>* >(
+ MutableRawRepeatedField(message, field,
+ FieldDescriptor::CPPTYPE_MESSAGE, -1,
+ NULL));
+}
+
+template<typename PB>
+inline const RepeatedPtrField<PB>& Reflection::GetRepeatedPtrField(
+ const Message& message, const FieldDescriptor* field) const {
+ return *static_cast<RepeatedPtrField<PB>* >(
+ MutableRawRepeatedField(const_cast<Message*>(&message), field,
+ FieldDescriptor::CPPTYPE_MESSAGE, -1,
+ PB::default_instance().GetDescriptor()));
+}
+
+template<typename PB>
+inline RepeatedPtrField<PB>* Reflection::MutableRepeatedPtrField(
+ Message* message, const FieldDescriptor* field) const {
+ return static_cast<RepeatedPtrField<PB>* >(
+ MutableRawRepeatedField(message, field,
+ FieldDescriptor::CPPTYPE_MESSAGE, -1,
+ PB::default_instance().GetDescriptor()));
+}
+
} // namespace protobuf
} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/message_lite.cc b/third_party/protobuf/src/google/protobuf/message_lite.cc
index 7c8f37d..49dbe6e 100644
--- a/third_party/protobuf/src/google/protobuf/message_lite.cc
+++ b/third_party/protobuf/src/google/protobuf/message_lite.cc
@@ -37,8 +37,8 @@
#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
diff --git a/third_party/protobuf/src/google/protobuf/message_lite.h b/third_party/protobuf/src/google/protobuf/message_lite.h
index ebf4ba3..1ec3068 100644
--- a/third_party/protobuf/src/google/protobuf/message_lite.h
+++ b/third_party/protobuf/src/google/protobuf/message_lite.h
@@ -40,11 +40,17 @@
#define GOOGLE_PROTOBUF_MESSAGE_LITE_H__
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/coded_stream.h>
namespace google {
namespace protobuf {
+namespace io {
+ class CodedInputStream;
+ class CodedOutputStream;
+ class ZeroCopyInputStream;
+ class ZeroCopyOutputStream;
+}
+
// Interface to light weight protocol messages.
//
// This interface is implemented by all protocol message objects. Non-lite
@@ -158,6 +164,7 @@
// followed by IsInitialized().
virtual bool MergePartialFromCodedStream(io::CodedInputStream* input) = 0;
+
// Serialization ---------------------------------------------------
// Methods for serializing in protocol buffer format. Most of these
// are just simple wrappers around ByteSize() and SerializeWithCachedSizes().
diff --git a/third_party/protobuf/src/google/protobuf/message_unittest.cc b/third_party/protobuf/src/google/protobuf/message_unittest.cc
index 33b9e77..8aaeabb 100644
--- a/third_party/protobuf/src/google/protobuf/message_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/message_unittest.cc
@@ -257,6 +257,78 @@
EXPECT_FALSE(message.ParseFromArray("\014", 1));
}
+namespace {
+
+void ExpectMessageMerged(const unittest::TestAllTypes& message) {
+ EXPECT_EQ(3, message.optional_int32());
+ EXPECT_EQ(2, message.optional_int64());
+ EXPECT_EQ("hello", message.optional_string());
+}
+
+void AssignParsingMergeMessages(
+ unittest::TestAllTypes* msg1,
+ unittest::TestAllTypes* msg2,
+ unittest::TestAllTypes* msg3) {
+ msg1->set_optional_int32(1);
+ msg2->set_optional_int64(2);
+ msg3->set_optional_int32(3);
+ msg3->set_optional_string("hello");
+}
+
+} // namespace
+
+// Test that if an optional or required message/group field appears multiple
+// times in the input, they need to be merged.
+TEST(MessageTest, ParsingMerge) {
+ unittest::TestParsingMerge::RepeatedFieldsGenerator generator;
+ unittest::TestAllTypes* msg1;
+ unittest::TestAllTypes* msg2;
+ unittest::TestAllTypes* msg3;
+
+#define ASSIGN_REPEATED_FIELD(FIELD) \
+ msg1 = generator.add_##FIELD(); \
+ msg2 = generator.add_##FIELD(); \
+ msg3 = generator.add_##FIELD(); \
+ AssignParsingMergeMessages(msg1, msg2, msg3)
+
+ ASSIGN_REPEATED_FIELD(field1);
+ ASSIGN_REPEATED_FIELD(field2);
+ ASSIGN_REPEATED_FIELD(field3);
+ ASSIGN_REPEATED_FIELD(ext1);
+ ASSIGN_REPEATED_FIELD(ext2);
+
+#undef ASSIGN_REPEATED_FIELD
+#define ASSIGN_REPEATED_GROUP(FIELD) \
+ msg1 = generator.add_##FIELD()->mutable_field1(); \
+ msg2 = generator.add_##FIELD()->mutable_field1(); \
+ msg3 = generator.add_##FIELD()->mutable_field1(); \
+ AssignParsingMergeMessages(msg1, msg2, msg3)
+
+ ASSIGN_REPEATED_GROUP(group1);
+ ASSIGN_REPEATED_GROUP(group2);
+
+#undef ASSIGN_REPEATED_GROUP
+
+ string buffer;
+ generator.SerializeToString(&buffer);
+ unittest::TestParsingMerge parsing_merge;
+ parsing_merge.ParseFromString(buffer);
+
+ // Required and optional fields should be merged.
+ ExpectMessageMerged(parsing_merge.required_all_types());
+ ExpectMessageMerged(parsing_merge.optional_all_types());
+ ExpectMessageMerged(
+ parsing_merge.optionalgroup().optional_group_all_types());
+ ExpectMessageMerged(
+ parsing_merge.GetExtension(unittest::TestParsingMerge::optional_ext));
+
+ // Repeated fields should not be merged.
+ EXPECT_EQ(3, parsing_merge.repeated_all_types_size());
+ EXPECT_EQ(3, parsing_merge.repeatedgroup_size());
+ EXPECT_EQ(3, parsing_merge.ExtensionSize(
+ unittest::TestParsingMerge::repeated_ext));
+}
+
TEST(MessageFactoryTest, GeneratedFactoryLookup) {
EXPECT_EQ(
MessageFactory::generated_factory()->GetPrototype(
@@ -277,5 +349,6 @@
MessageFactory::generated_factory()->GetPrototype(descriptor) == NULL);
}
+
} // namespace protobuf
} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/reflection_ops.cc b/third_party/protobuf/src/google/protobuf/reflection_ops.cc
index 897c0d7..f00997c 100644
--- a/third_party/protobuf/src/google/protobuf/reflection_ops.cc
+++ b/third_party/protobuf/src/google/protobuf/reflection_ops.cc
@@ -32,8 +32,12 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <string>
+#include <vector>
+
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/stubs/strutil.h>
@@ -151,11 +155,12 @@
for (int i = 0; i < fields.size(); i++) {
const FieldDescriptor* field = fields[i];
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+
if (field->is_repeated()) {
int size = reflection->FieldSize(message, field);
- for (int i = 0; i < size; i++) {
- if (!reflection->GetRepeatedMessage(message, field, i)
+ for (int j = 0; j < size; j++) {
+ if (!reflection->GetRepeatedMessage(message, field, j)
.IsInitialized()) {
return false;
}
@@ -183,8 +188,8 @@
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (field->is_repeated()) {
int size = reflection->FieldSize(*message, field);
- for (int i = 0; i < size; i++) {
- reflection->MutableRepeatedMessage(message, field, i)
+ for (int j = 0; j < size; j++) {
+ reflection->MutableRepeatedMessage(message, field, j)
->DiscardUnknownFields();
}
} else {
@@ -240,11 +245,11 @@
if (field->is_repeated()) {
int size = reflection->FieldSize(message, field);
- for (int i = 0; i < size; i++) {
+ for (int j = 0; j < size; j++) {
const Message& sub_message =
- reflection->GetRepeatedMessage(message, field, i);
+ reflection->GetRepeatedMessage(message, field, j);
FindInitializationErrors(sub_message,
- SubMessagePrefix(prefix, field, i),
+ SubMessagePrefix(prefix, field, j),
errors);
}
} else {
diff --git a/third_party/protobuf/src/google/protobuf/reflection_ops.h b/third_party/protobuf/src/google/protobuf/reflection_ops.h
index 355a0a5..60165c2 100644
--- a/third_party/protobuf/src/google/protobuf/reflection_ops.h
+++ b/third_party/protobuf/src/google/protobuf/reflection_ops.h
@@ -38,6 +38,7 @@
#ifndef GOOGLE_PROTOBUF_REFLECTION_OPS_H__
#define GOOGLE_PROTOBUF_REFLECTION_OPS_H__
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message.h>
namespace google {
diff --git a/third_party/protobuf/src/google/protobuf/repeated_field.cc b/third_party/protobuf/src/google/protobuf/repeated_field.cc
index 0937774..2c1f74c 100644
--- a/third_party/protobuf/src/google/protobuf/repeated_field.cc
+++ b/third_party/protobuf/src/google/protobuf/repeated_field.cc
@@ -46,42 +46,31 @@
if (total_size_ >= new_size) return;
void** old_elements = elements_;
- total_size_ = max(total_size_ * 2, new_size);
+ total_size_ = max(kMinRepeatedFieldAllocationSize,
+ max(total_size_ * 2, new_size));
elements_ = new void*[total_size_];
- memcpy(elements_, old_elements, allocated_size_ * sizeof(elements_[0]));
- if (old_elements != initial_space_) {
+ if (old_elements != NULL) {
+ memcpy(elements_, old_elements, allocated_size_ * sizeof(elements_[0]));
delete [] old_elements;
}
}
void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) {
+ if (this == other) return;
void** swap_elements = elements_;
int swap_current_size = current_size_;
int swap_allocated_size = allocated_size_;
int swap_total_size = total_size_;
- // We may not be using initial_space_ but it's not worth checking. Just
- // copy it anyway.
- void* swap_initial_space[kInitialSize];
- memcpy(swap_initial_space, initial_space_, sizeof(initial_space_));
elements_ = other->elements_;
current_size_ = other->current_size_;
allocated_size_ = other->allocated_size_;
total_size_ = other->total_size_;
- memcpy(initial_space_, other->initial_space_, sizeof(initial_space_));
other->elements_ = swap_elements;
other->current_size_ = swap_current_size;
other->allocated_size_ = swap_allocated_size;
other->total_size_ = swap_total_size;
- memcpy(other->initial_space_, swap_initial_space, sizeof(swap_initial_space));
-
- if (elements_ == other->initial_space_) {
- elements_ = initial_space_;
- }
- if (other->elements_ == initial_space_) {
- other->elements_ = other->initial_space_;
- }
}
string* StringTypeHandlerBase::New() {
diff --git a/third_party/protobuf/src/google/protobuf/repeated_field.h b/third_party/protobuf/src/google/protobuf/repeated_field.h
index aed4ce9..b9db2b6 100644
--- a/third_party/protobuf/src/google/protobuf/repeated_field.h
+++ b/third_party/protobuf/src/google/protobuf/repeated_field.h
@@ -46,24 +46,35 @@
#ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_H__
#define GOOGLE_PROTOBUF_REPEATED_FIELD_H__
+#include <algorithm>
#include <string>
#include <iterator>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/type_traits.h>
+#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/message_lite.h>
namespace google {
+namespace upb {
+namespace proto2_bridge_opensource {
+class FieldAccessor;
+} // namespace protobuf_bridge_opensource
+} // namespace upb
+
namespace protobuf {
class Message;
namespace internal {
-// We need this (from generated_message_reflection.cc).
-LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
+static const int kMinRepeatedFieldAllocationSize = 4;
+// A utility function for logging that doesn't need any template types.
+void LogIndexOutOfBounds(int index, int size);
} // namespace internal
+
// RepeatedField is used to represent repeated fields of a primitive type (in
// other words, everything except strings and nested Messages). Most users will
// not ever use a RepeatedField directly; they will use the get-by-index,
@@ -73,6 +84,8 @@
public:
RepeatedField();
RepeatedField(const RepeatedField& other);
+ template <typename Iter>
+ RepeatedField(Iter begin, const Iter& end);
~RepeatedField();
RepeatedField& operator=(const RepeatedField& other);
@@ -85,12 +98,14 @@
void Add(const Element& value);
Element* Add();
// Remove the last element in the array.
- // We don't provide a way to remove any element other than the last
- // because it invites inefficient use, such as O(n^2) filtering loops
- // that should have been O(n). If you want to remove an element other
- // than the last, the best way to do it is to re-arrange the elements
- // so that the one you want removed is at the end, then call RemoveLast().
void RemoveLast();
+
+ // Extract elements with indices in "[start .. start+num-1]".
+ // Copy them into "elements[0 .. num-1]" if "elements" is not NULL.
+ // Caution: implementation also moves elements with indices [start+num ..].
+ // Calling this routine inside a loop can cause quadratic behavior.
+ void ExtractSubrange(int start, int num, Element* elements);
+
void Clear();
void MergeFrom(const RepeatedField& other);
void CopyFrom(const RepeatedField& other);
@@ -121,25 +136,45 @@
typedef Element* iterator;
typedef const Element* const_iterator;
typedef Element value_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef int size_type;
+ typedef ptrdiff_t difference_type;
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
+ // Reverse iterator support
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ reverse_iterator rbegin() {
+ return reverse_iterator(end());
+ }
+ const_reverse_iterator rbegin() const {
+ return const_reverse_iterator(end());
+ }
+ reverse_iterator rend() {
+ return reverse_iterator(begin());
+ }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(begin());
+ }
+
// Returns the number of bytes used by the repeated field, excluding
// sizeof(*this)
int SpaceUsedExcludingSelf() const;
private:
- static const int kInitialSize = 4;
+ static const int kInitialSize = 0;
Element* elements_;
int current_size_;
int total_size_;
- Element initial_space_[kInitialSize];
-
// Move the contents of |from| into |to|, possibly clobbering |from| in the
// process. For primitive types this is just a memcpy(), but it could be
// specialized for non-primitive types to, say, swap each element instead.
@@ -151,7 +186,21 @@
namespace internal {
template <typename It> class RepeatedPtrIterator;
-template <typename It> class RepeatedPtrOverPtrsIterator;
+template <typename It, typename VoidPtr> class RepeatedPtrOverPtrsIterator;
+} // namespace internal
+
+namespace internal {
+
+// This is a helper template to copy an array of elements effeciently when they
+// have a trivial copy constructor, and correctly otherwise. This really
+// shouldn't be necessary, but our compiler doesn't optimize std::copy very
+// effectively.
+template <typename Element,
+ bool HasTrivialCopy = has_trivial_copy<Element>::value>
+struct ElementCopier {
+ void operator()(Element to[], const Element from[], int array_size);
+};
+
} // namespace internal
namespace internal {
@@ -186,6 +235,10 @@
// use of AddFromCleared(), which is not part of the public interface.
friend class ExtensionSet;
+ // To parse directly into a proto2 generated class, the upb FieldAccessor
+ // needs to be able to modify a RepeatedPtrFieldBase directly.
+ friend class LIBPROTOBUF_EXPORT upb::proto2_bridge_opensource::FieldAccessor;
+
RepeatedPtrFieldBase();
// Must be called from destructor.
@@ -209,6 +262,14 @@
template <typename TypeHandler>
void CopyFrom(const RepeatedPtrFieldBase& other);
+ void CloseGap(int start, int num) {
+ // Close up a gap of "num" elements starting at offset "start".
+ for (int i = start + num; i < allocated_size_; ++i)
+ elements_[i - num] = elements_[i];
+ current_size_ -= num;
+ allocated_size_ -= num;
+ }
+
void Reserve(int new_size);
int Capacity() const;
@@ -250,15 +311,13 @@
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase);
- static const int kInitialSize = 4;
+ static const int kInitialSize = 0;
void** elements_;
int current_size_;
int allocated_size_;
int total_size_;
- void* initial_space_[kInitialSize];
-
template <typename TypeHandler>
static inline typename TypeHandler::Type* cast(void* element) {
return reinterpret_cast<typename TypeHandler::Type*>(element);
@@ -280,6 +339,7 @@
to->MergeFrom(from);
}
static int SpaceUsed(const GenericType& value) { return value.SpaceUsed(); }
+ static const Type& default_instance() { return Type::default_instance(); }
};
template <>
@@ -288,6 +348,25 @@
to->CheckTypeAndMergeFrom(from);
}
+template <>
+inline const MessageLite& GenericTypeHandler<MessageLite>::default_instance() {
+ // Yes, the behavior of the code is undefined, but this function is only
+ // called when we're already deep into the world of undefined, because the
+ // caller called Get(index) out of bounds.
+ MessageLite* null = NULL;
+ return *null;
+}
+
+template <>
+inline const Message& GenericTypeHandler<Message>::default_instance() {
+ // Yes, the behavior of the code is undefined, but this function is only
+ // called when we're already deep into the world of undefined, because the
+ // caller called Get(index) out of bounds.
+ Message* null = NULL;
+ return *null;
+}
+
+
// HACK: If a class is declared as DLL-exported in MSVC, it insists on
// generating copies of all its methods -- even inline ones -- to include
// in the DLL. But SpaceUsed() calls StringSpaceUsedExcludingSelf() which
@@ -303,6 +382,9 @@
static void Delete(string* value);
static void Clear(string* value) { value->clear(); }
static void Merge(const string& from, string* to) { *to = from; }
+ static const Type& default_instance() {
+ return ::google::protobuf::internal::kEmptyString;
+ }
};
class StringTypeHandler : public StringTypeHandlerBase {
@@ -322,6 +404,8 @@
public:
RepeatedPtrField();
RepeatedPtrField(const RepeatedPtrField& other);
+ template <typename Iter>
+ RepeatedPtrField(Iter begin, const Iter& end);
~RepeatedPtrField();
RepeatedPtrField& operator=(const RepeatedPtrField& other);
@@ -331,7 +415,16 @@
const Element& Get(int index) const;
Element* Mutable(int index);
Element* Add();
- void RemoveLast(); // Remove the last element in the array.
+
+ // Remove the last element in the array.
+ // Ownership of the element is retained by the array.
+ void RemoveLast();
+
+ // Delete elements with indices in the range [start .. start+num-1].
+ // Caution: implementation moves all elements with indices [start+num .. ].
+ // Calling this routine inside a loop can cause quadratic behavior.
+ void DeleteSubrange(int start, int num);
+
void Clear();
void MergeFrom(const RepeatedPtrField& other);
void CopyFrom(const RepeatedPtrField& other);
@@ -358,42 +451,78 @@
typedef internal::RepeatedPtrIterator<Element> iterator;
typedef internal::RepeatedPtrIterator<const Element> const_iterator;
typedef Element value_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef int size_type;
+ typedef ptrdiff_t difference_type;
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
+ // Reverse iterator support
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ reverse_iterator rbegin() {
+ return reverse_iterator(end());
+ }
+ const_reverse_iterator rbegin() const {
+ return const_reverse_iterator(end());
+ }
+ reverse_iterator rend() {
+ return reverse_iterator(begin());
+ }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(begin());
+ }
+
// Custom STL-like iterator that iterates over and returns the underlying
// pointers to Element rather than Element itself.
- typedef internal::RepeatedPtrOverPtrsIterator<Element> pointer_iterator;
+ typedef internal::RepeatedPtrOverPtrsIterator<Element, void*>
+ pointer_iterator;
+ typedef internal::RepeatedPtrOverPtrsIterator<const Element, const void*>
+ const_pointer_iterator;
pointer_iterator pointer_begin();
+ const_pointer_iterator pointer_begin() const;
pointer_iterator pointer_end();
+ const_pointer_iterator pointer_end() const;
// Returns (an estimate of) the number of bytes used by the repeated field,
// excluding sizeof(*this).
int SpaceUsedExcludingSelf() const;
// Advanced memory management --------------------------------------
- // When hardcore memory management becomes necessary -- as it often
+ // When hardcore memory management becomes necessary -- as it sometimes
// does here at Google -- the following methods may be useful.
// Add an already-allocated object, passing ownership to the
// RepeatedPtrField.
void AddAllocated(Element* value);
- // Remove the last element and return it, passing ownership to the
- // caller.
+ // Remove the last element and return it, passing ownership to the caller.
// Requires: size() > 0
Element* ReleaseLast();
+ // Extract elements with indices in the range "[start .. start+num-1]".
+ // The caller assumes ownership of the extracted elements and is responsible
+ // for deleting them when they are no longer needed.
+ // If "elements" is non-NULL, then pointers to the extracted elements
+ // are stored in "elements[0 .. num-1]" for the convenience of the caller.
+ // If "elements" is NULL, then the caller must use some other mechanism
+ // to perform any further operations (like deletion) on these elements.
+ // Caution: implementation also moves elements with indices [start+num ..].
+ // Calling this routine inside a loop can cause quadratic behavior.
+ void ExtractSubrange(int start, int num, Element** elements);
+
// When elements are removed by calls to RemoveLast() or Clear(), they
// are not actually freed. Instead, they are cleared and kept so that
// they can be reused later. This can save lots of CPU time when
// repeatedly reusing a protocol message for similar purposes.
//
- // Really, extremely hardcore programs may actually want to manipulate
- // these objects to better-optimize memory management. These methods
- // allow that.
+ // Hardcore programs may choose to manipulate these cleared objects
+ // to better optimize memory management using the following routines.
// Get the number of cleared objects that are currently being kept
// around for reuse.
@@ -420,30 +549,40 @@
template <typename Element>
inline RepeatedField<Element>::RepeatedField()
- : elements_(initial_space_),
+ : elements_(NULL),
current_size_(0),
total_size_(kInitialSize) {
}
template <typename Element>
inline RepeatedField<Element>::RepeatedField(const RepeatedField& other)
- : elements_(initial_space_),
+ : elements_(NULL),
current_size_(0),
total_size_(kInitialSize) {
CopyFrom(other);
}
template <typename Element>
-RepeatedField<Element>::~RepeatedField() {
- if (elements_ != initial_space_) {
- delete [] elements_;
+template <typename Iter>
+inline RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end)
+ : elements_(NULL),
+ current_size_(0),
+ total_size_(kInitialSize) {
+ for (; begin != end; ++begin) {
+ Add(*begin);
}
}
template <typename Element>
+RepeatedField<Element>::~RepeatedField() {
+ delete [] elements_;
+}
+
+template <typename Element>
inline RepeatedField<Element>&
RepeatedField<Element>::operator=(const RepeatedField& other) {
- CopyFrom(other);
+ if (this != &other)
+ CopyFrom(other);
return *this;
}
@@ -506,15 +645,38 @@
}
template <typename Element>
+void RepeatedField<Element>::ExtractSubrange(
+ int start, int num, Element* elements) {
+ GOOGLE_DCHECK_GE(start, 0);
+ GOOGLE_DCHECK_GE(num, 0);
+ GOOGLE_DCHECK_LE(start + num, this->size());
+
+ // Save the values of the removed elements if requested.
+ if (elements != NULL) {
+ for (int i = 0; i < num; ++i)
+ elements[i] = this->Get(i + start);
+ }
+
+ // Slide remaining elements down to fill the gap.
+ if (num > 0) {
+ for (int i = start + num; i < this->size(); ++i)
+ this->Set(i - num, this->Get(i));
+ this->Truncate(this->size() - num);
+ }
+}
+
+template <typename Element>
inline void RepeatedField<Element>::Clear() {
current_size_ = 0;
}
template <typename Element>
inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) {
- Reserve(current_size_ + other.current_size_);
- CopyArray(elements_ + current_size_, other.elements_, other.current_size_);
- current_size_ += other.current_size_;
+ if (other.current_size_ != 0) {
+ Reserve(current_size_ + other.current_size_);
+ CopyArray(elements_ + current_size_, other.elements_, other.current_size_);
+ current_size_ += other.current_size_;
+ }
}
template <typename Element>
@@ -536,30 +698,18 @@
template <typename Element>
void RepeatedField<Element>::Swap(RepeatedField* other) {
+ if (this == other) return;
Element* swap_elements = elements_;
int swap_current_size = current_size_;
int swap_total_size = total_size_;
- // We may not be using initial_space_ but it's not worth checking. Just
- // copy it anyway.
- Element swap_initial_space[kInitialSize];
- MoveArray(swap_initial_space, initial_space_, kInitialSize);
elements_ = other->elements_;
current_size_ = other->current_size_;
total_size_ = other->total_size_;
- MoveArray(initial_space_, other->initial_space_, kInitialSize);
other->elements_ = swap_elements;
other->current_size_ = swap_current_size;
other->total_size_ = swap_total_size;
- MoveArray(other->initial_space_, swap_initial_space, kInitialSize);
-
- if (elements_ == other->initial_space_) {
- elements_ = initial_space_;
- }
- if (other->elements_ == initial_space_) {
- other->elements_ = other->initial_space_;
- }
}
template <typename Element>
@@ -590,20 +740,21 @@
template <typename Element>
inline int RepeatedField<Element>::SpaceUsedExcludingSelf() const {
- return (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0;
+ return (elements_ != NULL) ? total_size_ * sizeof(elements_[0]) : 0;
}
-// Avoid inlining of Reserve(): new, memcpy, and delete[] lead to a significant
+// Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant
// amount of code bloat.
template <typename Element>
void RepeatedField<Element>::Reserve(int new_size) {
if (total_size_ >= new_size) return;
Element* old_elements = elements_;
- total_size_ = max(total_size_ * 2, new_size);
+ total_size_ = max(google::protobuf::internal::kMinRepeatedFieldAllocationSize,
+ max(total_size_ * 2, new_size));
elements_ = new Element[total_size_];
- MoveArray(elements_, old_elements, current_size_);
- if (old_elements != initial_space_) {
+ if (old_elements != NULL) {
+ MoveArray(elements_, old_elements, current_size_);
delete [] old_elements;
}
}
@@ -617,22 +768,39 @@
template <typename Element>
inline void RepeatedField<Element>::MoveArray(
Element to[], Element from[], int array_size) {
- memcpy(to, from, array_size * sizeof(Element));
+ CopyArray(to, from, array_size);
}
template <typename Element>
inline void RepeatedField<Element>::CopyArray(
Element to[], const Element from[], int array_size) {
- memcpy(to, from, array_size * sizeof(Element));
+ internal::ElementCopier<Element>()(to, from, array_size);
}
+namespace internal {
+
+template <typename Element, bool HasTrivialCopy>
+void ElementCopier<Element, HasTrivialCopy>::operator()(
+ Element to[], const Element from[], int array_size) {
+ std::copy(from, from + array_size, to);
+}
+
+template <typename Element>
+struct ElementCopier<Element, true> {
+ void operator()(Element to[], const Element from[], int array_size) {
+ memcpy(to, from, array_size * sizeof(Element));
+ }
+};
+
+} // namespace internal
+
// -------------------------------------------------------------------
namespace internal {
inline RepeatedPtrFieldBase::RepeatedPtrFieldBase()
- : elements_(initial_space_),
+ : elements_(NULL),
current_size_(0),
allocated_size_(0),
total_size_(kInitialSize) {
@@ -643,16 +811,13 @@
for (int i = 0; i < allocated_size_; i++) {
TypeHandler::Delete(cast<TypeHandler>(elements_[i]));
}
- if (elements_ != initial_space_) {
- delete [] elements_;
- }
+ delete [] elements_;
}
inline int RepeatedPtrFieldBase::size() const {
return current_size_;
}
-
template <typename TypeHandler>
inline const typename TypeHandler::Type&
RepeatedPtrFieldBase::Get(int index) const {
@@ -660,6 +825,7 @@
return *cast<TypeHandler>(elements_[index]);
}
+
template <typename TypeHandler>
inline typename TypeHandler::Type*
RepeatedPtrFieldBase::Mutable(int index) {
@@ -741,7 +907,7 @@
template <typename TypeHandler>
inline int RepeatedPtrFieldBase::SpaceUsedExcludingSelf() const {
int allocated_bytes =
- (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0;
+ (elements_ != NULL) ? total_size_ * sizeof(elements_[0]) : 0;
for (int i = 0; i < allocated_size_; ++i) {
allocated_bytes += TypeHandler::SpaceUsed(*cast<TypeHandler>(elements_[i]));
}
@@ -798,7 +964,6 @@
return result;
}
-
inline int RepeatedPtrFieldBase::ClearedCount() const {
return allocated_size_ - current_size_;
}
@@ -822,11 +987,13 @@
template <typename Element>
class RepeatedPtrField<Element>::TypeHandler
- : public internal::GenericTypeHandler<Element> {};
+ : public internal::GenericTypeHandler<Element> {
+};
template <>
class RepeatedPtrField<string>::TypeHandler
- : public internal::StringTypeHandler {};
+ : public internal::StringTypeHandler {
+};
template <typename Element>
@@ -839,6 +1006,15 @@
}
template <typename Element>
+template <typename Iter>
+inline RepeatedPtrField<Element>::RepeatedPtrField(
+ Iter begin, const Iter& end) {
+ for (; begin != end; ++begin) {
+ *Add() = *begin;
+ }
+}
+
+template <typename Element>
RepeatedPtrField<Element>::~RepeatedPtrField() {
Destroy<TypeHandler>();
}
@@ -846,7 +1022,8 @@
template <typename Element>
inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=(
const RepeatedPtrField& other) {
- CopyFrom(other);
+ if (this != &other)
+ CopyFrom(other);
return *this;
}
@@ -860,6 +1037,7 @@
return RepeatedPtrFieldBase::Get<TypeHandler>(index);
}
+
template <typename Element>
inline Element* RepeatedPtrField<Element>::Mutable(int index) {
return RepeatedPtrFieldBase::Mutable<TypeHandler>(index);
@@ -876,6 +1054,33 @@
}
template <typename Element>
+inline void RepeatedPtrField<Element>::DeleteSubrange(int start, int num) {
+ GOOGLE_DCHECK_GE(start, 0);
+ GOOGLE_DCHECK_GE(num, 0);
+ GOOGLE_DCHECK_LE(start + num, size());
+ for (int i = 0; i < num; ++i)
+ delete RepeatedPtrFieldBase::Mutable<TypeHandler>(start + i);
+ ExtractSubrange(start, num, NULL);
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::ExtractSubrange(
+ int start, int num, Element** elements) {
+ GOOGLE_DCHECK_GE(start, 0);
+ GOOGLE_DCHECK_GE(num, 0);
+ GOOGLE_DCHECK_LE(start + num, size());
+
+ if (num > 0) {
+ // Save the values of the removed elements if requested.
+ if (elements != NULL) {
+ for (int i = 0; i < num; ++i)
+ elements[i] = RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
+ }
+ CloseGap(start, num);
+ }
+}
+
+template <typename Element>
inline void RepeatedPtrField<Element>::Clear() {
RepeatedPtrFieldBase::Clear<TypeHandler>();
}
@@ -961,7 +1166,7 @@
// refer to this class directly; use RepeatedPtrField<T>::iterator instead.
//
// The iterator for RepeatedPtrField<T>, RepeatedPtrIterator<T>, is
-// very similar to iterator_ptr<T**> in util/gtl/iterator_adaptors-inl.h,
+// very similar to iterator_ptr<T**> in util/gtl/iterator_adaptors.h,
// but adds random-access operators and is modified to wrap a void** base
// iterator (since RepeatedPtrField stores its array as a void* array and
// casting void** to T** would violate C++ aliasing rules).
@@ -1057,11 +1262,14 @@
// rather than the objects themselves as RepeatedPtrIterator does.
// Consider using this when working with stl algorithms that change
// the array.
-template<typename Element>
+// The VoidPtr template parameter holds the type-agnostic pointer value
+// referenced by the iterator. It should either be "void *" for a mutable
+// iterator, or "const void *" for a constant iterator.
+template<typename Element, typename VoidPtr>
class RepeatedPtrOverPtrsIterator
: public std::iterator<std::random_access_iterator_tag, Element*> {
public:
- typedef RepeatedPtrOverPtrsIterator<Element> iterator;
+ typedef RepeatedPtrOverPtrsIterator<Element, VoidPtr> iterator;
typedef std::iterator<
std::random_access_iterator_tag, Element*> superclass;
@@ -1072,7 +1280,7 @@
typedef typename superclass::difference_type difference_type;
RepeatedPtrOverPtrsIterator() : it_(NULL) {}
- explicit RepeatedPtrOverPtrsIterator(void** it) : it_(it) {}
+ explicit RepeatedPtrOverPtrsIterator(VoidPtr* it) : it_(it) {}
// dereferenceable
reference operator*() const { return *reinterpret_cast<Element**>(it_); }
@@ -1127,10 +1335,9 @@
friend class RepeatedPtrIterator;
// The internal iterator.
- void** it_;
+ VoidPtr* it_;
};
-
} // namespace internal
template <typename Element>
@@ -1160,10 +1367,21 @@
return pointer_iterator(raw_mutable_data());
}
template <typename Element>
+inline typename RepeatedPtrField<Element>::const_pointer_iterator
+RepeatedPtrField<Element>::pointer_begin() const {
+ return const_pointer_iterator(const_cast<const void**>(raw_mutable_data()));
+}
+template <typename Element>
inline typename RepeatedPtrField<Element>::pointer_iterator
RepeatedPtrField<Element>::pointer_end() {
return pointer_iterator(raw_mutable_data() + size());
}
+template <typename Element>
+inline typename RepeatedPtrField<Element>::const_pointer_iterator
+RepeatedPtrField<Element>::pointer_end() const {
+ return const_pointer_iterator(
+ const_cast<const void**>(raw_mutable_data() + size()));
+}
// Iterators and helper functions that follow the spirit of the STL
@@ -1173,7 +1391,7 @@
// std::copy(some_sequence.begin(), some_sequence.end(),
// google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence()));
//
-// Ported by johannes from util/gtl/proto-array-iterators-inl.h
+// Ported by johannes from util/gtl/proto-array-iterators.h
namespace internal {
// A back inserter for RepeatedField objects.
@@ -1194,7 +1412,7 @@
RepeatedFieldBackInsertIterator<T>& operator++() {
return *this;
}
- RepeatedFieldBackInsertIterator<T>& operator++(int ignores_parameter) {
+ RepeatedFieldBackInsertIterator<T>& operator++(int /* unused */) {
return *this;
}
@@ -1225,7 +1443,7 @@
RepeatedPtrFieldBackInsertIterator<T>& operator++() {
return *this;
}
- RepeatedPtrFieldBackInsertIterator<T>& operator++(int ignores_parameter) {
+ RepeatedPtrFieldBackInsertIterator<T>& operator++(int /* unused */) {
return *this;
}
@@ -1254,7 +1472,7 @@
return *this;
}
AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++(
- int ignores_parameter) {
+ int /* unused */) {
return *this;
}
@@ -1264,16 +1482,22 @@
} // namespace internal
// Provides a back insert iterator for RepeatedField instances,
-// similar to std::back_inserter(). Note the identically named
-// function for RepeatedPtrField instances.
+// similar to std::back_inserter().
template<typename T> internal::RepeatedFieldBackInsertIterator<T>
RepeatedFieldBackInserter(RepeatedField<T>* const mutable_field) {
return internal::RepeatedFieldBackInsertIterator<T>(mutable_field);
}
// Provides a back insert iterator for RepeatedPtrField instances,
-// similar to std::back_inserter(). Note the identically named
-// function for RepeatedField instances.
+// similar to std::back_inserter().
+template<typename T> internal::RepeatedPtrFieldBackInsertIterator<T>
+RepeatedPtrFieldBackInserter(RepeatedPtrField<T>* const mutable_field) {
+ return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field);
+}
+
+// Special back insert iterator for RepeatedPtrField instances, just in
+// case someone wants to write generic template code that can access both
+// RepeatedFields and RepeatedPtrFields using a common name.
template<typename T> internal::RepeatedPtrFieldBackInsertIterator<T>
RepeatedFieldBackInserter(RepeatedPtrField<T>* const mutable_field) {
return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field);
diff --git a/third_party/protobuf/src/google/protobuf/repeated_field_reflection_unittest.cc b/third_party/protobuf/src/google/protobuf/repeated_field_reflection_unittest.cc
new file mode 100644
index 0000000..5fcfb00
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/repeated_field_reflection_unittest.cc
@@ -0,0 +1,193 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: tgs@google.com (Tom Szymanski)
+//
+// Test reflection methods for aggregate access to Repeated[Ptr]Fields.
+// This test proto2 methods on a proto2 layout.
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/test_util.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+
+using unittest::ForeignMessage;
+using unittest::TestAllTypes;
+using unittest::TestAllExtensions;
+
+namespace {
+
+static int Func(int i, int j) {
+ return i * j;
+}
+
+static string StrFunc(int i, int j) {
+ string str;
+ SStringPrintf(&str, "%d", Func(i, 4));
+ return str;
+}
+
+
+TEST(RepeatedFieldReflectionTest, RegularFields) {
+ TestAllTypes message;
+ const Reflection* refl = message.GetReflection();
+ const Descriptor* desc = message.GetDescriptor();
+
+ for (int i = 0; i < 10; ++i) {
+ message.add_repeated_int32(Func(i, 1));
+ message.add_repeated_double(Func(i, 2));
+ message.add_repeated_string(StrFunc(i, 5));
+ message.add_repeated_foreign_message()->set_c(Func(i, 6));
+ }
+
+ // Get FieldDescriptors for all the fields of interest.
+ const FieldDescriptor* fd_repeated_int32 =
+ desc->FindFieldByName("repeated_int32");
+ const FieldDescriptor* fd_repeated_double =
+ desc->FindFieldByName("repeated_double");
+ const FieldDescriptor* fd_repeated_string =
+ desc->FindFieldByName("repeated_string");
+ const FieldDescriptor* fd_repeated_foreign_message =
+ desc->FindFieldByName("repeated_foreign_message");
+
+ // Get RepeatedField objects for all fields of interest.
+ const RepeatedField<int32>& rf_int32 =
+ refl->GetRepeatedField<int32>(message, fd_repeated_int32);
+ const RepeatedField<double>& rf_double =
+ refl->GetRepeatedField<double>(message, fd_repeated_double);
+
+ // Get mutable RepeatedField objects for all fields of interest.
+ RepeatedField<int32>* mrf_int32 =
+ refl->MutableRepeatedField<int32>(&message, fd_repeated_int32);
+ RepeatedField<double>* mrf_double =
+ refl->MutableRepeatedField<double>(&message, fd_repeated_double);
+
+ // Get RepeatedPtrField objects for all fields of interest.
+ const RepeatedPtrField<string>& rpf_string =
+ refl->GetRepeatedPtrField<string>(message, fd_repeated_string);
+ const RepeatedPtrField<ForeignMessage>& rpf_foreign_message =
+ refl->GetRepeatedPtrField<ForeignMessage>(
+ message, fd_repeated_foreign_message);
+ const RepeatedPtrField<Message>& rpf_message =
+ refl->GetRepeatedPtrField<Message>(
+ message, fd_repeated_foreign_message);
+
+ // Get mutable RepeatedPtrField objects for all fields of interest.
+ RepeatedPtrField<string>* mrpf_string =
+ refl->MutableRepeatedPtrField<string>(&message, fd_repeated_string);
+ RepeatedPtrField<ForeignMessage>* mrpf_foreign_message =
+ refl->MutableRepeatedPtrField<ForeignMessage>(
+ &message, fd_repeated_foreign_message);
+ RepeatedPtrField<Message>* mrpf_message =
+ refl->MutableRepeatedPtrField<Message>(
+ &message, fd_repeated_foreign_message);
+
+ // Make sure we can do get and sets through the Repeated[Ptr]Field objects.
+ for (int i = 0; i < 10; ++i) {
+ // Check gets through const objects.
+ EXPECT_EQ(rf_int32.Get(i), Func(i, 1));
+ EXPECT_EQ(rf_double.Get(i), Func(i, 2));
+ EXPECT_EQ(rpf_string.Get(i), StrFunc(i, 5));
+ EXPECT_EQ(rpf_foreign_message.Get(i).c(), Func(i, 6));
+ EXPECT_EQ(down_cast<const ForeignMessage&>(rpf_message.Get(i)).c(),
+ Func(i, 6));
+
+ // Check gets through mutable objects.
+ EXPECT_EQ(mrf_int32->Get(i), Func(i, 1));
+ EXPECT_EQ(mrf_double->Get(i), Func(i, 2));
+ EXPECT_EQ(mrpf_string->Get(i), StrFunc(i, 5));
+ EXPECT_EQ(mrpf_foreign_message->Get(i).c(), Func(i, 6));
+ EXPECT_EQ(down_cast<const ForeignMessage&>(mrpf_message->Get(i)).c(),
+ Func(i, 6));
+
+ // Check sets through mutable objects.
+ mrf_int32->Set(i, Func(i, -1));
+ mrf_double->Set(i, Func(i, -2));
+ mrpf_string->Mutable(i)->assign(StrFunc(i, -5));
+ mrpf_foreign_message->Mutable(i)->set_c(Func(i, -6));
+ EXPECT_EQ(message.repeated_int32(i), Func(i, -1));
+ EXPECT_EQ(message.repeated_double(i), Func(i, -2));
+ EXPECT_EQ(message.repeated_string(i), StrFunc(i, -5));
+ EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, -6));
+ down_cast<ForeignMessage*>(mrpf_message->Mutable(i))->set_c(Func(i, 7));
+ EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, 7));
+ }
+
+ // Make sure types are checked correctly at runtime.
+ const FieldDescriptor* fd_optional_int32 =
+ desc->FindFieldByName("optional_int32");
+ EXPECT_DEATH(refl->GetRepeatedField<int32>(
+ message, fd_optional_int32), "requires a repeated field");
+ EXPECT_DEATH(refl->GetRepeatedField<double>(
+ message, fd_repeated_int32), "not the right type");
+ EXPECT_DEATH(refl->GetRepeatedPtrField<TestAllTypes>(
+ message, fd_repeated_foreign_message), "wrong submessage type");
+}
+
+
+
+
+TEST(RepeatedFieldReflectionTest, ExtensionFields) {
+ TestAllExtensions extended_message;
+ const Reflection* refl = extended_message.GetReflection();
+ const Descriptor* desc = extended_message.GetDescriptor();
+
+ for (int i = 0; i < 10; ++i) {
+ extended_message.AddExtension(
+ unittest::repeated_int64_extension, Func(i, 1));
+ }
+
+ const FieldDescriptor* fd_repeated_int64_extension =
+ desc->file()->FindExtensionByName("repeated_int64_extension");
+ GOOGLE_CHECK(fd_repeated_int64_extension != NULL);
+
+ const RepeatedField<int64>& rf_int64_extension =
+ refl->GetRepeatedField<int64>(extended_message,
+ fd_repeated_int64_extension);
+
+ RepeatedField<int64>* mrf_int64_extension =
+ refl->MutableRepeatedField<int64>(&extended_message,
+ fd_repeated_int64_extension);
+
+ for (int i = 0; i < 10; ++i) {
+ EXPECT_EQ(Func(i, 1), rf_int64_extension.Get(i));
+ mrf_int64_extension->Set(i, Func(i, -1));
+ EXPECT_EQ(Func(i, -1),
+ extended_message.GetExtension(unittest::repeated_int64_extension, i));
+ }
+}
+
+} // namespace
+} // namespace protobuf
+} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/repeated_field_unittest.cc b/third_party/protobuf/src/google/protobuf/repeated_field_unittest.cc
index e7e1e99..99d5842 100644
--- a/third_party/protobuf/src/google/protobuf/repeated_field_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/repeated_field_unittest.cc
@@ -36,6 +36,7 @@
// other proto2 unittests.
#include <algorithm>
+#include <limits>
#include <list>
#include <vector>
@@ -46,7 +47,7 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
using protobuf_unittest::TestAllTypes;
@@ -54,8 +55,7 @@
namespace protobuf {
namespace {
-// Test operations on a RepeatedField which is small enough that it does
-// not allocate a separate array for storage.
+// Test operations on a small RepeatedField.
TEST(RepeatedField, Small) {
RepeatedField<int> field;
@@ -77,7 +77,6 @@
EXPECT_EQ(field.size(), 2);
EXPECT_EQ(field.Get(0), 5);
EXPECT_EQ(field.Get(1), 23);
- EXPECT_EQ(field.SpaceUsedExcludingSelf(), 0);
field.RemoveLast();
@@ -87,9 +86,11 @@
field.Clear();
EXPECT_EQ(field.size(), 0);
- EXPECT_EQ(field.SpaceUsedExcludingSelf(), 0);
+ int expected_usage = 4 * sizeof(int);
+ EXPECT_EQ(field.SpaceUsedExcludingSelf(), expected_usage);
}
+
// Test operations on a RepeatedField which is large enough to allocate a
// separate array.
TEST(RepeatedField, Large) {
@@ -213,10 +214,8 @@
TEST(RepeatedField, MergeFrom) {
RepeatedField<int> source, destination;
-
source.Add(4);
source.Add(5);
-
destination.Add(1);
destination.Add(2);
destination.Add(3);
@@ -224,7 +223,6 @@
destination.MergeFrom(source);
ASSERT_EQ(5, destination.size());
-
EXPECT_EQ(1, destination.Get(0));
EXPECT_EQ(2, destination.Get(1));
EXPECT_EQ(3, destination.Get(2));
@@ -234,10 +232,8 @@
TEST(RepeatedField, CopyFrom) {
RepeatedField<int> source, destination;
-
source.Add(4);
source.Add(5);
-
destination.Add(1);
destination.Add(2);
destination.Add(3);
@@ -245,7 +241,6 @@
destination.CopyFrom(source);
ASSERT_EQ(2, destination.size());
-
EXPECT_EQ(4, destination.Get(0));
EXPECT_EQ(5, destination.Get(1));
}
@@ -262,12 +257,26 @@
EXPECT_EQ(2, destination.Get(1));
}
+TEST(RepeatedField, IteratorConstruct) {
+ vector<int> values;
+ values.push_back(1);
+ values.push_back(2);
+
+ RepeatedField<int> field(values.begin(), values.end());
+ ASSERT_EQ(values.size(), field.size());
+ EXPECT_EQ(values[0], field.Get(0));
+ EXPECT_EQ(values[1], field.Get(1));
+
+ RepeatedField<int> other(field.begin(), field.end());
+ ASSERT_EQ(values.size(), other.size());
+ EXPECT_EQ(values[0], other.Get(0));
+ EXPECT_EQ(values[1], other.Get(1));
+}
+
TEST(RepeatedField, CopyAssign) {
RepeatedField<int> source, destination;
-
source.Add(4);
source.Add(5);
-
destination.Add(1);
destination.Add(2);
destination.Add(3);
@@ -275,11 +284,24 @@
destination = source;
ASSERT_EQ(2, destination.size());
-
EXPECT_EQ(4, destination.Get(0));
EXPECT_EQ(5, destination.Get(1));
}
+TEST(RepeatedField, SelfAssign) {
+ // Verify that assignment to self does not destroy data.
+ RepeatedField<int> source, *p;
+ p = &source;
+ source.Add(7);
+ source.Add(8);
+
+ *p = source;
+
+ ASSERT_EQ(2, source.size());
+ EXPECT_EQ(7, source.Get(0));
+ EXPECT_EQ(8, source.Get(1));
+}
+
TEST(RepeatedField, MutableDataIsMutable) {
RepeatedField<int> field;
field.Add(1);
@@ -315,6 +337,41 @@
}
+TEST(RepeatedField, ExtractSubrange) {
+ // Exhaustively test every subrange in arrays of all sizes from 0 through 9.
+ for (int sz = 0; sz < 10; ++sz) {
+ for (int num = 0; num <= sz; ++num) {
+ for (int start = 0; start < sz - num; ++start) {
+ // Create RepeatedField with sz elements having values 0 through sz-1.
+ RepeatedField<int32> field;
+ for (int i = 0; i < sz; ++i)
+ field.Add(i);
+ EXPECT_EQ(field.size(), sz);
+
+ // Create a catcher array and call ExtractSubrange.
+ int32 catcher[10];
+ for (int i = 0; i < 10; ++i)
+ catcher[i] = -1;
+ field.ExtractSubrange(start, num, catcher);
+
+ // Does the resulting array have the right size?
+ EXPECT_EQ(field.size(), sz - num);
+
+ // Were the removed elements extracted into the catcher array?
+ for (int i = 0; i < num; ++i)
+ EXPECT_EQ(catcher[i], start + i);
+ EXPECT_EQ(catcher[num], -1);
+
+ // Does the resulting array contain the right values?
+ for (int i = 0; i < start; ++i)
+ EXPECT_EQ(field.Get(i), i);
+ for (int i = start; i < field.size(); ++i)
+ EXPECT_EQ(field.Get(i), i + num);
+ }
+ }
+ }
+}
+
// ===================================================================
// RepeatedPtrField tests. These pretty much just mirror the RepeatedField
// tests above.
@@ -351,6 +408,7 @@
EXPECT_EQ(field.size(), 0);
}
+
TEST(RepeatedPtrField, Large) {
RepeatedPtrField<string> field;
@@ -565,10 +623,8 @@
TEST(RepeatedPtrField, MergeFrom) {
RepeatedPtrField<string> source, destination;
-
source.Add()->assign("4");
source.Add()->assign("5");
-
destination.Add()->assign("1");
destination.Add()->assign("2");
destination.Add()->assign("3");
@@ -576,7 +632,6 @@
destination.MergeFrom(source);
ASSERT_EQ(5, destination.size());
-
EXPECT_EQ("1", destination.Get(0));
EXPECT_EQ("2", destination.Get(1));
EXPECT_EQ("3", destination.Get(2));
@@ -586,10 +641,8 @@
TEST(RepeatedPtrField, CopyFrom) {
RepeatedPtrField<string> source, destination;
-
source.Add()->assign("4");
source.Add()->assign("5");
-
destination.Add()->assign("1");
destination.Add()->assign("2");
destination.Add()->assign("3");
@@ -597,14 +650,12 @@
destination.CopyFrom(source);
ASSERT_EQ(2, destination.size());
-
EXPECT_EQ("4", destination.Get(0));
EXPECT_EQ("5", destination.Get(1));
}
TEST(RepeatedPtrField, CopyConstruct) {
RepeatedPtrField<string> source;
-
source.Add()->assign("1");
source.Add()->assign("2");
@@ -615,12 +666,45 @@
EXPECT_EQ("2", destination.Get(1));
}
+TEST(RepeatedPtrField, IteratorConstruct_String) {
+ vector<string> values;
+ values.push_back("1");
+ values.push_back("2");
+
+ RepeatedPtrField<string> field(values.begin(), values.end());
+ ASSERT_EQ(values.size(), field.size());
+ EXPECT_EQ(values[0], field.Get(0));
+ EXPECT_EQ(values[1], field.Get(1));
+
+ RepeatedPtrField<string> other(field.begin(), field.end());
+ ASSERT_EQ(values.size(), other.size());
+ EXPECT_EQ(values[0], other.Get(0));
+ EXPECT_EQ(values[1], other.Get(1));
+}
+
+TEST(RepeatedPtrField, IteratorConstruct_Proto) {
+ typedef TestAllTypes::NestedMessage Nested;
+ vector<Nested> values;
+ values.push_back(Nested());
+ values.back().set_bb(1);
+ values.push_back(Nested());
+ values.back().set_bb(2);
+
+ RepeatedPtrField<Nested> field(values.begin(), values.end());
+ ASSERT_EQ(values.size(), field.size());
+ EXPECT_EQ(values[0].bb(), field.Get(0).bb());
+ EXPECT_EQ(values[1].bb(), field.Get(1).bb());
+
+ RepeatedPtrField<Nested> other(field.begin(), field.end());
+ ASSERT_EQ(values.size(), other.size());
+ EXPECT_EQ(values[0].bb(), other.Get(0).bb());
+ EXPECT_EQ(values[1].bb(), other.Get(1).bb());
+}
+
TEST(RepeatedPtrField, CopyAssign) {
RepeatedPtrField<string> source, destination;
-
source.Add()->assign("4");
source.Add()->assign("5");
-
destination.Add()->assign("1");
destination.Add()->assign("2");
destination.Add()->assign("3");
@@ -628,11 +712,24 @@
destination = source;
ASSERT_EQ(2, destination.size());
-
EXPECT_EQ("4", destination.Get(0));
EXPECT_EQ("5", destination.Get(1));
}
+TEST(RepeatedPtrField, SelfAssign) {
+ // Verify that assignment to self does not destroy data.
+ RepeatedPtrField<string> source, *p;
+ p = &source;
+ source.Add()->assign("7");
+ source.Add()->assign("8");
+
+ *p = source;
+
+ ASSERT_EQ(2, source.size());
+ EXPECT_EQ("7", source.Get(0));
+ EXPECT_EQ("8", source.Get(1));
+}
+
TEST(RepeatedPtrField, MutableDataIsMutable) {
RepeatedPtrField<string> field;
*field.Add() = "1";
@@ -644,6 +741,77 @@
EXPECT_EQ("2", field.Get(0));
}
+TEST(RepeatedPtrField, ExtractSubrange) {
+ // Exhaustively test every subrange in arrays of all sizes from 0 through 9
+ // with 0 through 3 cleared elements at the end.
+ for (int sz = 0; sz < 10; ++sz) {
+ for (int num = 0; num <= sz; ++num) {
+ for (int start = 0; start < sz - num; ++start) {
+ for (int extra = 0; extra < 4; ++extra) {
+ vector<string*> subject;
+
+ // Create an array with "sz" elements and "extra" cleared elements.
+ RepeatedPtrField<string> field;
+ for (int i = 0; i < sz + extra; ++i) {
+ subject.push_back(new string());
+ field.AddAllocated(subject[i]);
+ }
+ EXPECT_EQ(field.size(), sz + extra);
+ for (int i = 0; i < extra; ++i)
+ field.RemoveLast();
+ EXPECT_EQ(field.size(), sz);
+ EXPECT_EQ(field.ClearedCount(), extra);
+
+ // Create a catcher array and call ExtractSubrange.
+ string* catcher[10];
+ for (int i = 0; i < 10; ++i)
+ catcher[i] = NULL;
+ field.ExtractSubrange(start, num, catcher);
+
+ // Does the resulting array have the right size?
+ EXPECT_EQ(field.size(), sz - num);
+
+ // Were the removed elements extracted into the catcher array?
+ for (int i = 0; i < num; ++i)
+ EXPECT_EQ(catcher[i], subject[start + i]);
+ EXPECT_EQ(NULL, catcher[num]);
+
+ // Does the resulting array contain the right values?
+ for (int i = 0; i < start; ++i)
+ EXPECT_EQ(field.Mutable(i), subject[i]);
+ for (int i = start; i < field.size(); ++i)
+ EXPECT_EQ(field.Mutable(i), subject[i + num]);
+
+ // Reinstate the cleared elements.
+ EXPECT_EQ(field.ClearedCount(), extra);
+ for (int i = 0; i < extra; ++i)
+ field.Add();
+ EXPECT_EQ(field.ClearedCount(), 0);
+ EXPECT_EQ(field.size(), sz - num + extra);
+
+ // Make sure the extra elements are all there (in some order).
+ for (int i = sz; i < sz + extra; ++i) {
+ int count = 0;
+ for (int j = sz; j < sz + extra; ++j) {
+ if (field.Mutable(j - num) == subject[i])
+ count += 1;
+ }
+ EXPECT_EQ(count, 1);
+ }
+
+ // Release the caught elements.
+ for (int i = 0; i < num; ++i)
+ delete catcher[i];
+ }
+ }
+ }
+ }
+}
+
+TEST(RepeatedPtrField, DeleteSubrange) {
+ // DeleteSubrange is a trivial extension of ExtendSubrange.
+}
+
// ===================================================================
// Iterator tests stolen from net/proto/proto-array_unittest.
@@ -738,6 +906,30 @@
EXPECT_EQ("baz", *(--const_proto_array.end()));
}
+TEST_F(RepeatedPtrFieldIteratorTest, MutableReverseIteration) {
+ RepeatedPtrField<string>::reverse_iterator iter = proto_array_.rbegin();
+ EXPECT_EQ("baz", *iter);
+ ++iter;
+ EXPECT_EQ("bar", *(iter++));
+ EXPECT_EQ("foo", *iter);
+ ++iter;
+ EXPECT_TRUE(proto_array_.rend() == iter);
+ EXPECT_EQ("foo", *(--proto_array_.rend()));
+}
+
+TEST_F(RepeatedPtrFieldIteratorTest, ConstReverseIteration) {
+ const RepeatedPtrField<string>& const_proto_array = proto_array_;
+ RepeatedPtrField<string>::const_reverse_iterator iter
+ = const_proto_array.rbegin();
+ EXPECT_EQ("baz", *iter);
+ ++iter;
+ EXPECT_EQ("bar", *(iter++));
+ EXPECT_EQ("foo", *iter);
+ ++iter;
+ EXPECT_TRUE(const_proto_array.rend() == iter);
+ EXPECT_EQ("foo", *(--const_proto_array.rend()));
+}
+
TEST_F(RepeatedPtrFieldIteratorTest, RandomAccess) {
RepeatedPtrField<string>::iterator iter = proto_array_.begin();
RepeatedPtrField<string>::iterator iter2 = iter;
@@ -805,9 +997,11 @@
proto_array_.Add()->assign("foo");
proto_array_.Add()->assign("bar");
proto_array_.Add()->assign("baz");
+ const_proto_array_ = &proto_array_;
}
RepeatedPtrField<string> proto_array_;
+ const RepeatedPtrField<string>* const_proto_array_;
};
TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertiblePtr) {
@@ -815,6 +1009,11 @@
proto_array_.pointer_begin();
}
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertibleConstPtr) {
+ RepeatedPtrField<string>::const_pointer_iterator iter =
+ const_proto_array_->pointer_begin();
+}
+
TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) {
RepeatedPtrField<string>::pointer_iterator iter =
proto_array_.pointer_begin();
@@ -827,6 +1026,18 @@
EXPECT_EQ("baz", **(--proto_array_.pointer_end()));
}
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutableConstPtrIteration) {
+ RepeatedPtrField<string>::const_pointer_iterator iter =
+ const_proto_array_->pointer_begin();
+ EXPECT_EQ("foo", **iter);
+ ++iter;
+ EXPECT_EQ("bar", **(iter++));
+ EXPECT_EQ("baz", **iter);
+ ++iter;
+ EXPECT_TRUE(const_proto_array_->pointer_end() == iter);
+ EXPECT_EQ("baz", **(--const_proto_array_->pointer_end()));
+}
+
TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomPtrAccess) {
RepeatedPtrField<string>::pointer_iterator iter =
proto_array_.pointer_begin();
@@ -840,6 +1051,19 @@
EXPECT_EQ(3, proto_array_.end() - proto_array_.begin());
}
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomConstPtrAccess) {
+ RepeatedPtrField<string>::const_pointer_iterator iter =
+ const_proto_array_->pointer_begin();
+ RepeatedPtrField<string>::const_pointer_iterator iter2 = iter;
+ ++iter2;
+ ++iter2;
+ EXPECT_TRUE(iter + 2 == iter2);
+ EXPECT_TRUE(iter == iter2 - 2);
+ EXPECT_EQ("baz", *iter[2]);
+ EXPECT_EQ("baz", **(iter + 2));
+ EXPECT_EQ(3, const_proto_array_->end() - const_proto_array_->begin());
+}
+
TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparablePtr) {
RepeatedPtrField<string>::pointer_iterator iter =
proto_array_.pointer_begin();
@@ -854,6 +1078,20 @@
EXPECT_TRUE(iter >= iter);
}
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparableConstPtr) {
+ RepeatedPtrField<string>::const_pointer_iterator iter =
+ const_proto_array_->pointer_begin();
+ RepeatedPtrField<string>::const_pointer_iterator iter2 = iter + 1;
+ EXPECT_TRUE(iter == iter);
+ EXPECT_TRUE(iter != iter2);
+ EXPECT_TRUE(iter < iter2);
+ EXPECT_TRUE(iter <= iter2);
+ EXPECT_TRUE(iter <= iter);
+ EXPECT_TRUE(iter2 > iter);
+ EXPECT_TRUE(iter2 >= iter);
+ EXPECT_TRUE(iter >= iter);
+}
+
// Uninitialized iterator does not point to any of the RepeatedPtrOverPtrs.
// Dereferencing an uninitialized iterator crashes the process.
TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedPtrIterator) {
@@ -865,6 +1103,14 @@
EXPECT_TRUE(iter != proto_array_.pointer_end());
}
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedConstPtrIterator) {
+ RepeatedPtrField<string>::const_pointer_iterator iter;
+ EXPECT_TRUE(iter != const_proto_array_->pointer_begin());
+ EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 1);
+ EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 2);
+ EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 3);
+ EXPECT_TRUE(iter != const_proto_array_->pointer_end());
+}
// This comparison functor is required by the tests for RepeatedPtrOverPtrs.
// They operate on strings and need to compare strings as strings in
@@ -889,17 +1135,33 @@
proto_array_.Add()->assign("x");
proto_array_.Add()->assign("y");
- RepeatedPtrField<string>::pointer_iterator iter =
- proto_array_.pointer_begin();
- string v = "f";
- RepeatedPtrField<string>::pointer_iterator it =
- lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(),
- &v, StringLessThan());
+ {
+ RepeatedPtrField<string>::pointer_iterator iter =
+ proto_array_.pointer_begin();
+ string v = "f";
+ RepeatedPtrField<string>::pointer_iterator it =
+ lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(),
+ &v, StringLessThan());
- GOOGLE_CHECK(*it != NULL);
+ GOOGLE_CHECK(*it != NULL);
- EXPECT_EQ(**it, "n");
- EXPECT_TRUE(it == proto_array_.pointer_begin() + 3);
+ EXPECT_EQ(**it, "n");
+ EXPECT_TRUE(it == proto_array_.pointer_begin() + 3);
+ }
+ {
+ RepeatedPtrField<string>::const_pointer_iterator iter =
+ const_proto_array_->pointer_begin();
+ string v = "f";
+ RepeatedPtrField<string>::const_pointer_iterator it =
+ lower_bound(const_proto_array_->pointer_begin(),
+ const_proto_array_->pointer_end(),
+ &v, StringLessThan());
+
+ GOOGLE_CHECK(*it != NULL);
+
+ EXPECT_EQ(**it, "n");
+ EXPECT_TRUE(it == const_proto_array_->pointer_begin() + 3);
+ }
}
TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrMutation) {
@@ -1025,13 +1287,24 @@
TEST_F(RepeatedFieldInsertionIteratorsTest, Words) {
ASSERT_EQ(words.size(), protobuffer.repeated_string_size());
- EXPECT_EQ(words.at(0), protobuffer.repeated_string(0));
- EXPECT_EQ(words.at(1), protobuffer.repeated_string(1));
- EXPECT_EQ(words.at(2), protobuffer.repeated_string(2));
- EXPECT_EQ(words.at(3), protobuffer.repeated_string(3));
- EXPECT_EQ(words.at(4), protobuffer.repeated_string(4));
- EXPECT_EQ(words.at(5), protobuffer.repeated_string(5));
- EXPECT_EQ(words.at(6), protobuffer.repeated_string(6));
+ for (int i = 0; i < words.size(); ++i)
+ EXPECT_EQ(words.at(i), protobuffer.repeated_string(i));
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest, Words2) {
+ words.clear();
+ words.push_back("sing");
+ words.push_back("a");
+ words.push_back("song");
+ words.push_back("of");
+ words.push_back("six");
+ words.push_back("pence");
+ protobuffer.mutable_repeated_string()->Clear();
+ std::copy(words.begin(), words.end(), RepeatedPtrFieldBackInserter(
+ protobuffer.mutable_repeated_string()));
+ ASSERT_EQ(words.size(), protobuffer.repeated_string_size());
+ for (int i = 0; i < words.size(); ++i)
+ EXPECT_EQ(words.at(i), protobuffer.repeated_string(i));
}
TEST_F(RepeatedFieldInsertionIteratorsTest, Nesteds) {
diff --git a/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h b/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h
index e9d8679..8d9a726 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h
+++ b/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h
@@ -44,7 +44,7 @@
// On LP64 platforms, AtomicWord and Atomic64 are both always long,
// so this problem doesn't occur.
-#if !defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
+#if !defined(GOOGLE_PROTOBUF_HOST_ARCH_64_BIT)
namespace google {
namespace protobuf {
@@ -117,6 +117,6 @@
} // namespace protobuf
} // namespace google
-#endif // !defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
+#endif // !defined(GOOGLE_PROTOBUF_HOST_ARCH_64_BIT)
#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_
diff --git a/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_macosx.h b/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_macosx.h
index f9b7581..9af6d63 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_macosx.h
+++ b/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_macosx.h
@@ -136,7 +136,7 @@
Atomic64 prev_value;
do {
if (OSAtomicCompareAndSwap64(old_value, new_value,
- reinterpret_cast<volatile int64_t*>(ptr))) {
+ const_cast<Atomic64*>(ptr))) {
return old_value;
}
prev_value = *ptr;
@@ -150,19 +150,18 @@
do {
old_value = *ptr;
} while (!OSAtomicCompareAndSwap64(old_value, new_value,
- reinterpret_cast<volatile int64_t*>(ptr)));
+ const_cast<Atomic64*>(ptr)));
return old_value;
}
inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
Atomic64 increment) {
- return OSAtomicAdd64(increment, reinterpret_cast<volatile int64_t*>(ptr));
+ return OSAtomicAdd64(increment, const_cast<Atomic64*>(ptr));
}
inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
Atomic64 increment) {
- return OSAtomicAdd64Barrier(increment,
- reinterpret_cast<volatile int64_t*>(ptr));
+ return OSAtomicAdd64Barrier(increment, const_cast<Atomic64*>(ptr));
}
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
@@ -170,8 +169,8 @@
Atomic64 new_value) {
Atomic64 prev_value;
do {
- if (OSAtomicCompareAndSwap64Barrier(
- old_value, new_value, reinterpret_cast<volatile int64_t*>(ptr))) {
+ if (OSAtomicCompareAndSwap64Barrier(old_value, new_value,
+ const_cast<Atomic64*>(ptr))) {
return old_value;
}
prev_value = *ptr;
diff --git a/third_party/protobuf/src/google/protobuf/stubs/common.cc b/third_party/protobuf/src/google/protobuf/stubs/common.cc
index 7b15be4..16d7852 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/common.cc
+++ b/third_party/protobuf/src/google/protobuf/stubs/common.cc
@@ -320,6 +320,24 @@
#endif
// ===================================================================
+// emulates google3/util/endian/endian.h
+//
+// TODO(xiaofeng): PROTOBUF_LITTLE_ENDIAN is unfortunately defined in
+// google/protobuf/io/coded_stream.h and therefore can not be used here.
+// Maybe move that macro definition here in the furture.
+uint32 ghtonl(uint32 x) {
+ union {
+ uint32 result;
+ uint8 result_array[4];
+ };
+ result_array[0] = static_cast<uint8>(x >> 24);
+ result_array[1] = static_cast<uint8>((x >> 16) & 0xFF);
+ result_array[2] = static_cast<uint8>((x >> 8) & 0xFF);
+ result_array[3] = static_cast<uint8>(x & 0xFF);
+ return result;
+}
+
+// ===================================================================
// Shutdown support.
namespace internal {
diff --git a/third_party/protobuf/src/google/protobuf/stubs/common.h b/third_party/protobuf/src/google/protobuf/stubs/common.h
index cad22fa..4c3e0cb 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/common.h
+++ b/third_party/protobuf/src/google/protobuf/stubs/common.h
@@ -356,6 +356,12 @@
return static_cast<To>(f);
}
+// Simplified down_cast for reference type.
+template<typename To, typename From>
+inline To down_cast(From& f) {
+ return static_cast<To>(f);
+}
+
} // namespace internal
// We made these internal so that they would show up as such in the docs,
@@ -701,6 +707,7 @@
#undef GOOGLE_CHECK_LE
#undef GOOGLE_CHECK_GT
#undef GOOGLE_CHECK_GE
+#undef GOOGLE_CHECK_NOTNULL
#undef GOOGLE_DLOG
#undef GOOGLE_DCHECK
@@ -727,6 +734,18 @@
#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) > (B))
#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B))
+namespace internal {
+template<typename T>
+T* CheckNotNull(const char *file, int line, const char *name, T* val) {
+ if (val == NULL) {
+ GOOGLE_LOG(FATAL) << name;
+ }
+ return val;
+}
+} // namespace internal
+#define GOOGLE_CHECK_NOTNULL(A) \
+ internal::CheckNotNull(__FILE__, __LINE__, "'" #A "' must not be NULL", (A))
+
#ifdef NDEBUG
#define GOOGLE_DLOG GOOGLE_LOG_IF(INFO, false)
@@ -1151,20 +1170,10 @@
using internal::MutexLockMaybe;
// ===================================================================
-// from google3/base/type_traits.h
+// from google3/util/utf8/public/unilib.h
namespace internal {
-// Specified by TR1 [4.7.4] Pointer modifications.
-template<typename T> struct remove_pointer { typedef T type; };
-template<typename T> struct remove_pointer<T*> { typedef T type; };
-template<typename T> struct remove_pointer<T* const> { typedef T type; };
-template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
-template<typename T> struct remove_pointer<T* const volatile> {
- typedef T type; };
-
-// ===================================================================
-
// Checks if the buffer contains structurally-valid UTF-8. Implemented in
// structurally_valid.cc.
LIBPROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len);
@@ -1172,6 +1181,10 @@
} // namespace internal
// ===================================================================
+// from google3/util/endian/endian.h
+LIBPROTOBUF_EXPORT uint32 ghtonl(uint32 x);
+
+// ===================================================================
// Shutdown support.
// Shut down the entire protocol buffers library, deleting all static-duration
diff --git a/third_party/protobuf/src/google/protobuf/stubs/hash.h b/third_party/protobuf/src/google/protobuf/stubs/hash.h
index 822d605..f7d1071 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/hash.h
+++ b/third_party/protobuf/src/google/protobuf/stubs/hash.h
@@ -90,12 +90,16 @@
typename HashFcn = hash<Key>,
typename EqualKey = int >
class hash_map : public std::map<Key, Data, HashFcn> {
+ public:
+ hash_map(int = 0) {}
};
template <typename Key,
typename HashFcn = hash<Key>,
typename EqualKey = int >
class hash_set : public std::set<Key, HashFcn> {
+ public:
+ hash_set(int = 0) {}
};
#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION)
@@ -123,6 +127,8 @@
typename EqualKey = int >
class hash_map : public HASH_NAMESPACE::hash_map<
Key, Data, HashFcn> {
+ public:
+ hash_map(int = 0) {}
};
template <typename Key,
@@ -130,6 +136,8 @@
typename EqualKey = int >
class hash_set : public HASH_NAMESPACE::hash_set<
Key, HashFcn> {
+ public:
+ hash_set(int = 0) {}
};
#else
@@ -163,6 +171,8 @@
typename EqualKey = std::equal_to<Key> >
class hash_map : public HASH_NAMESPACE::HASH_MAP_CLASS<
Key, Data, HashFcn, EqualKey> {
+ public:
+ hash_map(int = 0) {}
};
template <typename Key,
@@ -170,6 +180,8 @@
typename EqualKey = std::equal_to<Key> >
class hash_set : public HASH_NAMESPACE::HASH_SET_CLASS<
Key, HashFcn, EqualKey> {
+ public:
+ hash_set(int = 0) {}
};
#endif
diff --git a/third_party/protobuf/src/google/protobuf/stubs/map-util.h b/third_party/protobuf/src/google/protobuf/stubs/map-util.h
index f5c9d6b..775848b 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/map-util.h
+++ b/third_party/protobuf/src/google/protobuf/stubs/map-util.h
@@ -68,6 +68,30 @@
return &it->second;
}
+// Perform a lookup in a map or hash_map, assuming that the key exists.
+// Crash if it does not.
+//
+// This is intended as a replacement for operator[] as an rvalue (for reading)
+// when the key is guaranteed to exist.
+//
+// operator[] is discouraged for several reasons:
+// * It has a side-effect of inserting missing keys
+// * It is not thread-safe (even when it is not inserting, it can still
+// choose to resize the underlying storage)
+// * It invalidates iterators (when it chooses to resize)
+// * It default constructs a value object even if it doesn't need to
+//
+// This version assumes the key is printable, and includes it in the fatal log
+// message.
+template <class Collection>
+const typename Collection::value_type::second_type&
+FindOrDie(const Collection& collection,
+ const typename Collection::value_type::first_type& key) {
+ typename Collection::const_iterator it = collection.find(key);
+ GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key;
+ return it->second;
+}
+
// Perform a lookup in a map or hash_map whose values are pointers.
// If the key is present a const pointer to the associated value is returned,
// otherwise a NULL pointer is returned.
diff --git a/third_party/protobuf/src/google/protobuf/stubs/stl_util.h b/third_party/protobuf/src/google/protobuf/stubs/stl_util.h
new file mode 100644
index 0000000..9021dad
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/stl_util.h
@@ -0,0 +1,121 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// from google3/util/gtl/stl_util.h
+
+#ifndef GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
+#define GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+// STLDeleteContainerPointers()
+// For a range within a container of pointers, calls delete
+// (non-array version) on these pointers.
+// NOTE: for these three functions, we could just implement a DeleteObject
+// functor and then call for_each() on the range and functor, but this
+// requires us to pull in all of algorithm.h, which seems expensive.
+// For hash_[multi]set, it is important that this deletes behind the iterator
+// because the hash_set may call the hash function on the iterator when it is
+// advanced, which could result in the hash function trying to deference a
+// stale pointer.
+template <class ForwardIterator>
+void STLDeleteContainerPointers(ForwardIterator begin,
+ ForwardIterator end) {
+ while (begin != end) {
+ ForwardIterator temp = begin;
+ ++begin;
+ delete *temp;
+ }
+}
+
+// Inside Google, this function implements a horrible, disgusting hack in which
+// we reach into the string's private implementation and resize it without
+// initializing the new bytes. In some cases doing this can significantly
+// improve performance. However, since it's totally non-portable it has no
+// place in open source code. Feel free to fill this function in with your
+// own disgusting hack if you want the perf boost.
+inline void STLStringResizeUninitialized(string* s, size_t new_size) {
+ s->resize(new_size);
+}
+
+// Return a mutable char* pointing to a string's internal buffer,
+// which may not be null-terminated. Writing through this pointer will
+// modify the string.
+//
+// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
+// next call to a string method that invalidates iterators.
+//
+// As of 2006-04, there is no standard-blessed way of getting a
+// mutable reference to a string's internal buffer. However, issue 530
+// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530)
+// proposes this as the method. According to Matt Austern, this should
+// already work on all current implementations.
+inline char* string_as_array(string* str) {
+ // DO NOT USE const_cast<char*>(str->data())! See the unittest for why.
+ return str->empty() ? NULL : &*str->begin();
+}
+
+// STLDeleteElements() deletes all the elements in an STL container and clears
+// the container. This function is suitable for use with a vector, set,
+// hash_set, or any other STL container which defines sensible begin(), end(),
+// and clear() methods.
+//
+// If container is NULL, this function is a no-op.
+//
+// As an alternative to calling STLDeleteElements() directly, consider
+// ElementDeleter (defined below), which ensures that your container's elements
+// are deleted when the ElementDeleter goes out of scope.
+template <class T>
+void STLDeleteElements(T *container) {
+ if (!container) return;
+ STLDeleteContainerPointers(container->begin(), container->end());
+ container->clear();
+}
+
+// Given an STL container consisting of (key, value) pairs, STLDeleteValues
+// deletes all the "value" components and clears the container. Does nothing
+// in the case it's given a NULL pointer.
+
+template <class T>
+void STLDeleteValues(T *v) {
+ if (!v) return;
+ for (typename T::iterator i = v->begin(); i != v->end(); ++i) {
+ delete i->second;
+ }
+ v->clear();
+}
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
diff --git a/third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc b/third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc
new file mode 100644
index 0000000..4a5b858
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc
@@ -0,0 +1,175 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// from google3/base/stringprintf.cc
+
+#include <google/protobuf/stubs/stringprintf.h>
+
+#include <errno.h>
+#include <stdarg.h> // For va_list and related operations
+#include <stdio.h> // MSVC requires this for _vsnprintf
+#include <vector>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/testing/googletest.h>
+
+namespace google {
+namespace protobuf {
+
+#ifdef _MSC_VER
+enum { IS_COMPILER_MSVC = 1 };
+#ifndef va_copy
+// Define va_copy for MSVC. This is a hack, assuming va_list is simply a
+// pointer into the stack and is safe to copy.
+#define va_copy(dest, src) ((dest) = (src))
+#endif
+#else
+enum { IS_COMPILER_MSVC = 0 };
+#endif
+
+void StringAppendV(string* dst, const char* format, va_list ap) {
+ // First try with a small fixed size buffer
+ static const int kSpaceLength = 1024;
+ char space[kSpaceLength];
+
+ // It's possible for methods that use a va_list to invalidate
+ // the data in it upon use. The fix is to make a copy
+ // of the structure before using it and use that copy instead.
+ va_list backup_ap;
+ va_copy(backup_ap, ap);
+ int result = vsnprintf(space, kSpaceLength, format, backup_ap);
+ va_end(backup_ap);
+
+ if (result < kSpaceLength) {
+ if (result >= 0) {
+ // Normal case -- everything fit.
+ dst->append(space, result);
+ return;
+ }
+
+ if (IS_COMPILER_MSVC) {
+ // Error or MSVC running out of space. MSVC 8.0 and higher
+ // can be asked about space needed with the special idiom below:
+ va_copy(backup_ap, ap);
+ result = vsnprintf(NULL, 0, format, backup_ap);
+ va_end(backup_ap);
+ }
+
+ if (result < 0) {
+ // Just an error.
+ return;
+ }
+ }
+
+ // Increase the buffer size to the size requested by vsnprintf,
+ // plus one for the closing \0.
+ int length = result+1;
+ char* buf = new char[length];
+
+ // Restore the va_list before we use it again
+ va_copy(backup_ap, ap);
+ result = vsnprintf(buf, length, format, backup_ap);
+ va_end(backup_ap);
+
+ if (result >= 0 && result < length) {
+ // It fit
+ dst->append(buf, result);
+ }
+ delete[] buf;
+}
+
+
+string StringPrintf(const char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ string result;
+ StringAppendV(&result, format, ap);
+ va_end(ap);
+ return result;
+}
+
+const string& SStringPrintf(string* dst, const char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ dst->clear();
+ StringAppendV(dst, format, ap);
+ va_end(ap);
+ return *dst;
+}
+
+void StringAppendF(string* dst, const char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ StringAppendV(dst, format, ap);
+ va_end(ap);
+}
+
+// Max arguments supported by StringPrintVector
+const int kStringPrintfVectorMaxArgs = 32;
+
+// An empty block of zero for filler arguments. This is const so that if
+// printf tries to write to it (via %n) then the program gets a SIGSEGV
+// and we can fix the problem or protect against an attack.
+static const char string_printf_empty_block[256] = { '\0' };
+
+string StringPrintfVector(const char* format, const vector<string>& v) {
+ GOOGLE_CHECK_LE(v.size(), kStringPrintfVectorMaxArgs)
+ << "StringPrintfVector currently only supports up to "
+ << kStringPrintfVectorMaxArgs << " arguments. "
+ << "Feel free to add support for more if you need it.";
+
+ // Add filler arguments so that bogus format+args have a harder time
+ // crashing the program, corrupting the program (%n),
+ // or displaying random chunks of memory to users.
+
+ const char* cstr[kStringPrintfVectorMaxArgs];
+ for (int i = 0; i < v.size(); ++i) {
+ cstr[i] = v[i].c_str();
+ }
+ for (int i = v.size(); i < GOOGLE_ARRAYSIZE(cstr); ++i) {
+ cstr[i] = &string_printf_empty_block[0];
+ }
+
+ // I do not know any way to pass kStringPrintfVectorMaxArgs arguments,
+ // or any way to build a va_list by hand, or any API for printf
+ // that accepts an array of arguments. The best I can do is stick
+ // this COMPILE_ASSERT right next to the actual statement.
+
+ GOOGLE_COMPILE_ASSERT(kStringPrintfVectorMaxArgs == 32, arg_count_mismatch);
+ return StringPrintf(format,
+ cstr[0], cstr[1], cstr[2], cstr[3], cstr[4],
+ cstr[5], cstr[6], cstr[7], cstr[8], cstr[9],
+ cstr[10], cstr[11], cstr[12], cstr[13], cstr[14],
+ cstr[15], cstr[16], cstr[17], cstr[18], cstr[19],
+ cstr[20], cstr[21], cstr[22], cstr[23], cstr[24],
+ cstr[25], cstr[26], cstr[27], cstr[28], cstr[29],
+ cstr[30], cstr[31]);
+}
+} // namespace protobuf
+} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/stubs/stringprintf.h b/third_party/protobuf/src/google/protobuf/stubs/stringprintf.h
new file mode 100644
index 0000000..573f30f
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/stringprintf.h
@@ -0,0 +1,76 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// from google3/base/stringprintf.h
+//
+// Printf variants that place their output in a C++ string.
+//
+// Usage:
+// string result = StringPrintf("%d %s\n", 10, "hello");
+// SStringPrintf(&result, "%d %s\n", 10, "hello");
+// StringAppendF(&result, "%d %s\n", 20, "there");
+
+#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
+#define GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
+
+#include <stdarg.h>
+#include <string>
+#include <vector>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+// Return a C++ string
+extern string StringPrintf(const char* format, ...);
+
+// Store result into a supplied string and return it
+extern const string& SStringPrintf(string* dst, const char* format, ...);
+
+// Append result to a supplied string
+extern void StringAppendF(string* dst, const char* format, ...);
+
+// Lower-level routine that takes a va_list and appends to a specified
+// string. All other routines are just convenience wrappers around it.
+extern void StringAppendV(string* dst, const char* format, va_list ap);
+
+// The max arguments supported by StringPrintfVector
+extern const int kStringPrintfVectorMaxArgs;
+
+// You can use this version when all your arguments are strings, but
+// you don't know how many arguments you'll have at compile time.
+// StringPrintfVector will LOG(FATAL) if v.size() > kStringPrintfVectorMaxArgs
+extern string StringPrintfVector(const char* format, const vector<string>& v);
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
diff --git a/third_party/protobuf/src/google/protobuf/stubs/stringprintf_unittest.cc b/third_party/protobuf/src/google/protobuf/stubs/stringprintf_unittest.cc
new file mode 100644
index 0000000..a78a202
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/stringprintf_unittest.cc
@@ -0,0 +1,152 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// from google3/base/stringprintf_unittest.cc
+
+#include <google/protobuf/stubs/stringprintf.h>
+
+#include <cerrno>
+#include <string>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+TEST(StringPrintfTest, Empty) {
+#if 0
+ // gcc 2.95.3, gcc 4.1.0, and gcc 4.2.2 all warn about this:
+ // warning: zero-length printf format string.
+ // so we do not allow them in google3.
+ EXPECT_EQ("", StringPrintf(""));
+#endif
+ EXPECT_EQ("", StringPrintf("%s", string().c_str()));
+ EXPECT_EQ("", StringPrintf("%s", ""));
+}
+
+TEST(StringPrintfTest, Misc) {
+// MSVC does not support $ format specifier.
+#if !defined(_MSC_VER)
+ EXPECT_EQ("123hello w", StringPrintf("%3$d%2$s %1$c", 'w', "hello", 123));
+#endif // !_MSC_VER
+}
+
+TEST(StringAppendFTest, Empty) {
+ string value("Hello");
+ const char* empty = "";
+ StringAppendF(&value, "%s", empty);
+ EXPECT_EQ("Hello", value);
+}
+
+TEST(StringAppendFTest, EmptyString) {
+ string value("Hello");
+ StringAppendF(&value, "%s", "");
+ EXPECT_EQ("Hello", value);
+}
+
+TEST(StringAppendFTest, String) {
+ string value("Hello");
+ StringAppendF(&value, " %s", "World");
+ EXPECT_EQ("Hello World", value);
+}
+
+TEST(StringAppendFTest, Int) {
+ string value("Hello");
+ StringAppendF(&value, " %d", 123);
+ EXPECT_EQ("Hello 123", value);
+}
+
+TEST(StringPrintfTest, Multibyte) {
+ // If we are in multibyte mode and feed invalid multibyte sequence,
+ // StringPrintf should return an empty string instead of running
+ // out of memory while trying to determine destination buffer size.
+ // see b/4194543.
+
+ char* old_locale = setlocale(LC_CTYPE, NULL);
+ // Push locale with multibyte mode
+ setlocale(LC_CTYPE, "en_US.utf8");
+
+ const char kInvalidCodePoint[] = "\375\067s";
+ string value = StringPrintf("%.*s", 3, kInvalidCodePoint);
+
+ // In some versions of glibc (e.g. eglibc-2.11.1, aka GRTEv2), snprintf
+ // returns error given an invalid codepoint. Other versions
+ // (e.g. eglibc-2.15, aka pre-GRTEv3) emit the codepoint verbatim.
+ // We test that the output is one of the above.
+ EXPECT_TRUE(value.empty() || value == kInvalidCodePoint);
+
+ // Repeat with longer string, to make sure that the dynamically
+ // allocated path in StringAppendV is handled correctly.
+ int n = 2048;
+ char* buf = new char[n+1];
+ memset(buf, ' ', n-3);
+ memcpy(buf + n - 3, kInvalidCodePoint, 4);
+ value = StringPrintf("%.*s", n, buf);
+ // See GRTEv2 vs. GRTEv3 comment above.
+ EXPECT_TRUE(value.empty() || value == buf);
+ delete[] buf;
+
+ setlocale(LC_CTYPE, old_locale);
+}
+
+TEST(StringPrintfTest, NoMultibyte) {
+ // No multibyte handling, but the string contains funny chars.
+ char* old_locale = setlocale(LC_CTYPE, NULL);
+ setlocale(LC_CTYPE, "POSIX");
+ string value = StringPrintf("%.*s", 3, "\375\067s");
+ setlocale(LC_CTYPE, old_locale);
+ EXPECT_EQ("\375\067s", value);
+}
+
+TEST(StringPrintfTest, DontOverwriteErrno) {
+ // Check that errno isn't overwritten unless we're printing
+ // something significantly larger than what people are normally
+ // printing in their badly written PLOG() statements.
+ errno = ECHILD;
+ string value = StringPrintf("Hello, %s!", "World");
+ EXPECT_EQ(ECHILD, errno);
+}
+
+TEST(StringPrintfTest, LargeBuf) {
+ // Check that the large buffer is handled correctly.
+ int n = 2048;
+ char* buf = new char[n+1];
+ memset(buf, ' ', n);
+ buf[n] = 0;
+ string value = StringPrintf("%s", buf);
+ EXPECT_EQ(buf, value);
+ delete[] buf;
+}
+
+} // anonymous namespace
+} // namespace protobuf
+} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/stubs/strutil.cc b/third_party/protobuf/src/google/protobuf/stubs/strutil.cc
index ee07ce7..917b3e9 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/strutil.cc
+++ b/third_party/protobuf/src/google/protobuf/stubs/strutil.cc
@@ -189,6 +189,44 @@
SplitStringToIteratorUsing(full, delim, it);
}
+// Split a string using a character delimiter. Append the components
+// to 'result'. If there are consecutive delimiters, this function
+// will return corresponding empty strings. The string is split into
+// at most the specified number of pieces greedily. This means that the
+// last piece may possibly be split further. To split into as many pieces
+// as possible, specify 0 as the number of pieces.
+//
+// If "full" is the empty string, yields an empty string as the only value.
+//
+// If "pieces" is negative for some reason, it returns the whole string
+// ----------------------------------------------------------------------
+template <typename StringType, typename ITR>
+static inline
+void SplitStringToIteratorAllowEmpty(const StringType& full,
+ const char* delim,
+ int pieces,
+ ITR& result) {
+ string::size_type begin_index, end_index;
+ begin_index = 0;
+
+ for (int i = 0; (i < pieces-1) || (pieces == 0); i++) {
+ end_index = full.find_first_of(delim, begin_index);
+ if (end_index == string::npos) {
+ *result++ = full.substr(begin_index);
+ return;
+ }
+ *result++ = full.substr(begin_index, (end_index - begin_index));
+ begin_index = end_index + 1;
+ }
+ *result++ = full.substr(begin_index);
+}
+
+void SplitStringAllowEmpty(const string& full, const char* delim,
+ vector<string>* result) {
+ back_insert_iterator<vector<string> > it(*result);
+ SplitStringToIteratorAllowEmpty(full, delim, 0, it);
+}
+
// ----------------------------------------------------------------------
// JoinStrings()
// This merges a vector of string components with delim inserted
diff --git a/third_party/protobuf/src/google/protobuf/stubs/strutil.h b/third_party/protobuf/src/google/protobuf/stubs/strutil.h
index 4a79c22..a401c63 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/strutil.h
+++ b/third_party/protobuf/src/google/protobuf/stubs/strutil.h
@@ -168,6 +168,18 @@
LIBPROTOBUF_EXPORT void SplitStringUsing(const string& full, const char* delim,
vector<string>* res);
+// Split a string using one or more byte delimiters, presented
+// as a nul-terminated c string. Append the components to 'result'.
+// If there are consecutive delimiters, this function will return
+// corresponding empty strings. If you want to drop the empty
+// strings, try SplitStringUsing().
+//
+// If "full" is the empty string, yields an empty string as the only value.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT void SplitStringAllowEmpty(const string& full,
+ const char* delim,
+ vector<string>* result);
+
// ----------------------------------------------------------------------
// JoinStrings()
// These methods concatenate a vector of strings into a C++ string, using
@@ -453,5 +465,3 @@
} // namespace google
#endif // GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
-
-
diff --git a/third_party/protobuf/src/google/protobuf/stubs/substitute.cc b/third_party/protobuf/src/google/protobuf/stubs/substitute.cc
index b542aaa..259245b 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/substitute.cc
+++ b/third_party/protobuf/src/google/protobuf/stubs/substitute.cc
@@ -32,7 +32,7 @@
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
diff --git a/third_party/protobuf/src/google/protobuf/stubs/template_util.h b/third_party/protobuf/src/google/protobuf/stubs/template_util.h
new file mode 100644
index 0000000..4f30ffa
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/template_util.h
@@ -0,0 +1,138 @@
+// Copyright 2005 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ----
+// Author: lar@google.com (Laramie Leavitt)
+//
+// Template metaprogramming utility functions.
+//
+// This code is compiled directly on many platforms, including client
+// platforms like Windows, Mac, and embedded systems. Before making
+// any changes here, make sure that you're not breaking any platforms.
+//
+//
+// The names choosen here reflect those used in tr1 and the boost::mpl
+// library, there are similar operations used in the Loki library as
+// well. I prefer the boost names for 2 reasons:
+// 1. I think that portions of the Boost libraries are more likely to
+// be included in the c++ standard.
+// 2. It is not impossible that some of the boost libraries will be
+// included in our own build in the future.
+// Both of these outcomes means that we may be able to directly replace
+// some of these with boost equivalents.
+//
+#ifndef GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
+#define GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Types small_ and big_ are guaranteed such that sizeof(small_) <
+// sizeof(big_)
+typedef char small_;
+
+struct big_ {
+ char dummy[2];
+};
+
+// Identity metafunction.
+template <class T>
+struct identity_ {
+ typedef T type;
+};
+
+// integral_constant, defined in tr1, is a wrapper for an integer
+// value. We don't really need this generality; we could get away
+// with hardcoding the integer type to bool. We use the fully
+// general integer_constant for compatibility with tr1.
+
+template<class T, T v>
+struct integral_constant {
+ static const T value = v;
+ typedef T value_type;
+ typedef integral_constant<T, v> type;
+};
+
+template <class T, T v> const T integral_constant<T, v>::value;
+
+
+// Abbreviations: true_type and false_type are structs that represent boolean
+// true and false values. Also define the boost::mpl versions of those names,
+// true_ and false_.
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+typedef true_type true_;
+typedef false_type false_;
+
+// if_ is a templatized conditional statement.
+// if_<cond, A, B> is a compile time evaluation of cond.
+// if_<>::type contains A if cond is true, B otherwise.
+template<bool cond, typename A, typename B>
+struct if_{
+ typedef A type;
+};
+
+template<typename A, typename B>
+struct if_<false, A, B> {
+ typedef B type;
+};
+
+
+// type_equals_ is a template type comparator, similar to Loki IsSameType.
+// type_equals_<A, B>::value is true iff "A" is the same type as "B".
+//
+// New code should prefer base::is_same, defined in base/type_traits.h.
+// It is functionally identical, but is_same is the standard spelling.
+template<typename A, typename B>
+struct type_equals_ : public false_ {
+};
+
+template<typename A>
+struct type_equals_<A, A> : public true_ {
+};
+
+// and_ is a template && operator.
+// and_<A, B>::value evaluates "A::value && B::value".
+template<typename A, typename B>
+struct and_ : public integral_constant<bool, (A::value && B::value)> {
+};
+
+// or_ is a template || operator.
+// or_<A, B>::value evaluates "A::value || B::value".
+template<typename A, typename B>
+struct or_ : public integral_constant<bool, (A::value || B::value)> {
+};
+
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
diff --git a/third_party/protobuf/src/google/protobuf/stubs/template_util_unittest.cc b/third_party/protobuf/src/google/protobuf/stubs/template_util_unittest.cc
new file mode 100644
index 0000000..b1745e2
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/template_util_unittest.cc
@@ -0,0 +1,130 @@
+// Copyright 2005 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ----
+// Author: lar@google.com (Laramie Leavitt)
+//
+// These tests are really compile time tests.
+// If you try to step through this in a debugger
+// you will not see any evaluations, merely that
+// value is assigned true or false sequentially.
+
+#include <google/protobuf/stubs/template_util.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace GOOGLE_NAMESPACE = google::protobuf::internal;
+
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace {
+
+TEST(TemplateUtilTest, TestSize) {
+ EXPECT_GT(sizeof(GOOGLE_NAMESPACE::big_), sizeof(GOOGLE_NAMESPACE::small_));
+}
+
+TEST(TemplateUtilTest, TestIntegralConstants) {
+ // test the built-in types.
+ EXPECT_TRUE(true_type::value);
+ EXPECT_FALSE(false_type::value);
+
+ typedef integral_constant<int, 1> one_type;
+ EXPECT_EQ(1, one_type::value);
+}
+
+TEST(TemplateUtilTest, TestTemplateIf) {
+ typedef if_<true, true_type, false_type>::type if_true;
+ EXPECT_TRUE(if_true::value);
+
+ typedef if_<false, true_type, false_type>::type if_false;
+ EXPECT_FALSE(if_false::value);
+}
+
+TEST(TemplateUtilTest, TestTemplateTypeEquals) {
+ // Check that the TemplateTypeEquals works correctly.
+ bool value = false;
+
+ // Test the same type is true.
+ value = type_equals_<int, int>::value;
+ EXPECT_TRUE(value);
+
+ // Test different types are false.
+ value = type_equals_<float, int>::value;
+ EXPECT_FALSE(value);
+
+ // Test type aliasing.
+ typedef const int foo;
+ value = type_equals_<const foo, const int>::value;
+ EXPECT_TRUE(value);
+}
+
+TEST(TemplateUtilTest, TestTemplateAndOr) {
+ // Check that the TemplateTypeEquals works correctly.
+ bool value = false;
+
+ // Yes && Yes == true.
+ value = and_<true_, true_>::value;
+ EXPECT_TRUE(value);
+ // Yes && No == false.
+ value = and_<true_, false_>::value;
+ EXPECT_FALSE(value);
+ // No && Yes == false.
+ value = and_<false_, true_>::value;
+ EXPECT_FALSE(value);
+ // No && No == false.
+ value = and_<false_, false_>::value;
+ EXPECT_FALSE(value);
+
+ // Yes || Yes == true.
+ value = or_<true_, true_>::value;
+ EXPECT_TRUE(value);
+ // Yes || No == true.
+ value = or_<true_, false_>::value;
+ EXPECT_TRUE(value);
+ // No || Yes == true.
+ value = or_<false_, true_>::value;
+ EXPECT_TRUE(value);
+ // No || No == false.
+ value = or_<false_, false_>::value;
+ EXPECT_FALSE(value);
+}
+
+TEST(TemplateUtilTest, TestIdentity) {
+ EXPECT_TRUE(
+ (type_equals_<GOOGLE_NAMESPACE::identity_<int>::type, int>::value));
+ EXPECT_TRUE(
+ (type_equals_<GOOGLE_NAMESPACE::identity_<void>::type, void>::value));
+}
+
+} // anonymous namespace
+} // namespace internal
+} // namespace protobuf
+} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/stubs/type_traits.h b/third_party/protobuf/src/google/protobuf/stubs/type_traits.h
new file mode 100644
index 0000000..997f35d
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/type_traits.h
@@ -0,0 +1,346 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ----
+// Author: Matt Austern
+//
+// This code is compiled directly on many platforms, including client
+// platforms like Windows, Mac, and embedded systems. Before making
+// any changes here, make sure that you're not breaking any platforms.
+//
+// Define a small subset of tr1 type traits. The traits we define are:
+// is_integral
+// is_floating_point
+// is_pointer
+// is_enum
+// is_reference
+// is_pod
+// has_trivial_constructor
+// has_trivial_copy
+// has_trivial_assign
+// has_trivial_destructor
+// remove_const
+// remove_volatile
+// remove_cv
+// remove_reference
+// add_reference
+// remove_pointer
+// is_same
+// is_convertible
+// We can add more type traits as required.
+
+#ifndef GOOGLE_PROTOBUF_TYPE_TRAITS_H_
+#define GOOGLE_PROTOBUF_TYPE_TRAITS_H_
+
+#include <utility> // For pair
+
+#include <google/protobuf/stubs/template_util.h> // For true_type and false_type
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+template <class T> struct is_integral;
+template <class T> struct is_floating_point;
+template <class T> struct is_pointer;
+// MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least)
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+// is_enum uses is_convertible, which is not available on MSVC.
+template <class T> struct is_enum;
+#endif
+template <class T> struct is_reference;
+template <class T> struct is_pod;
+template <class T> struct has_trivial_constructor;
+template <class T> struct has_trivial_copy;
+template <class T> struct has_trivial_assign;
+template <class T> struct has_trivial_destructor;
+template <class T> struct remove_const;
+template <class T> struct remove_volatile;
+template <class T> struct remove_cv;
+template <class T> struct remove_reference;
+template <class T> struct add_reference;
+template <class T> struct remove_pointer;
+template <class T, class U> struct is_same;
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+template <class From, class To> struct is_convertible;
+#endif
+
+// is_integral is false except for the built-in integer types. A
+// cv-qualified type is integral if and only if the underlying type is.
+template <class T> struct is_integral : false_type { };
+template<> struct is_integral<bool> : true_type { };
+template<> struct is_integral<char> : true_type { };
+template<> struct is_integral<unsigned char> : true_type { };
+template<> struct is_integral<signed char> : true_type { };
+#if defined(_MSC_VER)
+// wchar_t is not by default a distinct type from unsigned short in
+// Microsoft C.
+// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx
+template<> struct is_integral<__wchar_t> : true_type { };
+#else
+template<> struct is_integral<wchar_t> : true_type { };
+#endif
+template<> struct is_integral<short> : true_type { };
+template<> struct is_integral<unsigned short> : true_type { };
+template<> struct is_integral<int> : true_type { };
+template<> struct is_integral<unsigned int> : true_type { };
+template<> struct is_integral<long> : true_type { };
+template<> struct is_integral<unsigned long> : true_type { };
+#ifdef HAVE_LONG_LONG
+template<> struct is_integral<long long> : true_type { };
+template<> struct is_integral<unsigned long long> : true_type { };
+#endif
+template <class T> struct is_integral<const T> : is_integral<T> { };
+template <class T> struct is_integral<volatile T> : is_integral<T> { };
+template <class T> struct is_integral<const volatile T> : is_integral<T> { };
+
+// is_floating_point is false except for the built-in floating-point types.
+// A cv-qualified type is integral if and only if the underlying type is.
+template <class T> struct is_floating_point : false_type { };
+template<> struct is_floating_point<float> : true_type { };
+template<> struct is_floating_point<double> : true_type { };
+template<> struct is_floating_point<long double> : true_type { };
+template <class T> struct is_floating_point<const T>
+ : is_floating_point<T> { };
+template <class T> struct is_floating_point<volatile T>
+ : is_floating_point<T> { };
+template <class T> struct is_floating_point<const volatile T>
+ : is_floating_point<T> { };
+
+// is_pointer is false except for pointer types. A cv-qualified type (e.g.
+// "int* const", as opposed to "int const*") is cv-qualified if and only if
+// the underlying type is.
+template <class T> struct is_pointer : false_type { };
+template <class T> struct is_pointer<T*> : true_type { };
+template <class T> struct is_pointer<const T> : is_pointer<T> { };
+template <class T> struct is_pointer<volatile T> : is_pointer<T> { };
+template <class T> struct is_pointer<const volatile T> : is_pointer<T> { };
+
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+
+namespace internal {
+
+template <class T> struct is_class_or_union {
+ template <class U> static small_ tester(void (U::*)());
+ template <class U> static big_ tester(...);
+ static const bool value = sizeof(tester<T>(0)) == sizeof(small_);
+};
+
+// is_convertible chokes if the first argument is an array. That's why
+// we use add_reference here.
+template <bool NotUnum, class T> struct is_enum_impl
+ : is_convertible<typename add_reference<T>::type, int> { };
+
+template <class T> struct is_enum_impl<true, T> : false_type { };
+
+} // namespace internal
+
+// Specified by TR1 [4.5.1] primary type categories.
+
+// Implementation note:
+//
+// Each type is either void, integral, floating point, array, pointer,
+// reference, member object pointer, member function pointer, enum,
+// union or class. Out of these, only integral, floating point, reference,
+// class and enum types are potentially convertible to int. Therefore,
+// if a type is not a reference, integral, floating point or class and
+// is convertible to int, it's a enum. Adding cv-qualification to a type
+// does not change whether it's an enum.
+//
+// Is-convertible-to-int check is done only if all other checks pass,
+// because it can't be used with some types (e.g. void or classes with
+// inaccessible conversion operators).
+template <class T> struct is_enum
+ : internal::is_enum_impl<
+ is_same<T, void>::value ||
+ is_integral<T>::value ||
+ is_floating_point<T>::value ||
+ is_reference<T>::value ||
+ internal::is_class_or_union<T>::value,
+ T> { };
+
+template <class T> struct is_enum<const T> : is_enum<T> { };
+template <class T> struct is_enum<volatile T> : is_enum<T> { };
+template <class T> struct is_enum<const volatile T> : is_enum<T> { };
+
+#endif
+
+// is_reference is false except for reference types.
+template<typename T> struct is_reference : false_type {};
+template<typename T> struct is_reference<T&> : true_type {};
+
+
+// We can't get is_pod right without compiler help, so fail conservatively.
+// We will assume it's false except for arithmetic types, enumerations,
+// pointers and cv-qualified versions thereof. Note that std::pair<T,U>
+// is not a POD even if T and U are PODs.
+template <class T> struct is_pod
+ : integral_constant<bool, (is_integral<T>::value ||
+ is_floating_point<T>::value ||
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+ // is_enum is not available on MSVC.
+ is_enum<T>::value ||
+#endif
+ is_pointer<T>::value)> { };
+template <class T> struct is_pod<const T> : is_pod<T> { };
+template <class T> struct is_pod<volatile T> : is_pod<T> { };
+template <class T> struct is_pod<const volatile T> : is_pod<T> { };
+
+
+// We can't get has_trivial_constructor right without compiler help, so
+// fail conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial
+// constructors. (3) array of a type with a trivial constructor.
+// (4) const versions thereof.
+template <class T> struct has_trivial_constructor : is_pod<T> { };
+template <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
+ : integral_constant<bool,
+ (has_trivial_constructor<T>::value &&
+ has_trivial_constructor<U>::value)> { };
+template <class A, int N> struct has_trivial_constructor<A[N]>
+ : has_trivial_constructor<A> { };
+template <class T> struct has_trivial_constructor<const T>
+ : has_trivial_constructor<T> { };
+
+// We can't get has_trivial_copy right without compiler help, so fail
+// conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial copy
+// constructors. (3) array of a type with a trivial copy constructor.
+// (4) const versions thereof.
+template <class T> struct has_trivial_copy : is_pod<T> { };
+template <class T, class U> struct has_trivial_copy<std::pair<T, U> >
+ : integral_constant<bool,
+ (has_trivial_copy<T>::value &&
+ has_trivial_copy<U>::value)> { };
+template <class A, int N> struct has_trivial_copy<A[N]>
+ : has_trivial_copy<A> { };
+template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };
+
+// We can't get has_trivial_assign right without compiler help, so fail
+// conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial copy
+// constructors. (3) array of a type with a trivial assign constructor.
+template <class T> struct has_trivial_assign : is_pod<T> { };
+template <class T, class U> struct has_trivial_assign<std::pair<T, U> >
+ : integral_constant<bool,
+ (has_trivial_assign<T>::value &&
+ has_trivial_assign<U>::value)> { };
+template <class A, int N> struct has_trivial_assign<A[N]>
+ : has_trivial_assign<A> { };
+
+// We can't get has_trivial_destructor right without compiler help, so
+// fail conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial
+// destructors. (3) array of a type with a trivial destructor.
+// (4) const versions thereof.
+template <class T> struct has_trivial_destructor : is_pod<T> { };
+template <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
+ : integral_constant<bool,
+ (has_trivial_destructor<T>::value &&
+ has_trivial_destructor<U>::value)> { };
+template <class A, int N> struct has_trivial_destructor<A[N]>
+ : has_trivial_destructor<A> { };
+template <class T> struct has_trivial_destructor<const T>
+ : has_trivial_destructor<T> { };
+
+// Specified by TR1 [4.7.1]
+template<typename T> struct remove_const { typedef T type; };
+template<typename T> struct remove_const<T const> { typedef T type; };
+template<typename T> struct remove_volatile { typedef T type; };
+template<typename T> struct remove_volatile<T volatile> { typedef T type; };
+template<typename T> struct remove_cv {
+ typedef typename remove_const<typename remove_volatile<T>::type>::type type;
+};
+
+
+// Specified by TR1 [4.7.2] Reference modifications.
+template<typename T> struct remove_reference { typedef T type; };
+template<typename T> struct remove_reference<T&> { typedef T type; };
+
+template <typename T> struct add_reference { typedef T& type; };
+template <typename T> struct add_reference<T&> { typedef T& type; };
+
+// Specified by TR1 [4.7.4] Pointer modifications.
+template<typename T> struct remove_pointer { typedef T type; };
+template<typename T> struct remove_pointer<T*> { typedef T type; };
+template<typename T> struct remove_pointer<T* const> { typedef T type; };
+template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
+template<typename T> struct remove_pointer<T* const volatile> {
+ typedef T type; };
+
+// Specified by TR1 [4.6] Relationships between types
+template<typename T, typename U> struct is_same : public false_type { };
+template<typename T> struct is_same<T, T> : public true_type { };
+
+// Specified by TR1 [4.6] Relationships between types
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+namespace internal {
+
+// This class is an implementation detail for is_convertible, and you
+// don't need to know how it works to use is_convertible. For those
+// who care: we declare two different functions, one whose argument is
+// of type To and one with a variadic argument list. We give them
+// return types of different size, so we can use sizeof to trick the
+// compiler into telling us which function it would have chosen if we
+// had called it with an argument of type From. See Alexandrescu's
+// _Modern C++ Design_ for more details on this sort of trick.
+
+template <typename From, typename To>
+struct ConvertHelper {
+ static small_ Test(To);
+ static big_ Test(...);
+ static From Create();
+};
+} // namespace internal
+
+// Inherits from true_type if From is convertible to To, false_type otherwise.
+template <typename From, typename To>
+struct is_convertible
+ : integral_constant<bool,
+ sizeof(internal::ConvertHelper<From, To>::Test(
+ internal::ConvertHelper<From, To>::Create()))
+ == sizeof(small_)> {
+};
+#endif
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google
+
+// Right now these macros are no-ops, and mostly just document the fact
+// these types are PODs, for human use. They may be made more contentful
+// later. The typedef is just to make it legal to put a semicolon after
+// these macros.
+#define DECLARE_POD(TypeName) typedef int Dummy_Type_For_DECLARE_POD
+#define DECLARE_NESTED_POD(TypeName) DECLARE_POD(TypeName)
+#define PROPAGATE_POD_FROM_TEMPLATE_ARGUMENT(TemplateName) \
+ typedef int Dummy_Type_For_PROPAGATE_POD_FROM_TEMPLATE_ARGUMENT
+#define ENFORCE_POD(TypeName) typedef int Dummy_Type_For_ENFORCE_POD
+
+#endif // GOOGLE_PROTOBUF_TYPE_TRAITS_H_
diff --git a/third_party/protobuf/src/google/protobuf/stubs/type_traits_unittest.cc b/third_party/protobuf/src/google/protobuf/stubs/type_traits_unittest.cc
new file mode 100644
index 0000000..00e5a47
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/type_traits_unittest.cc
@@ -0,0 +1,647 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ----
+// Author: Matt Austern
+
+#include <google/protobuf/stubs/type_traits.h>
+
+#include <stdlib.h> // for exit()
+#include <stdio.h>
+#include <string>
+#include <vector>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+typedef int int32;
+typedef long int64;
+
+using std::string;
+using std::vector;
+using std::pair;
+
+using google::protobuf::internal::add_reference;
+using google::protobuf::internal::has_trivial_assign;
+using google::protobuf::internal::has_trivial_constructor;
+using google::protobuf::internal::has_trivial_copy;
+using google::protobuf::internal::has_trivial_destructor;
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+using google::protobuf::internal::is_convertible;
+using google::protobuf::internal::is_enum;
+#endif
+using google::protobuf::internal::is_floating_point;
+using google::protobuf::internal::is_integral;
+using google::protobuf::internal::is_pointer;
+using google::protobuf::internal::is_pod;
+using google::protobuf::internal::is_reference;
+using google::protobuf::internal::is_same;
+using google::protobuf::internal::remove_const;
+using google::protobuf::internal::remove_cv;
+using google::protobuf::internal::remove_pointer;
+using google::protobuf::internal::remove_reference;
+using google::protobuf::internal::remove_volatile;
+
+
+// This assertion produces errors like "error: invalid use of
+// incomplete type 'struct <unnamed>::AssertTypesEq<const int, int>'"
+// when it fails.
+template<typename T, typename U> struct AssertTypesEq;
+template<typename T> struct AssertTypesEq<T, T> {};
+#define COMPILE_ASSERT_TYPES_EQ(T, U) static_cast<void>(AssertTypesEq<T, U>())
+
+// A user-defined POD type.
+struct A {
+ int n_;
+};
+
+// A user-defined non-POD type with a trivial copy constructor.
+class B {
+ public:
+ explicit B(int n) : n_(n) { }
+ private:
+ int n_;
+};
+
+// Another user-defined non-POD type with a trivial copy constructor.
+// We will explicitly declare C to have a trivial copy constructor
+// by specializing has_trivial_copy.
+class C {
+ public:
+ explicit C(int n) : n_(n) { }
+ private:
+ int n_;
+};
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<> struct has_trivial_copy<C> : true_type { };
+} // namespace internal
+} // namespace protobuf
+} // namespace google
+
+// Another user-defined non-POD type with a trivial assignment operator.
+// We will explicitly declare C to have a trivial assignment operator
+// by specializing has_trivial_assign.
+class D {
+ public:
+ explicit D(int n) : n_(n) { }
+ private:
+ int n_;
+};
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<> struct has_trivial_assign<D> : true_type { };
+} // namespace internal
+} // namespace protobuf
+} // namespace google
+
+// Another user-defined non-POD type with a trivial constructor.
+// We will explicitly declare E to have a trivial constructor
+// by specializing has_trivial_constructor.
+class E {
+ public:
+ int n_;
+};
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<> struct has_trivial_constructor<E> : true_type { };
+} // namespace internal
+} // namespace protobuf
+} // namespace google
+
+// Another user-defined non-POD type with a trivial destructor.
+// We will explicitly declare E to have a trivial destructor
+// by specializing has_trivial_destructor.
+class F {
+ public:
+ explicit F(int n) : n_(n) { }
+ private:
+ int n_;
+};
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<> struct has_trivial_destructor<F> : true_type { };
+} // namespace internal
+} // namespace protobuf
+} // namespace google
+
+enum G {};
+
+union H {};
+
+class I {
+ public:
+ operator int() const;
+};
+
+class J {
+ private:
+ operator int() const;
+};
+
+namespace google {
+namespace protobuf {
+namespace {
+
+// A base class and a derived class that inherits from it, used for
+// testing conversion type traits.
+class Base {
+ public:
+ virtual ~Base() { }
+};
+
+class Derived : public Base {
+};
+
+TEST(TypeTraitsTest, TestIsInteger) {
+ // Verify that is_integral is true for all integer types.
+ EXPECT_TRUE(is_integral<bool>::value);
+ EXPECT_TRUE(is_integral<char>::value);
+ EXPECT_TRUE(is_integral<unsigned char>::value);
+ EXPECT_TRUE(is_integral<signed char>::value);
+ EXPECT_TRUE(is_integral<wchar_t>::value);
+ EXPECT_TRUE(is_integral<int>::value);
+ EXPECT_TRUE(is_integral<unsigned int>::value);
+ EXPECT_TRUE(is_integral<short>::value);
+ EXPECT_TRUE(is_integral<unsigned short>::value);
+ EXPECT_TRUE(is_integral<long>::value);
+ EXPECT_TRUE(is_integral<unsigned long>::value);
+
+ // Verify that is_integral is false for a few non-integer types.
+ EXPECT_FALSE(is_integral<void>::value);
+ EXPECT_FALSE(is_integral<float>::value);
+ EXPECT_FALSE(is_integral<string>::value);
+ EXPECT_FALSE(is_integral<int*>::value);
+ EXPECT_FALSE(is_integral<A>::value);
+ EXPECT_FALSE((is_integral<pair<int, int> >::value));
+
+ // Verify that cv-qualified integral types are still integral, and
+ // cv-qualified non-integral types are still non-integral.
+ EXPECT_TRUE(is_integral<const char>::value);
+ EXPECT_TRUE(is_integral<volatile bool>::value);
+ EXPECT_TRUE(is_integral<const volatile unsigned int>::value);
+ EXPECT_FALSE(is_integral<const float>::value);
+ EXPECT_FALSE(is_integral<int* volatile>::value);
+ EXPECT_FALSE(is_integral<const volatile string>::value);
+}
+
+TEST(TypeTraitsTest, TestIsFloating) {
+ // Verify that is_floating_point is true for all floating-point types.
+ EXPECT_TRUE(is_floating_point<float>::value);
+ EXPECT_TRUE(is_floating_point<double>::value);
+ EXPECT_TRUE(is_floating_point<long double>::value);
+
+ // Verify that is_floating_point is false for a few non-float types.
+ EXPECT_FALSE(is_floating_point<void>::value);
+ EXPECT_FALSE(is_floating_point<long>::value);
+ EXPECT_FALSE(is_floating_point<string>::value);
+ EXPECT_FALSE(is_floating_point<float*>::value);
+ EXPECT_FALSE(is_floating_point<A>::value);
+ EXPECT_FALSE((is_floating_point<pair<int, int> >::value));
+
+ // Verify that cv-qualified floating point types are still floating, and
+ // cv-qualified non-floating types are still non-floating.
+ EXPECT_TRUE(is_floating_point<const float>::value);
+ EXPECT_TRUE(is_floating_point<volatile double>::value);
+ EXPECT_TRUE(is_floating_point<const volatile long double>::value);
+ EXPECT_FALSE(is_floating_point<const int>::value);
+ EXPECT_FALSE(is_floating_point<volatile string>::value);
+ EXPECT_FALSE(is_floating_point<const volatile char>::value);
+}
+
+TEST(TypeTraitsTest, TestIsPointer) {
+ // Verify that is_pointer is true for some pointer types.
+ EXPECT_TRUE(is_pointer<int*>::value);
+ EXPECT_TRUE(is_pointer<void*>::value);
+ EXPECT_TRUE(is_pointer<string*>::value);
+ EXPECT_TRUE(is_pointer<const void*>::value);
+ EXPECT_TRUE(is_pointer<volatile float* const*>::value);
+
+ // Verify that is_pointer is false for some non-pointer types.
+ EXPECT_FALSE(is_pointer<void>::value);
+ EXPECT_FALSE(is_pointer<float&>::value);
+ EXPECT_FALSE(is_pointer<long>::value);
+ EXPECT_FALSE(is_pointer<vector<int*> >::value);
+ EXPECT_FALSE(is_pointer<int[5]>::value);
+
+ // A function pointer is a pointer, but a function type, or a function
+ // reference type, is not.
+ EXPECT_TRUE(is_pointer<int (*)(int x)>::value);
+ EXPECT_FALSE(is_pointer<void(char x)>::value);
+ EXPECT_FALSE(is_pointer<double (&)(string x)>::value);
+
+ // Verify that is_pointer<T> is true for some cv-qualified pointer types,
+ // and false for some cv-qualified non-pointer types.
+ EXPECT_TRUE(is_pointer<int* const>::value);
+ EXPECT_TRUE(is_pointer<const void* volatile>::value);
+ EXPECT_TRUE(is_pointer<char** const volatile>::value);
+ EXPECT_FALSE(is_pointer<const int>::value);
+ EXPECT_FALSE(is_pointer<volatile vector<int*> >::value);
+ EXPECT_FALSE(is_pointer<const volatile double>::value);
+}
+
+TEST(TypeTraitsTest, TestIsEnum) {
+// is_enum isn't supported on MSVC or gcc 3.x
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+ // Verify that is_enum is true for enum types.
+ EXPECT_TRUE(is_enum<G>::value);
+ EXPECT_TRUE(is_enum<const G>::value);
+ EXPECT_TRUE(is_enum<volatile G>::value);
+ EXPECT_TRUE(is_enum<const volatile G>::value);
+
+ // Verify that is_enum is false for a few non-enum types.
+ EXPECT_FALSE(is_enum<void>::value);
+ EXPECT_FALSE(is_enum<G&>::value);
+ EXPECT_FALSE(is_enum<G[1]>::value);
+ EXPECT_FALSE(is_enum<const G[1]>::value);
+ EXPECT_FALSE(is_enum<G[]>::value);
+ EXPECT_FALSE(is_enum<int>::value);
+ EXPECT_FALSE(is_enum<float>::value);
+ EXPECT_FALSE(is_enum<A>::value);
+ EXPECT_FALSE(is_enum<A*>::value);
+ EXPECT_FALSE(is_enum<const A>::value);
+ EXPECT_FALSE(is_enum<H>::value);
+ EXPECT_FALSE(is_enum<I>::value);
+ EXPECT_FALSE(is_enum<J>::value);
+ EXPECT_FALSE(is_enum<void()>::value);
+ EXPECT_FALSE(is_enum<void(*)()>::value);
+ EXPECT_FALSE(is_enum<int A::*>::value);
+ EXPECT_FALSE(is_enum<void (A::*)()>::value);
+#endif
+}
+
+TEST(TypeTraitsTest, TestIsReference) {
+ // Verifies that is_reference is true for all reference types.
+ typedef float& RefFloat;
+ EXPECT_TRUE(is_reference<float&>::value);
+ EXPECT_TRUE(is_reference<const int&>::value);
+ EXPECT_TRUE(is_reference<const int*&>::value);
+ EXPECT_TRUE(is_reference<int (&)(bool)>::value);
+ EXPECT_TRUE(is_reference<RefFloat>::value);
+ EXPECT_TRUE(is_reference<const RefFloat>::value);
+ EXPECT_TRUE(is_reference<volatile RefFloat>::value);
+ EXPECT_TRUE(is_reference<const volatile RefFloat>::value);
+
+
+ // Verifies that is_reference is false for all non-reference types.
+ EXPECT_FALSE(is_reference<float>::value);
+ EXPECT_FALSE(is_reference<const float>::value);
+ EXPECT_FALSE(is_reference<volatile float>::value);
+ EXPECT_FALSE(is_reference<const volatile float>::value);
+ EXPECT_FALSE(is_reference<const int*>::value);
+ EXPECT_FALSE(is_reference<int()>::value);
+ EXPECT_FALSE(is_reference<void(*)(const char&)>::value);
+}
+
+TEST(TypeTraitsTest, TestAddReference) {
+ COMPILE_ASSERT_TYPES_EQ(int&, add_reference<int>::type);
+ COMPILE_ASSERT_TYPES_EQ(const int&, add_reference<const int>::type);
+ COMPILE_ASSERT_TYPES_EQ(volatile int&,
+ add_reference<volatile int>::type);
+ COMPILE_ASSERT_TYPES_EQ(const volatile int&,
+ add_reference<const volatile int>::type);
+ COMPILE_ASSERT_TYPES_EQ(int&, add_reference<int&>::type);
+ COMPILE_ASSERT_TYPES_EQ(const int&, add_reference<const int&>::type);
+ COMPILE_ASSERT_TYPES_EQ(volatile int&,
+ add_reference<volatile int&>::type);
+ COMPILE_ASSERT_TYPES_EQ(const volatile int&,
+ add_reference<const volatile int&>::type);
+}
+
+TEST(TypeTraitsTest, TestIsPod) {
+ // Verify that arithmetic types and pointers are marked as PODs.
+ EXPECT_TRUE(is_pod<bool>::value);
+ EXPECT_TRUE(is_pod<char>::value);
+ EXPECT_TRUE(is_pod<unsigned char>::value);
+ EXPECT_TRUE(is_pod<signed char>::value);
+ EXPECT_TRUE(is_pod<wchar_t>::value);
+ EXPECT_TRUE(is_pod<int>::value);
+ EXPECT_TRUE(is_pod<unsigned int>::value);
+ EXPECT_TRUE(is_pod<short>::value);
+ EXPECT_TRUE(is_pod<unsigned short>::value);
+ EXPECT_TRUE(is_pod<long>::value);
+ EXPECT_TRUE(is_pod<unsigned long>::value);
+ EXPECT_TRUE(is_pod<float>::value);
+ EXPECT_TRUE(is_pod<double>::value);
+ EXPECT_TRUE(is_pod<long double>::value);
+ EXPECT_TRUE(is_pod<string*>::value);
+ EXPECT_TRUE(is_pod<A*>::value);
+ EXPECT_TRUE(is_pod<const B*>::value);
+ EXPECT_TRUE(is_pod<C**>::value);
+ EXPECT_TRUE(is_pod<const int>::value);
+ EXPECT_TRUE(is_pod<char* volatile>::value);
+ EXPECT_TRUE(is_pod<const volatile double>::value);
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+ EXPECT_TRUE(is_pod<G>::value);
+ EXPECT_TRUE(is_pod<const G>::value);
+ EXPECT_TRUE(is_pod<volatile G>::value);
+ EXPECT_TRUE(is_pod<const volatile G>::value);
+#endif
+
+ // Verify that some non-POD types are not marked as PODs.
+ EXPECT_FALSE(is_pod<void>::value);
+ EXPECT_FALSE(is_pod<string>::value);
+ EXPECT_FALSE((is_pod<pair<int, int> >::value));
+ EXPECT_FALSE(is_pod<A>::value);
+ EXPECT_FALSE(is_pod<B>::value);
+ EXPECT_FALSE(is_pod<C>::value);
+ EXPECT_FALSE(is_pod<const string>::value);
+ EXPECT_FALSE(is_pod<volatile A>::value);
+ EXPECT_FALSE(is_pod<const volatile B>::value);
+}
+
+TEST(TypeTraitsTest, TestHasTrivialConstructor) {
+ // Verify that arithmetic types and pointers have trivial constructors.
+ EXPECT_TRUE(has_trivial_constructor<bool>::value);
+ EXPECT_TRUE(has_trivial_constructor<char>::value);
+ EXPECT_TRUE(has_trivial_constructor<unsigned char>::value);
+ EXPECT_TRUE(has_trivial_constructor<signed char>::value);
+ EXPECT_TRUE(has_trivial_constructor<wchar_t>::value);
+ EXPECT_TRUE(has_trivial_constructor<int>::value);
+ EXPECT_TRUE(has_trivial_constructor<unsigned int>::value);
+ EXPECT_TRUE(has_trivial_constructor<short>::value);
+ EXPECT_TRUE(has_trivial_constructor<unsigned short>::value);
+ EXPECT_TRUE(has_trivial_constructor<long>::value);
+ EXPECT_TRUE(has_trivial_constructor<unsigned long>::value);
+ EXPECT_TRUE(has_trivial_constructor<float>::value);
+ EXPECT_TRUE(has_trivial_constructor<double>::value);
+ EXPECT_TRUE(has_trivial_constructor<long double>::value);
+ EXPECT_TRUE(has_trivial_constructor<string*>::value);
+ EXPECT_TRUE(has_trivial_constructor<A*>::value);
+ EXPECT_TRUE(has_trivial_constructor<const B*>::value);
+ EXPECT_TRUE(has_trivial_constructor<C**>::value);
+
+ // Verify that pairs and arrays of such types have trivial
+ // constructors.
+ typedef int int10[10];
+ EXPECT_TRUE((has_trivial_constructor<pair<int, char*> >::value));
+ EXPECT_TRUE(has_trivial_constructor<int10>::value);
+
+ // Verify that pairs of types without trivial constructors
+ // are not marked as trivial.
+ EXPECT_FALSE((has_trivial_constructor<pair<int, string> >::value));
+ EXPECT_FALSE((has_trivial_constructor<pair<string, int> >::value));
+
+ // Verify that types without trivial constructors are
+ // correctly marked as such.
+ EXPECT_FALSE(has_trivial_constructor<string>::value);
+ EXPECT_FALSE(has_trivial_constructor<vector<int> >::value);
+
+ // Verify that E, which we have declared to have a trivial
+ // constructor, is correctly marked as such.
+ EXPECT_TRUE(has_trivial_constructor<E>::value);
+}
+
+TEST(TypeTraitsTest, TestHasTrivialCopy) {
+ // Verify that arithmetic types and pointers have trivial copy
+ // constructors.
+ EXPECT_TRUE(has_trivial_copy<bool>::value);
+ EXPECT_TRUE(has_trivial_copy<char>::value);
+ EXPECT_TRUE(has_trivial_copy<unsigned char>::value);
+ EXPECT_TRUE(has_trivial_copy<signed char>::value);
+ EXPECT_TRUE(has_trivial_copy<wchar_t>::value);
+ EXPECT_TRUE(has_trivial_copy<int>::value);
+ EXPECT_TRUE(has_trivial_copy<unsigned int>::value);
+ EXPECT_TRUE(has_trivial_copy<short>::value);
+ EXPECT_TRUE(has_trivial_copy<unsigned short>::value);
+ EXPECT_TRUE(has_trivial_copy<long>::value);
+ EXPECT_TRUE(has_trivial_copy<unsigned long>::value);
+ EXPECT_TRUE(has_trivial_copy<float>::value);
+ EXPECT_TRUE(has_trivial_copy<double>::value);
+ EXPECT_TRUE(has_trivial_copy<long double>::value);
+ EXPECT_TRUE(has_trivial_copy<string*>::value);
+ EXPECT_TRUE(has_trivial_copy<A*>::value);
+ EXPECT_TRUE(has_trivial_copy<const B*>::value);
+ EXPECT_TRUE(has_trivial_copy<C**>::value);
+
+ // Verify that pairs and arrays of such types have trivial
+ // copy constructors.
+ typedef int int10[10];
+ EXPECT_TRUE((has_trivial_copy<pair<int, char*> >::value));
+ EXPECT_TRUE(has_trivial_copy<int10>::value);
+
+ // Verify that pairs of types without trivial copy constructors
+ // are not marked as trivial.
+ EXPECT_FALSE((has_trivial_copy<pair<int, string> >::value));
+ EXPECT_FALSE((has_trivial_copy<pair<string, int> >::value));
+
+ // Verify that types without trivial copy constructors are
+ // correctly marked as such.
+ EXPECT_FALSE(has_trivial_copy<string>::value);
+ EXPECT_FALSE(has_trivial_copy<vector<int> >::value);
+
+ // Verify that C, which we have declared to have a trivial
+ // copy constructor, is correctly marked as such.
+ EXPECT_TRUE(has_trivial_copy<C>::value);
+}
+
+TEST(TypeTraitsTest, TestHasTrivialAssign) {
+ // Verify that arithmetic types and pointers have trivial assignment
+ // operators.
+ EXPECT_TRUE(has_trivial_assign<bool>::value);
+ EXPECT_TRUE(has_trivial_assign<char>::value);
+ EXPECT_TRUE(has_trivial_assign<unsigned char>::value);
+ EXPECT_TRUE(has_trivial_assign<signed char>::value);
+ EXPECT_TRUE(has_trivial_assign<wchar_t>::value);
+ EXPECT_TRUE(has_trivial_assign<int>::value);
+ EXPECT_TRUE(has_trivial_assign<unsigned int>::value);
+ EXPECT_TRUE(has_trivial_assign<short>::value);
+ EXPECT_TRUE(has_trivial_assign<unsigned short>::value);
+ EXPECT_TRUE(has_trivial_assign<long>::value);
+ EXPECT_TRUE(has_trivial_assign<unsigned long>::value);
+ EXPECT_TRUE(has_trivial_assign<float>::value);
+ EXPECT_TRUE(has_trivial_assign<double>::value);
+ EXPECT_TRUE(has_trivial_assign<long double>::value);
+ EXPECT_TRUE(has_trivial_assign<string*>::value);
+ EXPECT_TRUE(has_trivial_assign<A*>::value);
+ EXPECT_TRUE(has_trivial_assign<const B*>::value);
+ EXPECT_TRUE(has_trivial_assign<C**>::value);
+
+ // Verify that pairs and arrays of such types have trivial
+ // assignment operators.
+ typedef int int10[10];
+ EXPECT_TRUE((has_trivial_assign<pair<int, char*> >::value));
+ EXPECT_TRUE(has_trivial_assign<int10>::value);
+
+ // Verify that pairs of types without trivial assignment operators
+ // are not marked as trivial.
+ EXPECT_FALSE((has_trivial_assign<pair<int, string> >::value));
+ EXPECT_FALSE((has_trivial_assign<pair<string, int> >::value));
+
+ // Verify that types without trivial assignment operators are
+ // correctly marked as such.
+ EXPECT_FALSE(has_trivial_assign<string>::value);
+ EXPECT_FALSE(has_trivial_assign<vector<int> >::value);
+
+ // Verify that D, which we have declared to have a trivial
+ // assignment operator, is correctly marked as such.
+ EXPECT_TRUE(has_trivial_assign<D>::value);
+}
+
+TEST(TypeTraitsTest, TestHasTrivialDestructor) {
+ // Verify that arithmetic types and pointers have trivial destructors.
+ EXPECT_TRUE(has_trivial_destructor<bool>::value);
+ EXPECT_TRUE(has_trivial_destructor<char>::value);
+ EXPECT_TRUE(has_trivial_destructor<unsigned char>::value);
+ EXPECT_TRUE(has_trivial_destructor<signed char>::value);
+ EXPECT_TRUE(has_trivial_destructor<wchar_t>::value);
+ EXPECT_TRUE(has_trivial_destructor<int>::value);
+ EXPECT_TRUE(has_trivial_destructor<unsigned int>::value);
+ EXPECT_TRUE(has_trivial_destructor<short>::value);
+ EXPECT_TRUE(has_trivial_destructor<unsigned short>::value);
+ EXPECT_TRUE(has_trivial_destructor<long>::value);
+ EXPECT_TRUE(has_trivial_destructor<unsigned long>::value);
+ EXPECT_TRUE(has_trivial_destructor<float>::value);
+ EXPECT_TRUE(has_trivial_destructor<double>::value);
+ EXPECT_TRUE(has_trivial_destructor<long double>::value);
+ EXPECT_TRUE(has_trivial_destructor<string*>::value);
+ EXPECT_TRUE(has_trivial_destructor<A*>::value);
+ EXPECT_TRUE(has_trivial_destructor<const B*>::value);
+ EXPECT_TRUE(has_trivial_destructor<C**>::value);
+
+ // Verify that pairs and arrays of such types have trivial
+ // destructors.
+ typedef int int10[10];
+ EXPECT_TRUE((has_trivial_destructor<pair<int, char*> >::value));
+ EXPECT_TRUE(has_trivial_destructor<int10>::value);
+
+ // Verify that pairs of types without trivial destructors
+ // are not marked as trivial.
+ EXPECT_FALSE((has_trivial_destructor<pair<int, string> >::value));
+ EXPECT_FALSE((has_trivial_destructor<pair<string, int> >::value));
+
+ // Verify that types without trivial destructors are
+ // correctly marked as such.
+ EXPECT_FALSE(has_trivial_destructor<string>::value);
+ EXPECT_FALSE(has_trivial_destructor<vector<int> >::value);
+
+ // Verify that F, which we have declared to have a trivial
+ // destructor, is correctly marked as such.
+ EXPECT_TRUE(has_trivial_destructor<F>::value);
+}
+
+// Tests remove_pointer.
+TEST(TypeTraitsTest, TestRemovePointer) {
+ COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int>::type);
+ COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int*>::type);
+ COMPILE_ASSERT_TYPES_EQ(const int, remove_pointer<const int*>::type);
+ COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int* const>::type);
+ COMPILE_ASSERT_TYPES_EQ(int, remove_pointer<int* volatile>::type);
+}
+
+TEST(TypeTraitsTest, TestRemoveConst) {
+ COMPILE_ASSERT_TYPES_EQ(int, remove_const<int>::type);
+ COMPILE_ASSERT_TYPES_EQ(int, remove_const<const int>::type);
+ COMPILE_ASSERT_TYPES_EQ(int *, remove_const<int * const>::type);
+ // TR1 examples.
+ COMPILE_ASSERT_TYPES_EQ(const int *, remove_const<const int *>::type);
+ COMPILE_ASSERT_TYPES_EQ(volatile int,
+ remove_const<const volatile int>::type);
+}
+
+TEST(TypeTraitsTest, TestRemoveVolatile) {
+ COMPILE_ASSERT_TYPES_EQ(int, remove_volatile<int>::type);
+ COMPILE_ASSERT_TYPES_EQ(int, remove_volatile<volatile int>::type);
+ COMPILE_ASSERT_TYPES_EQ(int *, remove_volatile<int * volatile>::type);
+ // TR1 examples.
+ COMPILE_ASSERT_TYPES_EQ(volatile int *,
+ remove_volatile<volatile int *>::type);
+ COMPILE_ASSERT_TYPES_EQ(const int,
+ remove_volatile<const volatile int>::type);
+}
+
+TEST(TypeTraitsTest, TestRemoveCV) {
+ COMPILE_ASSERT_TYPES_EQ(int, remove_cv<int>::type);
+ COMPILE_ASSERT_TYPES_EQ(int, remove_cv<volatile int>::type);
+ COMPILE_ASSERT_TYPES_EQ(int, remove_cv<const int>::type);
+ COMPILE_ASSERT_TYPES_EQ(int *, remove_cv<int * const volatile>::type);
+ // TR1 examples.
+ COMPILE_ASSERT_TYPES_EQ(const volatile int *,
+ remove_cv<const volatile int *>::type);
+ COMPILE_ASSERT_TYPES_EQ(int,
+ remove_cv<const volatile int>::type);
+}
+
+TEST(TypeTraitsTest, TestRemoveReference) {
+ COMPILE_ASSERT_TYPES_EQ(int, remove_reference<int>::type);
+ COMPILE_ASSERT_TYPES_EQ(int, remove_reference<int&>::type);
+ COMPILE_ASSERT_TYPES_EQ(const int, remove_reference<const int&>::type);
+ COMPILE_ASSERT_TYPES_EQ(int*, remove_reference<int * &>::type);
+}
+
+TEST(TypeTraitsTest, TestIsSame) {
+ EXPECT_TRUE((is_same<int32, int32>::value));
+ EXPECT_FALSE((is_same<int32, int64>::value));
+ EXPECT_FALSE((is_same<int64, int32>::value));
+ EXPECT_FALSE((is_same<int, const int>::value));
+
+ EXPECT_TRUE((is_same<void, void>::value));
+ EXPECT_FALSE((is_same<void, int>::value));
+ EXPECT_FALSE((is_same<int, void>::value));
+
+ EXPECT_TRUE((is_same<int*, int*>::value));
+ EXPECT_TRUE((is_same<void*, void*>::value));
+ EXPECT_FALSE((is_same<int*, void*>::value));
+ EXPECT_FALSE((is_same<void*, int*>::value));
+ EXPECT_FALSE((is_same<void*, const void*>::value));
+ EXPECT_FALSE((is_same<void*, void* const>::value));
+
+ EXPECT_TRUE((is_same<Base*, Base*>::value));
+ EXPECT_TRUE((is_same<Derived*, Derived*>::value));
+ EXPECT_FALSE((is_same<Base*, Derived*>::value));
+ EXPECT_FALSE((is_same<Derived*, Base*>::value));
+}
+
+TEST(TypeTraitsTest, TestConvertible) {
+#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+ EXPECT_TRUE((is_convertible<int, int>::value));
+ EXPECT_TRUE((is_convertible<int, long>::value));
+ EXPECT_TRUE((is_convertible<long, int>::value));
+
+ EXPECT_TRUE((is_convertible<int*, void*>::value));
+ EXPECT_FALSE((is_convertible<void*, int*>::value));
+
+ EXPECT_TRUE((is_convertible<Derived*, Base*>::value));
+ EXPECT_FALSE((is_convertible<Base*, Derived*>::value));
+ EXPECT_TRUE((is_convertible<Derived*, const Base*>::value));
+ EXPECT_FALSE((is_convertible<const Derived*, Base*>::value));
+#endif
+}
+
+} // anonymous namespace
+} // namespace protobuf
+} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/test_util.cc b/third_party/protobuf/src/google/protobuf/test_util.cc
index af8b390..841f4b3 100644
--- a/third_party/protobuf/src/google/protobuf/test_util.cc
+++ b/third_party/protobuf/src/google/protobuf/test_util.cc
@@ -50,6 +50,13 @@
namespace protobuf {
void TestUtil::SetAllFields(unittest::TestAllTypes* message) {
+ SetOptionalFields(message);
+ AddRepeatedFields1(message);
+ AddRepeatedFields2(message);
+ SetDefaultFields(message);
+}
+
+void TestUtil::SetOptionalFields(unittest::TestAllTypes* message) {
message->set_optional_int32 (101);
message->set_optional_int64 (102);
message->set_optional_uint32 (103);
@@ -66,10 +73,12 @@
message->set_optional_string ("115");
message->set_optional_bytes ("116");
- message->mutable_optionalgroup ()->set_a(117);
- message->mutable_optional_nested_message ()->set_bb(118);
- message->mutable_optional_foreign_message()->set_c(119);
- message->mutable_optional_import_message ()->set_d(120);
+ message->mutable_optionalgroup ()->set_a(117);
+ message->mutable_optional_nested_message ()->set_bb(118);
+ message->mutable_optional_foreign_message ()->set_c(119);
+ message->mutable_optional_import_message ()->set_d(120);
+ message->mutable_optional_public_import_message()->set_e(126);
+ message->mutable_optional_lazy_message ()->set_bb(127);
message->set_optional_nested_enum (unittest::TestAllTypes::BAZ);
message->set_optional_foreign_enum(unittest::FOREIGN_BAZ );
@@ -87,9 +96,11 @@
message->GetDescriptor()->FindFieldByName("optional_cord"),
"125");
#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
+}
- // -----------------------------------------------------------------
+// -------------------------------------------------------------------
+void TestUtil::AddRepeatedFields1(unittest::TestAllTypes* message) {
message->add_repeated_int32 (201);
message->add_repeated_int64 (202);
message->add_repeated_uint32 (203);
@@ -110,6 +121,7 @@
message->add_repeated_nested_message ()->set_bb(218);
message->add_repeated_foreign_message()->set_c(219);
message->add_repeated_import_message ()->set_d(220);
+ message->add_repeated_lazy_message ()->set_bb(227);
message->add_repeated_nested_enum (unittest::TestAllTypes::BAR);
message->add_repeated_foreign_enum(unittest::FOREIGN_BAR );
@@ -125,7 +137,9 @@
message->GetDescriptor()->FindFieldByName("repeated_cord"),
"225");
#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
+}
+void TestUtil::AddRepeatedFields2(unittest::TestAllTypes* message) {
// Add a second one of each field.
message->add_repeated_int32 (301);
message->add_repeated_int64 (302);
@@ -147,6 +161,7 @@
message->add_repeated_nested_message ()->set_bb(318);
message->add_repeated_foreign_message()->set_c(319);
message->add_repeated_import_message ()->set_d(320);
+ message->add_repeated_lazy_message ()->set_bb(327);
message->add_repeated_nested_enum (unittest::TestAllTypes::BAZ);
message->add_repeated_foreign_enum(unittest::FOREIGN_BAZ );
@@ -162,9 +177,11 @@
message->GetDescriptor()->FindFieldByName("repeated_cord"),
"325");
#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
+}
- // -----------------------------------------------------------------
+// -------------------------------------------------------------------
+void TestUtil::SetDefaultFields(unittest::TestAllTypes* message) {
message->set_default_int32 (401);
message->set_default_int64 (402);
message->set_default_uint32 (403);
@@ -220,6 +237,7 @@
message->mutable_repeated_nested_message (1)->set_bb(518);
message->mutable_repeated_foreign_message(1)->set_c(519);
message->mutable_repeated_import_message (1)->set_d(520);
+ message->mutable_repeated_lazy_message (1)->set_bb(527);
message->set_repeated_nested_enum (1, unittest::TestAllTypes::FOO);
message->set_repeated_foreign_enum(1, unittest::FOREIGN_FOO );
@@ -256,15 +274,19 @@
EXPECT_TRUE(message.has_optional_string ());
EXPECT_TRUE(message.has_optional_bytes ());
- EXPECT_TRUE(message.has_optionalgroup ());
- EXPECT_TRUE(message.has_optional_nested_message ());
- EXPECT_TRUE(message.has_optional_foreign_message());
- EXPECT_TRUE(message.has_optional_import_message ());
+ EXPECT_TRUE(message.has_optionalgroup ());
+ EXPECT_TRUE(message.has_optional_nested_message ());
+ EXPECT_TRUE(message.has_optional_foreign_message ());
+ EXPECT_TRUE(message.has_optional_import_message ());
+ EXPECT_TRUE(message.has_optional_public_import_message());
+ EXPECT_TRUE(message.has_optional_lazy_message ());
- EXPECT_TRUE(message.optionalgroup ().has_a());
- EXPECT_TRUE(message.optional_nested_message ().has_bb());
- EXPECT_TRUE(message.optional_foreign_message().has_c());
- EXPECT_TRUE(message.optional_import_message ().has_d());
+ EXPECT_TRUE(message.optionalgroup ().has_a());
+ EXPECT_TRUE(message.optional_nested_message ().has_bb());
+ EXPECT_TRUE(message.optional_foreign_message ().has_c());
+ EXPECT_TRUE(message.optional_import_message ().has_d());
+ EXPECT_TRUE(message.optional_public_import_message().has_e());
+ EXPECT_TRUE(message.optional_lazy_message ().has_bb());
EXPECT_TRUE(message.has_optional_nested_enum ());
EXPECT_TRUE(message.has_optional_foreign_enum());
@@ -291,10 +313,12 @@
EXPECT_EQ("115", message.optional_string ());
EXPECT_EQ("116", message.optional_bytes ());
- EXPECT_EQ(117, message.optionalgroup ().a());
- EXPECT_EQ(118, message.optional_nested_message ().bb());
- EXPECT_EQ(119, message.optional_foreign_message().c());
- EXPECT_EQ(120, message.optional_import_message ().d());
+ EXPECT_EQ(117, message.optionalgroup ().a());
+ EXPECT_EQ(118, message.optional_nested_message ().bb());
+ EXPECT_EQ(119, message.optional_foreign_message ().c());
+ EXPECT_EQ(120, message.optional_import_message ().d());
+ EXPECT_EQ(126, message.optional_public_import_message ().e());
+ EXPECT_EQ(127, message.optional_lazy_message ().bb());
EXPECT_EQ(unittest::TestAllTypes::BAZ, message.optional_nested_enum ());
EXPECT_EQ(unittest::FOREIGN_BAZ , message.optional_foreign_enum());
@@ -323,6 +347,7 @@
ASSERT_EQ(2, message.repeated_nested_message_size ());
ASSERT_EQ(2, message.repeated_foreign_message_size());
ASSERT_EQ(2, message.repeated_import_message_size ());
+ ASSERT_EQ(2, message.repeated_lazy_message_size ());
ASSERT_EQ(2, message.repeated_nested_enum_size ());
ASSERT_EQ(2, message.repeated_foreign_enum_size ());
ASSERT_EQ(2, message.repeated_import_enum_size ());
@@ -352,6 +377,7 @@
EXPECT_EQ(218, message.repeated_nested_message (0).bb());
EXPECT_EQ(219, message.repeated_foreign_message(0).c());
EXPECT_EQ(220, message.repeated_import_message (0).d());
+ EXPECT_EQ(227, message.repeated_lazy_message (0).bb());
EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0));
@@ -378,6 +404,7 @@
EXPECT_EQ(318, message.repeated_nested_message (1).bb());
EXPECT_EQ(319, message.repeated_foreign_message(1).c());
EXPECT_EQ(320, message.repeated_import_message (1).d());
+ EXPECT_EQ(327, message.repeated_lazy_message (1).bb());
EXPECT_EQ(unittest::TestAllTypes::BAZ, message.repeated_nested_enum (1));
EXPECT_EQ(unittest::FOREIGN_BAZ , message.repeated_foreign_enum(1));
@@ -449,10 +476,12 @@
EXPECT_FALSE(message.has_optional_string ());
EXPECT_FALSE(message.has_optional_bytes ());
- EXPECT_FALSE(message.has_optionalgroup ());
- EXPECT_FALSE(message.has_optional_nested_message ());
- EXPECT_FALSE(message.has_optional_foreign_message());
- EXPECT_FALSE(message.has_optional_import_message ());
+ EXPECT_FALSE(message.has_optionalgroup ());
+ EXPECT_FALSE(message.has_optional_nested_message ());
+ EXPECT_FALSE(message.has_optional_foreign_message ());
+ EXPECT_FALSE(message.has_optional_import_message ());
+ EXPECT_FALSE(message.has_optional_public_import_message());
+ EXPECT_FALSE(message.has_optional_lazy_message ());
EXPECT_FALSE(message.has_optional_nested_enum ());
EXPECT_FALSE(message.has_optional_foreign_enum());
@@ -479,15 +508,19 @@
EXPECT_EQ("" , message.optional_bytes ());
// Embedded messages should also be clear.
- EXPECT_FALSE(message.optionalgroup ().has_a());
- EXPECT_FALSE(message.optional_nested_message ().has_bb());
- EXPECT_FALSE(message.optional_foreign_message().has_c());
- EXPECT_FALSE(message.optional_import_message ().has_d());
+ EXPECT_FALSE(message.optionalgroup ().has_a());
+ EXPECT_FALSE(message.optional_nested_message ().has_bb());
+ EXPECT_FALSE(message.optional_foreign_message ().has_c());
+ EXPECT_FALSE(message.optional_import_message ().has_d());
+ EXPECT_FALSE(message.optional_public_import_message().has_e());
+ EXPECT_FALSE(message.optional_lazy_message ().has_bb());
- EXPECT_EQ(0, message.optionalgroup ().a());
- EXPECT_EQ(0, message.optional_nested_message ().bb());
- EXPECT_EQ(0, message.optional_foreign_message().c());
- EXPECT_EQ(0, message.optional_import_message ().d());
+ EXPECT_EQ(0, message.optionalgroup ().a());
+ EXPECT_EQ(0, message.optional_nested_message ().bb());
+ EXPECT_EQ(0, message.optional_foreign_message ().c());
+ EXPECT_EQ(0, message.optional_import_message ().d());
+ EXPECT_EQ(0, message.optional_public_import_message().e());
+ EXPECT_EQ(0, message.optional_lazy_message ().bb());
// Enums without defaults are set to the first value in the enum.
EXPECT_EQ(unittest::TestAllTypes::FOO, message.optional_nested_enum ());
@@ -516,6 +549,7 @@
EXPECT_EQ(0, message.repeated_nested_message_size ());
EXPECT_EQ(0, message.repeated_foreign_message_size());
EXPECT_EQ(0, message.repeated_import_message_size ());
+ EXPECT_EQ(0, message.repeated_lazy_message_size ());
EXPECT_EQ(0, message.repeated_nested_enum_size ());
EXPECT_EQ(0, message.repeated_foreign_enum_size ());
EXPECT_EQ(0, message.repeated_import_enum_size ());
@@ -595,6 +629,7 @@
ASSERT_EQ(2, message.repeated_nested_message_size ());
ASSERT_EQ(2, message.repeated_foreign_message_size());
ASSERT_EQ(2, message.repeated_import_message_size ());
+ ASSERT_EQ(2, message.repeated_lazy_message_size ());
ASSERT_EQ(2, message.repeated_nested_enum_size ());
ASSERT_EQ(2, message.repeated_foreign_enum_size ());
ASSERT_EQ(2, message.repeated_import_enum_size ());
@@ -624,6 +659,7 @@
EXPECT_EQ(218, message.repeated_nested_message (0).bb());
EXPECT_EQ(219, message.repeated_foreign_message(0).c());
EXPECT_EQ(220, message.repeated_import_message (0).d());
+ EXPECT_EQ(227, message.repeated_lazy_message (0).bb());
EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0));
EXPECT_EQ(unittest::FOREIGN_BAR , message.repeated_foreign_enum(0));
@@ -651,6 +687,7 @@
EXPECT_EQ(518, message.repeated_nested_message (1).bb());
EXPECT_EQ(519, message.repeated_foreign_message(1).c());
EXPECT_EQ(520, message.repeated_import_message (1).d());
+ EXPECT_EQ(527, message.repeated_lazy_message (1).bb());
EXPECT_EQ(unittest::TestAllTypes::FOO, message.repeated_nested_enum (1));
EXPECT_EQ(unittest::FOREIGN_FOO , message.repeated_foreign_enum(1));
@@ -953,6 +990,9 @@
message->SetExtension(unittest::optional_string_piece_extension, "124");
message->SetExtension(unittest::optional_cord_extension, "125");
+ message->MutableExtension(unittest::optional_public_import_message_extension)->set_e(126);
+ message->MutableExtension(unittest::optional_lazy_message_extension)->set_bb(127);
+
// -----------------------------------------------------------------
message->AddExtension(unittest::repeated_int32_extension , 201);
@@ -975,6 +1015,7 @@
message->AddExtension(unittest::repeated_nested_message_extension )->set_bb(218);
message->AddExtension(unittest::repeated_foreign_message_extension)->set_c(219);
message->AddExtension(unittest::repeated_import_message_extension )->set_d(220);
+ message->AddExtension(unittest::repeated_lazy_message_extension )->set_bb(227);
message->AddExtension(unittest::repeated_nested_enum_extension , unittest::TestAllTypes::BAR);
message->AddExtension(unittest::repeated_foreign_enum_extension, unittest::FOREIGN_BAR );
@@ -1004,6 +1045,7 @@
message->AddExtension(unittest::repeated_nested_message_extension )->set_bb(318);
message->AddExtension(unittest::repeated_foreign_message_extension)->set_c(319);
message->AddExtension(unittest::repeated_import_message_extension )->set_d(320);
+ message->AddExtension(unittest::repeated_lazy_message_extension )->set_bb(327);
message->AddExtension(unittest::repeated_nested_enum_extension , unittest::TestAllTypes::BAZ);
message->AddExtension(unittest::repeated_foreign_enum_extension, unittest::FOREIGN_BAZ );
@@ -1073,6 +1115,7 @@
message->MutableExtension(unittest::repeated_nested_message_extension , 1)->set_bb(518);
message->MutableExtension(unittest::repeated_foreign_message_extension, 1)->set_c(519);
message->MutableExtension(unittest::repeated_import_message_extension , 1)->set_d(520);
+ message->MutableExtension(unittest::repeated_lazy_message_extension , 1)->set_bb(527);
message->SetExtension(unittest::repeated_nested_enum_extension , 1, unittest::TestAllTypes::FOO);
message->SetExtension(unittest::repeated_foreign_enum_extension, 1, unittest::FOREIGN_FOO );
@@ -1102,15 +1145,19 @@
EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension ));
EXPECT_TRUE(message.HasExtension(unittest::optional_bytes_extension ));
- EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension ));
- EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension ));
- EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension));
- EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension ));
+ EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension ));
+ EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension ));
+ EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension ));
+ EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension ));
+ EXPECT_TRUE(message.HasExtension(unittest::optional_public_import_message_extension));
+ EXPECT_TRUE(message.HasExtension(unittest::optional_lazy_message_extension ));
- EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension ).has_a());
- EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension ).has_bb());
- EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension).has_c());
- EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension ).has_d());
+ EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension ).has_a());
+ EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension ).has_bb());
+ EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension ).has_c());
+ EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension ).has_d());
+ EXPECT_TRUE(message.GetExtension(unittest::optional_public_import_message_extension).has_e());
+ EXPECT_TRUE(message.GetExtension(unittest::optional_lazy_message_extension ).has_bb());
EXPECT_TRUE(message.HasExtension(unittest::optional_nested_enum_extension ));
EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_enum_extension));
@@ -1146,6 +1193,8 @@
EXPECT_EQ("124", message.GetExtension(unittest::optional_string_piece_extension));
EXPECT_EQ("125", message.GetExtension(unittest::optional_cord_extension));
+ EXPECT_EQ(126, message.GetExtension(unittest::optional_public_import_message_extension ).e());
+ EXPECT_EQ(127, message.GetExtension(unittest::optional_lazy_message_extension).bb());
// -----------------------------------------------------------------
@@ -1169,6 +1218,7 @@
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension ));
@@ -1196,6 +1246,7 @@
EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+ EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension , 0).bb());
EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0));
EXPECT_EQ(unittest::FOREIGN_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension, 0));
@@ -1224,6 +1275,7 @@
EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb());
EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c());
EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension , 1).d());
+ EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension , 1).bb());
EXPECT_EQ(unittest::TestAllTypes::BAZ, message.GetExtension(unittest::repeated_nested_enum_extension , 1));
EXPECT_EQ(unittest::FOREIGN_BAZ , message.GetExtension(unittest::repeated_foreign_enum_extension, 1));
@@ -1307,10 +1359,12 @@
EXPECT_FALSE(message.HasExtension(unittest::optional_string_extension ));
EXPECT_FALSE(message.HasExtension(unittest::optional_bytes_extension ));
- EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension ));
- EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension ));
- EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension));
- EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension ));
+ EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension ));
+ EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension ));
+ EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension ));
+ EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension ));
+ EXPECT_FALSE(message.HasExtension(unittest::optional_public_import_message_extension));
+ EXPECT_FALSE(message.HasExtension(unittest::optional_lazy_message_extension ));
EXPECT_FALSE(message.HasExtension(unittest::optional_nested_enum_extension ));
EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_enum_extension));
@@ -1337,15 +1391,19 @@
EXPECT_EQ("" , message.GetExtension(unittest::optional_bytes_extension ));
// Embedded messages should also be clear.
- EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension ).has_a());
- EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension ).has_bb());
- EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension).has_c());
- EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension ).has_d());
+ EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension ).has_a());
+ EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension ).has_bb());
+ EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension ).has_c());
+ EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension ).has_d());
+ EXPECT_FALSE(message.GetExtension(unittest::optional_public_import_message_extension).has_e());
+ EXPECT_FALSE(message.GetExtension(unittest::optional_lazy_message_extension ).has_bb());
- EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension ).a());
- EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension ).bb());
- EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension).c());
- EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension ).d());
+ EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension ).a());
+ EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension ).bb());
+ EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension ).c());
+ EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension ).d());
+ EXPECT_EQ(0, message.GetExtension(unittest::optional_public_import_message_extension).e());
+ EXPECT_EQ(0, message.GetExtension(unittest::optional_lazy_message_extension ).bb());
// Enums without defaults are set to the first value in the enum.
EXPECT_EQ(unittest::TestAllTypes::FOO, message.GetExtension(unittest::optional_nested_enum_extension ));
@@ -1376,6 +1434,7 @@
EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_message_extension ));
EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_message_extension));
EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_message_extension ));
+ EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_lazy_message_extension ));
EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_enum_extension ));
EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_enum_extension ));
EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_enum_extension ));
@@ -1459,6 +1518,7 @@
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension ));
@@ -1486,6 +1546,7 @@
EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+ EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension , 0).bb());
EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0));
EXPECT_EQ(unittest::FOREIGN_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension, 0));
@@ -1515,6 +1576,7 @@
EXPECT_EQ(518, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb());
EXPECT_EQ(519, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c());
EXPECT_EQ(520, message.GetExtension(unittest::repeated_import_message_extension , 1).d());
+ EXPECT_EQ(527, message.GetExtension(unittest::repeated_lazy_message_extension , 1).bb());
EXPECT_EQ(unittest::TestAllTypes::FOO, message.GetExtension(unittest::repeated_nested_enum_extension , 1));
EXPECT_EQ(unittest::FOREIGN_FOO , message.GetExtension(unittest::repeated_foreign_enum_extension, 1));
@@ -1750,6 +1812,7 @@
ASSERT_EQ(1, message.repeated_nested_message_size ());
ASSERT_EQ(1, message.repeated_foreign_message_size());
ASSERT_EQ(1, message.repeated_import_message_size ());
+ ASSERT_EQ(1, message.repeated_import_message_size ());
ASSERT_EQ(1, message.repeated_nested_enum_size ());
ASSERT_EQ(1, message.repeated_foreign_enum_size ());
ASSERT_EQ(1, message.repeated_import_enum_size ());
@@ -1780,6 +1843,7 @@
EXPECT_EQ(218, message.repeated_nested_message (0).bb());
EXPECT_EQ(219, message.repeated_foreign_message(0).c());
EXPECT_EQ(220, message.repeated_import_message (0).d());
+ EXPECT_EQ(220, message.repeated_import_message (0).d());
EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (0));
EXPECT_EQ(unittest::FOREIGN_BAR , message.repeated_foreign_enum(0));
@@ -1810,6 +1874,7 @@
ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_message_extension ));
ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_message_extension));
ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_message_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_lazy_message_extension ));
ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_enum_extension ));
ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_enum_extension ));
ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_enum_extension ));
@@ -1838,6 +1903,7 @@
EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+ EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension , 0).bb());
EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 0));
EXPECT_EQ(unittest::FOREIGN_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension, 0));
@@ -1847,6 +1913,36 @@
EXPECT_EQ("225", message.GetExtension(unittest::repeated_cord_extension, 0));
}
+void TestUtil::ExpectLastRepeatedsReleased(
+ const unittest::TestAllTypes& message) {
+ ASSERT_EQ(1, message.repeatedgroup_size ());
+ ASSERT_EQ(1, message.repeated_nested_message_size ());
+ ASSERT_EQ(1, message.repeated_foreign_message_size());
+ ASSERT_EQ(1, message.repeated_import_message_size ());
+ ASSERT_EQ(1, message.repeated_import_message_size ());
+
+ EXPECT_EQ(217, message.repeatedgroup (0).a());
+ EXPECT_EQ(218, message.repeated_nested_message (0).bb());
+ EXPECT_EQ(219, message.repeated_foreign_message(0).c());
+ EXPECT_EQ(220, message.repeated_import_message (0).d());
+ EXPECT_EQ(220, message.repeated_import_message (0).d());
+}
+
+void TestUtil::ExpectLastRepeatedExtensionsReleased(
+ const unittest::TestAllExtensions& message) {
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeatedgroup_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_nested_message_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_foreign_message_extension));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_import_message_extension ));
+ ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_lazy_message_extension ));
+
+ EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension , 0).a());
+ EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
+ EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
+ EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+ EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension , 0).bb());
+}
+
void TestUtil::ExpectRepeatedsSwapped(
const unittest::TestAllTypes& message) {
ASSERT_EQ(2, message.repeated_int32_size ());
@@ -1869,6 +1965,7 @@
ASSERT_EQ(2, message.repeated_nested_message_size ());
ASSERT_EQ(2, message.repeated_foreign_message_size());
ASSERT_EQ(2, message.repeated_import_message_size ());
+ ASSERT_EQ(2, message.repeated_import_message_size ());
ASSERT_EQ(2, message.repeated_nested_enum_size ());
ASSERT_EQ(2, message.repeated_foreign_enum_size ());
ASSERT_EQ(2, message.repeated_import_enum_size ());
@@ -1899,6 +1996,7 @@
EXPECT_EQ(218, message.repeated_nested_message (1).bb());
EXPECT_EQ(219, message.repeated_foreign_message(1).c());
EXPECT_EQ(220, message.repeated_import_message (1).d());
+ EXPECT_EQ(220, message.repeated_import_message (1).d());
EXPECT_EQ(unittest::TestAllTypes::BAR, message.repeated_nested_enum (1));
EXPECT_EQ(unittest::FOREIGN_BAR , message.repeated_foreign_enum(1));
@@ -1924,6 +2022,7 @@
EXPECT_EQ(318, message.repeated_nested_message (0).bb());
EXPECT_EQ(319, message.repeated_foreign_message(0).c());
EXPECT_EQ(320, message.repeated_import_message (0).d());
+ EXPECT_EQ(320, message.repeated_import_message (0).d());
EXPECT_EQ(unittest::TestAllTypes::BAZ, message.repeated_nested_enum (0));
EXPECT_EQ(unittest::FOREIGN_BAZ , message.repeated_foreign_enum(0));
@@ -1953,6 +2052,7 @@
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension ));
@@ -1980,6 +2080,7 @@
EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension , 1).bb());
EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension, 1).c());
EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension , 1).d());
+ EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension , 1).bb());
EXPECT_EQ(unittest::TestAllTypes::BAR, message.GetExtension(unittest::repeated_nested_enum_extension , 1));
EXPECT_EQ(unittest::FOREIGN_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension, 1));
@@ -2008,6 +2109,7 @@
EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension , 0).bb());
EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension, 0).c());
EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension , 0).d());
+ EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension , 0).bb());
EXPECT_EQ(unittest::TestAllTypes::BAZ, message.GetExtension(unittest::repeated_nested_enum_extension , 0));
EXPECT_EQ(unittest::FOREIGN_BAZ , message.GetExtension(unittest::repeated_foreign_enum_extension, 0));
@@ -2031,6 +2133,8 @@
pool->FindFieldByName("protobuf_unittest.ForeignMessage.c");
import_d_ =
pool->FindFieldByName("protobuf_unittest_import.ImportMessage.d");
+ import_e_ =
+ pool->FindFieldByName("protobuf_unittest_import.PublicImportMessage.e");
nested_foo_ =
pool->FindEnumValueByName("protobuf_unittest.TestAllTypes.FOO");
nested_bar_ =
@@ -2067,6 +2171,7 @@
EXPECT_TRUE(nested_b_ != NULL);
EXPECT_TRUE(foreign_c_ != NULL);
EXPECT_TRUE(import_d_ != NULL);
+ EXPECT_TRUE(import_e_ != NULL);
EXPECT_TRUE(nested_foo_ != NULL);
EXPECT_TRUE(nested_bar_ != NULL);
EXPECT_TRUE(nested_baz_ != NULL);
@@ -2129,6 +2234,12 @@
reflection->SetString(message, F("optional_string_piece"), "124");
reflection->SetString(message, F("optional_cord"), "125");
+ sub_message = reflection->MutableMessage(message, F("optional_public_import_message"));
+ sub_message->GetReflection()->SetInt32(sub_message, import_e_, 126);
+
+ sub_message = reflection->MutableMessage(message, F("optional_lazy_message"));
+ sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 127);
+
// -----------------------------------------------------------------
reflection->AddInt32 (message, F("repeated_int32" ), 201);
@@ -2155,6 +2266,8 @@
sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 219);
sub_message = reflection->AddMessage(message, F("repeated_import_message"));
sub_message->GetReflection()->SetInt32(sub_message, import_d_, 220);
+ sub_message = reflection->AddMessage(message, F("repeated_lazy_message"));
+ sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 227);
reflection->AddEnum(message, F("repeated_nested_enum" ), nested_bar_);
reflection->AddEnum(message, F("repeated_foreign_enum"), foreign_bar_);
@@ -2188,6 +2301,8 @@
sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 319);
sub_message = reflection->AddMessage(message, F("repeated_import_message"));
sub_message->GetReflection()->SetInt32(sub_message, import_d_, 320);
+ sub_message = reflection->AddMessage(message, F("repeated_lazy_message"));
+ sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 327);
reflection->AddEnum(message, F("repeated_nested_enum" ), nested_baz_);
reflection->AddEnum(message, F("repeated_foreign_enum"), foreign_baz_);
@@ -2289,10 +2404,12 @@
EXPECT_TRUE(reflection->HasField(message, F("optional_string" )));
EXPECT_TRUE(reflection->HasField(message, F("optional_bytes" )));
- EXPECT_TRUE(reflection->HasField(message, F("optionalgroup" )));
- EXPECT_TRUE(reflection->HasField(message, F("optional_nested_message" )));
- EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_message")));
- EXPECT_TRUE(reflection->HasField(message, F("optional_import_message" )));
+ EXPECT_TRUE(reflection->HasField(message, F("optionalgroup" )));
+ EXPECT_TRUE(reflection->HasField(message, F("optional_nested_message" )));
+ EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_message" )));
+ EXPECT_TRUE(reflection->HasField(message, F("optional_import_message" )));
+ EXPECT_TRUE(reflection->HasField(message, F("optional_public_import_message")));
+ EXPECT_TRUE(reflection->HasField(message, F("optional_lazy_message" )));
sub_message = &reflection->GetMessage(message, F("optionalgroup"));
EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, group_a_));
@@ -2302,6 +2419,10 @@
EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, foreign_c_));
sub_message = &reflection->GetMessage(message, F("optional_import_message"));
EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, import_d_));
+ sub_message = &reflection->GetMessage(message, F("optional_public_import_message"));
+ EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, import_e_));
+ sub_message = &reflection->GetMessage(message, F("optional_lazy_message"));
+ EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, nested_b_));
EXPECT_TRUE(reflection->HasField(message, F("optional_nested_enum" )));
EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_enum")));
@@ -2337,6 +2458,10 @@
EXPECT_EQ(119, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_));
sub_message = &reflection->GetMessage(message, F("optional_import_message"));
EXPECT_EQ(120, sub_message->GetReflection()->GetInt32(*sub_message, import_d_));
+ sub_message = &reflection->GetMessage(message, F("optional_public_import_message"));
+ EXPECT_EQ(126, sub_message->GetReflection()->GetInt32(*sub_message, import_e_));
+ sub_message = &reflection->GetMessage(message, F("optional_lazy_message"));
+ EXPECT_EQ(127, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
EXPECT_EQ( nested_baz_, reflection->GetEnum(message, F("optional_nested_enum" )));
EXPECT_EQ(foreign_baz_, reflection->GetEnum(message, F("optional_foreign_enum")));
@@ -2347,6 +2472,7 @@
EXPECT_EQ("125", reflection->GetString(message, F("optional_cord")));
EXPECT_EQ("125", reflection->GetStringReference(message, F("optional_cord"), &scratch));
+
}
void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection2(
@@ -2377,6 +2503,7 @@
ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_nested_message" )));
ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_foreign_message")));
ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_import_message" )));
+ ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_lazy_message" )));
ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_nested_enum" )));
ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_foreign_enum" )));
ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_import_enum" )));
@@ -2411,6 +2538,8 @@
EXPECT_EQ(219, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_));
sub_message = &reflection->GetRepeatedMessage(message, F("repeated_import_message"), 0);
EXPECT_EQ(220, sub_message->GetReflection()->GetInt32(*sub_message, import_d_));
+ sub_message = &reflection->GetRepeatedMessage(message, F("repeated_lazy_message"), 0);
+ EXPECT_EQ(227, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
EXPECT_EQ( nested_bar_, reflection->GetRepeatedEnum(message, F("repeated_nested_enum" ),0));
EXPECT_EQ(foreign_bar_, reflection->GetRepeatedEnum(message, F("repeated_foreign_enum"),0));
@@ -2453,6 +2582,8 @@
EXPECT_EQ(319, sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_));
sub_message = &reflection->GetRepeatedMessage(message, F("repeated_import_message"), 1);
EXPECT_EQ(320, sub_message->GetReflection()->GetInt32(*sub_message, import_d_));
+ sub_message = &reflection->GetRepeatedMessage(message, F("repeated_lazy_message"), 1);
+ EXPECT_EQ(327, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
EXPECT_EQ( nested_baz_, reflection->GetRepeatedEnum(message, F("repeated_nested_enum" ),1));
EXPECT_EQ(foreign_baz_, reflection->GetRepeatedEnum(message, F("repeated_foreign_enum"),1));
@@ -2609,6 +2740,8 @@
EXPECT_FALSE(reflection->HasField(message, F("optional_nested_message" )));
EXPECT_FALSE(reflection->HasField(message, F("optional_foreign_message")));
EXPECT_FALSE(reflection->HasField(message, F("optional_import_message" )));
+ EXPECT_FALSE(reflection->HasField(message, F("optional_public_import_message")));
+ EXPECT_FALSE(reflection->HasField(message, F("optional_lazy_message")));
EXPECT_FALSE(reflection->HasField(message, F("optional_nested_enum" )));
EXPECT_FALSE(reflection->HasField(message, F("optional_foreign_enum")));
@@ -2650,6 +2783,12 @@
sub_message = &reflection->GetMessage(message, F("optional_import_message"));
EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, import_d_));
EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, import_d_));
+ sub_message = &reflection->GetMessage(message, F("optional_public_import_message"));
+ EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, import_e_));
+ EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, import_e_));
+ sub_message = &reflection->GetMessage(message, F("optional_lazy_message"));
+ EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, nested_b_));
+ EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_));
// Enums without defaults are set to the first value in the enum.
EXPECT_EQ( nested_foo_, reflection->GetEnum(message, F("optional_nested_enum" )));
@@ -2683,6 +2822,7 @@
EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_nested_message" )));
EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_foreign_message")));
EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_import_message" )));
+ EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_lazy_message" )));
EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_nested_enum" )));
EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_foreign_enum" )));
EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_import_enum" )));
@@ -2796,6 +2936,8 @@
sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 519);
sub_message = reflection->MutableRepeatedMessage(message, F("repeated_import_message"), 1);
sub_message->GetReflection()->SetInt32(sub_message, import_d_, 520);
+ sub_message = reflection->MutableRepeatedMessage(message, F("repeated_lazy_message"), 1);
+ sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 527);
reflection->SetRepeatedEnum(message, F("repeated_nested_enum" ), 1, nested_foo_);
reflection->SetRepeatedEnum(message, F("repeated_foreign_enum"), 1, foreign_foo_);
@@ -2824,7 +2966,8 @@
reflection->SetRepeatedEnum (message, F("packed_enum" ), 1, foreign_foo_);
}
-void TestUtil::ReflectionTester::RemoveLastRepeatedsViaReflection(Message* message) {
+void TestUtil::ReflectionTester::RemoveLastRepeatedsViaReflection(
+ Message* message) {
const Reflection* reflection = message->GetReflection();
vector<const FieldDescriptor*> output;
@@ -2837,6 +2980,26 @@
}
}
+void TestUtil::ReflectionTester::ReleaseLastRepeatedsViaReflection(
+ Message* message, bool expect_extensions_notnull) {
+ const Reflection* reflection = message->GetReflection();
+
+ vector<const FieldDescriptor*> output;
+ reflection->ListFields(*message, &output);
+ for (int i=0; i<output.size(); ++i) {
+ const FieldDescriptor* field = output[i];
+ if (!field->is_repeated()) continue;
+ if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue;
+
+ Message* released = reflection->ReleaseLast(message, field);
+ if (!field->is_extension() || expect_extensions_notnull) {
+ ASSERT_TRUE(released != NULL) << "ReleaseLast returned NULL for: "
+ << field->name();
+ }
+ delete released;
+ }
+}
+
void TestUtil::ReflectionTester::SwapRepeatedsViaReflection(Message* message) {
const Reflection* reflection = message->GetReflection();
@@ -2850,5 +3013,35 @@
}
}
+void TestUtil::ReflectionTester::ExpectMessagesReleasedViaReflection(
+ Message* message,
+ TestUtil::ReflectionTester::MessageReleaseState expected_release_state) {
+ const Reflection* reflection = message->GetReflection();
+
+ static const char* fields[] = {
+ "optionalgroup",
+ "optional_nested_message",
+ "optional_foreign_message",
+ "optional_import_message",
+ };
+ for (int i = 0; i < GOOGLE_ARRAYSIZE(fields); i++) {
+ const Message& sub_message = reflection->GetMessage(*message, F(fields[i]));
+ Message* released = reflection->ReleaseMessage(message, F(fields[i]));
+ switch (expected_release_state) {
+ case IS_NULL:
+ EXPECT_TRUE(released == NULL);
+ break;
+ case NOT_NULL:
+ EXPECT_TRUE(released != NULL);
+ EXPECT_EQ(&sub_message, released);
+ break;
+ case CAN_BE_NULL:
+ break;
+ }
+ delete released;
+ EXPECT_FALSE(reflection->HasField(*message, F(fields[i])));
+ }
+}
+
} // namespace protobuf
} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/test_util.h b/third_party/protobuf/src/google/protobuf/test_util.h
index 25165f3..4551957 100644
--- a/third_party/protobuf/src/google/protobuf/test_util.h
+++ b/third_party/protobuf/src/google/protobuf/test_util.h
@@ -43,13 +43,17 @@
namespace google {
namespace protobuf {
-namespace unittest = protobuf_unittest;
+namespace unittest = ::protobuf_unittest;
namespace unittest_import = protobuf_unittest_import;
class TestUtil {
public:
// Set every field in the message to a unique value.
static void SetAllFields(unittest::TestAllTypes* message);
+ static void SetOptionalFields(unittest::TestAllTypes* message);
+ static void AddRepeatedFields1(unittest::TestAllTypes* message);
+ static void AddRepeatedFields2(unittest::TestAllTypes* message);
+ static void SetDefaultFields(unittest::TestAllTypes* message);
static void SetAllExtensions(unittest::TestAllExtensions* message);
static void SetAllFieldsAndExtensions(unittest::TestFieldOrderings* message);
static void SetPackedFields(unittest::TestPackedTypes* message);
@@ -104,6 +108,10 @@
const unittest::TestAllTypes& message);
static void ExpectLastRepeatedExtensionsRemoved(
const unittest::TestAllExtensions& message);
+ static void ExpectLastRepeatedsReleased(
+ const unittest::TestAllTypes& message);
+ static void ExpectLastRepeatedExtensionsReleased(
+ const unittest::TestAllExtensions& message);
// Check that all repeated fields have had their first and last elements
// swapped.
@@ -132,8 +140,18 @@
void ExpectPackedClearViaReflection(const Message& message);
void RemoveLastRepeatedsViaReflection(Message* message);
+ void ReleaseLastRepeatedsViaReflection(
+ Message* message, bool expect_extensions_notnull);
void SwapRepeatedsViaReflection(Message* message);
+ enum MessageReleaseState {
+ IS_NULL,
+ CAN_BE_NULL,
+ NOT_NULL,
+ };
+ void ExpectMessagesReleasedViaReflection(
+ Message* message, MessageReleaseState expected_release_state);
+
private:
const FieldDescriptor* F(const string& name);
@@ -144,6 +162,7 @@
const FieldDescriptor* nested_b_;
const FieldDescriptor* foreign_c_;
const FieldDescriptor* import_d_;
+ const FieldDescriptor* import_e_;
const EnumValueDescriptor* nested_foo_;
const EnumValueDescriptor* nested_bar_;
diff --git a/third_party/protobuf/src/google/protobuf/test_util_lite.cc b/third_party/protobuf/src/google/protobuf/test_util_lite.cc
index d7140e0..9099292 100644
--- a/third_party/protobuf/src/google/protobuf/test_util_lite.cc
+++ b/third_party/protobuf/src/google/protobuf/test_util_lite.cc
@@ -62,10 +62,12 @@
message->set_optional_string ("115");
message->set_optional_bytes ("116");
- message->mutable_optionalgroup ()->set_a(117);
- message->mutable_optional_nested_message ()->set_bb(118);
- message->mutable_optional_foreign_message()->set_c(119);
- message->mutable_optional_import_message ()->set_d(120);
+ message->mutable_optionalgroup ()->set_a(117);
+ message->mutable_optional_nested_message ()->set_bb(118);
+ message->mutable_optional_foreign_message ()->set_c(119);
+ message->mutable_optional_import_message ()->set_d(120);
+ message->mutable_optional_public_import_message()->set_e(126);
+ message->mutable_optional_lazy_message ()->set_bb(127);
message->set_optional_nested_enum (unittest::TestAllTypesLite::BAZ );
message->set_optional_foreign_enum(unittest::FOREIGN_LITE_BAZ );
@@ -94,6 +96,7 @@
message->add_repeated_nested_message ()->set_bb(218);
message->add_repeated_foreign_message()->set_c(219);
message->add_repeated_import_message ()->set_d(220);
+ message->add_repeated_lazy_message ()->set_bb(227);
message->add_repeated_nested_enum (unittest::TestAllTypesLite::BAR );
message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAR );
@@ -121,6 +124,7 @@
message->add_repeated_nested_message ()->set_bb(318);
message->add_repeated_foreign_message()->set_c(319);
message->add_repeated_import_message ()->set_d(320);
+ message->add_repeated_lazy_message ()->set_bb(327);
message->add_repeated_nested_enum (unittest::TestAllTypesLite::BAZ );
message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAZ );
@@ -174,6 +178,7 @@
message->mutable_repeated_nested_message (1)->set_bb(518);
message->mutable_repeated_foreign_message(1)->set_c(519);
message->mutable_repeated_import_message (1)->set_d(520);
+ message->mutable_repeated_lazy_message (1)->set_bb(527);
message->set_repeated_nested_enum (1, unittest::TestAllTypesLite::FOO );
message->set_repeated_foreign_enum(1, unittest::FOREIGN_LITE_FOO );
@@ -201,15 +206,19 @@
EXPECT_TRUE(message.has_optional_string ());
EXPECT_TRUE(message.has_optional_bytes ());
- EXPECT_TRUE(message.has_optionalgroup ());
- EXPECT_TRUE(message.has_optional_nested_message ());
- EXPECT_TRUE(message.has_optional_foreign_message());
- EXPECT_TRUE(message.has_optional_import_message ());
+ EXPECT_TRUE(message.has_optionalgroup ());
+ EXPECT_TRUE(message.has_optional_nested_message ());
+ EXPECT_TRUE(message.has_optional_foreign_message ());
+ EXPECT_TRUE(message.has_optional_import_message ());
+ EXPECT_TRUE(message.has_optional_public_import_message());
+ EXPECT_TRUE(message.has_optional_lazy_message ());
- EXPECT_TRUE(message.optionalgroup ().has_a());
- EXPECT_TRUE(message.optional_nested_message ().has_bb());
- EXPECT_TRUE(message.optional_foreign_message().has_c());
- EXPECT_TRUE(message.optional_import_message ().has_d());
+ EXPECT_TRUE(message.optionalgroup ().has_a());
+ EXPECT_TRUE(message.optional_nested_message ().has_bb());
+ EXPECT_TRUE(message.optional_foreign_message ().has_c());
+ EXPECT_TRUE(message.optional_import_message ().has_d());
+ EXPECT_TRUE(message.optional_public_import_message().has_e());
+ EXPECT_TRUE(message.optional_lazy_message ().has_bb());
EXPECT_TRUE(message.has_optional_nested_enum ());
EXPECT_TRUE(message.has_optional_foreign_enum());
@@ -232,10 +241,12 @@
EXPECT_EQ("115", message.optional_string ());
EXPECT_EQ("116", message.optional_bytes ());
- EXPECT_EQ(117, message.optionalgroup ().a());
- EXPECT_EQ(118, message.optional_nested_message ().bb());
- EXPECT_EQ(119, message.optional_foreign_message().c());
- EXPECT_EQ(120, message.optional_import_message ().d());
+ EXPECT_EQ(117, message.optionalgroup ().a());
+ EXPECT_EQ(118, message.optional_nested_message ().bb());
+ EXPECT_EQ(119, message.optional_foreign_message ().c());
+ EXPECT_EQ(120, message.optional_import_message ().d());
+ EXPECT_EQ(126, message.optional_public_import_message().e());
+ EXPECT_EQ(127, message.optional_lazy_message ().bb());
EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.optional_nested_enum ());
EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.optional_foreign_enum());
@@ -264,6 +275,7 @@
ASSERT_EQ(2, message.repeated_nested_message_size ());
ASSERT_EQ(2, message.repeated_foreign_message_size());
ASSERT_EQ(2, message.repeated_import_message_size ());
+ ASSERT_EQ(2, message.repeated_lazy_message_size ());
ASSERT_EQ(2, message.repeated_nested_enum_size ());
ASSERT_EQ(2, message.repeated_foreign_enum_size ());
ASSERT_EQ(2, message.repeated_import_enum_size ());
@@ -289,6 +301,7 @@
EXPECT_EQ(218, message.repeated_nested_message (0).bb());
EXPECT_EQ(219, message.repeated_foreign_message(0).c());
EXPECT_EQ(220, message.repeated_import_message (0).d());
+ EXPECT_EQ(227, message.repeated_lazy_message (0).bb());
EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.repeated_nested_enum (0));
@@ -315,6 +328,7 @@
EXPECT_EQ(318, message.repeated_nested_message (1).bb());
EXPECT_EQ(319, message.repeated_foreign_message(1).c());
EXPECT_EQ(320, message.repeated_import_message (1).d());
+ EXPECT_EQ(327, message.repeated_lazy_message (1).bb());
EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.repeated_nested_enum (1));
EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.repeated_foreign_enum(1));
@@ -386,10 +400,12 @@
EXPECT_FALSE(message.has_optional_string ());
EXPECT_FALSE(message.has_optional_bytes ());
- EXPECT_FALSE(message.has_optionalgroup ());
- EXPECT_FALSE(message.has_optional_nested_message ());
- EXPECT_FALSE(message.has_optional_foreign_message());
- EXPECT_FALSE(message.has_optional_import_message ());
+ EXPECT_FALSE(message.has_optionalgroup ());
+ EXPECT_FALSE(message.has_optional_nested_message ());
+ EXPECT_FALSE(message.has_optional_foreign_message ());
+ EXPECT_FALSE(message.has_optional_import_message ());
+ EXPECT_FALSE(message.has_optional_public_import_message());
+ EXPECT_FALSE(message.has_optional_lazy_message ());
EXPECT_FALSE(message.has_optional_nested_enum ());
EXPECT_FALSE(message.has_optional_foreign_enum());
@@ -414,10 +430,12 @@
EXPECT_EQ("" , message.optional_bytes ());
// Embedded messages should also be clear.
- EXPECT_FALSE(message.optionalgroup ().has_a());
- EXPECT_FALSE(message.optional_nested_message ().has_bb());
- EXPECT_FALSE(message.optional_foreign_message().has_c());
- EXPECT_FALSE(message.optional_import_message ().has_d());
+ EXPECT_FALSE(message.optionalgroup ().has_a());
+ EXPECT_FALSE(message.optional_nested_message ().has_bb());
+ EXPECT_FALSE(message.optional_foreign_message ().has_c());
+ EXPECT_FALSE(message.optional_import_message ().has_d());
+ EXPECT_FALSE(message.optional_public_import_message().has_e());
+ EXPECT_FALSE(message.optional_lazy_message ().has_bb());
EXPECT_EQ(0, message.optionalgroup ().a());
EXPECT_EQ(0, message.optional_nested_message ().bb());
@@ -451,6 +469,7 @@
EXPECT_EQ(0, message.repeated_nested_message_size ());
EXPECT_EQ(0, message.repeated_foreign_message_size());
EXPECT_EQ(0, message.repeated_import_message_size ());
+ EXPECT_EQ(0, message.repeated_lazy_message_size ());
EXPECT_EQ(0, message.repeated_nested_enum_size ());
EXPECT_EQ(0, message.repeated_foreign_enum_size ());
EXPECT_EQ(0, message.repeated_import_enum_size ());
@@ -528,6 +547,7 @@
ASSERT_EQ(2, message.repeated_nested_message_size ());
ASSERT_EQ(2, message.repeated_foreign_message_size());
ASSERT_EQ(2, message.repeated_import_message_size ());
+ ASSERT_EQ(2, message.repeated_lazy_message_size ());
ASSERT_EQ(2, message.repeated_nested_enum_size ());
ASSERT_EQ(2, message.repeated_foreign_enum_size ());
ASSERT_EQ(2, message.repeated_import_enum_size ());
@@ -553,6 +573,7 @@
EXPECT_EQ(218, message.repeated_nested_message (0).bb());
EXPECT_EQ(219, message.repeated_foreign_message(0).c());
EXPECT_EQ(220, message.repeated_import_message (0).d());
+ EXPECT_EQ(227, message.repeated_lazy_message (0).bb());
EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.repeated_nested_enum (0));
EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.repeated_foreign_enum(0));
@@ -580,6 +601,7 @@
EXPECT_EQ(518, message.repeated_nested_message (1).bb());
EXPECT_EQ(519, message.repeated_foreign_message(1).c());
EXPECT_EQ(520, message.repeated_import_message (1).d());
+ EXPECT_EQ(527, message.repeated_lazy_message (1).bb());
EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.repeated_nested_enum (1));
EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.repeated_foreign_enum(1));
@@ -787,10 +809,12 @@
message->SetExtension(unittest::optional_string_extension_lite , "115");
message->SetExtension(unittest::optional_bytes_extension_lite , "116");
- message->MutableExtension(unittest::optionalgroup_extension_lite )->set_a(117);
- message->MutableExtension(unittest::optional_nested_message_extension_lite )->set_bb(118);
- message->MutableExtension(unittest::optional_foreign_message_extension_lite)->set_c(119);
- message->MutableExtension(unittest::optional_import_message_extension_lite )->set_d(120);
+ message->MutableExtension(unittest::optionalgroup_extension_lite )->set_a(117);
+ message->MutableExtension(unittest::optional_nested_message_extension_lite )->set_bb(118);
+ message->MutableExtension(unittest::optional_foreign_message_extension_lite )->set_c(119);
+ message->MutableExtension(unittest::optional_import_message_extension_lite )->set_d(120);
+ message->MutableExtension(unittest::optional_public_import_message_extension_lite)->set_e(126);
+ message->MutableExtension(unittest::optional_lazy_message_extension_lite )->set_bb(127);
message->SetExtension(unittest::optional_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ );
message->SetExtension(unittest::optional_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ );
@@ -819,6 +843,7 @@
message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(218);
message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(219);
message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(220);
+ message->AddExtension(unittest::repeated_lazy_message_extension_lite )->set_bb(227);
message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAR );
message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAR );
@@ -846,6 +871,7 @@
message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(318);
message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(319);
message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(320);
+ message->AddExtension(unittest::repeated_lazy_message_extension_lite )->set_bb(327);
message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ );
message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ );
@@ -900,6 +926,7 @@
message->MutableExtension(unittest::repeated_nested_message_extension_lite , 1)->set_bb(518);
message->MutableExtension(unittest::repeated_foreign_message_extension_lite, 1)->set_c(519);
message->MutableExtension(unittest::repeated_import_message_extension_lite , 1)->set_d(520);
+ message->MutableExtension(unittest::repeated_lazy_message_extension_lite , 1)->set_bb(527);
message->SetExtension(unittest::repeated_nested_enum_extension_lite , 1, unittest::TestAllTypesLite::FOO );
message->SetExtension(unittest::repeated_foreign_enum_extension_lite, 1, unittest::FOREIGN_LITE_FOO );
@@ -927,15 +954,19 @@
EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension_lite ));
EXPECT_TRUE(message.HasExtension(unittest::optional_bytes_extension_lite ));
- EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension_lite ));
- EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension_lite ));
- EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension_lite));
- EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension_lite ));
+ EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension_lite ));
+ EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension_lite ));
+ EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension_lite ));
+ EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension_lite ));
+ EXPECT_TRUE(message.HasExtension(unittest::optional_public_import_message_extension_lite));
+ EXPECT_TRUE(message.HasExtension(unittest::optional_lazy_message_extension_lite ));
- EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension_lite ).has_a());
- EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb());
- EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension_lite).has_c());
- EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d());
+ EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension_lite ).has_a());
+ EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb());
+ EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension_lite ).has_c());
+ EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d());
+ EXPECT_TRUE(message.GetExtension(unittest::optional_public_import_message_extension_lite).has_e());
+ EXPECT_TRUE(message.GetExtension(unittest::optional_lazy_message_extension_lite ).has_bb());
EXPECT_TRUE(message.HasExtension(unittest::optional_nested_enum_extension_lite ));
EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_enum_extension_lite));
@@ -958,10 +989,12 @@
EXPECT_EQ("115", message.GetExtension(unittest::optional_string_extension_lite ));
EXPECT_EQ("116", message.GetExtension(unittest::optional_bytes_extension_lite ));
- EXPECT_EQ(117, message.GetExtension(unittest::optionalgroup_extension_lite ).a());
- EXPECT_EQ(118, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb());
- EXPECT_EQ(119, message.GetExtension(unittest::optional_foreign_message_extension_lite).c());
- EXPECT_EQ(120, message.GetExtension(unittest::optional_import_message_extension_lite ).d());
+ EXPECT_EQ(117, message.GetExtension(unittest::optionalgroup_extension_lite ).a());
+ EXPECT_EQ(118, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb());
+ EXPECT_EQ(119, message.GetExtension(unittest::optional_foreign_message_extension_lite ).c());
+ EXPECT_EQ(120, message.GetExtension(unittest::optional_import_message_extension_lite ).d());
+ EXPECT_EQ(126, message.GetExtension(unittest::optional_public_import_message_extension_lite).e());
+ EXPECT_EQ(127, message.GetExtension(unittest::optional_lazy_message_extension_lite ).bb());
EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::optional_nested_enum_extension_lite ));
EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.GetExtension(unittest::optional_foreign_enum_extension_lite));
@@ -990,6 +1023,7 @@
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite ));
@@ -1015,6 +1049,7 @@
EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb());
EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c());
EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d());
+ EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 0).bb());
EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0));
EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0));
@@ -1041,6 +1076,7 @@
EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb());
EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c());
EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d());
+ EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 1).bb());
EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1));
EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1));
@@ -1118,10 +1154,12 @@
EXPECT_FALSE(message.HasExtension(unittest::optional_string_extension_lite ));
EXPECT_FALSE(message.HasExtension(unittest::optional_bytes_extension_lite ));
- EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension_lite ));
- EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension_lite ));
- EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension_lite));
- EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension_lite ));
+ EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension_lite ));
+ EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension_lite ));
+ EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension_lite ));
+ EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension_lite ));
+ EXPECT_FALSE(message.HasExtension(unittest::optional_public_import_message_extension_lite));
+ EXPECT_FALSE(message.HasExtension(unittest::optional_lazy_message_extension_lite ));
EXPECT_FALSE(message.HasExtension(unittest::optional_nested_enum_extension_lite ));
EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_enum_extension_lite));
@@ -1146,15 +1184,19 @@
EXPECT_EQ("" , message.GetExtension(unittest::optional_bytes_extension_lite ));
// Embedded messages should also be clear.
- EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension_lite ).has_a());
- EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb());
- EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension_lite).has_c());
- EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d());
+ EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension_lite ).has_a());
+ EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb());
+ EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension_lite ).has_c());
+ EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d());
+ EXPECT_FALSE(message.GetExtension(unittest::optional_public_import_message_extension_lite).has_e());
+ EXPECT_FALSE(message.GetExtension(unittest::optional_lazy_message_extension_lite ).has_bb());
- EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension_lite ).a());
- EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb());
- EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension_lite).c());
- EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension_lite ).d());
+ EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension_lite ).a());
+ EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb());
+ EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension_lite ).c());
+ EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension_lite ).d());
+ EXPECT_EQ(0, message.GetExtension(unittest::optional_public_import_message_extension_lite).e());
+ EXPECT_EQ(0, message.GetExtension(unittest::optional_lazy_message_extension_lite ).bb());
// Enums without defaults are set to the first value in the enum.
EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::optional_nested_enum_extension_lite ));
@@ -1183,6 +1225,7 @@
EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_message_extension_lite ));
EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite));
EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_message_extension_lite ));
+ EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite ));
EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite ));
EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite ));
EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_enum_extension_lite ));
@@ -1260,6 +1303,7 @@
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite ));
+ ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite ));
ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite ));
@@ -1285,6 +1329,7 @@
EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb());
EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c());
EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d());
+ EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 0).bb());
EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0));
EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0));
@@ -1312,6 +1357,7 @@
EXPECT_EQ(518, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb());
EXPECT_EQ(519, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c());
EXPECT_EQ(520, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d());
+ EXPECT_EQ(527, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 1).bb());
EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1));
EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1));
diff --git a/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_data.txt b/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_data.txt
index feea8f7..bbe5882 100644
--- a/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_data.txt
+++ b/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_data.txt
@@ -30,6 +30,12 @@
optional_import_enum: IMPORT_BAZ
optional_string_piece: "124"
optional_cord: "125"
+optional_public_import_message {
+ e: 126
+}
+optional_lazy_message {
+ bb: 127
+}
repeated_int32: 201
repeated_int32: 301
repeated_int64: 202
@@ -94,6 +100,12 @@
repeated_string_piece: "324"
repeated_cord: "225"
repeated_cord: "325"
+repeated_lazy_message {
+ bb: 227
+}
+repeated_lazy_message {
+ bb: 327
+}
default_int32: 401
default_int64: 402
default_uint32: 403
diff --git a/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt b/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt
index 057beae..0a217f0 100644
--- a/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt
+++ b/third_party/protobuf/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt
@@ -30,6 +30,12 @@
[protobuf_unittest.optional_import_enum_extension]: IMPORT_BAZ
[protobuf_unittest.optional_string_piece_extension]: "124"
[protobuf_unittest.optional_cord_extension]: "125"
+[protobuf_unittest.optional_public_import_message_extension] {
+ e: 126
+}
+[protobuf_unittest.optional_lazy_message_extension] {
+ bb: 127
+}
[protobuf_unittest.repeated_int32_extension]: 201
[protobuf_unittest.repeated_int32_extension]: 301
[protobuf_unittest.repeated_int64_extension]: 202
@@ -94,6 +100,12 @@
[protobuf_unittest.repeated_string_piece_extension]: "324"
[protobuf_unittest.repeated_cord_extension]: "225"
[protobuf_unittest.repeated_cord_extension]: "325"
+[protobuf_unittest.repeated_lazy_message_extension] {
+ bb: 227
+}
+[protobuf_unittest.repeated_lazy_message_extension] {
+ bb: 327
+}
[protobuf_unittest.default_int32_extension]: 401
[protobuf_unittest.default_int64_extension]: 402
[protobuf_unittest.default_uint32_extension]: 403
diff --git a/third_party/protobuf/src/google/protobuf/testing/googletest.cc b/third_party/protobuf/src/google/protobuf/testing/googletest.cc
index cd094d0..a8da6b1 100644
--- a/third_party/protobuf/src/google/protobuf/testing/googletest.cc
+++ b/third_party/protobuf/src/google/protobuf/testing/googletest.cc
@@ -223,16 +223,17 @@
active_log_ = NULL;
}
-const vector<string>& ScopedMemoryLog::GetMessages(LogLevel dummy) const {
- GOOGLE_CHECK_EQ(dummy, ERROR);
- return messages_;
+const vector<string>& ScopedMemoryLog::GetMessages(LogLevel level) {
+ GOOGLE_CHECK(level == ERROR ||
+ level == WARNING);
+ return messages_[level];
}
void ScopedMemoryLog::HandleLog(LogLevel level, const char* filename,
int line, const string& message) {
GOOGLE_CHECK(active_log_ != NULL);
- if (level == ERROR) {
- active_log_->messages_.push_back(message);
+ if (level == ERROR || level == WARNING) {
+ active_log_->messages_[level].push_back(message);
}
}
diff --git a/third_party/protobuf/src/google/protobuf/testing/googletest.h b/third_party/protobuf/src/google/protobuf/testing/googletest.h
index 71444c9..6b17ae4 100644
--- a/third_party/protobuf/src/google/protobuf/testing/googletest.h
+++ b/third_party/protobuf/src/google/protobuf/testing/googletest.h
@@ -34,6 +34,7 @@
#ifndef GOOGLE_PROTOBUF_GOOGLETEST_H__
#define GOOGLE_PROTOBUF_GOOGLETEST_H__
+#include <map>
#include <vector>
#include <google/protobuf/stubs/common.h>
@@ -60,6 +61,7 @@
// ScopedMemoryLog refers to LOGLEVEL_ERROR as just ERROR.
#undef ERROR // defend against promiscuous windows.h
static const LogLevel ERROR = LOGLEVEL_ERROR;
+static const LogLevel WARNING = LOGLEVEL_WARNING;
// Receives copies of all LOG(ERROR) messages while in scope. Sample usage:
// {
@@ -74,14 +76,11 @@
ScopedMemoryLog();
virtual ~ScopedMemoryLog();
- // Fetches all messages logged. The internal version of this class
- // would only fetch messages at the given security level, but the protobuf
- // open source version ignores the argument since we always pass ERROR
- // anyway.
- const vector<string>& GetMessages(LogLevel dummy) const;
+ // Fetches all messages with the given severity level.
+ const vector<string>& GetMessages(LogLevel error);
private:
- vector<string> messages_;
+ map<LogLevel, vector<string> > messages_;
LogHandler* old_handler_;
static void HandleLog(LogLevel level, const char* filename, int line,
diff --git a/third_party/protobuf/src/google/protobuf/text_format.cc b/third_party/protobuf/src/google/protobuf/text_format.cc
index 1494ebd..1ee3df5 100644
--- a/third_party/protobuf/src/google/protobuf/text_format.cc
+++ b/third_party/protobuf/src/google/protobuf/text_format.cc
@@ -49,6 +49,8 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
@@ -94,6 +96,73 @@
// ===========================================================================
+// Implementation of the parse information tree class.
+TextFormat::ParseInfoTree::ParseInfoTree() { }
+
+TextFormat::ParseInfoTree::~ParseInfoTree() {
+ // Remove any nested information trees, as they are owned by this tree.
+ for (NestedMap::iterator it = nested_.begin(); it != nested_.end(); ++it) {
+ STLDeleteElements(&(it->second));
+ }
+}
+
+void TextFormat::ParseInfoTree::RecordLocation(
+ const FieldDescriptor* field,
+ TextFormat::ParseLocation location) {
+ locations_[field].push_back(location);
+}
+
+TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::CreateNested(
+ const FieldDescriptor* field) {
+ // Owned by us in the map.
+ TextFormat::ParseInfoTree* instance = new TextFormat::ParseInfoTree();
+ vector<TextFormat::ParseInfoTree*>* trees = &nested_[field];
+ GOOGLE_CHECK(trees);
+ trees->push_back(instance);
+ return instance;
+}
+
+void CheckFieldIndex(const FieldDescriptor* field, int index) {
+ if (field == NULL) { return; }
+
+ if (field->is_repeated() && index == -1) {
+ GOOGLE_LOG(DFATAL) << "Index must be in range of repeated field values. "
+ << "Field: " << field->name();
+ } else if (!field->is_repeated() && index != -1) {
+ GOOGLE_LOG(DFATAL) << "Index must be -1 for singular fields."
+ << "Field: " << field->name();
+ }
+}
+
+TextFormat::ParseLocation TextFormat::ParseInfoTree::GetLocation(
+ const FieldDescriptor* field, int index) const {
+ CheckFieldIndex(field, index);
+ if (index == -1) { index = 0; }
+
+ const vector<TextFormat::ParseLocation>* locations =
+ FindOrNull(locations_, field);
+ if (locations == NULL || index >= locations->size()) {
+ return TextFormat::ParseLocation();
+ }
+
+ return (*locations)[index];
+}
+
+TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested(
+ const FieldDescriptor* field, int index) const {
+ CheckFieldIndex(field, index);
+ if (index == -1) { index = 0; }
+
+ const vector<TextFormat::ParseInfoTree*>* trees = FindOrNull(nested_, field);
+ if (trees == NULL || index >= trees->size()) {
+ return NULL;
+ }
+
+ return (*trees)[index];
+}
+
+
+// ===========================================================================
// Internal class for parsing an ASCII representation of a Protocol Message.
// This class makes use of the Protocol Message compiler's tokenizer found
// in //google/protobuf/io/tokenizer.h. Note that class's Parse
@@ -120,13 +189,17 @@
io::ZeroCopyInputStream* input_stream,
io::ErrorCollector* error_collector,
TextFormat::Finder* finder,
- SingularOverwritePolicy singular_overwrite_policy)
+ ParseInfoTree* parse_info_tree,
+ SingularOverwritePolicy singular_overwrite_policy,
+ bool allow_unknown_field)
: error_collector_(error_collector),
finder_(finder),
+ parse_info_tree_(parse_info_tree),
tokenizer_error_collector_(this),
tokenizer_(input_stream, &tokenizer_error_collector_),
root_message_type_(root_message_type),
singular_overwrite_policy_(singular_overwrite_policy),
+ allow_unknown_field_(allow_unknown_field),
had_errors_(false) {
// For backwards-compatibility with proto1, we need to allow the 'f' suffix
// for floats.
@@ -240,6 +313,8 @@
string field_name;
const FieldDescriptor* field = NULL;
+ int start_line = tokenizer_.current().line;
+ int start_column = tokenizer_.current().column;
if (TryConsume("[")) {
// Extension.
@@ -257,10 +332,16 @@
: reflection->FindKnownExtensionByName(field_name));
if (field == NULL) {
- ReportError("Extension \"" + field_name + "\" is not defined or "
- "is not an extension of \"" +
- descriptor->full_name() + "\".");
- return false;
+ if (!allow_unknown_field_) {
+ ReportError("Extension \"" + field_name + "\" is not defined or "
+ "is not an extension of \"" +
+ descriptor->full_name() + "\".");
+ return false;
+ } else {
+ ReportWarning("Extension \"" + field_name + "\" is not defined or "
+ "is not an extension of \"" +
+ descriptor->full_name() + "\".");
+ }
}
} else {
DO(ConsumeIdentifier(&field_name));
@@ -285,9 +366,30 @@
}
if (field == NULL) {
- ReportError("Message type \"" + descriptor->full_name() +
- "\" has no field named \"" + field_name + "\".");
- return false;
+ if (!allow_unknown_field_) {
+ ReportError("Message type \"" + descriptor->full_name() +
+ "\" has no field named \"" + field_name + "\".");
+ return false;
+ } else {
+ ReportWarning("Message type \"" + descriptor->full_name() +
+ "\" has no field named \"" + field_name + "\".");
+ }
+ }
+ }
+
+ // Skips unknown field.
+ if (field == NULL) {
+ GOOGLE_CHECK(allow_unknown_field_);
+ // Try to guess the type of this field.
+ // If this field is not a message, there should be a ":" between the
+ // field name and the field value and also the field value should not
+ // start with "{" or "<" which indicates the begining of a message body.
+ // If there is no ":" or there is a "{" or "<" after ":", this field has
+ // to be a message or the input is ill-formed.
+ if (TryConsume(":") && !LookingAt("{") && !LookingAt("<")) {
+ return SkipFieldValue();
+ } else {
+ return SkipFieldMessage();
}
}
@@ -329,12 +431,61 @@
+ field_name + "\"");
}
+ // If a parse info tree exists, add the location for the parsed
+ // field.
+ if (parse_info_tree_ != NULL) {
+ parse_info_tree_->RecordLocation(field,
+ ParseLocation(start_line, start_column));
+ }
+
+ return true;
+ }
+
+ // Skips the next field including the field's name and value.
+ bool SkipField() {
+ string field_name;
+ if (TryConsume("[")) {
+ // Extension name.
+ DO(ConsumeIdentifier(&field_name));
+ while (TryConsume(".")) {
+ string part;
+ DO(ConsumeIdentifier(&part));
+ field_name += ".";
+ field_name += part;
+ }
+ DO(Consume("]"));
+ } else {
+ DO(ConsumeIdentifier(&field_name));
+ }
+
+ // Try to guess the type of this field.
+ // If this field is not a message, there should be a ":" between the
+ // field name and the field value and also the field value should not
+ // start with "{" or "<" which indicates the begining of a message body.
+ // If there is no ":" or there is a "{" or "<" after ":", this field has
+ // to be a message or the input is ill-formed.
+ if (TryConsume(":") && !LookingAt("{") && !LookingAt("<")) {
+ DO(SkipFieldValue());
+ } else {
+ DO(SkipFieldMessage());
+ }
+ // For historical reasons, fields may optionally be separated by commas or
+ // semicolons.
+ TryConsume(";") || TryConsume(",");
return true;
}
bool ConsumeFieldMessage(Message* message,
const Reflection* reflection,
const FieldDescriptor* field) {
+
+ // If the parse information tree is not NULL, create a nested one
+ // for the nested message.
+ ParseInfoTree* parent = parse_info_tree_;
+ if (parent != NULL) {
+ parse_info_tree_ = parent->CreateNested(field);
+ }
+
string delimeter;
if (TryConsume("<")) {
delimeter = ">";
@@ -349,6 +500,26 @@
DO(ConsumeMessage(reflection->MutableMessage(message, field),
delimeter));
}
+
+ // Reset the parse information tree.
+ parse_info_tree_ = parent;
+ return true;
+ }
+
+ // Skips the whole body of a message including the begining delimeter and
+ // the ending delimeter.
+ bool SkipFieldMessage() {
+ string delimeter;
+ if (TryConsume("<")) {
+ delimeter = ">";
+ } else {
+ DO(Consume("{"));
+ delimeter = "}";
+ }
+ while (!LookingAt(">") && !LookingAt("}")) {
+ DO(SkipField());
+ }
+ DO(Consume(delimeter));
return true;
}
@@ -479,6 +650,60 @@
return true;
}
+ bool SkipFieldValue() {
+ if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+ while (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+ tokenizer_.Next();
+ }
+ return true;
+ }
+ // Possible field values other than string:
+ // 12345 => TYPE_INTEGER
+ // -12345 => TYPE_SYMBOL + TYPE_INTEGER
+ // 1.2345 => TYPE_FLOAT
+ // -1.2345 => TYPE_SYMBOL + TYPE_FLOAT
+ // inf => TYPE_IDENTIFIER
+ // -inf => TYPE_SYMBOL + TYPE_IDENTIFIER
+ // TYPE_INTEGER => TYPE_IDENTIFIER
+ // Divides them into two group, one with TYPE_SYMBOL
+ // and the other without:
+ // Group one:
+ // 12345 => TYPE_INTEGER
+ // 1.2345 => TYPE_FLOAT
+ // inf => TYPE_IDENTIFIER
+ // TYPE_INTEGER => TYPE_IDENTIFIER
+ // Group two:
+ // -12345 => TYPE_SYMBOL + TYPE_INTEGER
+ // -1.2345 => TYPE_SYMBOL + TYPE_FLOAT
+ // -inf => TYPE_SYMBOL + TYPE_IDENTIFIER
+ // As we can see, the field value consists of an optional '-' and one of
+ // TYPE_INTEGER, TYPE_FLOAT and TYPE_IDENTIFIER.
+ bool has_minus = TryConsume("-");
+ if (!LookingAtType(io::Tokenizer::TYPE_INTEGER) &&
+ !LookingAtType(io::Tokenizer::TYPE_FLOAT) &&
+ !LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+ return false;
+ }
+ // Combination of '-' and TYPE_IDENTIFIER may result in an invalid field
+ // value while other combinations all generate valid values.
+ // We check if the value of this combination is valid here.
+ // TYPE_IDENTIFIER after a '-' should be one of the float values listed
+ // below:
+ // inf, inff, infinity, nan
+ if (has_minus && LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
+ string text = tokenizer_.current().text;
+ LowerString(&text);
+ if (text != "inf" &&
+ text != "infinity" &&
+ text != "nan") {
+ ReportError("Invalid float number: " + text);
+ return false;
+ }
+ }
+ tokenizer_.Next();
+ return true;
+ }
+
// Returns true if the current token's text is equal to that specified.
bool LookingAt(const string& text) {
return tokenizer_.current().text == text;
@@ -596,7 +821,8 @@
} else if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
string text = tokenizer_.current().text;
LowerString(&text);
- if (text == "inf" || text == "infinity") {
+ if (text == "inf" ||
+ text == "infinity") {
*value = std::numeric_limits<double>::infinity();
tokenizer_.Next();
} else if (text == "nan") {
@@ -670,10 +896,12 @@
io::ErrorCollector* error_collector_;
TextFormat::Finder* finder_;
+ ParseInfoTree* parse_info_tree_;
ParserErrorCollector tokenizer_error_collector_;
io::Tokenizer tokenizer_;
const Descriptor* root_message_type_;
SingularOverwritePolicy singular_overwrite_policy_;
+ bool allow_unknown_field_;
bool had_errors_;
};
@@ -699,7 +927,7 @@
~TextGenerator() {
// Only BackUp() if we're sure we've successfully called Next() at least
// once.
- if (buffer_size_ > 0) {
+ if (!failed_ && buffer_size_ > 0) {
output_->BackUp(buffer_size_);
}
}
@@ -809,7 +1037,9 @@
TextFormat::Parser::Parser()
: error_collector_(NULL),
finder_(NULL),
- allow_partial_(false) {
+ parse_info_tree_(NULL),
+ allow_partial_(false),
+ allow_unknown_field_(false) {
}
TextFormat::Parser::~Parser() {}
@@ -818,7 +1048,9 @@
Message* output) {
output->Clear();
ParserImpl parser(output->GetDescriptor(), input, error_collector_,
- finder_, ParserImpl::FORBID_SINGULAR_OVERWRITES);
+ finder_, parse_info_tree_,
+ ParserImpl::FORBID_SINGULAR_OVERWRITES,
+ allow_unknown_field_);
return MergeUsingImpl(input, output, &parser);
}
@@ -831,7 +1063,9 @@
bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input,
Message* output) {
ParserImpl parser(output->GetDescriptor(), input, error_collector_,
- finder_, ParserImpl::ALLOW_SINGULAR_OVERWRITES);
+ finder_, parse_info_tree_,
+ ParserImpl::ALLOW_SINGULAR_OVERWRITES,
+ allow_unknown_field_);
return MergeUsingImpl(input, output, &parser);
}
@@ -861,7 +1095,9 @@
Message* output) {
io::ArrayInputStream input_stream(input.data(), input.size());
ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_,
- finder_, ParserImpl::ALLOW_SINGULAR_OVERWRITES);
+ finder_, parse_info_tree_,
+ ParserImpl::ALLOW_SINGULAR_OVERWRITES,
+ allow_unknown_field_);
return parser.ParseField(field, output);
}
diff --git a/third_party/protobuf/src/google/protobuf/text_format.h b/third_party/protobuf/src/google/protobuf/text_format.h
index 03c0491..0974139 100644
--- a/third_party/protobuf/src/google/protobuf/text_format.h
+++ b/third_party/protobuf/src/google/protobuf/text_format.h
@@ -38,7 +38,10 @@
#ifndef GOOGLE_PROTOBUF_TEXT_FORMAT_H__
#define GOOGLE_PROTOBUF_TEXT_FORMAT_H__
+#include <map>
#include <string>
+#include <vector>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>
@@ -220,6 +223,57 @@
const string& name) const = 0;
};
+ // A location in the parsed text.
+ struct ParseLocation {
+ int line;
+ int column;
+
+ ParseLocation() : line(-1), column(-1) {}
+ ParseLocation(int line_param, int column_param)
+ : line(line_param), column(column_param) {}
+ };
+
+ // Data structure which is populated with the locations of each field
+ // value parsed from the text.
+ class LIBPROTOBUF_EXPORT ParseInfoTree {
+ public:
+ ParseInfoTree();
+ ~ParseInfoTree();
+
+ // Returns the parse location for index-th value of the field in the parsed
+ // text. If none exists, returns a location with line = -1. Index should be
+ // -1 for not-repeated fields.
+ ParseLocation GetLocation(const FieldDescriptor* field, int index) const;
+
+ // Returns the parse info tree for the given field, which must be a message
+ // type. The nested information tree is owned by the root tree and will be
+ // deleted when it is deleted.
+ ParseInfoTree* GetTreeForNested(const FieldDescriptor* field,
+ int index) const;
+
+ private:
+ // Allow the text format parser to record information into the tree.
+ friend class TextFormat;
+
+ // Records the starting location of a single value for a field.
+ void RecordLocation(const FieldDescriptor* field, ParseLocation location);
+
+ // Create and records a nested tree for a nested message field.
+ ParseInfoTree* CreateNested(const FieldDescriptor* field);
+
+ // Defines the map from the index-th field descriptor to its parse location.
+ typedef map<const FieldDescriptor*, vector<ParseLocation> > LocationMap;
+
+ // Defines the map from the index-th field descriptor to the nested parse
+ // info tree.
+ typedef map<const FieldDescriptor*, vector<ParseInfoTree*> > NestedMap;
+
+ LocationMap locations_;
+ NestedMap nested_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParseInfoTree);
+ };
+
// For more control over parsing, use this class.
class LIBPROTOBUF_EXPORT Parser {
public:
@@ -248,6 +302,12 @@
finder_ = finder;
}
+ // Sets where location information about the parse will be written. If NULL
+ // (the default), then no location will be written.
+ void WriteLocationsTo(ParseInfoTree* tree) {
+ parse_info_tree_ = tree;
+ }
+
// Normally parsing fails if, after parsing, output->IsInitialized()
// returns false. Call AllowPartialMessage(true) to skip this check.
void AllowPartialMessage(bool allow) {
@@ -259,6 +319,7 @@
const FieldDescriptor* field,
Message* output);
+
private:
// Forward declaration of an internal class used to parse text
// representations (see text_format.cc for implementation).
@@ -272,7 +333,9 @@
io::ErrorCollector* error_collector_;
Finder* finder_;
+ ParseInfoTree* parse_info_tree_;
bool allow_partial_;
+ bool allow_unknown_field_;
};
private:
diff --git a/third_party/protobuf/src/google/protobuf/text_format_unittest.cc b/third_party/protobuf/src/google/protobuf/text_format_unittest.cc
index 00ea8c3..353a5e4 100644
--- a/third_party/protobuf/src/google/protobuf/text_format_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/text_format_unittest.cc
@@ -339,6 +339,21 @@
text);
}
+TEST_F(TextFormatTest, PrintBufferTooSmall) {
+ // Test printing a message to a buffer that is too small.
+
+ protobuf_unittest::TestAllTypes message;
+
+ message.add_repeated_string("abc");
+ message.add_repeated_string("def");
+
+ char buffer[1] = "";
+ io::ArrayOutputStream output_stream(buffer, 1);
+ EXPECT_FALSE(TextFormat::Print(message, &output_stream));
+ EXPECT_EQ(buffer[0], 'r');
+ EXPECT_EQ(output_stream.ByteCount(), 1);
+}
+
TEST_F(TextFormatTest, ParseBasic) {
io::ArrayInputStream input_stream(proto_debug_string_.data(),
proto_debug_string_.size());
@@ -728,6 +743,25 @@
error_collector.text_);
}
+ void ExpectSuccessAndTree(const string& input, Message* proto,
+ TextFormat::ParseInfoTree* info_tree) {
+ TextFormat::Parser parser;
+ MockErrorCollector error_collector;
+ parser.RecordErrorsTo(&error_collector);
+ parser.WriteLocationsTo(info_tree);
+
+ EXPECT_TRUE(parser.ParseFromString(input, proto));
+ }
+
+ void ExpectLocation(TextFormat::ParseInfoTree* tree,
+ const Descriptor* d, const string& field_name,
+ int index, int line, int column) {
+ TextFormat::ParseLocation location = tree->GetLocation(
+ d->FindFieldByName(field_name), index);
+ EXPECT_EQ(line, location.line);
+ EXPECT_EQ(column, location.column);
+ }
+
// An error collector which simply concatenates all its errors into a big
// block of text which can be checked.
class MockErrorCollector : public io::ErrorCollector {
@@ -749,6 +783,71 @@
};
};
+TEST_F(TextFormatParserTest, ParseInfoTreeBuilding) {
+ scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
+ const Descriptor* d = message->GetDescriptor();
+
+ string stringData =
+ "optional_int32: 1\n"
+ "optional_int64: 2\n"
+ " optional_double: 2.4\n"
+ "repeated_int32: 5\n"
+ "repeated_int32: 10\n"
+ "optional_nested_message <\n"
+ " bb: 78\n"
+ ">\n"
+ "repeated_nested_message <\n"
+ " bb: 79\n"
+ ">\n"
+ "repeated_nested_message <\n"
+ " bb: 80\n"
+ ">";
+
+
+ TextFormat::ParseInfoTree tree;
+ ExpectSuccessAndTree(stringData, message.get(), &tree);
+
+ // Verify that the tree has the correct positions.
+ ExpectLocation(&tree, d, "optional_int32", -1, 0, 0);
+ ExpectLocation(&tree, d, "optional_int64", -1, 1, 0);
+ ExpectLocation(&tree, d, "optional_double", -1, 2, 2);
+
+ ExpectLocation(&tree, d, "repeated_int32", 0, 3, 0);
+ ExpectLocation(&tree, d, "repeated_int32", 1, 4, 0);
+
+ ExpectLocation(&tree, d, "optional_nested_message", -1, 5, 0);
+ ExpectLocation(&tree, d, "repeated_nested_message", 0, 8, 0);
+ ExpectLocation(&tree, d, "repeated_nested_message", 1, 11, 0);
+
+ // Check for fields not set. For an invalid field, the location returned
+ // should be -1, -1.
+ ExpectLocation(&tree, d, "repeated_int64", 0, -1, -1);
+ ExpectLocation(&tree, d, "repeated_int32", 6, -1, -1);
+ ExpectLocation(&tree, d, "some_unknown_field", -1, -1, -1);
+
+ // Verify inside the nested message.
+ const FieldDescriptor* nested_field =
+ d->FindFieldByName("optional_nested_message");
+
+ TextFormat::ParseInfoTree* nested_tree =
+ tree.GetTreeForNested(nested_field, -1);
+ ExpectLocation(nested_tree, nested_field->message_type(), "bb", -1, 6, 2);
+
+ // Verify inside another nested message.
+ nested_field = d->FindFieldByName("repeated_nested_message");
+ nested_tree = tree.GetTreeForNested(nested_field, 0);
+ ExpectLocation(nested_tree, nested_field->message_type(), "bb", -1, 9, 2);
+
+ nested_tree = tree.GetTreeForNested(nested_field, 1);
+ ExpectLocation(nested_tree, nested_field->message_type(), "bb", -1, 12, 2);
+
+ // Verify a NULL tree for an unknown nested field.
+ TextFormat::ParseInfoTree* unknown_nested_tree =
+ tree.GetTreeForNested(nested_field, 2);
+
+ EXPECT_EQ(NULL, unknown_nested_tree);
+}
+
TEST_F(TextFormatParserTest, ParseFieldValueFromString) {
scoped_ptr<unittest::TestAllTypes> message(new unittest::TestAllTypes);
const Descriptor* d = message->GetDescriptor();
@@ -921,10 +1020,10 @@
1, 16);
ExpectFailure("optional_int32: 0x80000000\n",
"Integer out of range.", 1, 17);
- ExpectFailure("optional_int32: -0x80000001\n",
- "Integer out of range.", 1, 18);
ExpectFailure("optional_int64: 0x8000000000000000\n",
"Integer out of range.", 1, 17);
+ ExpectFailure("optional_int32: -0x80000001\n",
+ "Integer out of range.", 1, 18);
ExpectFailure("optional_int64: -0x8000000000000001\n",
"Integer out of range.", 1, 18);
@@ -1136,6 +1235,7 @@
EXPECT_EQ(2, descriptors.size());
}
+
} // namespace text_format_unittest
} // namespace protobuf
} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/unittest.proto b/third_party/protobuf/src/google/protobuf/unittest.proto
index 97ec674..0305be6 100644
--- a/third_party/protobuf/src/google/protobuf/unittest.proto
+++ b/third_party/protobuf/src/google/protobuf/unittest.proto
@@ -103,6 +103,12 @@
optional string optional_string_piece = 24 [ctype=STRING_PIECE];
optional string optional_cord = 25 [ctype=CORD];
+ // Defined in unittest_import_public.proto
+ optional protobuf_unittest_import.PublicImportMessage
+ optional_public_import_message = 26;
+
+ optional NestedMessage optional_lazy_message = 27 [lazy=true];
+
// Repeated
repeated int32 repeated_int32 = 31;
repeated int64 repeated_int64 = 32;
@@ -135,6 +141,8 @@
repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
repeated string repeated_cord = 55 [ctype=CORD];
+ repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
// Singular with defaults
optional int32 default_int32 = 61 [default = 41 ];
optional int64 default_int64 = 62 [default = 42 ];
@@ -216,6 +224,12 @@
optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE];
optional string optional_cord_extension = 25 [ctype=CORD];
+ optional protobuf_unittest_import.PublicImportMessage
+ optional_public_import_message_extension = 26;
+
+ optional TestAllTypes.NestedMessage
+ optional_lazy_message_extension = 27 [lazy=true];
+
// Repeated
repeated int32 repeated_int32_extension = 31;
repeated int64 repeated_int64_extension = 32;
@@ -250,6 +264,9 @@
repeated string repeated_string_piece_extension = 54 [ctype=STRING_PIECE];
repeated string repeated_cord_extension = 55 [ctype=CORD];
+ repeated TestAllTypes.NestedMessage
+ repeated_lazy_message_extension = 57 [lazy=true];
+
// Singular with defaults
optional int32 default_int32_extension = 61 [default = 41 ];
optional int64 default_int64_extension = 62 [default = 42 ];
@@ -397,6 +414,13 @@
optional group Bar = 3 { optional int32 a = 1; } // NO_PROTO1
} // NO_PROTO1
+// Additional messages for testing lazy fields.
+message TestEagerMessage {
+ optional TestAllTypes sub_message = 1 [lazy=false];
+}
+message TestLazyMessage {
+ optional TestAllTypes sub_message = 1 [lazy=true];
+}
// Needed for a Python test.
message TestNestedMessageHasBits {
@@ -470,6 +494,8 @@
optional uint64 large_uint64 = 3 [default = 0xFFFFFFFFFFFFFFFF];
optional int32 small_int32 = 4 [default = -0x7FFFFFFF];
optional int64 small_int64 = 5 [default = -0x7FFFFFFFFFFFFFFF];
+ optional int32 really_small_int32 = 21 [default = -0x80000000];
+ optional int64 really_small_int64 = 22 [default = -0x8000000000000000];
// The default value here is UTF-8 for "\u1234". (We could also just type
// the UTF-8 text directly into this text file rather than escape it, but
@@ -500,6 +526,14 @@
// Note that in .proto file, "\?" is a valid way to escape ? in string
// literals.
optional string cpp_trigraph = 20 [default = "? \? ?? \?? \??? ??/ ?\?-"];
+
+ // String defaults containing the character '\000'
+ optional string string_with_zero = 23 [default = "hel\000lo"];
+ optional bytes bytes_with_zero = 24 [default = "wor\000ld"];
+ optional string string_piece_with_zero = 25 [ctype=STRING_PIECE,
+ default="ab\000c"];
+ optional string cord_with_zero = 26 [ctype=CORD,
+ default="12\0003"];
}
message SparseEnumMessage {
@@ -511,10 +545,19 @@
optional string data = 1;
}
+message MoreString {
+ repeated string data = 1;
+}
+
message OneBytes {
optional bytes data = 1;
}
+message MoreBytes {
+ repeated bytes data = 1;
+}
+
+
// Test messages for packed fields
message TestPackedTypes {
@@ -615,11 +658,56 @@
repeated uint64 repeated_uint64 = 262143;
}
+// Test that if an optional or required message/group field appears multiple
+// times in the input, they need to be merged.
+message TestParsingMerge {
+ // RepeatedFieldsGenerator defines matching field types as TestParsingMerge,
+ // except that all fields are repeated. In the tests, we will serialize the
+ // RepeatedFieldsGenerator to bytes, and parse the bytes to TestParsingMerge.
+ // Repeated fields in RepeatedFieldsGenerator are expected to be merged into
+ // the corresponding required/optional fields in TestParsingMerge.
+ message RepeatedFieldsGenerator {
+ repeated TestAllTypes field1 = 1;
+ repeated TestAllTypes field2 = 2;
+ repeated TestAllTypes field3 = 3;
+ repeated group Group1 = 10 {
+ optional TestAllTypes field1 = 11;
+ }
+ repeated group Group2 = 20 {
+ optional TestAllTypes field1 = 21;
+ }
+ repeated TestAllTypes ext1 = 1000;
+ repeated TestAllTypes ext2 = 1001;
+ }
+ required TestAllTypes required_all_types = 1;
+ optional TestAllTypes optional_all_types = 2;
+ repeated TestAllTypes repeated_all_types = 3;
+ optional group OptionalGroup = 10 {
+ optional TestAllTypes optional_group_all_types = 11;
+ }
+ repeated group RepeatedGroup = 20 {
+ optional TestAllTypes repeated_group_all_types = 21;
+ }
+ extensions 1000 to max;
+ extend TestParsingMerge {
+ optional TestAllTypes optional_ext = 1000;
+ repeated TestAllTypes repeated_ext = 1001;
+ }
+}
+
+message TestCommentInjectionMessage {
+ // */ <- This should not close the generated doc comment
+ optional string a = 1 [default="*/ <- Neither should this."];
+}
+
// Test that RPC services work.
message FooRequest {}
message FooResponse {}
+message FooClientMessage {}
+message FooServerMessage{}
+
service TestService {
rpc Foo(FooRequest) returns (FooResponse);
rpc Bar(BarRequest) returns (BarResponse);
diff --git a/third_party/protobuf/src/google/protobuf/unittest_custom_options.proto b/third_party/protobuf/src/google/protobuf/unittest_custom_options.proto
index a610785..e591d29 100644
--- a/third_party/protobuf/src/google/protobuf/unittest_custom_options.proto
+++ b/third_party/protobuf/src/google/protobuf/unittest_custom_options.proto
@@ -116,6 +116,12 @@
message CustomOptionFooResponse {
}
+message CustomOptionFooClientMessage {
+}
+
+message CustomOptionFooServerMessage {
+}
+
service TestServiceWithCustomOptions {
option (service_opt1) = -9876543210;
@@ -364,3 +370,18 @@
option (enumopt) = { s:'EnumAnnotation' };
VALUE = 1 [(enumvalopt) = { s:'EnumValueAnnotation' }];
}
+
+// Test custom options for nested type.
+message NestedOptionType {
+ message NestedMessage {
+ option (message_opt1) = 1001;
+ optional int32 nested_field = 1 [(field_opt1) = 1002];
+ }
+ enum NestedEnum {
+ option (enum_opt1) = 1003;
+ NESTED_ENUM_VALUE = 1 [(enum_value_opt1) = 1004];
+ }
+ extend google.protobuf.FileOptions {
+ optional int32 nested_extension = 7912573 [(field_opt2) = 1005];
+ }
+}
diff --git a/third_party/protobuf/src/google/protobuf/unittest_import.proto b/third_party/protobuf/src/google/protobuf/unittest_import.proto
index cd533ec..c115b11 100644
--- a/third_party/protobuf/src/google/protobuf/unittest_import.proto
+++ b/third_party/protobuf/src/google/protobuf/unittest_import.proto
@@ -49,6 +49,9 @@
// Do not set a java_outer_classname here to verify that Proto2 works without
// one.
+// Test public import
+import public "google/protobuf/unittest_import_public.proto";
+
message ImportMessage {
optional int32 d = 1;
}
diff --git a/third_party/protobuf/src/google/protobuf/unittest_import_lite.proto b/third_party/protobuf/src/google/protobuf/unittest_import_lite.proto
index ebaab5c..81b117f 100644
--- a/third_party/protobuf/src/google/protobuf/unittest_import_lite.proto
+++ b/third_party/protobuf/src/google/protobuf/unittest_import_lite.proto
@@ -38,6 +38,8 @@
option java_package = "com.google.protobuf";
+import public "google/protobuf/unittest_import_public_lite.proto";
+
message ImportMessageLite {
optional int32 d = 1;
}
diff --git a/third_party/protobuf/src/google/protobuf/unittest_import_public.proto b/third_party/protobuf/src/google/protobuf/unittest_import_public.proto
new file mode 100644
index 0000000..ea5d1b1
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/unittest_import_public.proto
@@ -0,0 +1,40 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: liujisi@google.com (Pherl Liu)
+
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf.test";
+
+message PublicImportMessage {
+ optional int32 e = 1;
+}
diff --git a/third_party/protobuf/src/google/protobuf/unittest_import_public_lite.proto b/third_party/protobuf/src/google/protobuf/unittest_import_public_lite.proto
new file mode 100644
index 0000000..d077563
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/unittest_import_public_lite.proto
@@ -0,0 +1,42 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: liujisi@google.com (Pherl Liu)
+
+
+package protobuf_unittest_import;
+
+option optimize_for = LITE_RUNTIME;
+
+option java_package = "com.google.protobuf";
+
+message PublicImportMessageLite {
+ optional int32 e = 1;
+}
diff --git a/third_party/protobuf/src/google/protobuf/unittest_lite.proto b/third_party/protobuf/src/google/protobuf/unittest_lite.proto
index cca6b49..a1764aa 100644
--- a/third_party/protobuf/src/google/protobuf/unittest_lite.proto
+++ b/third_party/protobuf/src/google/protobuf/unittest_lite.proto
@@ -85,6 +85,12 @@
optional string optional_string_piece = 24 [ctype=STRING_PIECE];
optional string optional_cord = 25 [ctype=CORD];
+ // Defined in unittest_import_public.proto
+ optional protobuf_unittest_import.PublicImportMessageLite
+ optional_public_import_message = 26;
+
+ optional NestedMessage optional_lazy_message = 27 [lazy=true];
+
// Repeated
repeated int32 repeated_int32 = 31;
repeated int64 repeated_int64 = 32;
@@ -118,6 +124,8 @@
repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
repeated string repeated_cord = 55 [ctype=CORD];
+ repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
// Singular with defaults
optional int32 default_int32 = 61 [default = 41 ];
optional int64 default_int64 = 62 [default = 42 ];
@@ -213,6 +221,12 @@
[ctype=STRING_PIECE];
optional string optional_cord_extension_lite = 25 [ctype=CORD];
+ optional protobuf_unittest_import.PublicImportMessageLite
+ optional_public_import_message_extension_lite = 26;
+
+ optional TestAllTypesLite.NestedMessage
+ optional_lazy_message_extension_lite = 27 [lazy=true];
+
// Repeated
repeated int32 repeated_int32_extension_lite = 31;
repeated int64 repeated_int64_extension_lite = 32;
@@ -249,6 +263,9 @@
[ctype=STRING_PIECE];
repeated string repeated_cord_extension_lite = 55 [ctype=CORD];
+ repeated TestAllTypesLite.NestedMessage
+ repeated_lazy_message_extension_lite = 57 [lazy=true];
+
// Singular with defaults
optional int32 default_int32_extension_lite = 61 [default = 41 ];
optional int64 default_int64_extension_lite = 62 [default = 42 ];
@@ -310,3 +327,34 @@
message TestDeprecatedLite {
optional int32 deprecated_field = 1 [deprecated = true];
}
+
+// See the comments of the same type in unittest.proto.
+message TestParsingMergeLite {
+ message RepeatedFieldsGenerator {
+ repeated TestAllTypesLite field1 = 1;
+ repeated TestAllTypesLite field2 = 2;
+ repeated TestAllTypesLite field3 = 3;
+ repeated group Group1 = 10 {
+ optional TestAllTypesLite field1 = 11;
+ }
+ repeated group Group2 = 20 {
+ optional TestAllTypesLite field1 = 21;
+ }
+ repeated TestAllTypesLite ext1 = 1000;
+ repeated TestAllTypesLite ext2 = 1001;
+ }
+ required TestAllTypesLite required_all_types = 1;
+ optional TestAllTypesLite optional_all_types = 2;
+ repeated TestAllTypesLite repeated_all_types = 3;
+ optional group OptionalGroup = 10 {
+ optional TestAllTypesLite optional_group_all_types = 11;
+ }
+ repeated group RepeatedGroup = 20 {
+ optional TestAllTypesLite repeated_group_all_types = 21;
+ }
+ extensions 1000 to max;
+ extend TestParsingMergeLite {
+ optional TestAllTypesLite optional_ext = 1000;
+ repeated TestAllTypesLite repeated_ext = 1001;
+ }
+}
diff --git a/third_party/protobuf/src/google/protobuf/unknown_field_set.cc b/third_party/protobuf/src/google/protobuf/unknown_field_set.cc
index 38a36d5..b6aaa18 100644
--- a/third_party/protobuf/src/google/protobuf/unknown_field_set.cc
+++ b/third_party/protobuf/src/google/protobuf/unknown_field_set.cc
@@ -32,13 +32,14 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/stubs/common.h>
#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
@@ -75,6 +76,14 @@
fields_->clear();
}
+void UnknownFieldSet::ClearAndFreeMemory() {
+ if (fields_ != NULL) {
+ Clear();
+ delete fields_;
+ fields_ = NULL;
+ }
+}
+
void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
for (int i = 0; i < other.field_count(); i++) {
AddField(other.field(i));
@@ -89,8 +98,9 @@
const UnknownField& field = (*fields_)[i];
switch (field.type()) {
case UnknownField::TYPE_LENGTH_DELIMITED:
- total_size += sizeof(*field.length_delimited_) +
- internal::StringSpaceUsedExcludingSelf(*field.length_delimited_);
+ total_size += sizeof(*field.length_delimited_.string_value_) +
+ internal::StringSpaceUsedExcludingSelf(
+ *field.length_delimited_.string_value_);
break;
case UnknownField::TYPE_GROUP:
total_size += field.group_->SpaceUsed();
@@ -138,11 +148,12 @@
UnknownField field;
field.number_ = number;
field.type_ = UnknownField::TYPE_LENGTH_DELIMITED;
- field.length_delimited_ = new string;
+ field.length_delimited_.string_value_ = new string;
fields_->push_back(field);
- return field.length_delimited_;
+ return field.length_delimited_.string_value_;
}
+
UnknownFieldSet* UnknownFieldSet::AddGroup(int number) {
if (fields_ == NULL) fields_ = new vector<UnknownField>;
UnknownField field;
@@ -159,6 +170,39 @@
fields_->back().DeepCopy();
}
+void UnknownFieldSet::DeleteSubrange(int start, int num) {
+ GOOGLE_DCHECK(fields_ != NULL);
+ // Delete the specified fields.
+ for (int i = 0; i < num; ++i) {
+ (*fields_)[i + start].Delete();
+ }
+ // Slide down the remaining fields.
+ for (int i = start + num; i < fields_->size(); ++i) {
+ (*fields_)[i - num] = (*fields_)[i];
+ }
+ // Pop off the # of deleted fields.
+ for (int i = 0; i < num; ++i) {
+ fields_->pop_back();
+ }
+}
+
+void UnknownFieldSet::DeleteByNumber(int number) {
+ if (fields_ == NULL) return;
+ int left = 0; // The number of fields left after deletion.
+ for (int i = 0; i < fields_->size(); ++i) {
+ UnknownField* field = &(*fields_)[i];
+ if (field->number() == number) {
+ field->Delete();
+ } else {
+ if (i != left) {
+ (*fields_)[left] = (*fields_)[i];
+ }
+ ++left;
+ }
+ }
+ fields_->resize(left);
+}
+
bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) {
UnknownFieldSet other;
@@ -190,7 +234,7 @@
void UnknownField::Delete() {
switch (type()) {
case UnknownField::TYPE_LENGTH_DELIMITED:
- delete length_delimited_;
+ delete length_delimited_.string_value_;
break;
case UnknownField::TYPE_GROUP:
delete group_;
@@ -203,7 +247,8 @@
void UnknownField::DeepCopy() {
switch (type()) {
case UnknownField::TYPE_LENGTH_DELIMITED:
- length_delimited_ = new string(*length_delimited_);
+ length_delimited_.string_value_ = new string(
+ *length_delimited_.string_value_);
break;
case UnknownField::TYPE_GROUP: {
UnknownFieldSet* group = new UnknownFieldSet;
@@ -216,5 +261,22 @@
}
}
+
+void UnknownField::SerializeLengthDelimitedNoTag(
+ io::CodedOutputStream* output) const {
+ GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_);
+ const string& data = *length_delimited_.string_value_;
+ output->WriteVarint32(data.size());
+ output->WriteString(data);
+}
+
+uint8* UnknownField::SerializeLengthDelimitedNoTagToArray(uint8* target) const {
+ GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_);
+ const string& data = *length_delimited_.string_value_;
+ target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target);
+ target = io::CodedOutputStream::WriteStringToArray(data, target);
+ return target;
+}
+
} // namespace protobuf
} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/unknown_field_set.h b/third_party/protobuf/src/google/protobuf/unknown_field_set.h
index 84c2e2b..825bba8 100644
--- a/third_party/protobuf/src/google/protobuf/unknown_field_set.h
+++ b/third_party/protobuf/src/google/protobuf/unknown_field_set.h
@@ -38,12 +38,24 @@
#ifndef GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
#define GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
+#include <assert.h>
#include <string>
#include <vector>
-#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/stubs/common.h>
+// TODO(jasonh): some people seem to rely on protobufs to include this for them!
namespace google {
namespace protobuf {
+ namespace io {
+ class CodedInputStream; // coded_stream.h
+ class CodedOutputStream; // coded_stream.h
+ class ZeroCopyInputStream; // zero_copy_stream.h
+ }
+ namespace internal {
+ class WireFormat; // wire_format.h
+ class UnknownFieldSetFieldSkipperUsingCord;
+ // extension_set_heavy.cc
+ }
class Message; // message.h
class UnknownField; // below
@@ -68,6 +80,9 @@
// Remove all fields.
inline void Clear();
+ // Remove all fields and deallocate internal data objects
+ void ClearAndFreeMemory();
+
// Is this set empty?
inline bool empty() const;
@@ -107,6 +122,15 @@
// Adds an unknown field from another set.
void AddField(const UnknownField& field);
+ // Delete fields with indices in the range [start .. start+num-1].
+ // Caution: implementation moves all fields with indices [start+num .. ].
+ void DeleteSubrange(int start, int num);
+
+ // Delete all fields with a specific field number. The order of left fields
+ // is preserved.
+ // Caution: implementation moves all fields after the first deleted field.
+ void DeleteByNumber(int number);
+
// Parsing helpers -------------------------------------------------
// These work exactly like the similarly-named methods of Message.
@@ -119,6 +143,7 @@
}
private:
+
void ClearFallback();
vector<UnknownField>* fields_;
@@ -159,6 +184,15 @@
inline string* mutable_length_delimited();
inline UnknownFieldSet* mutable_group();
+ // Serialization API.
+ // These methods can take advantage of the underlying implementation and may
+ // archieve a better performance than using getters to retrieve the data and
+ // do the serialization yourself.
+ void SerializeLengthDelimitedNoTag(io::CodedOutputStream* output) const;
+ uint8* SerializeLengthDelimitedNoTagToArray(uint8* target) const;
+
+ inline int GetLengthDelimitedSize() const;
+
private:
friend class UnknownFieldSet;
@@ -168,13 +202,16 @@
// Make a deep copy of any pointers in this UnknownField.
void DeepCopy();
+
unsigned int number_ : 29;
unsigned int type_ : 3;
union {
uint64 varint_;
uint32 fixed32_;
uint64 fixed64_;
- string* length_delimited_;
+ mutable union {
+ string* string_value_;
+ } length_delimited_;
UnknownFieldSet* group_;
};
};
@@ -211,57 +248,63 @@
AddLengthDelimited(number)->assign(value);
}
+
inline int UnknownField::number() const { return number_; }
inline UnknownField::Type UnknownField::type() const {
return static_cast<Type>(type_);
}
inline uint64 UnknownField::varint () const {
- GOOGLE_DCHECK_EQ(type_, TYPE_VARINT);
+ assert(type_ == TYPE_VARINT);
return varint_;
}
inline uint32 UnknownField::fixed32() const {
- GOOGLE_DCHECK_EQ(type_, TYPE_FIXED32);
+ assert(type_ == TYPE_FIXED32);
return fixed32_;
}
inline uint64 UnknownField::fixed64() const {
- GOOGLE_DCHECK_EQ(type_, TYPE_FIXED64);
+ assert(type_ == TYPE_FIXED64);
return fixed64_;
}
inline const string& UnknownField::length_delimited() const {
- GOOGLE_DCHECK_EQ(type_, TYPE_LENGTH_DELIMITED);
- return *length_delimited_;
+ assert(type_ == TYPE_LENGTH_DELIMITED);
+ return *length_delimited_.string_value_;
}
inline const UnknownFieldSet& UnknownField::group() const {
- GOOGLE_DCHECK_EQ(type_, TYPE_GROUP);
+ assert(type_ == TYPE_GROUP);
return *group_;
}
inline void UnknownField::set_varint(uint64 value) {
- GOOGLE_DCHECK_EQ(type_, TYPE_VARINT);
+ assert(type_ == TYPE_VARINT);
varint_ = value;
}
inline void UnknownField::set_fixed32(uint32 value) {
- GOOGLE_DCHECK_EQ(type_, TYPE_FIXED32);
+ assert(type_ == TYPE_FIXED32);
fixed32_ = value;
}
inline void UnknownField::set_fixed64(uint64 value) {
- GOOGLE_DCHECK_EQ(type_, TYPE_FIXED64);
+ assert(type_ == TYPE_FIXED64);
fixed64_ = value;
}
inline void UnknownField::set_length_delimited(const string& value) {
- GOOGLE_DCHECK_EQ(type_, TYPE_LENGTH_DELIMITED);
- length_delimited_->assign(value);
+ assert(type_ == TYPE_LENGTH_DELIMITED);
+ length_delimited_.string_value_->assign(value);
}
inline string* UnknownField::mutable_length_delimited() {
- GOOGLE_DCHECK_EQ(type_, TYPE_LENGTH_DELIMITED);
- return length_delimited_;
+ assert(type_ == TYPE_LENGTH_DELIMITED);
+ return length_delimited_.string_value_;
}
inline UnknownFieldSet* UnknownField::mutable_group() {
- GOOGLE_DCHECK_EQ(type_, TYPE_GROUP);
+ assert(type_ == TYPE_GROUP);
return group_;
}
+inline int UnknownField::GetLengthDelimitedSize() const {
+ GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_);
+ return length_delimited_.string_value_->size();
+}
+
} // namespace protobuf
} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/unknown_field_set_unittest.cc b/third_party/protobuf/src/google/protobuf/unknown_field_set_unittest.cc
index 1235c9e..c6b8769 100644
--- a/third_party/protobuf/src/google/protobuf/unknown_field_set_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/unknown_field_set_unittest.cc
@@ -46,15 +46,13 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
using internal::WireFormat;
-namespace {
-
class UnknownFieldSetTest : public testing::Test {
protected:
virtual void SetUp() {
@@ -107,6 +105,8 @@
UnknownFieldSet* unknown_fields_;
};
+namespace {
+
TEST_F(UnknownFieldSetTest, AllFieldsPresent) {
// All fields of TestAllTypes should be present, in numeric order (because
// that's the order we parsed them in). Fields that are not valid field
@@ -297,12 +297,21 @@
destination.DebugString());
}
+
TEST_F(UnknownFieldSetTest, Clear) {
// Clear the set.
empty_message_.Clear();
EXPECT_EQ(0, unknown_fields_->field_count());
}
+TEST_F(UnknownFieldSetTest, ClearAndFreeMemory) {
+ EXPECT_GT(unknown_fields_->field_count(), 0);
+ unknown_fields_->ClearAndFreeMemory();
+ EXPECT_EQ(0, unknown_fields_->field_count());
+ unknown_fields_->AddVarint(123456, 654321);
+ EXPECT_EQ(1, unknown_fields_->field_count());
+}
+
TEST_F(UnknownFieldSetTest, ParseKnownAndUnknown) {
// Test mixing known and unknown fields when parsing.
@@ -498,6 +507,7 @@
EXPECT_LT(base_size, empty_message.SpaceUsed());
}
+
TEST_F(UnknownFieldSetTest, Empty) {
UnknownFieldSet unknown_fields;
EXPECT_TRUE(unknown_fields.empty());
@@ -507,6 +517,78 @@
EXPECT_TRUE(unknown_fields.empty());
}
+TEST_F(UnknownFieldSetTest, DeleteSubrange) {
+ // Exhaustively test the deletion of every possible subrange in arrays of all
+ // sizes from 0 through 9.
+ for (int size = 0; size < 10; ++size) {
+ for (int num = 0; num <= size; ++num) {
+ for (int start = 0; start < size - num; ++start) {
+ // Create a set with "size" fields.
+ UnknownFieldSet unknown;
+ for (int i = 0; i < size; ++i) {
+ unknown.AddFixed32(i, i);
+ }
+ // Delete the specified subrange.
+ unknown.DeleteSubrange(start, num);
+ // Make sure the resulting field values are still correct.
+ EXPECT_EQ(size - num, unknown.field_count());
+ for (int i = 0; i < unknown.field_count(); ++i) {
+ if (i < start) {
+ EXPECT_EQ(i, unknown.field(i).fixed32());
+ } else {
+ EXPECT_EQ(i + num, unknown.field(i).fixed32());
+ }
+ }
+ }
+ }
+ }
+}
+
+void CheckDeleteByNumber(const vector<int>& field_numbers, int deleted_number,
+ const vector<int>& expected_field_nubmers) {
+ UnknownFieldSet unknown_fields;
+ for (int i = 0; i < field_numbers.size(); ++i) {
+ unknown_fields.AddFixed32(field_numbers[i], i);
+ }
+ unknown_fields.DeleteByNumber(deleted_number);
+ ASSERT_EQ(expected_field_nubmers.size(), unknown_fields.field_count());
+ for (int i = 0; i < expected_field_nubmers.size(); ++i) {
+ EXPECT_EQ(expected_field_nubmers[i],
+ unknown_fields.field(i).number());
+ }
+}
+
+#define MAKE_VECTOR(x) vector<int>(x, x + GOOGLE_ARRAYSIZE(x))
+TEST_F(UnknownFieldSetTest, DeleteByNumber) {
+ CheckDeleteByNumber(vector<int>(), 1, vector<int>());
+ static const int kTestFieldNumbers1[] = {1, 2, 3};
+ static const int kFieldNumberToDelete1 = 1;
+ static const int kExpectedFieldNumbers1[] = {2, 3};
+ CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers1), kFieldNumberToDelete1,
+ MAKE_VECTOR(kExpectedFieldNumbers1));
+ static const int kTestFieldNumbers2[] = {1, 2, 3};
+ static const int kFieldNumberToDelete2 = 2;
+ static const int kExpectedFieldNumbers2[] = {1, 3};
+ CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers2), kFieldNumberToDelete2,
+ MAKE_VECTOR(kExpectedFieldNumbers2));
+ static const int kTestFieldNumbers3[] = {1, 2, 3};
+ static const int kFieldNumberToDelete3 = 3;
+ static const int kExpectedFieldNumbers3[] = {1, 2};
+ CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers3), kFieldNumberToDelete3,
+ MAKE_VECTOR(kExpectedFieldNumbers3));
+ static const int kTestFieldNumbers4[] = {1, 2, 1, 4, 1};
+ static const int kFieldNumberToDelete4 = 1;
+ static const int kExpectedFieldNumbers4[] = {2, 4};
+ CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers4), kFieldNumberToDelete4,
+ MAKE_VECTOR(kExpectedFieldNumbers4));
+ static const int kTestFieldNumbers5[] = {1, 2, 3, 4, 5};
+ static const int kFieldNumberToDelete5 = 6;
+ static const int kExpectedFieldNumbers5[] = {1, 2, 3, 4, 5};
+ CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers5), kFieldNumberToDelete5,
+ MAKE_VECTOR(kExpectedFieldNumbers5));
+}
+#undef MAKE_VECTOR
} // namespace
+
} // namespace protobuf
} // namespace google
diff --git a/third_party/protobuf/src/google/protobuf/wire_format.cc b/third_party/protobuf/src/google/protobuf/wire_format.cc
index d07f633..491eede 100644
--- a/third_party/protobuf/src/google/protobuf/wire_format.cc
+++ b/third_party/protobuf/src/google/protobuf/wire_format.cc
@@ -48,12 +48,11 @@
#include <google/protobuf/unknown_field_set.h>
+
namespace google {
namespace protobuf {
namespace internal {
-using internal::WireFormatLite;
-
namespace {
// This function turns out to be convenient when using some macros later.
@@ -340,10 +339,7 @@
const FieldDescriptor* field = NULL;
// If we see message data before the type_id, we'll append it to this so
- // we can parse it later. This will probably never happen in practice,
- // as no MessageSet encoder I know of writes the message before the type ID.
- // But, it's technically valid so we should allow it.
- // TODO(kenton): Use a Cord instead? Do I care?
+ // we can parse it later.
string message_data;
while (true) {
@@ -381,7 +377,10 @@
uint32 length;
if (!input->ReadVarint32(&length)) return false;
if (!input->ReadString(&temp, length)) return false;
- message_data.append(temp);
+ io::StringOutputStream output_stream(&message_data);
+ io::CodedOutputStream coded_output(&output_stream);
+ coded_output.WriteVarint32(length);
+ coded_output.WriteString(temp);
} else {
// Already saw type_id, so we can parse this directly.
if (!ParseAndMergeField(fake_tag, field, message, input)) {
@@ -754,10 +753,10 @@
break;
// no default case: have the compiler warn if a case is not covered.
}
- GOOGLE_LOG(ERROR) << "Encountered string containing invalid UTF-8 data while "
+ GOOGLE_LOG(ERROR) << "String field contains invalid UTF-8 data when "
<< operation_str
- << " protocol buffer. Strings must contain only UTF-8; "
- "use the 'bytes' type for raw bytes.";
+ << " a protocol buffer. Use the 'bytes' type if you intend to "
+ "send raw bytes.";
}
}
diff --git a/third_party/protobuf/src/google/protobuf/wire_format.h b/third_party/protobuf/src/google/protobuf/wire_format.h
index d52bc4a..8a89881 100644
--- a/third_party/protobuf/src/google/protobuf/wire_format.h
+++ b/third_party/protobuf/src/google/protobuf/wire_format.h
@@ -40,6 +40,7 @@
#define GOOGLE_PROTOBUF_WIRE_FORMAT_H__
#include <string>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
diff --git a/third_party/protobuf/src/google/protobuf/wire_format_lite.cc b/third_party/protobuf/src/google/protobuf/wire_format_lite.cc
index 3bf9268..6c21478 100644
--- a/third_party/protobuf/src/google/protobuf/wire_format_lite.cc
+++ b/third_party/protobuf/src/google/protobuf/wire_format_lite.cc
@@ -40,7 +40,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream_inl.h>
#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/unknown_field_set.h>
namespace google {
@@ -506,12 +506,14 @@
io::CodedOutputStream* output) {
// String is for UTF-8 text only
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+ GOOGLE_CHECK(value.size() <= kint32max);
output->WriteVarint32(value.size());
output->WriteString(value);
}
void WireFormatLite::WriteBytes(int field_number, const string& value,
io::CodedOutputStream* output) {
WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+ GOOGLE_CHECK(value.size() <= kint32max);
output->WriteVarint32(value.size());
output->WriteString(value);
}
diff --git a/third_party/protobuf/src/google/protobuf/wire_format_lite.h b/third_party/protobuf/src/google/protobuf/wire_format_lite.h
index 5f9f2a3..98d8004 100644
--- a/third_party/protobuf/src/google/protobuf/wire_format_lite.h
+++ b/third_party/protobuf/src/google/protobuf/wire_format_lite.h
@@ -41,16 +41,14 @@
#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
#include <string>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message_lite.h>
+#include <google/protobuf/io/coded_stream.h> // for CodedOutputStream::Varint32Size
namespace google {
namespace protobuf {
template <typename T> class RepeatedField; // repeated_field.h
- namespace io {
- class CodedInputStream; // coded_stream.h
- class CodedOutputStream; // coded_stream.h
- }
class UnknownFieldSet;
}
@@ -521,6 +519,10 @@
template<typename MessageType>
static inline int MessageSizeNoVirtual(const MessageType& value);
+ // Given the length of data, calculate the byte size of the data on the
+ // wire if we encode the data as a length delimited field.
+ static inline int LengthDelimitedSize(int length);
+
private:
// A helper method for the repeated primitive reader. This method has
// optimizations for primitive types that have fixed size on the wire, and
@@ -556,7 +558,7 @@
// saves it as an unknown varint.
void SkipUnknownEnum(int field_number, int value);
- private:
+ protected:
UnknownFieldSet* unknown_fields_;
};
diff --git a/third_party/protobuf/src/google/protobuf/wire_format_lite_inl.h b/third_party/protobuf/src/google/protobuf/wire_format_lite_inl.h
index 103b0bd..0f97386 100644
--- a/third_party/protobuf/src/google/protobuf/wire_format_lite_inl.h
+++ b/third_party/protobuf/src/google/protobuf/wire_format_lite_inl.h
@@ -41,7 +41,6 @@
#include <google/protobuf/message_lite.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/io/coded_stream.h>
@@ -749,8 +748,7 @@
return value.ByteSize();
}
inline int WireFormatLite::MessageSize(const MessageLite& value) {
- int size = value.ByteSize();
- return io::CodedOutputStream::VarintSize32(size) + size;
+ return LengthDelimitedSize(value.ByteSize());
}
// See comment on ReadGroupNoVirtual to understand the need for this template
@@ -763,8 +761,12 @@
template<typename MessageType_WorkAroundCppLookupDefect>
inline int WireFormatLite::MessageSizeNoVirtual(
const MessageType_WorkAroundCppLookupDefect& value) {
- int size = value.MessageType_WorkAroundCppLookupDefect::ByteSize();
- return io::CodedOutputStream::VarintSize32(size) + size;
+ return LengthDelimitedSize(
+ value.MessageType_WorkAroundCppLookupDefect::ByteSize());
+}
+
+inline int WireFormatLite::LengthDelimitedSize(int length) {
+ return io::CodedOutputStream::VarintSize32(length) + length;
}
} // namespace internal
diff --git a/third_party/protobuf/src/google/protobuf/wire_format_unittest.cc b/third_party/protobuf/src/google/protobuf/wire_format_unittest.cc
index 867970c..9822828 100644
--- a/third_party/protobuf/src/google/protobuf/wire_format_unittest.cc
+++ b/third_party/protobuf/src/google/protobuf/wire_format_unittest.cc
@@ -44,7 +44,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util-inl.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
@@ -480,6 +480,54 @@
EXPECT_EQ(message_set.DebugString(), dynamic_message_set.DebugString());
}
+TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) {
+ string data;
+ {
+ unittest::TestMessageSetExtension1 message;
+ message.set_i(123);
+ // Build a MessageSet manually with its message content put before its
+ // type_id.
+ io::StringOutputStream output_stream(&data);
+ io::CodedOutputStream coded_output(&output_stream);
+ coded_output.WriteTag(WireFormatLite::kMessageSetItemStartTag);
+ // Write the message content first.
+ WireFormatLite::WriteTag(WireFormatLite::kMessageSetMessageNumber,
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+ &coded_output);
+ coded_output.WriteVarint32(message.ByteSize());
+ message.SerializeWithCachedSizes(&coded_output);
+ // Write the type id.
+ uint32 type_id = message.GetDescriptor()->extension(0)->number();
+ WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber,
+ type_id, &coded_output);
+ coded_output.WriteTag(WireFormatLite::kMessageSetItemEndTag);
+ }
+ {
+ unittest::TestMessageSet message_set;
+ ASSERT_TRUE(message_set.ParseFromString(data));
+
+ EXPECT_EQ(123, message_set.GetExtension(
+ unittest::TestMessageSetExtension1::message_set_extension).i());
+ }
+ {
+ // Test parse the message via Reflection.
+ unittest::TestMessageSet message_set;
+ io::CodedInputStream input(
+ reinterpret_cast<const uint8*>(data.data()), data.size());
+ EXPECT_TRUE(WireFormat::ParseAndMergePartial(&input, &message_set));
+ EXPECT_TRUE(input.ConsumedEntireMessage());
+
+ EXPECT_EQ(123, message_set.GetExtension(
+ unittest::TestMessageSetExtension1::message_set_extension).i());
+ }
+}
+
+TEST(WireFormatTest, ParseBrokenMessageSet) {
+ unittest::TestMessageSet message_set;
+ string input("goodbye"); // Invalid wire format data.
+ EXPECT_FALSE(message_set.ParseFromString(input));
+}
+
TEST(WireFormatTest, RecursionLimit) {
unittest::TestRecursiveMessage message;
message.mutable_a()->mutable_a()->mutable_a()->mutable_a()->set_i(1);
@@ -800,6 +848,10 @@
return message->ParseFromArray(wire_buffer.data(), wire_buffer.size());
}
+bool StartsWith(const string& s, const string& prefix) {
+ return s.substr(0, prefix.length()) == prefix;
+}
+
TEST(Utf8ValidationTest, WriteInvalidUTF8String) {
string wire_buffer;
protobuf_unittest::OneString input;
@@ -811,11 +863,10 @@
}
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
ASSERT_EQ(1, errors.size());
- EXPECT_EQ("Encountered string containing invalid UTF-8 data while "
- "serializing protocol buffer. Strings must contain only UTF-8; "
- "use the 'bytes' type for raw bytes.",
- errors[0]);
-
+ EXPECT_TRUE(StartsWith(errors[0],
+ "String field contains invalid UTF-8 data when "
+ "serializing a protocol buffer. Use the "
+ "'bytes' type if you intend to send raw bytes."));
#else
ASSERT_EQ(0, errors.size());
#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
@@ -834,10 +885,10 @@
}
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
ASSERT_EQ(1, errors.size());
- EXPECT_EQ("Encountered string containing invalid UTF-8 data while "
- "parsing protocol buffer. Strings must contain only UTF-8; "
- "use the 'bytes' type for raw bytes.",
- errors[0]);
+ EXPECT_TRUE(StartsWith(errors[0],
+ "String field contains invalid UTF-8 data when "
+ "parsing a protocol buffer. Use the "
+ "'bytes' type if you intend to send raw bytes."));
#else
ASSERT_EQ(0, errors.size());
@@ -899,6 +950,28 @@
EXPECT_EQ(input.data(), output.data());
}
+TEST(Utf8ValidationTest, ParseRepeatedString) {
+ protobuf_unittest::MoreBytes input;
+ input.add_data(kValidUTF8String);
+ input.add_data(kInvalidUTF8String);
+ input.add_data(kInvalidUTF8String);
+ string wire_buffer = input.SerializeAsString();
+
+ protobuf_unittest::MoreString output;
+ vector<string> errors;
+ {
+ ScopedMemoryLog log;
+ ReadMessage(wire_buffer, &output);
+ errors = log.GetMessages(ERROR);
+ }
+#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+ ASSERT_EQ(2, errors.size());
+#else
+ ASSERT_EQ(0, errors.size());
+#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+ EXPECT_EQ(wire_buffer, output.SerializeAsString());
+}
+
} // namespace
} // namespace internal
} // namespace protobuf
diff --git a/third_party/protobuf/vsprojects/extract_includes.bat b/third_party/protobuf/vsprojects/extract_includes.bat
index 70fdf73..4dcb4e1 100755
--- a/third_party/protobuf/vsprojects/extract_includes.bat
+++ b/third_party/protobuf/vsprojects/extract_includes.bat
@@ -17,6 +17,7 @@
copy ..\src\google\protobuf\descriptor_database.h include\google\protobuf\descriptor_database.h
copy ..\src\google\protobuf\dynamic_message.h include\google\protobuf\dynamic_message.h
copy ..\src\google\protobuf\extension_set.h include\google\protobuf\extension_set.h
+copy ..\src\google\protobuf\generated_enum_reflection.h include\google\protobuf\generated_enum_reflection.h
copy ..\src\google\protobuf\generated_message_util.h include\google\protobuf\generated_message_util.h
copy ..\src\google\protobuf\generated_message_reflection.h include\google\protobuf\generated_message_reflection.h
copy ..\src\google\protobuf\message.h include\google\protobuf\message.h
diff --git a/third_party/widevine/cdm/widevine_cdm.gyp b/third_party/widevine/cdm/widevine_cdm.gyp
index 0d08bc6..a4185e6 100644
--- a/third_party/widevine/cdm/widevine_cdm.gyp
+++ b/third_party/widevine/cdm/widevine_cdm.gyp
@@ -56,9 +56,9 @@
'widevine_cdm_binaries',
],
'sources': [
- '<(DEPTH)/webkit/renderer/media/crypto/ppapi/cdm_wrapper.cc',
- '<(DEPTH)/webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h',
- '<(DEPTH)/webkit/renderer/media/crypto/ppapi/linked_ptr.h',
+ '<(DEPTH)/media/cdm/ppapi/api/content_decryption_module.h',
+ '<(DEPTH)/media/cdm/ppapi/cdm_wrapper.cc',
+ '<(DEPTH)/media/cdm/ppapi/linked_ptr.h',
],
'conditions': [
[ 'os_posix == 1 and OS != "mac"', {
diff --git a/tools/bisect_utils.py b/tools/bisect_utils.py
index 2847c2c..37869df 100644
--- a/tools/bisect_utils.py
+++ b/tools/bisect_utils.py
@@ -22,6 +22,8 @@
"chrome/data/page_cycler/.git",
"src/data/dom_perf": "https://chrome-internal.googlesource.com/"
"chrome/data/dom_perf/.git",
+ "src/data/mach_ports": "https://chrome-internal.googlesource.com/"
+ "chrome/data/mach_ports/.git",
"src/tools/perf/data": "https://chrome-internal.googlesource.com/"
"chrome/tools/perf/data/.git",
"src/third_party/adobe/flash/binaries/ppapi/linux":
diff --git a/tools/checklicenses/checklicenses.py b/tools/checklicenses/checklicenses.py
index 9c27256..25dedc2 100755
--- a/tools/checklicenses/checklicenses.py
+++ b/tools/checklicenses/checklicenses.py
@@ -128,10 +128,6 @@
'data/tab_switching': [
'UNKNOWN',
],
- 'googleurl': [ # http://code.google.com/p/google-url/issues/detail?id=15
- 'UNKNOWN',
- ],
-
'native_client': [ # http://crbug.com/98099
'UNKNOWN',
],
diff --git a/tools/clang/plugins/ChromeClassTester.cpp b/tools/clang/plugins/ChromeClassTester.cpp
index 5784334..ee8452d 100644
--- a/tools/clang/plugins/ChromeClassTester.cpp
+++ b/tools/clang/plugins/ChromeClassTester.cpp
@@ -151,7 +151,6 @@
banned_directories_.push_back("ppapi/");
banned_directories_.push_back("usr/");
banned_directories_.push_back("testing/");
- banned_directories_.push_back("googleurl/");
banned_directories_.push_back("v8/");
banned_directories_.push_back("dart/");
banned_directories_.push_back("sdch/");
diff --git a/tools/deep_memory_profiler/lib/sorter.py b/tools/deep_memory_profiler/lib/sorter.py
index db50c70..64e0851 100644
--- a/tools/deep_memory_profiler/lib/sorter.py
+++ b/tools/deep_memory_profiler/lib/sorter.py
@@ -20,6 +20,8 @@
os.path.join(BASE_PATH, 'sorter.vm-sharing.json'),
]
+DEFAULT_TEMPLATES = os.path.join(BASE_PATH, 'templates.json')
+
class Unit(object):
"""Represents a minimum unit of memory usage categorization.
@@ -152,7 +154,7 @@
def __init__(self, dct):
self._name = dct['name']
self._hidden = dct.get('hidden', False)
- self._subworlds = dct.get('subworlds', [])
+ self._subs = dct.get('subs', [])
def match(self, unit):
raise NotImplementedError()
@@ -165,9 +167,9 @@
def hidden(self):
return self._hidden
- def iter_subworld(self):
- for subworld in self._subworlds:
- yield subworld
+ def iter_subs(self):
+ for sub in self._subs:
+ yield sub
class VMRule(AbstractRule):
@@ -328,6 +330,7 @@
self._version = dct['version']
self._world = dct['world']
self._name = dct['name']
+ self._root = dct.get('root', False)
self._order = dct['order']
self._rules = []
@@ -368,6 +371,10 @@
def name(self):
return self._name
+ @property
+ def root(self):
+ return self._root
+
def find(self, unit):
raise NotImplementedError()
@@ -414,6 +421,21 @@
assert False
+class SorterTemplates(object):
+ """Represents a template for sorters."""
+ def __init__(self, dct):
+ self._dict = dct
+
+ def as_dict(self):
+ return self._dict
+
+ @staticmethod
+ def load(filename):
+ with open(filename) as templates_f:
+ templates_dict = json.load(templates_f)
+ return SorterTemplates(templates_dict)
+
+
class SorterSet(object):
"""Represents an iterable set of Sorters."""
def __init__(self, additional=None, default=None):
@@ -427,6 +449,7 @@
if sorter.world not in self._sorters:
self._sorters[sorter.world] = []
self._sorters[sorter.world].append(sorter)
+ self._templates = SorterTemplates.load(DEFAULT_TEMPLATES)
def __repr__(self):
result = cStringIO.StringIO()
@@ -441,3 +464,7 @@
def iter_world(self, world):
for sorter in self._sorters.get(world, []):
yield sorter
+
+ @property
+ def templates(self):
+ return self._templates
diff --git a/tools/deep_memory_profiler/sorter.vm-map.json b/tools/deep_memory_profiler/sorter.vm-map.json
index f26e866..7fc4d27 100644
--- a/tools/deep_memory_profiler/sorter.vm-map.json
+++ b/tools/deep_memory_profiler/sorter.vm-map.json
@@ -3,6 +3,7 @@
"version": 1,
"world": "vm",
"name": "map",
+ "root": true,
"order": {},
"rules": [
{
@@ -46,8 +47,11 @@
{
"name": "mmap-tcmalloc",
"backtrace_function": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*",
- "mmap": true,
- "subworlds": [ "malloc" ]
+ "subs": [
+ [ "malloc", "component" ],
+ [ "malloc", "type" ]
+ ],
+ "mmap": true
},
{
"name": "mmap-v8-heap-newspace",
diff --git a/tools/deep_memory_profiler/sorter.vm-sharing.json b/tools/deep_memory_profiler/sorter.vm-sharing.json
index 788a5c3..4cb52a6 100644
--- a/tools/deep_memory_profiler/sorter.vm-sharing.json
+++ b/tools/deep_memory_profiler/sorter.vm-sharing.json
@@ -3,6 +3,7 @@
"version": 1,
"world": "vm",
"name": "sharing",
+ "root": true,
"order": {},
"rules": [
{
diff --git a/tools/deep_memory_profiler/subcommands/cat.py b/tools/deep_memory_profiler/subcommands/cat.py
index b7783b9..1e9e5b3 100644
--- a/tools/deep_memory_profiler/subcommands/cat.py
+++ b/tools/deep_memory_profiler/subcommands/cat.py
@@ -37,6 +37,9 @@
(bucket_set, dumps) = SubCommand.load_basic_files(
dump_path, True, alternative_dirs=alternative_dirs_dict)
+ # Load all sorters.
+ sorters = SorterSet()
+
json_root = OrderedDict()
json_root['version'] = 1
json_root['run_id'] = None
@@ -46,10 +49,14 @@
json_root['run_id'] = ''
break
json_root['run_id'] = dump.run_id
- json_root['snapshots'] = []
+ json_root['roots'] = []
+ for sorter in sorters:
+ if sorter.root:
+ json_root['roots'].append([sorter.world, sorter.name])
+ json_root['default_template'] = 'l2'
+ json_root['templates'] = sorters.templates.as_dict()
- # Load all sorters.
- sorters = SorterSet()
+ json_root['snapshots'] = []
for dump in dumps:
json_root['snapshots'].append(
@@ -76,9 +83,9 @@
def _fill_world(dump, bucket_set, sorters, world):
root = OrderedDict()
- root['name'] = 'world'
+ root['name'] = world
if world == 'vm':
- root['unit_fields'] = ['committed', 'reserved']
+ root['unit_fields'] = ['size', 'reserved']
elif world == 'malloc':
root['unit_fields'] = ['size', 'alloc_count', 'free_count']
@@ -107,11 +114,11 @@
category = OrderedDict()
category['name'] = found.name
category['color'] = 'random'
- subworlds = {}
- for subworld in found.iter_subworld():
- subworlds[subworld] = False
- if subworlds:
- category['subworlds'] = subworlds
+ subs = []
+ for sub_world, sub_breakdown in found.iter_subs():
+ subs.append([sub_world, sub_breakdown])
+ if subs:
+ category['subs'] = subs
if found.hidden:
category['hidden'] = True
category['units'] = []
diff --git a/tools/deep_memory_profiler/templates.json b/tools/deep_memory_profiler/templates.json
new file mode 100644
index 0000000..b4d9a4e
--- /dev/null
+++ b/tools/deep_memory_profiler/templates.json
@@ -0,0 +1,12 @@
+{
+ "l2": ["vm", "map", {
+ "mmap-tcmalloc": ["malloc", "component", {}]
+ }],
+ "details": ["vm", "map", {
+ "mmap-tcmalloc": ["malloc", "component", {
+ "webkit": ["malloc", "webkit-details", {}],
+ "skia": ["malloc", "skia-details", {}]
+ }],
+ "mmap-v8-heap": ["javascript", "type", {}]
+ }]
+}
diff --git a/tools/heapcheck/suppressions.txt b/tools/heapcheck/suppressions.txt
index 5f767c1..5d03b7b 100644
--- a/tools/heapcheck/suppressions.txt
+++ b/tools/heapcheck/suppressions.txt
@@ -640,20 +640,6 @@
fun:chromeos::input_method::InputMethodConfigurationTest_TestInitialize_Test::TestBody
}
{
- bug_181691
- Heapcheck:Leak
- ...
- fun:InitThread
- fun:ShCompile
- fun:gpu::gles2::ShaderTranslator::Translate
- fun:gpu::gles2::ProgramManager::ForceCompileShader
- fun:gpu::gles2::ProgramManager::DoCompileShader
- fun:gpu::gles2::GLES2DecoderImpl::DoCompileShader
- fun:gpu::gles2::GLES2DecoderImpl::HandleCompileShader
- fun:gpu::gles2::GLES2DecoderImpl::DoCommand
- fun:gpu::CommandParser::ProcessCommand
-}
-{
bug_233532
Heapcheck:Leak
...
@@ -855,3 +841,11 @@
fun:net::NSSCertDatabase::DeleteCertAndKey
fun:chromeos::NetworkCertMigratorTest::CleanupTestCert
}
+{
+ bug_270312
+ Heapcheck:Leak
+ ...
+ fun:MessageCenterButtonBar
+ fun:MessageCenterView
+ fun:message_center::MessageCenterViewTest::SetUp
+}
diff --git a/tools/licenses.py b/tools/licenses.py
index 4d1cb01..d2c535b 100755
--- a/tools/licenses.py
+++ b/tools/licenses.py
@@ -82,7 +82,6 @@
os.path.join('chrome', 'common', 'extensions', 'docs', 'examples'),
os.path.join('chrome', 'test', 'chromeos', 'autotest'),
os.path.join('chrome', 'test', 'data'),
- os.path.join('googleurl'),
os.path.join('native_client'),
os.path.join('native_client_sdk'),
os.path.join('net', 'tools', 'spdyshark'),
@@ -97,6 +96,7 @@
os.path.join('tools', 'grit'),
os.path.join('tools', 'gyp'),
os.path.join('tools', 'page_cycler', 'acid3'),
+ os.path.join('url', 'third_party', 'mozilla'),
os.path.join('v8'),
# Fake directory so we can include the strongtalk license.
os.path.join('v8', 'strongtalk'),
@@ -107,12 +107,6 @@
# can't provide a README.chromium. Please prefer a README.chromium
# wherever possible.
SPECIAL_CASES = {
- os.path.join('googleurl'): {
- "Name": "google-url",
- "URL": "http://code.google.com/p/google-url/",
- "License": "BSD and MPL 1.1/GPL 2.0/LGPL 2.1",
- "License File": "LICENSE.txt",
- },
os.path.join('native_client'): {
"Name": "native client",
"URL": "http://code.google.com/p/nativeclient",
diff --git a/tools/metrics/actions/chromeactions.txt b/tools/metrics/actions/chromeactions.txt
index f8c62b7..3970b94 100644
--- a/tools/metrics/actions/chromeactions.txt
+++ b/tools/metrics/actions/chromeactions.txt
@@ -1071,6 +1071,7 @@
0x9e77fb06de21d0b4 MobileContextMenuOpenLinkInIncognito
0xa024c8dce2320bb1 MobileContextMenuOpenLinkInNewTab
0xde20f676a6805404 MobileContextMenuSaveImage
+0xf123d71a7f1df18a MobileContextMenuSearchByImage
0x470fb8fde85c094b MobileContextMenuShareLink
0xb177bc454b6a2105 MobileContextMenuText
0xac284cf4338f8a66 MobileContextMenuViewImage
@@ -1129,6 +1130,10 @@
0x3deff4b1d1a6c795 MobileToolbarShowStackView
0xa358306810cb78c4 MobileToolbarStackViewNewTab
0x001b06917446ac95 MobileToolbarToggleBookmark
+0xfe5d7732799048fd MobileUsingMenuByHwButtonDragging
+0xb25fb65d8d767718 MobileUsingMenuByHwButtonTap
+0xaf60773aea14a7b5 MobileUsingMenuBySwButtonDragging
+0x15fd6bb5bff45129 MobileUsingMenuBySwButtonTap
0x409a073e57298782 MostVisited0
0xaf4909be766297ab MostVisited1
0x6028c57529e1608f MostVisited2
diff --git a/tools/metrics/actions/extract_actions.py b/tools/metrics/actions/extract_actions.py
index a1ea213..f6819af 100755
--- a/tools/metrics/actions/extract_actions.py
+++ b/tools/metrics/actions/extract_actions.py
@@ -212,6 +212,7 @@
actions.add('MobileContextMenuOpenLinkInIncognito')
actions.add('MobileContextMenuOpenLinkInNewTab')
actions.add('MobileContextMenuSaveImage')
+ actions.add('MobileContextMenuSearchByImage')
actions.add('MobileContextMenuShareLink')
actions.add('MobileContextMenuText')
actions.add('MobileContextMenuViewImage')
@@ -270,6 +271,10 @@
actions.add('MobileToolbarShowStackView')
actions.add('MobileToolbarStackViewNewTab')
actions.add('MobileToolbarToggleBookmark')
+ actions.add('MobileUsingMenuByHwButtonDragging')
+ actions.add('MobileUsingMenuByHwButtonTap')
+ actions.add('MobileUsingMenuBySwButtonDragging')
+ actions.add('MobileUsingMenuBySwButtonTap')
actions.add('SystemBack')
actions.add('SystemBackForNavigation')
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 3e7fe9d..f0c5161 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -1140,6 +1140,14 @@
</histogram>
<histogram name="CertificateType">
+ <obsolete>
+ Deprecated as of 8/2013. This histogram only considered the leaf certificate
+ expiry date as a proxy for whether a certificate was in-scope for the BRs,
+ but did not consider the issuance date. As some CAs have issued long-lived
+ certs prior to the BRs, this disproportionately reported those certs as
+ being subject to the BRs, but non-compliant, when in reality they're not
+ subject.
+ </obsolete>
<summary>
Information about the certificate algorithms and sizes in use on the web, to
examine compliance with the CA/Browser Forum requirements and security best
@@ -1147,6 +1155,15 @@
</summary>
</histogram>
+<histogram name="CertificateType2">
+ <summary>
+ Information about the certificate algorithms and sizes in use on the web, to
+ examine compliance with the CA/Browser Forum requirements and security best
+ practice. This histogram considers the notBefore as the issuance date, for
+ purposes of what requirements apply.
+ </summary>
+</histogram>
+
<histogram name="Chrome.SearchSelectExempt" enum="SearchEngine">
<obsolete>
Deprecated 8/2013. No longer tracked.
@@ -4056,6 +4073,14 @@
</summary>
</histogram>
+<histogram name="HistoryPage.ClickPositionSubset">
+ <summary>
+ Subset of the Click Position histogram. Contains only the first smaller
+ subset of entries on the page. Number of entries that the clicked entry is
+ older than in History page. Last bucket is entries of that value or higher.
+ </summary>
+</histogram>
+
<histogram name="HistoryPage.OtherDevicesMenu" enum="NtpOtherSessionsType">
<summary>
Histogram for usage of the section in the history page that allows the user
@@ -4071,6 +4096,16 @@
</summary>
</histogram>
+<histogram name="HistoryPage.RemoveEntryPositionSubset">
+ <summary>
+ Subset of Remove Entry Position histogram. Contains only the first smaller
+ subset of entries on the page. Number of entries that the deleted entry is
+ older than in History page. Last bucket is any entry of that value or
+ higher. Confirmed removal is not guaranteed, just an initiation of 'Remove
+ selected items'.
+ </summary>
+</histogram>
+
<histogram name="HttpCache.EntryLockWait" units="milliseconds">
<summary>
The time spent waiting for write lock on a disk cache entry.
@@ -7110,6 +7145,10 @@
</summary>
</histogram>
+<histogram name="Net.QuicSession.QuicVersion">
+ <summary>Version of the QUIC protocol used for this connection.</summary>
+</histogram>
+
<histogram name="Net.RenegotiationExtensionSupported">
<summary>
True if the HTTP request was sent to a server which supports the TLS
@@ -7117,6 +7156,13 @@
</summary>
</histogram>
+<histogram name="Net.ResourceLoader.ReadDeferral" units="milliseconds">
+ <summary>
+ When starting a cross-site navigation, the time between reading the headers
+ and body of the response.
+ </summary>
+</histogram>
+
<histogram name="Net.SocketIdleTimeBeforeNextUse_ReusedSocket">
<summary>The time an already used socket sat idle before being used.</summary>
</histogram>
@@ -9653,6 +9699,13 @@
</summary>
</histogram>
+<histogram name="Platform.DiskUsage.NumUserHomeDirectories"
+ units="home directories">
+ <summary>
+ Number of users home directories on the device. Logged once a day.
+ </summary>
+</histogram>
+
<histogram name="Platform.DiskUsage.OldestUserOnDevice">
<summary>
Days since last login of the least recently user on device. Logged once a
@@ -13233,6 +13286,20 @@
</summary>
</histogram>
+<histogram name="Settings.HomePageIsNewTabPage.PulledFromSync" enum="Boolean">
+ <summary>
+ The value of the home-page-is-new-tab-page pref when pulled down from sync
+ to update an out-of-sync local pref store.
+ </summary>
+</histogram>
+
+<histogram name="Settings.HomePageIsNewTabPage.PushedToSync" enum="Boolean">
+ <summary>
+ The value of the home-page-is-new-tab-page pref when pushed up to sync from
+ a change made locally.
+ </summary>
+</histogram>
+
<histogram name="Settings.ShowHomeButton" enum="BooleanEnabled">
<summary>
Whether or not the home button is enabled in user preferences when a profile
@@ -13240,10 +13307,39 @@
</summary>
</histogram>
+<histogram name="Settings.ShowHomeButton.PulledFromSync" enum="BooleanEnabled">
+ <summary>
+ The enabled state of the Home button pref when pulled down from sync to
+ update an out-of-sync local pref store.
+ </summary>
+</histogram>
+
+<histogram name="Settings.ShowHomeButton.PushedToSync" enum="BooleanEnabled">
+ <summary>
+ The enabled state of the Home button pref when pushed up to sync from a
+ change made locally.
+ </summary>
+</histogram>
+
<histogram name="Settings.StartupPageLoadSettings" enum="SessionStartupPref">
<summary>The startup page settings when a profile is loaded.</summary>
</histogram>
+<histogram name="Settings.StartupPageLoadSettings.PulledFromSync"
+ enum="SessionStartupPref">
+ <summary>
+ The startup page setting when pulled down from sync to update an out-of-sync
+ local pref store.
+ </summary>
+</histogram>
+
+<histogram name="Settings.StartupPageLoadSettings.PushedToSync"
+ enum="SessionStartupPref">
+ <summary>
+ The startup page setting when pushed up to sync from a change made locally.
+ </summary>
+</histogram>
+
<histogram name="Settings.StartupPageLoadURLs">
<summary>
The number of URLs to be loaded on startup when a profile is loaded, if the
@@ -14573,6 +14669,21 @@
</summary>
</histogram>
+<histogram name="UserManager.LoginUserType" enum="UserType">
+ <summary>
+ The number of users of different types that log in to the system (Chrome
+ OS).
+ </summary>
+</histogram>
+
+<histogram name="UserManager.LogoutToLoginDelay" units="seconds">
+ <summary>
+ The time between one regular user logging out and a different regular user
+ logging in (Chrome OS). Delays above thirty minutes or which span system
+ reboots or non-regular-user logins are not reported.
+ </summary>
+</histogram>
+
<histogram name="Variations.DisabledNoEntropyProvider" enum="BooleanHit">
<obsolete>
Deprecated 1/2013. No longer tracked.
@@ -15052,7 +15163,52 @@
</summary>
</histogram>
+<histogram name="WebFont.DownloadTime.0.Under10KB" units="milliseconds">
+ <summary>
+ The time it takes for a webfont download to finish, for webfonts of under
+ 10KB.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.1.10KBTo50KB" units="milliseconds">
+ <summary>
+ The time it takes for a webfont download to finish, for webfonts of
+ 10KB-50KB.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.2.50KBTo100KB" units="milliseconds">
+ <summary>
+ The time it takes for a webfont download to finish, for webfonts of
+ 50KB-100KB.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.3.100KBTo1MB" units="milliseconds">
+ <summary>
+ The time it takes for a webfont download to finish, for webfonts of
+ 100KB-1MB.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.4.Over1MB" units="milliseconds">
+ <summary>
+ The time it takes for a webfont download to finish, for webfonts of over
+ 1MB.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.LoadError" units="milliseconds">
+ <summary>
+ The time taken for a webfont download that failed. Includes aborted
+ requests.
+ </summary>
+</histogram>
+
<histogram name="WebFont.LoadTime.0.Under10KB" units="milliseconds">
+ <obsolete>
+ Deprecated as of 8/2013, replaced by WebFont.DownloadTime.0.Under10KB.
+ </obsolete>
<summary>
The time it takes for a webfont download to finish, for webfonts of under
10KB.
@@ -15060,6 +15216,9 @@
</histogram>
<histogram name="WebFont.LoadTime.1.10KBTo50KB" units="milliseconds">
+ <obsolete>
+ Deprecated as of 8/2013, replaced by WebFont.DownloadTime.1.10KBTo50KB.
+ </obsolete>
<summary>
The time it takes for a webfont download to finish, for webfonts of
10KB-50KB.
@@ -15067,6 +15226,9 @@
</histogram>
<histogram name="WebFont.LoadTime.2.50KBTo100KB" units="milliseconds">
+ <obsolete>
+ Deprecated as of 8/2013, replaced by WebFont.DownloadTime.2.50KBTo100KB.
+ </obsolete>
<summary>
The time it takes for a webfont download to finish, for webfonts of
50KB-100KB.
@@ -15074,6 +15236,9 @@
</histogram>
<histogram name="WebFont.LoadTime.3.100KBTo1MB" units="milliseconds">
+ <obsolete>
+ Deprecated as of 8/2013, replaced by WebFont.DownloadTime.3.100KBTo1MB.
+ </obsolete>
<summary>
The time it takes for a webfont download to finish, for webfonts of
100KB-1MB.
@@ -15081,6 +15246,9 @@
</histogram>
<histogram name="WebFont.LoadTime.4.Over1MB" units="milliseconds">
+ <obsolete>
+ Deprecated as of 8/2013, replaced by WebFont.DownloadTime.4.Over1MB.
+ </obsolete>
<summary>
The time it takes for a webfont download to finish, for webfonts of over
1MB.
@@ -15088,6 +15256,9 @@
</histogram>
<histogram name="WebFont.LoadTime.LoadError" units="milliseconds">
+ <obsolete>
+ Deprecated as of 8/2013, replaced by WebFont.DownloadTime.LoadError.
+ </obsolete>
<summary>
The time taken for a webfont download that failed. Includes aborted
requests.
@@ -16182,8 +16353,8 @@
<int value="7" label="Cancelled"/>
<int value="8" label="Started"/>
<int value="9" label="Interrupted"/>
- <int value="10" label="Calls to AppendDataToFile (Size)"/>
- <int value="11" label="Calls to AppendDataToFile (Count)"/>
+ <int value="10" label="Calls to AppendDataToFile (Size) (Obsolete)"/>
+ <int value="11" label="Calls to AppendDataToFile (Count) (Obsolete)"/>
<int value="12" label="Interrupted at End of Download"/>
<int value="13" label="Attempt to Append to Detached File"/>
<int value="14" label="File Missing After Successful Scan"/>
@@ -17450,6 +17621,7 @@
<int value="514" label="SYSTEM_STORAGE_GETALLAVAILABLECAPACITYWATCHES"/>
<int value="515" label="SYSTEM_STORAGE_REMOVEALLAVAILABLECAPACITYWATCHES"/>
<int value="516" label="INFOBARS_SHOW"/>
+ <int value="517" label="EXPERIMENTAL_INPUT_VIRTUALKEYBOARD_MOVECURSOR"/>
</enum>
<enum name="ExtensionInstallCause" type="int">
@@ -21980,6 +22152,8 @@
<int value="11" label="SHOW_UNDERSTAND"/>
<int value="12" label="SHOW_INTERNAL_HOSTNAME"/>
<int value="13" label="PROCEED_INTERNAL_HOSTNAME"/>
+ <int value="14" label="SHOW_NEW_SITE"/>
+ <int value="15" label="PROCEED_NEW_SITE"/>
</enum>
<enum name="SuspendStatus" type="int">
@@ -22002,6 +22176,8 @@
<int value="3" label="Partially evicted"/>
<int value="4" label="Reloaded due to backgrounding"/>
<int value="5" label="Reloaded due to incognito"/>
+ <int value="6" label="Reloaded due to cold start (fg tab on start)"/>
+ <int value="7" label="Reloaded due to cold start (bg tab on switch)"/>
</enum>
<enum name="TabSwitchedToForegroundLaunchedWithURL" type="int">
@@ -22241,6 +22417,15 @@
<int value="10" label="kFileSystemScheme"/>
</enum>
+<enum name="UserType" type="int">
+ <int value="0" label="Regular"/>
+ <int value="1" label="Guest"/>
+ <int value="2" label="Retail Mode"/>
+ <int value="3" label="Public Account"/>
+ <int value="4" label="Locally Managed"/>
+ <int value="5" label="Kiosk App"/>
+</enum>
+
<enum name="VariationsResourceRequestsAllowedState" type="int">
<int value="0" label="Resource requests allowed"/>
<int value="1" label="Resource requests not allowed"/>
@@ -22375,6 +22560,9 @@
<int value="8" label="Spending limit exceeded"/>
<int value="9" label="Unsupported API version"/>
<int value="10" label="Unknown error"/>
+ <int value="11" label="Unsupported merchant"/>
+ <int value="12" label="Unsupported buyer legal address"/>
+ <int value="13" label="Unverified know your customer status"/>
</enum>
<enum name="WalletRequiredActions" type="int">
@@ -22613,9 +22801,23 @@
<affected-histogram name="CertificateType.NonBR.Intermediate"/>
<affected-histogram name="CertificateType.NonBR.Leaf"/>
<affected-histogram name="CertificateType.NonBR.Root"/>
+ <affected-histogram name="CertificateType2.BR.Intermediate"/>
+ <affected-histogram name="CertificateType2.BR.Leaf"/>
+ <affected-histogram name="CertificateType2.BR.Root"/>
+ <affected-histogram name="CertificateType2.NonBR.Intermediate"/>
+ <affected-histogram name="CertificateType2.NonBR.Leaf"/>
+ <affected-histogram name="CertificateType2.NonBR.Root"/>
</fieldtrial>
<fieldtrial name="CertificateTypeBRValidity" separator=".">
+ <obsolete>
+ Deprecated as of 8/2013. This histogram only considered the leaf certificate
+ expiry date as a proxy for whether a certificate was in-scope for the BRs,
+ but did not consider the issuance date. As some CAs have issued long-lived
+ certs prior to the BRs, this disproportionately reported those certs as
+ being subject to the BRs, but non-compliant, when in reality they're not
+ subject.
+ </obsolete>
<group name="BR"
label="The *leaf* certificate of the chain expires after 2013-12-31,
meaning that it should be in scope for the Baseline
@@ -22626,12 +22828,26 @@
<affected-histogram name="CertificateType"/>
</fieldtrial>
+<fieldtrial name="CertificateTypeBRValidity2" separator=".">
+ <group name="BR"
+ label="The *leaf* certificate of the chain expires after 2013-12-31 and
+ was issued on or after 2012-07-01, as judged by the notBefore,
+ meaning that it should be in scope for the Baseline
+ Requirement's key size requirements"/>
+ <group name="NonBR"
+ label="The *leaf* certificate of the chain expires on or before
+ 2013-12-31 or was issued before 2012-07-01"/>
+ <affected-histogram name="CertificateType2"/>
+</fieldtrial>
+
<fieldtrial name="CertificateTypeChainPosition" separator=".">
<group name="Intermediate" label="Intermediate's SPKI"/>
<group name="Leaf" label="Leaf's SPKI"/>
<group name="Root" label="Root's SPKI"/>
<affected-histogram name="CertificateType.BR"/>
<affected-histogram name="CertificateType.NonBR"/>
+ <affected-histogram name="CertificateType2.BR"/>
+ <affected-histogram name="CertificateType2.NonBR"/>
</fieldtrial>
<fieldtrial name="ConnCountImpact">
diff --git a/tools/perf/benchmarks/pica.py b/tools/perf/benchmarks/pica.py
index fed16b6..01920bd 100644
--- a/tools/perf/benchmarks/pica.py
+++ b/tools/perf/benchmarks/pica.py
@@ -2,45 +2,15 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import os
-
from telemetry import test
-from telemetry.core import util
from telemetry.page import page_measurement
-from telemetry.page import page_set
-
class PicaMeasurement(page_measurement.PageMeasurement):
- def WillNavigateToPage(self, page, tab):
- page.script_to_evaluate_on_commit = """
- document.addEventListener('WebComponentsReady', function() {
- var unused = document.body.offsetHeight; // force layout
- window.__pica_load_time = performance.now();
- });
- """
-
def MeasurePage(self, _, tab, results):
- def _IsDone():
- return tab.EvaluateJavaScript('window.__pica_load_time != undefined')
- util.WaitFor(_IsDone, 60)
-
result = int(tab.EvaluateJavaScript('__pica_load_time'))
results.Add('Total', 'ms', result)
class Pica(test.Test):
test = PicaMeasurement
-
- def CreatePageSet(self, options):
- return page_set.PageSet.FromDict({
- 'archive_data_file': '../data/pica.json',
- # Pica requires non-deterministic Date and Math.random calls
- # See http://crbug.com/255641
- 'make_javascript_deterministic': False,
- 'pages': [
- {
- 'url': 'http://www.polymer-project.org/'
- 'polymer-all/projects/pica/index.html'
- }
- ]
- }, os.path.abspath(__file__))
+ page_set = 'page_sets/pica.json'
diff --git a/tools/perf/measurements/smoothness.py b/tools/perf/measurements/smoothness.py
index a553e95..4bdbe07 100644
--- a/tools/perf/measurements/smoothness.py
+++ b/tools/perf/measurements/smoothness.py
@@ -3,6 +3,7 @@
# found in the LICENSE file.
from metrics import loading
from metrics import smoothness
+from metrics.gpu_rendering_stats import GpuRenderingStats
from telemetry.page import page_measurement
class DidNotScrollException(page_measurement.MeasurementFailure):
@@ -59,11 +60,9 @@
loading.LoadingMetric().AddResults(tab, results)
smoothness.CalcFirstPaintTimeResults(results, tab)
- smoothness.CalcScrollResults(rendering_stats_deltas, results)
- smoothness.CalcTextureUploadResults(rendering_stats_deltas, results)
- smoothness.CalcImageDecodingResults(rendering_stats_deltas, results)
- smoothness.CalcAnalysisResults(rendering_stats_deltas, results)
- smoothness.CalcLatencyResults(rendering_stats_deltas, results)
+
+ benchmark_stats = GpuRenderingStats(rendering_stats_deltas)
+ smoothness.CalcResults(benchmark_stats, results)
if self.options.report_all_results:
for k, v in rendering_stats_deltas.iteritems():
diff --git a/tools/perf/metrics/gpu_rendering_stats.py b/tools/perf/metrics/gpu_rendering_stats.py
new file mode 100644
index 0000000..9af9f9e
--- /dev/null
+++ b/tools/perf/metrics/gpu_rendering_stats.py
@@ -0,0 +1,47 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class GpuRenderingStats(object):
+ def __init__(self, rendering_stats_deltas):
+ rs = rendering_stats_deltas
+
+ # Scroll Stats
+ self.total_time = rs.get('totalTimeInSeconds', 0)
+ self.screen_frame_count = rs.get('numFramesSentToScreen', 0)
+ self.dropped_frame_count = rs.get('droppedFrameCount', 0)
+ self.impl_thread_scroll_count = rs.get('numImplThreadScrolls', 0)
+ self.main_thread_scroll_count = rs.get('numMainThreadScrolls', 0)
+ self.drawn_layers_count = rs.get('numLayersDrawn', 0)
+ self.missing_tile_count = rs.get('numMissingTiles', 0)
+
+ # Texture Upload Stats
+ self.texture_upload_count = rs.get('textureUploadCount', 0)
+ self.texture_upload_time = rs.get('totalTextureUploadTimeInSeconds', 0)
+ self.commit_count = rs.get('totalCommitCount', 0)
+ self.commit_time = rs.get('totalCommitTimeInSeconds', 0)
+
+ # Image Decoding Stats
+ self.deferred_image_decode_count = rs.get(
+ 'totalDeferredImageDecodeCount', 0)
+ self.deferred_image_decode_time = rs.get(
+ 'totalDeferredImageDecodeTimeInSeconds', 0)
+ self.deferred_image_cache_hits = rs.get(
+ 'totalDeferredImageCacheHitCount', 0)
+ self.image_gathering_count = rs.get('totalImageGatheringCount', 0)
+ self.image_gathering_time = rs.get('totalImageGatheringTimeInSeconds', 0)
+
+ # Tile Analysis Stats
+ self.tile_analysis_count = rs.get('totalTilesAnalyzed', 0)
+ self.tile_analysis_time = rs.get('totalTileAnalysisTimeInSeconds', 0)
+ self.solid_color_tile_analysis_count = rs.get('solidColorTilesAnalyzed', 0)
+
+ # Latency Stats
+ self.input_event_count = rs.get('inputEventCount', 0)
+ self.input_event_latency = rs.get('totalInputLatency', 0)
+ self.touch_ui_count = rs.get('touchUICount', 0)
+ self.touch_ui_latency = rs.get('totalTouchUILatency', 0)
+ self.touch_acked_count = rs.get('touchAckedCount', 0)
+ self.touch_acked_latency = rs.get('totalTouchAckedLatency', 0)
+ self.scroll_update_count = rs.get('scrollUpdateCount', 0)
+ self.scroll_update_latency = rs.get('totalScrollUpdateLatency', 0)
diff --git a/tools/perf/metrics/smoothness.py b/tools/perf/metrics/smoothness.py
index f4ebfbc..c4ec7bc 100644
--- a/tools/perf/metrics/smoothness.py
+++ b/tools/perf/metrics/smoothness.py
@@ -51,66 +51,15 @@
return self._tab.EvaluateJavaScript(
'window.__renderingStats.getDeltas()')
-
-def DivideIfPossibleOrZero(numerator, denominator):
+def Average(numerator, denominator, scale = None, precision = None):
if denominator == 0:
return 0
- return numerator / denominator
-
-def CalcScrollResults(rendering_stats_deltas, results):
- num_frames_sent_to_screen = rendering_stats_deltas['numFramesSentToScreen']
-
- mean_frame_time_seconds = (
- rendering_stats_deltas['totalTimeInSeconds'] /
- float(num_frames_sent_to_screen))
-
- dropped_percent = (
- rendering_stats_deltas['droppedFrameCount'] /
- float(num_frames_sent_to_screen))
-
- num_impl_thread_scrolls = rendering_stats_deltas.get(
- 'numImplThreadScrolls', 0)
- num_main_thread_scrolls = rendering_stats_deltas.get(
- 'numMainThreadScrolls', 0)
-
- percent_impl_scrolled = DivideIfPossibleOrZero(
- float(num_impl_thread_scrolls),
- num_impl_thread_scrolls + num_main_thread_scrolls)
-
- num_layers = (
- rendering_stats_deltas.get('numLayersDrawn', 0) /
- float(num_frames_sent_to_screen))
-
- num_missing_tiles = (
- rendering_stats_deltas.get('numMissingTiles', 0) /
- float(num_frames_sent_to_screen))
-
- results.Add('mean_frame_time', 'ms', round(mean_frame_time_seconds * 1000, 3))
- results.Add('dropped_percent', '%', round(dropped_percent * 100, 1),
- data_type='unimportant')
- results.Add('percent_impl_scrolled', '%',
- round(percent_impl_scrolled * 100, 1),
- data_type='unimportant')
- results.Add('average_num_layers_drawn', '', round(num_layers, 1),
- data_type='unimportant')
- results.Add('average_num_missing_tiles', '', round(num_missing_tiles, 1),
- data_type='unimportant')
-
-def CalcTextureUploadResults(rendering_stats_deltas, results):
- if (('totalCommitCount' not in rendering_stats_deltas)
- or rendering_stats_deltas['totalCommitCount'] == 0) :
- averageCommitTimeMs = 0
- else :
- averageCommitTimeMs = (
- 1000 * rendering_stats_deltas['totalCommitTimeInSeconds'] /
- rendering_stats_deltas['totalCommitCount'])
-
- results.Add('texture_upload_count', 'count',
- rendering_stats_deltas.get('textureUploadCount', 0))
- results.Add('total_texture_upload_time', 'seconds',
- rendering_stats_deltas.get('totalTextureUploadTimeInSeconds', 0))
- results.Add('average_commit_time', 'ms', averageCommitTimeMs,
- data_type='unimportant')
+ avg = float(numerator) / float(denominator)
+ if scale:
+ avg *= scale
+ if precision:
+ avg = round(avg, precision)
+ return avg
def CalcFirstPaintTimeResults(results, tab):
if tab.browser.is_content_shell:
@@ -131,72 +80,78 @@
results.Add('first_paint', 'ms', round(first_paint_secs * 1000, 1))
-def CalcImageDecodingResults(rendering_stats_deltas, results):
- totalDeferredImageDecodeCount = rendering_stats_deltas.get(
- 'totalDeferredImageDecodeCount', 0)
- totalDeferredImageCacheHitCount = rendering_stats_deltas.get(
- 'totalDeferredImageCacheHitCount', 0)
- totalImageGatheringCount = rendering_stats_deltas.get(
- 'totalImageGatheringCount', 0)
- totalDeferredImageDecodeTimeInSeconds = rendering_stats_deltas.get(
- 'totalDeferredImageDecodeTimeInSeconds', 0)
- totalImageGatheringTimeInSeconds = rendering_stats_deltas.get(
- 'totalImageGatheringTimeInSeconds', 0)
+def CalcResults(benchmark_stats, results):
+ s = benchmark_stats
- averageImageGatheringTime = DivideIfPossibleOrZero(
- (totalImageGatheringTimeInSeconds * 1000), totalImageGatheringCount)
+ # Scroll Results
+ results.Add('mean_frame_time', 'ms',
+ Average(s.total_time, s.screen_frame_count, 1000, 3))
+ results.Add('dropped_percent', '%',
+ Average(s.dropped_frame_count, s.screen_frame_count,
+ 100, 1),
+ data_type='unimportant')
+ results.Add('percent_impl_scrolled', '%',
+ Average(s.impl_thread_scroll_count,
+ s.impl_thread_scroll_count +
+ s.main_thread_scroll_count,
+ 100, 1),
+ data_type='unimportant')
+ results.Add('average_num_layers_drawn', '',
+ Average(s.drawn_layers_count, s.screen_frame_count, 1, 1),
+ data_type='unimportant')
+ results.Add('average_num_missing_tiles', '',
+ Average(s.missing_tile_count, s.screen_frame_count, 1, 1),
+ data_type='unimportant')
+ # Texture Upload Results
+ results.Add('average_commit_time', 'ms',
+ Average(s.commit_time, s.commit_count, 1000, 3),
+ data_type='unimportant')
+ results.Add('texture_upload_count', 'count',
+ s.texture_upload_count)
+ results.Add('total_texture_upload_time', 'seconds',
+ s.texture_upload_time)
+
+ # Image Decoding Results
results.Add('total_deferred_image_decode_count', 'count',
- totalDeferredImageDecodeCount,
+ s.deferred_image_decode_count,
data_type='unimportant')
results.Add('total_image_cache_hit_count', 'count',
- totalDeferredImageCacheHitCount,
+ s.deferred_image_cache_hits,
data_type='unimportant')
- results.Add('average_image_gathering_time', 'ms', averageImageGatheringTime,
+ results.Add('average_image_gathering_time', 'ms',
+ Average(s.image_gathering_time, s.image_gathering_count,
+ 1000, 3),
data_type='unimportant')
results.Add('total_deferred_image_decoding_time', 'seconds',
- totalDeferredImageDecodeTimeInSeconds,
+ s.deferred_image_decode_time,
data_type='unimportant')
-def CalcAnalysisResults(rendering_stats_deltas, results):
- totalTilesAnalyzed = rendering_stats_deltas.get(
- 'totalTilesAnalyzed', 0)
- solidColorTilesAnalyzed = rendering_stats_deltas.get(
- 'solidColorTilesAnalyzed', 0)
- totalTileAnalysisTimeInSeconds = rendering_stats_deltas.get(
- 'totalTileAnalysisTimeInSeconds', 0)
-
- averageAnalysisTimeMS = \
- 1000 * DivideIfPossibleOrZero(totalTileAnalysisTimeInSeconds,
- totalTilesAnalyzed)
-
+ # Tile Analysis Results
results.Add('total_tiles_analyzed', 'count',
- totalTilesAnalyzed,
+ s.tile_analysis_count,
data_type='unimportant')
results.Add('solid_color_tiles_analyzed', 'count',
- solidColorTilesAnalyzed,
+ s.solid_color_tile_analysis_count,
data_type='unimportant')
results.Add('average_tile_analysis_time', 'ms',
- averageAnalysisTimeMS,
+ Average(s.tile_analysis_time, s.tile_analysis_count,
+ 1000, 3),
data_type='unimportant')
-def CalcLatency(rendering_stats_deltas, count_name, total_latency_name,
- result_name, results):
- eventCount = rendering_stats_deltas.get(count_name, 0)
- totalLatencyInSeconds = rendering_stats_deltas.get(total_latency_name, 0)
- averageLatency = DivideIfPossibleOrZero(
- (totalLatencyInSeconds * 1000), eventCount)
- results.Add(result_name, 'ms', averageLatency, data_type='unimportant')
-
-def CalcLatencyResults(rendering_stats_deltas, results):
- CalcLatency(rendering_stats_deltas, 'inputEventCount', 'totalInputLatency',
- 'average_latency', results)
- CalcLatency(rendering_stats_deltas, 'touchUICount', 'totalTouchUILatency',
- 'average_touch_ui_latency', results)
- CalcLatency(rendering_stats_deltas, 'touchAckedCount',
- 'totalTouchAckedLatency',
- 'average_touch_acked_latency',
- results)
- CalcLatency(rendering_stats_deltas, 'scrollUpdateCount',
- 'totalScrollUpdateLatency',
- 'average_scroll_update_latency', results)
+ # Latency Results
+ results.Add('average_latency', 'ms',
+ Average(s.input_event_latency, s.input_event_count,
+ 1000, 3),
+ data_type='unimportant')
+ results.Add('average_touch_ui_latency', 'ms',
+ Average(s.touch_ui_latency, s.touch_ui_count, 1000, 3),
+ data_type='unimportant')
+ results.Add('average_touch_acked_latency', 'ms',
+ Average(s.touch_acked_latency, s.touch_acked_count,
+ 1000, 3),
+ data_type='unimportant')
+ results.Add('average_scroll_update_latency', 'ms',
+ Average(s.scroll_update_latency, s.scroll_update_count,
+ 1000, 3),
+ data_type='unimportant')
diff --git a/tools/perf/metrics/smoothness_unittest.py b/tools/perf/metrics/smoothness_unittest.py
index e7b8778..2a42f9d 100644
--- a/tools/perf/metrics/smoothness_unittest.py
+++ b/tools/perf/metrics/smoothness_unittest.py
@@ -4,43 +4,110 @@
import unittest
from metrics import smoothness
+from metrics.gpu_rendering_stats import GpuRenderingStats
from telemetry.page import page
from telemetry.page.page_measurement_results import PageMeasurementResults
class SmoothnessMetricsUnitTest(unittest.TestCase):
-
- def testCalcResultsFromRAFRenderStats(self):
- rendering_stats = {'droppedFrameCount': 5,
- 'totalTimeInSeconds': 1,
- 'numAnimationFrames': 10,
- 'numFramesSentToScreen': 10}
- res = PageMeasurementResults()
- res.WillMeasurePage(page.Page('http://foo.com/', None))
- smoothness.CalcScrollResults(rendering_stats, res)
- res.DidMeasurePage()
- self.assertEquals(50, res.page_results[0]['dropped_percent'].value)
- self.assertAlmostEquals(
- 100,
- res.page_results[0]['mean_frame_time'].value, 2)
-
def testCalcResultsRealRenderStats(self):
- rendering_stats = {'numFramesSentToScreen': 60,
- 'globalTotalTextureUploadTimeInSeconds': 0,
- 'totalProcessingCommandsTimeInSeconds': 0,
- 'globalTextureUploadCount': 0,
- 'droppedFrameCount': 0,
- 'textureUploadCount': 0,
- 'numAnimationFrames': 10,
- 'totalPaintTimeInSeconds': 0.35374299999999986,
- 'globalTotalProcessingCommandsTimeInSeconds': 0,
- 'totalTextureUploadTimeInSeconds': 0,
- 'totalRasterizeTimeInSeconds': 0,
- 'totalTimeInSeconds': 1.0}
+ mock_rendering_stats_deltas = {
+ 'totalTimeInSeconds': 1.0,
+ 'numFramesSentToScreen': 100,
+ 'droppedFrameCount': 20,
+ 'numImplThreadScrolls': 50,
+ 'numMainThreadScrolls': 50,
+ 'numLayersDrawn': 240,
+ 'numMissingTiles': 10,
+ 'textureUploadCount': 120,
+ 'totalTextureUploadTimeInSeconds': 1.2,
+ 'totalCommitCount': 130,
+ 'totalCommitTimeInSeconds': 1.3,
+ 'totalDeferredImageDecodeCount': 140,
+ 'totalDeferredImageDecodeTimeInSeconds': 1.4,
+ 'totalDeferredImageCacheHitCount': 30,
+ 'totalImageGatheringCount': 150,
+ 'totalImageGatheringTimeInSeconds': 1.5,
+ 'totalTilesAnalyzed': 160,
+ 'totalTileAnalysisTimeInSeconds': 1.6,
+ 'solidColorTilesAnalyzed': 40,
+ 'inputEventCount': 170,
+ 'totalInputLatency': 1.7,
+ 'touchUICount': 180,
+ 'totalTouchUILatency': 1.8,
+ 'touchAckedCount': 190,
+ 'totalTouchAckedLatency': 1.9,
+ 'scrollUpdateCount': 200,
+ 'totalScrollUpdateLatency': 2.0}
+ stats = GpuRenderingStats(mock_rendering_stats_deltas)
+
res = PageMeasurementResults()
res.WillMeasurePage(page.Page('http://foo.com/', None))
- smoothness.CalcScrollResults(rendering_stats, res)
+ smoothness.CalcResults(stats, res)
res.DidMeasurePage()
- self.assertEquals(0, res.page_results[0]['dropped_percent'].value)
+
+ # Scroll Results
self.assertAlmostEquals(
- 1000 / 60.,
- res.page_results[0]['mean_frame_time'].value, 2)
+ 1.0 / 100.0 * 1000.0,
+ res.page_results[0]['mean_frame_time'].value, 2)
+ self.assertAlmostEquals(
+ 20.0 / 100.0 * 100.0,
+ res.page_results[0]['dropped_percent'].value)
+ self.assertAlmostEquals(
+ 50.0 / (50.0 + 50.0) * 100.0,
+ res.page_results[0]['percent_impl_scrolled'].value)
+ self.assertAlmostEquals(
+ 240.0 / 100.0,
+ res.page_results[0]['average_num_layers_drawn'].value)
+ self.assertAlmostEquals(
+ 10.0 / 100.0,
+ res.page_results[0]['average_num_missing_tiles'].value)
+
+ # Texture Upload Results
+ self.assertAlmostEquals(
+ 1.3 / 130.0 * 1000.0,
+ res.page_results[0]['average_commit_time'].value)
+ self.assertEquals(
+ 120,
+ res.page_results[0]['texture_upload_count'].value)
+ self.assertEquals(
+ 1.2,
+ res.page_results[0]['total_texture_upload_time'].value)
+
+ # Image Decoding Results
+ self.assertEquals(
+ 140,
+ res.page_results[0]['total_deferred_image_decode_count'].value)
+ self.assertEquals(
+ 30,
+ res.page_results[0]['total_image_cache_hit_count'].value)
+ self.assertAlmostEquals(
+ 1.5 / 150.0 * 1000.0,
+ res.page_results[0]['average_image_gathering_time'].value)
+ self.assertEquals(
+ 1.4,
+ res.page_results[0]['total_deferred_image_decoding_time'].value)
+
+ # Tile Analysis Results
+ self.assertEquals(
+ 160,
+ res.page_results[0]['total_tiles_analyzed'].value)
+ self.assertEquals(
+ 40,
+ res.page_results[0]['solid_color_tiles_analyzed'].value)
+ self.assertAlmostEquals(
+ 1.6 / 160.0 * 1000.0,
+ res.page_results[0]['average_tile_analysis_time'].value)
+
+ # Latency Results
+ self.assertAlmostEquals(
+ 1.7 / 170.0 * 1000.0,
+ res.page_results[0]['average_latency'].value)
+ self.assertAlmostEquals(
+ 1.8 / 180.0 * 1000.0,
+ res.page_results[0]['average_touch_ui_latency'].value)
+ self.assertAlmostEquals(
+ 1.9 / 190.0 * 1000.0,
+ res.page_results[0]['average_touch_acked_latency'].value)
+ self.assertAlmostEquals(
+ 2.0 / 200.0 * 1000.0,
+ res.page_results[0]['average_scroll_update_latency'].value)
diff --git a/tools/perf/page_sets/PRESUBMIT.py b/tools/perf/page_sets/PRESUBMIT.py
index 5fae0e8..f161443 100644
--- a/tools/perf/page_sets/PRESUBMIT.py
+++ b/tools/perf/page_sets/PRESUBMIT.py
@@ -1,4 +1,4 @@
-# Copyright 2013 The Chromium Authors. All rights reserved.
+# 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.
import os
@@ -6,9 +6,6 @@
import sys
-DEFAULT_BUCKET = 'chromium-wpr'
-
-
def _SyncFilesToCloud(input_api, output_api):
"""Searches for .sha1 files and uploads them to Cloud Storage.
@@ -23,7 +20,7 @@
finally:
sys.path = old_sys_path
- hashes_in_cloud_storage = cloud_storage.List(DEFAULT_BUCKET)
+ hashes_in_cloud_storage = cloud_storage.List(cloud_storage.DEFAULT_BUCKET)
results = []
for hash_path in input_api.AbsoluteLocalPaths():
@@ -52,7 +49,7 @@
continue
try:
- cloud_storage.Insert(DEFAULT_BUCKET, file_hash, file_path)
+ cloud_storage.Insert(cloud_storage.DEFAULT_BUCKET, file_hash, file_path)
except cloud_storage.CloudStorageError:
results.append(output_api.PresubmitError(
'Unable to upload to Cloud Storage: %s' % hash_path))
diff --git a/tools/perf/page_sets/pica.json b/tools/perf/page_sets/pica.json
new file mode 100644
index 0000000..2315276
--- /dev/null
+++ b/tools/perf/page_sets/pica.json
@@ -0,0 +1,16 @@
+{
+ "description": "Pica demo app for the Polymer UI toolkit",
+ "archive_data_file": "../data/pica.json",
+ "pages": [
+ { "url": "http://www.polymer-project.org/polymer-all/projects/pica/index.html",
+ "script_to_evaluate_on_commit":
+ "document.addEventListener('WebComponentsReady', function(){var unused = document.body.offsetHeight; window.__pica_load_time = performance.now(); setTimeout(function(){window.__web_components_ready=true}, 1000)})",
+ "wait_for_javascript_expression": "window.__web_components_ready",
+ "smoothness": {
+ "action": "tap_element",
+ "find_element_expression": "document.querySelector('pi-app').$.Topics.$.topics.$.container.querySelector('.item > .card')",
+ "wait_for_event": "g-panels-select"
+ }
+ }
+ ]
+}
diff --git a/tools/perf/page_sets/tough_video_cases/crowd.ogg b/tools/perf/page_sets/tough_video_cases/crowd.ogg
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd.ogg
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/crowd.wav b/tools/perf/page_sets/tough_video_cases/crowd.wav
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd.wav
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/crowd1080.mp4 b/tools/perf/page_sets/tough_video_cases/crowd1080.mp4
deleted file mode 100644
index e4cf00c..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd1080.mp4
+++ /dev/null
Binary files differ
diff --git a/tools/perf/page_sets/tough_video_cases/crowd1080.ogv b/tools/perf/page_sets/tough_video_cases/crowd1080.ogv
deleted file mode 100644
index e4cf00c..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd1080.ogv
+++ /dev/null
Binary files differ
diff --git a/tools/perf/page_sets/tough_video_cases/crowd1080.webm b/tools/perf/page_sets/tough_video_cases/crowd1080.webm
deleted file mode 100644
index e4cf00c..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd1080.webm
+++ /dev/null
Binary files differ
diff --git a/tools/perf/page_sets/tough_video_cases/crowd2160.mp4 b/tools/perf/page_sets/tough_video_cases/crowd2160.mp4
deleted file mode 100644
index a5a8a5f..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd2160.mp4
+++ /dev/null
Binary files differ
diff --git a/tools/perf/page_sets/tough_video_cases/crowd2160.ogv b/tools/perf/page_sets/tough_video_cases/crowd2160.ogv
deleted file mode 100644
index e4cf00c..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd2160.ogv
+++ /dev/null
Binary files differ
diff --git a/tools/perf/page_sets/tough_video_cases/crowd2160.webm b/tools/perf/page_sets/tough_video_cases/crowd2160.webm
deleted file mode 100644
index a5a8a5f..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd2160.webm
+++ /dev/null
Binary files differ
diff --git a/tools/perf/page_sets/tough_video_cases/crowd360.mp4 b/tools/perf/page_sets/tough_video_cases/crowd360.mp4
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd360.mp4
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/crowd360.ogv b/tools/perf/page_sets/tough_video_cases/crowd360.ogv
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd360.ogv
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/crowd360.webm b/tools/perf/page_sets/tough_video_cases/crowd360.webm
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd360.webm
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/crowd480.webm b/tools/perf/page_sets/tough_video_cases/crowd480.webm
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd480.webm
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/crowd720.webm b/tools/perf/page_sets/tough_video_cases/crowd720.webm
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/crowd720.webm
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/tulip2.m4a b/tools/perf/page_sets/tough_video_cases/tulip2.m4a
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/tulip2.m4a
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/tulip2.mp3 b/tools/perf/page_sets/tough_video_cases/tulip2.mp3
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/tulip2.mp3
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/tulip2.mp4 b/tools/perf/page_sets/tough_video_cases/tulip2.mp4
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/tulip2.mp4
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/tulip2.ogg b/tools/perf/page_sets/tough_video_cases/tulip2.ogg
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/tulip2.ogg
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/tulip2.ogv b/tools/perf/page_sets/tough_video_cases/tulip2.ogv
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/tulip2.ogv
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/tulip2.wav b/tools/perf/page_sets/tough_video_cases/tulip2.wav
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/tulip2.wav
+++ /dev/null
diff --git a/tools/perf/page_sets/tough_video_cases/tulip2.webm b/tools/perf/page_sets/tough_video_cases/tulip2.webm
deleted file mode 100644
index e69de29..0000000
--- a/tools/perf/page_sets/tough_video_cases/tulip2.webm
+++ /dev/null
diff --git a/tools/perf/run_measurement b/tools/perf/run_measurement
index 8893fcd..dd5ecc8 100755
--- a/tools/perf/run_measurement
+++ b/tools/perf/run_measurement
@@ -11,6 +11,7 @@
BOOTSTRAPPED_FILES_DIR = 'support/bootstrap_files'
PERF_DIR = 'src/tools/perf'
DEPS_FILE = 'bootstrap_deps'
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
def BootstrapIfNeeded(module_name, module_path, module_deps_url):
"""Ensures that the given module_name is available, grab from URL if not."""
@@ -18,9 +19,7 @@
imp.find_module(module_name)
return
except ImportError:
- sys.path.append(os.path.join(os.path.dirname(__file__),
- BOOTSTRAPPED_FILES_DIR,
- module_path))
+ sys.path.append(os.path.join(BASE_DIR, BOOTSTRAPPED_FILES_DIR, module_path))
try:
imp.find_module(module_name)
return
@@ -30,8 +29,7 @@
'telemetry_bootstrap.py').read()
bootstrap = imp.new_module('bootstrap')
exec bootstrap_txt in bootstrap.__dict__
- bootstrap.DownloadDepsURL(os.path.join(os.path.dirname(__file__),
- BOOTSTRAPPED_FILES_DIR),
+ bootstrap.DownloadDepsURL(os.path.join(BASE_DIR, BOOTSTRAPPED_FILES_DIR),
module_deps_url)
return
@@ -41,14 +39,12 @@
Returns: a list of telemetry deps.
"""
# Add telemetry_tools to sys.path for the import below
- telemetry_tools_path = os.path.join(os.path.dirname(__file__),
- os.pardir, 'telemetry_tools')
+ telemetry_tools_path = os.path.join(BASE_DIR, os.pardir, 'telemetry_tools')
sys.path.append(telemetry_tools_path)
import perf_tools
import telemetry_bootstrap
- deps_file = os.path.join(os.path.dirname(perf_tools.__file__),
- DEPS_FILE)
+ deps_file = os.path.join(os.path.dirname(perf_tools.__file__), DEPS_FILE)
return telemetry_bootstrap.ListAllDepsPaths(open(deps_file).read())
def main():
@@ -57,8 +53,7 @@
'/perf/perf_tools/' + DEPS_FILE)
# Add telemetry to sys.path for the import below
- telemetry_path = os.path.join(os.path.dirname(__file__),
- os.pardir, 'telemetry')
+ telemetry_path = os.path.join(BASE_DIR, os.pardir, 'telemetry')
sys.path.append(telemetry_path)
if '--print-bootstrap-deps' in sys.argv:
@@ -101,7 +96,7 @@
return old_benchmark_names[arg]
runner = MeasurementRunner()
- sys.exit(runner.Run(os.path.dirname(__file__), page_set_filenames))
+ sys.exit(runner.Run(BASE_DIR, page_set_filenames))
if __name__ == '__main__':
sys.exit(main())
diff --git a/tools/perf/run_tests b/tools/perf/run_tests
index 275e064..36eefbb 100755
--- a/tools/perf/run_tests
+++ b/tools/perf/run_tests
@@ -25,6 +25,9 @@
start_dir = 'perf_tools'
ret += run_tests.Main(sys.argv[1:], start_dir, top_level_dir, runner)
+ start_dir = 'metrics'
+ ret += run_tests.Main(sys.argv[1:], start_dir, top_level_dir, runner)
+
if runner.result:
runner.result.PrintSummary()
sys.exit(min(ret + runner.result.num_errors, 255))
diff --git a/tools/perf/test-info.json b/tools/perf/test-info.json
index 8f56e9b..79caaad 100644
--- a/tools/perf/test-info.json
+++ b/tools/perf/test-info.json
@@ -30,9 +30,7 @@
},
"dom_perf": {
"description": "Performance of DOM operations.",
- "code": [
- "chrome/src/tools/perf/benchmarks/dom_perf.py"
- ]
+ "code": ["chrome/src/tools/perf/benchmarks/dom_perf.py"]
},
"dromaeo_domcoreattr": {
"description": "Setting and getting DOM node attributes.",
@@ -143,7 +141,7 @@
"description": "Milliseconds to decode a large image of various formats (gif, jpg, png, webp).",
"code": [
"chrome/src/tools/perf/measurements/image_decoding.py",
- "chrome/src/chrome/test/data/image_decoding/"
+ "chrome/src/tools/perf/page_sets/image_decoding_measurement.json"
]
},
"indexeddb": {
@@ -204,7 +202,10 @@
},
"memory_measurement": {
"description": "Use (recorded versions of) real world web sites and measure memory consumption.",
- "code": ["chrome/src/tools/perf/measurements/memory.py"]
+ "code": [
+ "chrome/src/tools/perf/measurements/memory.py",
+ "chrome/src/tools/perf/page_sets/top_25.json"
+ ]
},
"memory_test": {
"description": "Loads a number of URLs across tabs and windows and measures the memory usage.",
@@ -246,7 +247,10 @@
},
"smoothness_measurement": {
"description": "Measures frame rate and a variety of other statistics while scrolling down the top 25 web pages. [Documentation](http://www.chromium.org/developers/design-documents/rendering-benchmarks).",
- "code": ["chrome/src/tools/perf/measurements/smoothness.py"]
+ "code": [
+ "chrome/src/tools/perf/measurements/smoothness.py",
+ "chrome/src/tools/perf/page_sets/top_25.json"
+ ]
},
"spaceport": {
"description": "Performance on [spaceport.io's perfmarks benchmark](http://spaceport.io/community/perfmarks). This test performs 3 animations (rotate, translate, scale) using a variety of methods (css, webgl, canvas, etc) and reports the number of objects that can be simultaneously animated while still achieving 30FPS.",
@@ -254,7 +258,10 @@
},
"startup_measurement": {
"description": "Measures startup time under various scenarios. This is a port of our old startup_test target to Telemetry.",
- "code": ["chrome/src/tools/perf/measurements/startup.py"]
+ "code": [
+ "chrome/src/tools/perf/measurements/startup.py",
+ "src/tools/perf/page_sets/blank_page.json"
+ ]
},
"startup_test": {
"description": "Measures startup and shutdown time for 1 tab, 5 tabs, and 10 tabs under a several different user profiles. These tests are in the process of being ported to Telemetry - see the startup_measurement test.",
diff --git a/tools/perf_expectations/perf_expectations.json b/tools/perf_expectations/perf_expectations.json
index d3d4cc8..52088ac 100644
--- a/tools/perf_expectations/perf_expectations.json
+++ b/tools/perf_expectations/perf_expectations.json
@@ -1,6 +1,6 @@
-{"linux-release-64/sizes/chrome-bss/bss": {"reva": 206130, "revb": 206207, "type": "absolute", "better": "lower", "improve": 490741, "regress": 542601, "sha1": "902edbc8"},
+{"linux-release-64/sizes/chrome-bss/bss": {"reva": 216421, "revb": 216430, "type": "absolute", "better": "lower", "improve": 523892, "regress": 579040, "sha1": "0b0195e2"},
"linux-release-64/sizes/chrome-data/data": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 3570183, "regress": 3946094, "sha1": "b0d5e0fc"},
- "linux-release-64/sizes/chrome-si/initializers": {"reva": 196313, "revb": 196318, "type": "absolute", "better": "lower", "improve": 34, "regress": 34, "tolerance": 0, "sha1": "cd47eda1"},
+ "linux-release-64/sizes/chrome-si/initializers": {"reva": 216959, "revb": 216961, "type": "absolute", "better": "lower", "improve": 33, "regress": 33, "tolerance": 0, "sha1": "ebd8c26b"},
"linux-release-64/sizes/chrome-text/text": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 94012670, "regress": 103908994, "sha1": "a8dc15a3"},
"linux-release-64/sizes/chrome.pak/chrome.pak": {"reva": 214295, "revb": 214296, "type": "absolute", "better": "lower", "improve": 4578193, "regress": 5060109, "sha1": "0785f1c1"},
"linux-release-64/sizes/chrome/chrome": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 128793270, "regress": 142351155, "sha1": "193926f5"},
@@ -365,7 +365,7 @@
"linux-release/media_tests_av_perf/ttp/Wifi_roller.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 867.35, "regress": 1041.075, "sha1": "d99ce51c"},
"linux-release/sizes/chrome-bss/bss": {"reva": 205093, "revb": 206368, "type": "absolute", "better": "lower", "improve": 316939, "regress": 389240, "sha1": "8d78343e"},
"linux-release/sizes/chrome-data/data": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 1936814, "regress": 2140724, "sha1": "915f9e72"},
- "linux-release/sizes/chrome-si/initializers": {"reva": 196188, "revb": 197308, "type": "absolute", "better": "lower", "improve": 35, "regress": 35, "tolerance": 0, "sha1": "86b46a4e"},
+ "linux-release/sizes/chrome-si/initializers": {"reva": 216959, "revb": 216961, "type": "absolute", "better": "lower", "improve": 34, "regress": 34, "tolerance": 0, "sha1": "69a4e038"},
"linux-release/sizes/chrome-text/text": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 79833368, "regress": 88237335, "sha1": "e1b38def"},
"linux-release/sizes/chrome-textrel/textrel": {"reva": 135570, "revb": 135664, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "832078e7"},
"linux-release/sizes/chrome.pak/chrome.pak": {"reva": 214295, "revb": 214296, "type": "absolute", "better": "lower", "improve": 4578193, "regress": 5060109, "sha1": "a95a611b"},
diff --git a/tools/telemetry/examples/rendering_microbenchmark_test.py b/tools/telemetry/examples/rendering_microbenchmark_test.py
deleted file mode 100755
index 59e452a..0000000
--- a/tools/telemetry/examples/rendering_microbenchmark_test.py
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/env python
-# 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.
-import os
-import re
-import sys
-
-sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
-
-from telemetry.core import browser_finder
-from telemetry.core import browser_options
-
-def Main(args):
- options = browser_options.BrowserOptions()
- parser = options.CreateParser('rendering_microbenchmark_test.py <sitelist>')
- # TODO(nduca): Add test specific options here, if any.
- options, args = parser.parse_args(args)
- if len(args) != 1:
- parser.print_usage()
- return 255
-
- urls = []
- with open(args[0], 'r') as f:
- for url in f.readlines():
- url = url.strip()
- if not re.match('(.+)://', url):
- url = 'http://%s' % url
- urls.append(url)
-
- options.extra_browser_args.append('--enable-gpu-benchmarking')
- browser_to_create = browser_finder.FindBrowser(options)
- if not browser_to_create:
- sys.stderr.write('No browser found! Supported types: %s' %
- browser_finder.GetAllAvailableBrowserTypes(options))
- return 255
- with browser_to_create.Create() as b:
- tab = b.tabs[0]
- # Check browser for benchmark API. Can only be done on non-chrome URLs.
- tab.Navigate('http://www.google.com')
- import time
- time.sleep(2)
- tab.WaitForDocumentReadyStateToBeComplete()
- if tab.EvaluateJavaScript('window.chrome.gpuBenchmarking === undefined'):
- print 'Browser does not support gpu benchmarks API.'
- return 255
-
- if tab.EvaluateJavaScript(
- 'window.chrome.gpuBenchmarking.runRenderingBenchmarks === undefined'):
- print 'Browser does not support rendering benchmarks API.'
- return 255
-
- # Run the test. :)
- first_line = []
- def DumpResults(url, results):
- if len(first_line) == 0:
- cols = ['url']
- for r in results:
- cols.append(r['benchmark'])
- print ','.join(cols)
- first_line.append(0)
- cols = [url]
- for r in results:
- cols.append(str(r['result']))
- print ','.join(cols)
-
- for u in urls:
- tab.Navigate(u)
- tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
- results = tab.EvaluateJavaScript(
- 'window.chrome.gpuBenchmarking.runRenderingBenchmarks();')
- DumpResults(url, results)
-
- return 0
-
-if __name__ == '__main__':
- sys.exit(Main(sys.argv[1:]))
diff --git a/tools/telemetry/support/html_output/results-template.html b/tools/telemetry/support/html_output/results-template.html
index b0b84c7..898d057 100644
--- a/tools/telemetry/support/html_output/results-template.html
+++ b/tools/telemetry/support/html_output/results-template.html
@@ -211,7 +211,9 @@
return (unit == 'kb' ||
unit == 'KB' ||
unit == 'MB' ||
- unit == 'bytes');
+ unit == 'bytes' ||
+ !metric.indexOf('V8.') ||
+ metric == 'processes');
}
this.addResult = function (newResult) {
testResults.push(newResult);
diff --git a/tools/telemetry/telemetry/core/browser_options.py b/tools/telemetry/telemetry/core/browser_options.py
index c27d158..69f3048 100644
--- a/tools/telemetry/telemetry/core/browser_options.py
+++ b/tools/telemetry/telemetry/core/browser_options.py
@@ -89,11 +89,15 @@
'--remote',
dest='cros_remote',
help='The IP address of a remote ChromeOS device to use.')
+ identity = None
+ testing_rsa = os.path.join(
+ util.GetChromiumSrcDir(),
+ 'third_party', 'chromite', 'ssh_keys', 'testing_rsa')
+ if os.path.exists(testing_rsa):
+ identity = testing_rsa
group.add_option('--identity',
dest='cros_ssh_identity',
- default=os.path.join(
- util.GetChromiumSrcDir(),
- 'third_party', 'chromite', 'ssh_keys', 'testing_rsa'),
+ default=identity,
help='The identity file to use when ssh\'ing into the ChromeOS device')
parser.add_option_group(group)
@@ -107,6 +111,10 @@
choices=profile_choices,
help=('The user profile to use. A clean profile is used by default. '
'Supported values: ' + ', '.join(profile_choices)))
+ group.add_option('--profile-dir',
+ dest='profile_dir',
+ help='Profile directory to launch the browser with. '
+ 'A clean profile is used by default')
group.add_option('--extra-browser-args',
dest='extra_browser_args_as_string',
help='Additional arguments to pass to the browser when it starts')
@@ -214,7 +222,12 @@
# Parse repeat options
self.repeat_options.UpdateFromParseResults(self, parser)
- self.profile_dir = profile_types.GetProfileDir(self.profile_type)
+ # TODO(jeremy): I'm in the process of adding explicit knowledge of profile
+ # directories to Telemetry. As part of this work profile_type needs to be
+ # reworked to not override profile_dir.
+ if not self.profile_dir:
+ self.profile_dir = profile_types.GetProfileDir(self.profile_type)
+
return ret
parser.parse_args = ParseArgs
return parser
@@ -222,3 +235,7 @@
def AppendExtraBrowserArg(self, arg):
if arg not in self.extra_browser_args:
self.extra_browser_args.append(arg)
+
+ def MergeDefaultValues(self, defaults):
+ for k, v in defaults.__dict__.items():
+ self.ensure_value(k, v)
diff --git a/tools/telemetry/telemetry/core/browser_options_unittest.py b/tools/telemetry/telemetry/core/browser_options_unittest.py
index df22b93..9f016fa 100644
--- a/tools/telemetry/telemetry/core/browser_options_unittest.py
+++ b/tools/telemetry/telemetry/core/browser_options_unittest.py
@@ -1,6 +1,7 @@
# 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.
+import optparse
import unittest
from telemetry.core import browser_options
@@ -58,3 +59,41 @@
options_ret, _ = parser.parse_args(['--browser', 'any'])
self.assertEquals(options_ret, options)
self.assertFalse(options.verbosity)
+
+ def testProfileDirDefault(self):
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser()
+ parser.parse_args(['--browser', 'any'])
+ self.assertEquals(options.profile_dir, None)
+
+ def testProfileDir(self):
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser()
+ parser.parse_args(['--browser', 'any', '--profile-dir', 'foo'])
+ self.assertEquals(options.profile_dir, 'foo')
+
+ def testMergeDefaultValues(self):
+ options = browser_options.BrowserOptions()
+ options.already_true = True
+ options.already_false = False
+ options.override_to_true = False
+ options.override_to_false = True
+
+ parser = optparse.OptionParser()
+ parser.add_option('--already_true', action='store_true')
+ parser.add_option('--already_false', action='store_true')
+ parser.add_option('--unset', action='store_true')
+ parser.add_option('--default_true', action='store_true', default=True)
+ parser.add_option('--default_false', action='store_true', default=False)
+ parser.add_option('--override_to_true', action='store_true', default=False)
+ parser.add_option('--override_to_false', action='store_true', default=True)
+
+ options.MergeDefaultValues(parser.get_default_values())
+
+ self.assertTrue(options.already_true)
+ self.assertFalse(options.already_false)
+ self.assertTrue(options.unset is None)
+ self.assertTrue(options.default_true)
+ self.assertFalse(options.default_false)
+ self.assertFalse(options.override_to_true)
+ self.assertTrue(options.override_to_false)
diff --git a/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py b/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py
index bad383c..c5dede5 100644
--- a/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py
+++ b/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py
@@ -87,6 +87,8 @@
'--login-screen=login',
# Skip user image selection screen, and post login screens.
'--oobe-skip-postlogin',
+ # Skip hwid check, for VMs and pre-MP lab devices.
+ '--skip-hwid-check',
# Allow devtools to connect to chrome.
'--remote-debugging-port=%i' % self._remote_debugging_port,
# Open a maximized window.
@@ -99,10 +101,6 @@
# This extension bypasses gaia and logs us in.
args.append('--auth-ext-path=%s' % self._login_ext_dir)
- # Skip hwid check on systems that don't have a hwid set, eg VMs.
- if not self.hwid:
- args.append('--skip-hwid-check')
-
return args
def _GetSessionManagerPid(self, procs):
diff --git a/tools/telemetry/telemetry/page/actions/scroll.py b/tools/telemetry/telemetry/page/actions/scroll.py
index f132bf9..f7df4ad 100644
--- a/tools/telemetry/telemetry/page/actions/scroll.py
+++ b/tools/telemetry/telemetry/page/actions/scroll.py
@@ -72,7 +72,7 @@
return True
def CustomizeBrowserOptions(self, options):
- options.extra_browser_args.append('--enable-gpu-benchmarking')
+ options.AppendExtraBrowserArg('--enable-gpu-benchmarking')
def BindMeasurementJavaScript(self, tab, start_js, stop_js):
# Make the scroll action start and stop measurement automatically.
diff --git a/tools/telemetry/telemetry/page/actions/tap_element.py b/tools/telemetry/telemetry/page/actions/tap_element.py
new file mode 100644
index 0000000..f3a4734
--- /dev/null
+++ b/tools/telemetry/telemetry/page/actions/tap_element.py
@@ -0,0 +1,45 @@
+# 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.
+
+from telemetry.core import exceptions
+from telemetry.core import util
+from telemetry.page import page as page_module
+from telemetry.page.actions import page_action
+
+class TapElementAction(page_action.PageAction):
+ """Page action that dispatches a custom 'tap' event at an element.
+
+ For pages that don't respond to 'click' events, this action offers
+ an alternative to ClickElementAction.
+
+ Configuration options:
+ find_element_expression: a JavaScript expression that should yield
+ the element to tap.
+ wait_for_event: an event name that will be listened for on the Document.
+ """
+ def __init__(self, attributes=None):
+ super(TapElementAction, self).__init__(attributes)
+
+ def RunAction(self, page, tab, previous_action):
+ def DoTap():
+ assert hasattr(self, 'find_element_expression')
+ event = 'new CustomEvent("tap", {bubbles: true})'
+ code = '(%s).dispatchEvent(%s)' % (self.find_element_expression, event)
+ try:
+ tab.ExecuteJavaScript(code)
+ except exceptions.EvaluateException:
+ raise page_action.PageActionFailed(
+ 'Cannot find element with code ' + self.find_element_javascript)
+
+ if hasattr(self, 'wait_for_event'):
+ code = ('document.addEventListener("%s", '
+ 'function(){window.__tap_event_finished=true})')
+ tab.ExecuteJavaScript(code % self.wait_for_event)
+ DoTap()
+ util.WaitFor(lambda: tab.EvaluateJavaScript(
+ 'window.__tap_event_finished'), 60)
+ else:
+ DoTap()
+
+ page_module.Page.WaitForPageToLoad(self, tab, 60)
diff --git a/tools/telemetry/telemetry/page/cloud_storage.py b/tools/telemetry/telemetry/page/cloud_storage.py
index 3d4d2e5..d52c622 100644
--- a/tools/telemetry/telemetry/page/cloud_storage.py
+++ b/tools/telemetry/telemetry/page/cloud_storage.py
@@ -16,6 +16,9 @@
from telemetry.core import util
+DEFAULT_BUCKET = 'chromium-wpr'
+
+
_GSUTIL_URL = 'http://storage.googleapis.com/pub/gsutil.tar.gz'
_DOWNLOAD_PATH = os.path.join(util.GetTelemetryDir(), 'third_party', 'gsutil')
@@ -73,23 +76,36 @@
def Delete(bucket, remote_path):
url = 'gs://%s/%s' % (bucket, remote_path)
- logging.debug('Deleting %s' % url)
+ logging.info('Deleting %s' % url)
_RunCommand(['rm', url])
def Get(bucket, remote_path, local_path):
url = 'gs://%s/%s' % (bucket, remote_path)
- logging.debug('Downloading %s to %s' % (url, local_path))
+ logging.info('Downloading %s to %s' % (url, local_path))
_RunCommand(['cp', url, local_path])
def Insert(bucket, remote_path, local_path):
url = 'gs://%s/%s' % (bucket, remote_path)
- logging.debug('Uploading %s to %s' % (local_path, url))
+ logging.info('Uploading %s to %s' % (local_path, url))
_RunCommand(['cp', local_path, url])
+def GetIfChanged(bucket, file_path):
+ """Gets the file at file_path if it has a hash file that doesn't match."""
+ hash_path = file_path + '.sha1'
+ if not os.path.exists(hash_path):
+ return
+
+ with open(hash_path, 'rb') as f:
+ expected_hash = f.read(1024).rstrip()
+ if not os.path.exists(file_path) or GetHash(file_path) != expected_hash:
+ Get(bucket, expected_hash, file_path)
+
+
def GetHash(file_path):
+ """Calculates and returns the hash of the file at file_path."""
sha1 = hashlib.sha1()
with open(file_path, 'rb') as f:
while True:
diff --git a/tools/telemetry/telemetry/page/page.py b/tools/telemetry/telemetry/page/page.py
index 63bfd69..5d06076 100644
--- a/tools/telemetry/telemetry/page/page.py
+++ b/tools/telemetry/telemetry/page/page.py
@@ -67,6 +67,16 @@
raise AttributeError()
@property
+ def is_file(self):
+ parsed_url = urlparse.urlparse(self.url)
+ return parsed_url.scheme == 'file'
+
+ @property
+ def is_local(self):
+ parsed_url = urlparse.urlparse(self.url)
+ return parsed_url.scheme == 'file' or parsed_url.scheme == 'chrome'
+
+ @property
def serving_dirs_and_file(self):
parsed_url = urlparse.urlparse(self.url)
path = _UrlPathJoin(self.base_dir, parsed_url.netloc, parsed_url.path)
@@ -88,11 +98,10 @@
@property
def display_url(self):
- if self.url.startswith('http'):
+ if not self.is_local:
return self.url
url_paths = ['/'.join(p.url.strip('/').split('/')[:-1])
- for p in self.page_set
- if p.url.startswith('file://')]
+ for p in self.page_set if p.is_file]
common_prefix = os.path.commonprefix(url_paths)
return self.url[len(common_prefix):].strip('/')
diff --git a/tools/telemetry/telemetry/page/page_runner.py b/tools/telemetry/telemetry/page/page_runner.py
index 423f07a..1df51de 100644
--- a/tools/telemetry/telemetry/page/page_runner.py
+++ b/tools/telemetry/telemetry/page/page_runner.py
@@ -9,7 +9,6 @@
import tempfile
import time
import traceback
-import urlparse
import random
from telemetry.core import browser_finder
@@ -18,6 +17,7 @@
from telemetry.core import wpr_modes
from telemetry.core.platform.profiler import profiler_finder
from telemetry.page import page_filter as page_filter_module
+from telemetry.page import page_measurement_results
from telemetry.page import page_runner_repeat
from telemetry.page import page_test
@@ -109,8 +109,7 @@
self._did_login = False
def PreparePage(self, page, tab, test=None):
- parsed_url = urlparse.urlparse(page.url)
- if parsed_url[0] == 'file':
+ if page.is_file:
serving_dirs, filename = page.serving_dirs_and_file
if tab.browser.SetHTTPServerDirectories(serving_dirs) and test:
test.DidStartHTTPServer(tab)
@@ -165,7 +164,7 @@
results_for_current_run = results
if state.first_page[page] and test.discard_first_result:
# If discarding results, substitute a dummy object.
- results_for_current_run = type(results)()
+ results_for_current_run = page_measurement_results.PageMeasurementResults()
results_for_current_run.StartTest(page)
tries = 3
while tries:
@@ -264,7 +263,7 @@
try:
test.WillRunTest(state.tab)
repeat_state = page_runner_repeat.PageRunnerRepeatState(
- options.repeat_options)
+ options.repeat_options)
repeat_state.WillRunPageSet()
while repeat_state.ShouldRepeatPageSet():
@@ -307,8 +306,7 @@
Logs warnings if any are missing."""
page_set_has_live_sites = False
for page in pages:
- parsed_url = urlparse.urlparse(page.url)
- if parsed_url.scheme != 'chrome' and parsed_url.scheme != 'file':
+ if not page.is_local:
page_set_has_live_sites = True
break
@@ -329,8 +327,7 @@
pages_missing_archive_data = []
for page in pages:
- parsed_url = urlparse.urlparse(page.url)
- if parsed_url.scheme == 'chrome' or parsed_url.scheme == 'file':
+ if page.is_local:
continue
if not page.archive_path:
diff --git a/tools/telemetry/telemetry/page/page_runner_unittest.py b/tools/telemetry/telemetry/page/page_runner_unittest.py
index dfce72d..2ff1cfc 100644
--- a/tools/telemetry/telemetry/page/page_runner_unittest.py
+++ b/tools/telemetry/telemetry/page/page_runner_unittest.py
@@ -9,6 +9,7 @@
from telemetry.core import user_agent
from telemetry.core import util
from telemetry.page import page as page_module
+from telemetry.page import page_measurement
from telemetry.page import page_set
from telemetry.page import page_test
from telemetry.page import page_runner
@@ -72,34 +73,42 @@
ps,
base_dir=os.path.dirname(__file__)))
- class Test(page_test.PageTest):
+ class Measurement(page_measurement.PageMeasurement):
@property
def discard_first_result(self):
return True
- def RunTest(self, *args):
+ def MeasurePage(self, *args):
pass
options = options_for_unittests.GetCopy()
options.output_format = 'none'
+ options.reset_html_results = None
options.repeat_options.page_repeat_iters = 1
options.repeat_options.pageset_repeat_iters = 1
- results = page_runner.Run(Test('RunTest'), ps, expectations, options)
+ results = page_runner.Run(Measurement(), ps, expectations, options)
self.assertEquals(0, len(results.successes))
self.assertEquals(0, len(results.failures))
options.repeat_options.page_repeat_iters = 1
options.repeat_options.pageset_repeat_iters = 2
- results = page_runner.Run(Test('RunTest'), ps, expectations, options)
+ results = page_runner.Run(Measurement(), ps, expectations, options)
self.assertEquals(2, len(results.successes))
self.assertEquals(0, len(results.failures))
options.repeat_options.page_repeat_iters = 2
options.repeat_options.pageset_repeat_iters = 1
- results = page_runner.Run(Test('RunTest'), ps, expectations, options)
+ results = page_runner.Run(Measurement(), ps, expectations, options)
self.assertEquals(2, len(results.successes))
self.assertEquals(0, len(results.failures))
+ options.output_format = 'html'
+ options.repeat_options.page_repeat_iters = 1
+ options.repeat_options.pageset_repeat_iters = 1
+ results = page_runner.Run(Measurement(), ps, expectations, options)
+ self.assertEquals(0, len(results.successes))
+ self.assertEquals(0, len(results.failures))
+
def testCredentialsWhenLoginFails(self):
credentials_backend = StubCredentialsBackend(login_return_value=False)
did_run = self.runCredentialsTest(credentials_backend)
diff --git a/tools/telemetry/telemetry/page/page_set.py b/tools/telemetry/telemetry/page/page_set.py
index 558b5c6..807c365 100644
--- a/tools/telemetry/telemetry/page/page_set.py
+++ b/tools/telemetry/telemetry/page/page_set.py
@@ -4,8 +4,8 @@
import csv
import json
import os
-import urlparse
+from telemetry.page import cloud_storage
from telemetry.page import page as page_module
from telemetry.page import page_set_archive_info
@@ -25,12 +25,8 @@
self.pages = []
if self.archive_data_file:
- if os.path.isdir(file_path):
- base_dir = file_path
- else:
- base_dir = os.path.dirname(file_path)
self.wpr_archive_info = page_set_archive_info.PageSetArchiveInfo.FromFile(
- os.path.join(base_dir, self.archive_data_file), file_path)
+ os.path.join(self._base_dir, self.archive_data_file), file_path)
else:
self.wpr_archive_info = None
@@ -38,29 +34,49 @@
def FromFile(cls, file_path):
with open(file_path, 'r') as f:
contents = f.read()
- data = json.loads(contents)
- return cls.FromDict(data, file_path)
+ data = json.loads(contents)
+ return cls.FromDict(data, file_path)
@classmethod
def FromDict(cls, data, file_path):
page_set = cls(file_path, data)
- if os.path.isdir(file_path):
- base_dir = file_path
- else:
- base_dir = os.path.dirname(file_path)
for page_attributes in data['pages']:
url = page_attributes.pop('url')
page = page_module.Page(url, page_set, attributes=page_attributes,
- base_dir=base_dir)
+ base_dir=page_set._base_dir) # pylint: disable=W0212
page_set.pages.append(page)
+
+ all_serving_dirs = set()
+ for page in page_set:
+ if page.is_file:
+ serving_dirs, _ = page.serving_dirs_and_file
+ if isinstance(serving_dirs, list):
+ all_serving_dirs |= set(serving_dirs)
+ else:
+ all_serving_dirs.add(serving_dirs)
+ for serving_dir in all_serving_dirs:
+ for dirpath, _, filenames in os.walk(serving_dir):
+ for filename in filenames:
+ file_path, extension = os.path.splitext(
+ os.path.join(dirpath, filename))
+ if extension != '.sha1':
+ continue
+ cloud_storage.GetIfChanged(cloud_storage.DEFAULT_BUCKET, file_path)
+
return page_set
+ @property
+ def _base_dir(self):
+ if os.path.isdir(self.file_path):
+ return self.file_path
+ else:
+ return os.path.dirname(self.file_path)
+
def ContainsOnlyFileURLs(self):
for page in self.pages:
- parsed_url = urlparse.urlparse(page.url)
- if parsed_url.scheme != 'file':
+ if not page.is_file:
return False
return True
diff --git a/tools/telemetry/telemetry/page/page_set_archive_info.py b/tools/telemetry/telemetry/page/page_set_archive_info.py
index 33502d8..adb7625 100644
--- a/tools/telemetry/telemetry/page/page_set_archive_info.py
+++ b/tools/telemetry/telemetry/page/page_set_archive_info.py
@@ -23,6 +23,9 @@
# Back pointer to the page set file.
self._page_set_file_path = page_set_file_path
+ for archive_path in data['archives']:
+ cloud_storage.GetIfChanged(cloud_storage.DEFAULT_BUCKET, archive_path)
+
# Map from the relative path (as it appears in the metadata file) of the
# .wpr file to a list of urls it supports.
self._wpr_file_to_urls = data['archives']
@@ -39,6 +42,8 @@
@classmethod
def FromFile(cls, file_path, page_set_file_path):
+ cloud_storage.GetIfChanged(cloud_storage.DEFAULT_BUCKET, file_path)
+
if os.path.exists(file_path):
with open(file_path, 'r') as f:
data = json.load(f)
diff --git a/tools/telemetry/telemetry/test.py b/tools/telemetry/telemetry/test.py
index df74a2a..3b5bcf3 100644
--- a/tools/telemetry/telemetry/test.py
+++ b/tools/telemetry/telemetry/test.py
@@ -1,6 +1,7 @@
# 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.
+import optparse
import os
from telemetry.core import repeat_options
@@ -33,6 +34,12 @@
test = self.test()
ps = self.CreatePageSet(options)
expectations = self.CreateExpectations(ps)
+
+ # Ensure the test's default options are set if needed.
+ parser = optparse.OptionParser()
+ test.AddCommandLineOptions(parser)
+ options.MergeDefaultValues(parser.get_default_values())
+
results = page_runner.Run(test, ps, expectations, options)
results.PrintSummary()
return len(results.failures) + len(results.errors)
diff --git a/tools/valgrind/gtest_exclude/content_unittests.gtest_mac.txt b/tools/valgrind/gtest_exclude/content_unittests.gtest_mac.txt
index dfbd75f..562c242 100644
--- a/tools/valgrind/gtest_exclude/content_unittests.gtest_mac.txt
+++ b/tools/valgrind/gtest_exclude/content_unittests.gtest_mac.txt
@@ -49,4 +49,7 @@
MacSandboxTest.FontLoadingTest
# http://crbug.com/247685
-ScreenCaptureDeviceTest.Capture
+DesktopCaptureDeviceTest.Capture
+
+# http://crbug.com/270254
+DeviceOrientationEventPumpTest.*
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt
index 6d773b7..da72868 100644
--- a/tools/valgrind/memcheck/suppressions.txt
+++ b/tools/valgrind/memcheck/suppressions.txt
@@ -6276,17 +6276,6 @@
fun:_ZN2v88internal8Debugger18CallCEventCallbackENS_10DebugEventENS0_6HandleINS0_6ObjectEEES5_PNS_5Debug10ClientDataE
}
{
- bug_181691
- Memcheck:Leak
- fun:_Znw*
- ...
- fun:_Z10InitThreadv
- fun:ShCompile
- fun:_ZN3gpu5gles216ShaderTranslator9TranslateEPKc
- fun:_ZN3gpu5gles214ProgramManager18ForceCompileShaderEPKSsPNS0_6ShaderEPNS0_16ShaderTranslatorEPNS0_11FeatureInfoE
- fun:_ZN3gpu5gles214ProgramManager15DoCompileShaderEPNS0_6ShaderEPNS0_16ShaderTranslatorEPNS0_11FeatureInfoE
-}
-{
bug_184264
Memcheck:Leak
fun:_Znw*
@@ -6547,44 +6536,6 @@
fun:_ZN7testing4Test11DeleteSelf_Ev
}
{
- bug_230366a
- Memcheck:Leak
- fun:_Znw*
- fun:_Z28InitializeGlobalParseContextv
- fun:_Z10InitThreadv
- fun:ShCompile
- fun:_ZN6webkit3gpu33WebGraphicsContext3DInProcessImpl25AngleValidateShaderSourceEPNS1_17ShaderSourceEntryE
- fun:_ZN6webkit3gpu33WebGraphicsContext3DInProcessImpl13compileShaderEj
- fun:_ZN2cc18ProgramBindingBase10LoadShaderEPN6WebKit20WebGraphicsContext3DEjRKSs
- fun:_ZN2cc18ProgramBindingBase4InitEPN6WebKit20WebGraphicsContext3DERKSsS5_
- fun:_ZN2cc14ProgramBindingINS_26VertexShaderPosTexIdentityENS_21FragmentShaderRGBATexEEC1EPN6WebKit20WebGraphicsContext3DENS_17TexCoordPrecisionE
- fun:_ZN2cc24AcceleratedTextureCopierC1EPN6WebKit20WebGraphicsContext3DEbi
- fun:_ZN2cc24AcceleratedTextureCopier6CreateEPN6WebKit20WebGraphicsContext3DEbi
- fun:_ZN2cc16ResourceProvider10InitializeEi
- fun:_ZN2cc16ResourceProvider6CreateEPNS_13OutputSurfaceEi
- fun:_ZN2cc17LayerTreeHostImpl18InitializeRendererE10scoped_ptrINS_13OutputSurfaceEN4base14DefaultDeleterIS2_EEE
- fun:_ZN2cc11ThreadProxy30InitializeRendererOnImplThreadEPNS_15CompletionEventEPbPNS_20RendererCapabilitiesE
-}
-{
- bug_230366b
- Memcheck:Leak
- fun:_Znw*
- fun:_Z21InitializeGlobalPoolsv
- fun:_Z10InitThreadv
- fun:ShCompile
- fun:_ZN6webkit3gpu33WebGraphicsContext3DInProcessImpl25AngleValidateShaderSourceEPNS1_17ShaderSourceEntryE
- fun:_ZN6webkit3gpu33WebGraphicsContext3DInProcessImpl13compileShaderEj
- fun:_ZN2cc18ProgramBindingBase10LoadShaderEPN6WebKit20WebGraphicsContext3DEjRKSs
- fun:_ZN2cc18ProgramBindingBase4InitEPN6WebKit20WebGraphicsContext3DERKSsS5_
- fun:_ZN2cc14ProgramBindingINS_26VertexShaderPosTexIdentityENS_21FragmentShaderRGBATexEEC1EPN6WebKit20WebGraphicsContext3DENS_17TexCoordPrecisionE
- fun:_ZN2cc24AcceleratedTextureCopierC1EPN6WebKit20WebGraphicsContext3DEbi
- fun:_ZN2cc24AcceleratedTextureCopier6CreateEPN6WebKit20WebGraphicsContext3DEbi
- fun:_ZN2cc16ResourceProvider10InitializeEi
- fun:_ZN2cc16ResourceProvider6CreateEPNS_13OutputSurfaceEi
- fun:_ZN2cc17LayerTreeHostImpl18InitializeRendererE10scoped_ptrINS_13OutputSurfaceEN4base14DefaultDeleterIS2_EEE
- fun:_ZN2cc11ThreadProxy30InitializeRendererOnImplThreadEPNS_15CompletionEventEPbPNS_20RendererCapabilitiesE
-}
-{
bug_233541
Memcheck:Leak
fun:_Znw*
@@ -6719,7 +6670,6 @@
fun:_ZN7WebCore6V8Node23appendChildMethodCustomERKN2v820FunctionCallbackInfoINS1_5ValueEEE
fun:_ZN7WebCore14NodeV8InternalL37appendChildMethodCallbackForMainWorldERKN2v820FunctionCallbackInfoINS1_5ValueEEE
}
-
{
bug_241932
Memcheck:Leak
@@ -7040,16 +6990,25 @@
fun:_ZN7content11ContentMainEiPPKcPNS_19ContentMainDelegateE
}
{
- bug_252641
+ bug_252641_a
Memcheck:Uninitialized
fun:pthread_rwlock_init$UNIX2003
fun:_ZN3re25MutexC2Ev
fun:_ZN3re25MutexC1Ev
...
fun:_ZN11leveldb_env19ParseMethodAndErrorEPKcPNS_8MethodIDEPi
- fun:_ZN7contentL21HistogramLevelDBErrorERKSsRKN7leveldb6StatusE
- fun:_ZN7content15LevelDBDatabase4OpenERKN4base8FilePathEPKNS_17LevelDBComparatorEPb
- fun:_ZN7content12_GLOBAL__N_139LevelDBDatabaseTest_CorruptionTest_Test8TestBodyEv
+}
+{
+ bug_252641_b
+ Memcheck:Uninitialized
+ fun:pthread_rwlock_init$UNIX2003
+ fun:_ZN3re25MutexC2Ev
+ fun:_ZN3re25MutexC1Ev
+ ...
+ fun:_ZN11leveldb_env19ParseMethodAndErrorEPKcPNS_8MethodIDEPi
+ fun:_ZN7content23RecoveryCouldBeFruitfulEN7leveldb6StatusE
+ fun:_ZN7content21IndexedDBBackingStore4OpenERKSsRKN4base8FilePathES2_PN6WebKit15WebIDBCallbacks8DataLossEPNS_14LevelDBFactoryE
+ fun:_ZN12_GLOBAL__N_137IndexedDBIOErrorTest_CleanUpTest_Test8TestBodyEv
}
{
bug_253797
@@ -7230,4 +7189,42 @@
fun:_ZN4base11MessageLoop8PostTaskERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEE
fun:_ZN8printing8PrintJob21UpdatePrintedDocumentEPNS_15PrintedDocumentE
fun:_ZN8printing8PrintJob4StopEv
- }
+}
+{
+ bug_269844
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorIPN4base11PendingTaskEE8allocateEmPKv
+ fun:_ZNSt11_Deque_baseIN4base11PendingTaskESaIS1_EE15_M_allocate_mapEm
+ fun:_ZNSt5dequeIN4base11PendingTaskESaIS1_EE17_M_reallocate_mapEmb
+ ...
+ fun:_ZN4base8internal17IncomingTaskQueue15PostPendingTaskEPNS_11PendingTaskE
+ fun:_ZN4base8internal17IncomingTaskQueue18AddToIncomingQueueERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEENS_9TimeDeltaEb
+ fun:_ZN4base11MessageLoop8PostTaskERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEE
+}
+{
+ bug_269884a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN24SkColorFilterImageFilter6CreateEP13SkColorFilterP13SkImageFilterPK7SkIRect
+ fun:_ZN7WebCore22SkiaImageFilterBuilder19transformColorSpaceEP13SkImageFilterNS_10ColorSpaceES3_
+ fun:_ZN7WebCore22SkiaImageFilterBuilder5buildERKNS_16FilterOperationsE
+}
+{
+ bug_269884b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN19SkPerlinNoiseShader15CreateTubulenceEffifPK7SkTSizeIiE
+ fun:_ZN7WebCore12FETurbulence12createShaderERKNS_7IntRectE
+ fun:_ZN7WebCore12FETurbulence17createImageFilterEPNS_22SkiaImageFilterBuilderE
+ fun:_ZN7WebCore22SkiaImageFilterBuilder5buildEPNS_12FilterEffectENS_10ColorSpaceE
+ fun:_ZN7WebCore22SkiaImageFilterBuilder5buildERKNS_16FilterOperationsE
+}
+{
+ bug_270312
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN14message_center22MessageCenterButtonBarC1EPNS_17MessageCenterViewEPNS_13MessageCenterEPNS_24NotifierSettingsProviderEb
+ fun:_ZN14message_center17MessageCenterViewC1EPNS_13MessageCenterEPNS_17MessageCenterTrayEibb
+ fun:_ZN14message_center21MessageCenterViewTest5SetUpEv
+}
diff --git a/tools/valgrind/tsan_v2/suppressions.txt b/tools/valgrind/tsan_v2/suppressions.txt
index c1c586d..682d33c 100644
--- a/tools/valgrind/tsan_v2/suppressions.txt
+++ b/tools/valgrind/tsan_v2/suppressions.txt
@@ -12,6 +12,9 @@
# Races in libevent, http://crbug.com/23244
race:libevent/event.c
+# http://crbug.com/46840
+race:history::HistoryBackend::DeleteFTSIndexDatabases
+
# http://crbug.com/84094
race:sqlite3StatusSet
race:pcache1EnforceMaxPage
@@ -93,5 +96,16 @@
# http://crbug.com/257543
race:*GetObjectFromEntryAddress
+# http://crbug.com/268924
+race:base::g_power_monitor
+race:base::PowerMonitor::PowerMonitor
+race:base::PowerMonitor::AddObserver
+
# http://crbug.com/268941
race:tracked_objects::ThreadData::tls_index_
+
+# http://crbug.com/269965
+race:DesktopMediaPickerModelTest_UpdateThumbnail_Test
+
+# http://crbug.com/270037
+race:gLibCleanupFunctions
diff --git a/ui/android/java/src/org/chromium/ui/ViewAndroid.java b/ui/android/java/src/org/chromium/ui/ViewAndroid.java
index 0f0ca11..97c8e1d 100644
--- a/ui/android/java/src/org/chromium/ui/ViewAndroid.java
+++ b/ui/android/java/src/org/chromium/ui/ViewAndroid.java
@@ -4,6 +4,8 @@
package org.chromium.ui;
+import android.view.View;
+
import org.chromium.base.JNINamespace;
import org.chromium.ui.ViewAndroidDelegate;
import org.chromium.ui.WindowAndroid;
@@ -23,6 +25,8 @@
private int mNativeViewAndroid = 0;
private final ViewAndroidDelegate mViewAndroidDelegate;
private final WindowAndroid mWindowAndroid;
+ private int mKeepScreenOnCount;
+ private View mKeepScreenOnView;
/**
* Constructs a View object.
@@ -55,6 +59,29 @@
return mNativeViewAndroid;
}
+ /**
+ * Set KeepScreenOn flag. If the flag already set, increase mKeepScreenOnCount.
+ */
+ public void incrementKeepScreenOnCount() {
+ mKeepScreenOnCount++;
+ if (mKeepScreenOnCount == 1) {
+ mKeepScreenOnView = mViewAndroidDelegate.acquireAnchorView();
+ mKeepScreenOnView.setKeepScreenOn(true);
+ }
+ }
+
+ /**
+ * Decrease mKeepScreenOnCount, if it is decreased to 0, remove the flag.
+ */
+ public void decrementKeepScreenOnCount() {
+ assert mKeepScreenOnCount > 0;
+ mKeepScreenOnCount--;
+ if (mKeepScreenOnCount == 0) {
+ mViewAndroidDelegate.releaseAnchorView(mKeepScreenOnView);
+ mKeepScreenOnView = null;
+ }
+ }
+
private native int nativeInit(int windowPtr);
private native void nativeDestroy(int nativeViewAndroid);
}
diff --git a/ui/android/java/src/org/chromium/ui/WindowAndroid.java b/ui/android/java/src/org/chromium/ui/WindowAndroid.java
index 316690b..3fec600 100644
--- a/ui/android/java/src/org/chromium/ui/WindowAndroid.java
+++ b/ui/android/java/src/org/chromium/ui/WindowAndroid.java
@@ -11,7 +11,6 @@
import android.content.Intent;
import android.os.Bundle;
import android.util.SparseArray;
-import android.view.WindowManager;
import android.widget.Toast;
import java.util.HashMap;
@@ -201,14 +200,6 @@
return mNativeWindowAndroid;
}
- public void keepScreenOn(boolean screenOn) {
- if (screenOn) {
- mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- } else {
- mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- }
- }
-
private native int nativeInit();
private native void nativeDestroy(int nativeWindowAndroid);
diff --git a/ui/app_list/cocoa/app_list_view_controller.mm b/ui/app_list/cocoa/app_list_view_controller.mm
index 37b6bf8..e464721 100644
--- a/ui/app_list/cocoa/app_list_view_controller.mm
+++ b/ui/app_list/cocoa/app_list_view_controller.mm
@@ -317,6 +317,7 @@
}
- (void)onSigninStatusChanged {
+ [appsSearchBoxController_ rebuildMenu];
app_list::SigninDelegate* signinDelegate = [self signinDelegate];
BOOL needsSignin = signinDelegate && signinDelegate->NeedSignin();
if (!needsSignin) {
diff --git a/ui/app_list/cocoa/apps_search_box_controller.h b/ui/app_list/cocoa/apps_search_box_controller.h
index 3e9b4b2..d28c67a 100644
--- a/ui/app_list/cocoa/apps_search_box_controller.h
+++ b/ui/app_list/cocoa/apps_search_box_controller.h
@@ -49,6 +49,9 @@
- (id)initWithFrame:(NSRect)frame;
- (void)clearSearch;
+// Rebuild the menu due to changes from the AppListViewDelegate.
+- (void)rebuildMenu;
+
@end
@interface AppsSearchBoxController (TestingAPI)
diff --git a/ui/app_list/cocoa/apps_search_box_controller.mm b/ui/app_list/cocoa/apps_search_box_controller.mm
index 6d38f94..4f02a20 100644
--- a/ui/app_list/cocoa/apps_search_box_controller.mm
+++ b/ui/app_list/cocoa/apps_search_box_controller.mm
@@ -30,8 +30,9 @@
// Size of the menu button on the right.
const CGFloat kMenuButtonDimension = 29;
-// Vertical offset that the menu should appear below the menu button.
-const CGFloat kMenuOffsetFromButton = 2;
+// Menu offset relative to the bottom-right corner of the menu button.
+const CGFloat kMenuYOffsetFromButton = -4;
+const CGFloat kMenuXOffsetFromButton = -7;
}
@@ -153,6 +154,15 @@
[self controlTextDidChange:nil];
}
+- (void)rebuildMenu {
+ if (![delegate_ appListDelegate])
+ return;
+
+ menuController_.reset([[AppListMenuController alloc]
+ initWithSearchBoxController:self]);
+ [menuButton_ setMenu:[menuController_ menu]]; // Menu will populate here.
+}
+
- (void)setDelegate:(id<AppsSearchBoxDelegate>)delegate {
[[menuButton_ menu] removeAllItems];
menuController_.reset();
@@ -167,9 +177,7 @@
return;
appListMenu_.reset(new app_list::AppListMenu([delegate_ appListDelegate]));
- menuController_.reset([[AppListMenuController alloc]
- initWithSearchBoxController:self]);
- [menuButton_ setMenu:[menuController_ menu]]; // Menu will populate here.
+ [self rebuildMenu];
}
- (NSTextField*)searchTextField {
@@ -385,8 +393,8 @@
NSRect anchorRect = [menuButton convertRect:[menuButton bounds]
toView:nil];
NSPoint anchorPoint = [[menuButton window] convertBaseToScreen:NSMakePoint(
- NSMaxX(anchorRect),
- NSMinY(anchorRect) - kMenuOffsetFromButton)];
+ NSMaxX(anchorRect) + kMenuXOffsetFromButton,
+ NSMinY(anchorRect) - kMenuYOffsetFromButton)];
NSRect confinementRect = [[menuButton window] frame];
confinementRect.size = NSMakeSize(anchorPoint.x - NSMinX(confinementRect),
anchorPoint.y - NSMinY(confinementRect));
diff --git a/ui/app_list/cocoa/apps_search_results_model_bridge.mm b/ui/app_list/cocoa/apps_search_results_model_bridge.mm
index 41e3fd6..d56c5fd 100644
--- a/ui/app_list/cocoa/apps_search_results_model_bridge.mm
+++ b/ui/app_list/cocoa/apps_search_results_model_bridge.mm
@@ -44,6 +44,7 @@
virtual void OnIsInstallingChanged() OVERRIDE {}
virtual void OnPercentDownloadedChanged() OVERRIDE {}
virtual void OnItemInstalled() OVERRIDE {}
+ virtual void OnItemUninstalled() OVERRIDE {}
private:
AppsSearchResultsModelBridge* bridge_; // Weak. Owns us.
diff --git a/ui/app_list/search_result.cc b/ui/app_list/search_result.cc
index ab40d31..cf90830 100644
--- a/ui/app_list/search_result.cc
+++ b/ui/app_list/search_result.cc
@@ -63,9 +63,11 @@
}
void SearchResult::NotifyItemInstalled() {
- FOR_EACH_OBSERVER(SearchResultObserver,
- observers_,
- OnItemInstalled());
+ FOR_EACH_OBSERVER(SearchResultObserver, observers_, OnItemInstalled());
+}
+
+void SearchResult::NotifyItemUninstalled() {
+ FOR_EACH_OBSERVER(SearchResultObserver, observers_, OnItemUninstalled());
}
void SearchResult::AddObserver(SearchResultObserver* observer) {
diff --git a/ui/app_list/search_result.h b/ui/app_list/search_result.h
index f2e94b2..5baa50f 100644
--- a/ui/app_list/search_result.h
+++ b/ui/app_list/search_result.h
@@ -101,6 +101,7 @@
void SetPercentDownloaded(int percent_downloaded);
void NotifyItemInstalled();
+ void NotifyItemUninstalled();
void AddObserver(SearchResultObserver* observer);
void RemoveObserver(SearchResultObserver* observer);
diff --git a/ui/app_list/search_result_list_view_delegate.h b/ui/app_list/search_result_list_view_delegate.h
index 7b64448..e45ac4b 100644
--- a/ui/app_list/search_result_list_view_delegate.h
+++ b/ui/app_list/search_result_list_view_delegate.h
@@ -28,6 +28,9 @@
// Called when the app represented by |result| is installed.
virtual void OnResultInstalled(SearchResult* result) = 0;
+ // Called when the app represented by |result| is uninstalled.
+ virtual void OnResultUninstalled(SearchResult* result) = 0;
+
protected:
virtual ~SearchResultListViewDelegate() {}
};
diff --git a/ui/app_list/search_result_observer.h b/ui/app_list/search_result_observer.h
index 6a2b1a5..bef7564 100644
--- a/ui/app_list/search_result_observer.h
+++ b/ui/app_list/search_result_observer.h
@@ -26,6 +26,9 @@
// Invoked when the item represented by the SearchResult is installed.
virtual void OnItemInstalled() = 0;
+ // Invoked when the item represented by the SearchResult is uninstalled.
+ virtual void OnItemUninstalled() = 0;
+
protected:
virtual ~SearchResultObserver() {}
};
diff --git a/ui/app_list/views/app_list_main_view.cc b/ui/app_list/views/app_list_main_view.cc
index 8874410..fa0de27 100644
--- a/ui/app_list/views/app_list_main_view.cc
+++ b/ui/app_list/views/app_list_main_view.cc
@@ -229,4 +229,8 @@
search_box_view_->ClearSearch();
}
+void AppListMainView::OnResultUninstalled(SearchResult* result) {
+ QueryChanged(search_box_view_);
+}
+
} // namespace app_list
diff --git a/ui/app_list/views/app_list_main_view.h b/ui/app_list/views/app_list_main_view.h
index dc73e8b..1909d97 100644
--- a/ui/app_list/views/app_list_main_view.h
+++ b/ui/app_list/views/app_list_main_view.h
@@ -85,6 +85,7 @@
int action_index,
int event_flags) OVERRIDE;
virtual void OnResultInstalled(SearchResult* result) OVERRIDE;
+ virtual void OnResultUninstalled(SearchResult* result) OVERRIDE;
AppListViewDelegate* delegate_;
AppListModel* model_;
diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc
index 863e25e..118ab2b 100644
--- a/ui/app_list/views/app_list_view.cc
+++ b/ui/app_list/views/app_list_view.cc
@@ -27,6 +27,7 @@
#if defined(USE_AURA)
#include "ui/aura/window.h"
+#include "ui/aura/root_window.h"
#if defined(OS_WIN)
#include "ui/base/win/shell.h"
#endif
@@ -182,6 +183,18 @@
app_list_main_view_->search_box_view()->InvalidateMenu();
}
+#if defined(OS_WIN)
+HWND AppListView::GetHWND() const {
+#if defined(USE_AURA)
+ gfx::NativeWindow window =
+ GetWidget()->GetTopLevelWidget()->GetNativeWindow();
+ return window->GetRootWindow()->GetAcceleratedWidget();
+#else
+ return GetWidget()->GetTopLevelWidget()->GetNativeWindow();
+#endif
+}
+#endif
+
views::View* AppListView::GetInitiallyFocusedView() {
return app_list_main_view_->search_box_view()->search_box();
}
diff --git a/ui/app_list/views/app_list_view.h b/ui/app_list/views/app_list_view.h
index eb21ceb..fff4815 100644
--- a/ui/app_list/views/app_list_view.h
+++ b/ui/app_list/views/app_list_view.h
@@ -70,6 +70,10 @@
// Invoked when the sign-in status is changed to switch on/off sign-in view.
void OnSigninStatusChanged();
+#if defined(OS_WIN)
+ HWND GetHWND() const;
+#endif
+
private:
// Overridden from views::WidgetDelegateView:
virtual views::View* GetInitiallyFocusedView() OVERRIDE;
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc
index 12d166a..1d997e5 100644
--- a/ui/app_list/views/search_box_view.cc
+++ b/ui/app_list/views/search_box_view.cc
@@ -29,6 +29,10 @@
const SkColor kHintTextColor = SkColorSetRGB(0xA0, 0xA0, 0xA0);
+// Menu offset relative to the bottom-right corner of the menu button.
+const int kMenuYOffsetFromButton = -4;
+const int kMenuXOffsetFromButton = -7;
+
} // namespace
SearchBoxView::SearchBoxView(SearchBoxViewDelegate* delegate,
@@ -158,8 +162,10 @@
if (!menu_)
menu_.reset(new AppListMenuViews(view_delegate_));
- menu_->RunMenuAt(menu_button_,
- menu_button_->GetBoundsInScreen().bottom_right());
+ const gfx::Point menu_location =
+ menu_button_->GetBoundsInScreen().bottom_right() +
+ gfx::Vector2d(kMenuXOffsetFromButton, kMenuYOffsetFromButton);
+ menu_->RunMenuAt(menu_button_, menu_location);
}
void SearchBoxView::IconChanged() {
diff --git a/ui/app_list/views/search_result_list_view.cc b/ui/app_list/views/search_result_list_view.cc
index 48c9157..5eaad3c 100644
--- a/ui/app_list/views/search_result_list_view.cc
+++ b/ui/app_list/views/search_result_list_view.cc
@@ -173,4 +173,9 @@
delegate_->OnResultInstalled(view->result());
}
+void SearchResultListView::OnSearchResultUninstalled(SearchResultView* view) {
+ if (delegate_ && view->result())
+ delegate_->OnResultUninstalled(view->result());
+}
+
} // namespace app_list
diff --git a/ui/app_list/views/search_result_list_view.h b/ui/app_list/views/search_result_list_view.h
index d6b0396..5b3fa48 100644
--- a/ui/app_list/views/search_result_list_view.h
+++ b/ui/app_list/views/search_result_list_view.h
@@ -59,6 +59,7 @@
size_t action_index,
int event_flags) OVERRIDE;
virtual void OnSearchResultInstalled(SearchResultView* view) OVERRIDE;
+ virtual void OnSearchResultUninstalled(SearchResultView* view) OVERRIDE;
SearchResultListViewDelegate* delegate_; // Not owned.
AppListModel::SearchResults* results_; // Owned by AppListModel.
diff --git a/ui/app_list/views/search_result_view.cc b/ui/app_list/views/search_result_view.cc
index 0361591..55b9e0b 100644
--- a/ui/app_list/views/search_result_view.cc
+++ b/ui/app_list/views/search_result_view.cc
@@ -279,6 +279,10 @@
delegate_->OnSearchResultInstalled(this);
}
+void SearchResultView::OnItemUninstalled() {
+ delegate_->OnSearchResultUninstalled(this);
+}
+
void SearchResultView::OnSearchResultActionActivated(size_t index,
int event_flags) {
DCHECK(result_);
diff --git a/ui/app_list/views/search_result_view.h b/ui/app_list/views/search_result_view.h
index 4d830e7..dde3669 100644
--- a/ui/app_list/views/search_result_view.h
+++ b/ui/app_list/views/search_result_view.h
@@ -80,6 +80,7 @@
virtual void OnIsInstallingChanged() OVERRIDE;
virtual void OnPercentDownloadedChanged() OVERRIDE;
virtual void OnItemInstalled() OVERRIDE;
+ virtual void OnItemUninstalled() OVERRIDE;
// SearchResultActionsViewDelegate overrides:
virtual void OnSearchResultActionActivated(size_t index,
diff --git a/ui/app_list/views/search_result_view_delegate.h b/ui/app_list/views/search_result_view_delegate.h
index 16b87ef..e86ccc8 100644
--- a/ui/app_list/views/search_result_view_delegate.h
+++ b/ui/app_list/views/search_result_view_delegate.h
@@ -24,6 +24,9 @@
// Called when the app represented by the search result is installed.
virtual void OnSearchResultInstalled(SearchResultView* view) = 0;
+ // Called when the app represented by the search result is uninstalled.
+ virtual void OnSearchResultUninstalled(SearchResultView* view) = 0;
+
protected:
virtual ~SearchResultViewDelegate() {}
};
diff --git a/ui/aura/demo/demo_main.cc b/ui/aura/demo/demo_main.cc
index aea286e..06938d8 100644
--- a/ui/aura/demo/demo_main.cc
+++ b/ui/aura/demo/demo_main.cc
@@ -11,6 +11,7 @@
#include "ui/aura/client/default_capture_client.h"
#include "ui/aura/client/stacking_client.h"
#include "ui/aura/env.h"
+#include "ui/aura/focus_manager.h"
#include "ui/aura/root_window.h"
#include "ui/aura/test/test_screen.h"
#include "ui/aura/window.h"
@@ -116,6 +117,8 @@
test_screen->CreateRootWindowForPrimaryDisplay());
scoped_ptr<DemoStackingClient> stacking_client(new DemoStackingClient(
root_window.get()));
+ aura::FocusManager focus_manager;
+ aura::client::SetFocusClient(root_window.get(), &focus_manager);
// Create a hierarchy of test windows.
DemoWindowDelegate window_delegate1(SK_ColorBLUE);
diff --git a/ui/aura/root_window_host_x11.cc b/ui/aura/root_window_host_x11.cc
index ad1b957..f69a54a 100644
--- a/ui/aura/root_window_host_x11.cc
+++ b/ui/aura/root_window_host_x11.cc
@@ -822,12 +822,16 @@
bool RootWindowHostX11::CopyAreaToSkCanvas(const gfx::Rect& source_bounds,
const gfx::Point& dest_offset,
SkCanvas* canvas) {
- scoped_ptr<ui::XScopedImage> scoped_image(GetXImage(source_bounds));
- if (!scoped_image)
+ ui::XScopedImage scoped_image(
+ XGetImage(xdisplay_, xwindow_,
+ source_bounds.x(), source_bounds.y(),
+ source_bounds.width(), source_bounds.height(),
+ AllPlanes, ZPixmap));
+ XImage* image = scoped_image.get();
+ if (!image) {
+ LOG(ERROR) << "XGetImage failed";
return false;
-
- XImage* image = scoped_image->get();
- DCHECK(image);
+ }
if (image->bits_per_pixel == 32) {
if ((0xff << SK_R32_SHIFT) != image->red_mask ||
@@ -1085,20 +1089,6 @@
delegate_->OnHostMouseEvent(event);
}
-scoped_ptr<ui::XScopedImage> RootWindowHostX11::GetXImage(
- const gfx::Rect& snapshot_bounds) {
- scoped_ptr<ui::XScopedImage> image(new ui::XScopedImage(
- XGetImage(xdisplay_, xwindow_,
- snapshot_bounds.x(), snapshot_bounds.y(),
- snapshot_bounds.width(), snapshot_bounds.height(),
- AllPlanes, ZPixmap)));
- if (!image) {
- LOG(ERROR) << "XGetImage failed";
- image.reset();
- }
- return image.Pass();
-}
-
void RootWindowHostX11::UpdateIsInternalDisplay() {
RootWindow* root_window = GetRootWindow();
gfx::Screen* screen = gfx::Screen::GetScreenFor(root_window);
diff --git a/ui/aura/root_window_host_x11.h b/ui/aura/root_window_host_x11.h
index b3b2788..c38002d 100644
--- a/ui/aura/root_window_host_x11.h
+++ b/ui/aura/root_window_host_x11.h
@@ -96,10 +96,6 @@
// dispatches the event to RootWindowHostDelegate.
void TranslateAndDispatchMouseEvent(ui::MouseEvent* event);
- // Copies and returns |snapshot_bounds| from |xwindow_|. Helper method for
- // CopyAreaToSkCanvas() and GrabSnapshot().
- scoped_ptr<ui::XScopedImage> GetXImage(const gfx::Rect& snapshot_bounds);
-
// Update is_internal_display_ based on delegate_ state
void UpdateIsInternalDisplay();
diff --git a/ui/base/dragdrop/drag_utils_win.cc b/ui/base/dragdrop/drag_utils_win.cc
index b760fa8..0bed7ea 100644
--- a/ui/base/dragdrop/drag_utils_win.cc
+++ b/ui/base/dragdrop/drag_utils_win.cc
@@ -9,6 +9,7 @@
#include <shobjidl.h>
#include "base/win/scoped_comptr.h"
+#include "base/win/scoped_hdc.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
@@ -39,18 +40,19 @@
// Blit the contents of the canvas to a new HBITMAP. It is the caller's
// responsibility to release the |bits| buffer.
static HBITMAP CreateHBITMAPFromSkBitmap(const SkBitmap& sk_bitmap) {
- HDC screen_dc = GetDC(NULL);
+ base::win::ScopedGetDC screen_dc(NULL);
BITMAPINFOHEADER header;
gfx::CreateBitmapHeader(sk_bitmap.width(), sk_bitmap.height(), &header);
void* bits;
HBITMAP bitmap =
CreateDIBSection(screen_dc, reinterpret_cast<BITMAPINFO*>(&header),
DIB_RGB_COLORS, &bits, NULL, 0);
+ if (!bitmap || !bits)
+ return NULL;
DCHECK_EQ(sk_bitmap.rowBytes(), static_cast<size_t>(sk_bitmap.width() * 4));
SkAutoLockPixels lock(sk_bitmap);
memcpy(
bits, sk_bitmap.getPixels(), sk_bitmap.height() * sk_bitmap.rowBytes());
- ReleaseDC(NULL, screen_dc);
return bitmap;
}
@@ -64,10 +66,11 @@
// SetDragImageOnDataObject(HBITMAP) takes ownership of the bitmap.
HBITMAP bitmap = CreateHBITMAPFromSkBitmap(
SkBitmapOperations::UnPreMultiply(*image_skia.bitmap()));
-
- // Attach 'bitmap' to the data_object.
- SetDragImageOnDataObject(bitmap, size, cursor_offset,
- ui::OSExchangeDataProviderWin::GetIDataObject(*data_object));
+ if (bitmap) {
+ // Attach 'bitmap' to the data_object.
+ SetDragImageOnDataObject(bitmap, size, cursor_offset,
+ ui::OSExchangeDataProviderWin::GetIDataObject(*data_object));
+ }
#if defined(USE_AURA)
// TODO: the above code is used in non-Ash, while below is used in Ash. If we
diff --git a/ui/base/ime/input_method_ibus_unittest.cc b/ui/base/ime/input_method_ibus_unittest.cc
index bd84738..99accfa 100644
--- a/ui/base/ime/input_method_ibus_unittest.cc
+++ b/ui/base/ime/input_method_ibus_unittest.cc
@@ -402,6 +402,9 @@
virtual TextInputType GetTextInputType() const OVERRIDE {
return input_type_;
}
+ virtual TextInputMode GetTextInputMode() const OVERRIDE {
+ return TEXT_INPUT_MODE_DEFAULT;
+ }
virtual bool CanComposeInline() const OVERRIDE {
return can_compose_inline_;
}
diff --git a/ui/base/ime/text_input_client.h b/ui/base/ime/text_input_client.h
index 82d0585..2fd14a2 100644
--- a/ui/base/ime/text_input_client.h
+++ b/ui/base/ime/text_input_client.h
@@ -9,6 +9,7 @@
#include "base/i18n/rtl.h"
#include "base/strings/string16.h"
#include "ui/base/ime/composition_text.h"
+#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/base/range/range.h"
#include "ui/base/ui_export.h"
@@ -63,6 +64,10 @@
// TEXT_INPUT_TYPE_NONE at runtime.
virtual ui::TextInputType GetTextInputType() const = 0;
+ // Returns current text input mode. It could be changed and even becomes
+ // TEXT_INPUT_MODE_DEFAULT at runtime.
+ virtual ui::TextInputMode GetTextInputMode() const = 0;
+
// Returns if the client supports inline composition currently.
virtual bool CanComposeInline() const = 0;
diff --git a/ui/base/ime/win/imm32_manager.h b/ui/base/ime/win/imm32_manager.h
index 08776ab..17892cb 100644
--- a/ui/base/ime/win/imm32_manager.h
+++ b/ui/base/ime/win/imm32_manager.h
@@ -77,7 +77,7 @@
class UI_EXPORT IMM32Manager {
public:
IMM32Manager();
- ~IMM32Manager();
+ virtual ~IMM32Manager();
// Retrieves whether or not there is an ongoing composition.
bool is_composing() const { return is_composing_; }
@@ -241,7 +241,7 @@
base::i18n::TextDirection GetTextDirection() const;
// Sets conversion status corresponding to |input_mode|.
- void SetTextInputMode(HWND window_handle, TextInputMode input_mode);
+ virtual void SetTextInputMode(HWND window_handle, TextInputMode input_mode);
// Helper functions ----------------------------------------------------------
diff --git a/ui/base/ime/win/tsf_text_store_unittest.cc b/ui/base/ime/win/tsf_text_store_unittest.cc
index baa4c8d..62772f2 100644
--- a/ui/base/ime/win/tsf_text_store_unittest.cc
+++ b/ui/base/ime/win/tsf_text_store_unittest.cc
@@ -28,6 +28,7 @@
MOCK_METHOD2(InsertChar, void(char16, int));
MOCK_CONST_METHOD0(GetAttachedWindow, gfx::NativeWindow());
MOCK_CONST_METHOD0(GetTextInputType, ui::TextInputType());
+ MOCK_CONST_METHOD0(GetTextInputMode, ui::TextInputMode());
MOCK_CONST_METHOD0(CanComposeInline, bool());
MOCK_METHOD0(GetCaretBounds, gfx::Rect());
MOCK_METHOD2(GetCompositionCharacterBounds, bool(uint32, gfx::Rect*));
diff --git a/ui/base/strings/ui_strings.grd b/ui/base/strings/ui_strings.grd
index 1a243e5..ec198ad 100644
--- a/ui/base/strings/ui_strings.grd
+++ b/ui/base/strings/ui_strings.grd
@@ -1530,16 +1530,12 @@
<message name="IDS_MESSAGE_CENTER_SETTINGS_GO_BACK_BUTTON_TOOLTIP" desc="The tooltip on back button that returns from settings to the notification list.">
Go back to notifications
</message>
- <if expr="is_macosx">
- <message name="IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION" desc="The label to describe the settings dialog.">
- Allow notifications from the following:
- </message>
- </if>
- <if expr="not is_macosx">
- <message name="IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION" desc="The label to describe the settings dialog.">
- Manage notifications per profile:
- </message>
- </if>
+ <message name="IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION" desc="The label to describe the settings dialog.">
+ Allow notifications from the following:
+ </message>
+ <message name="IDS_MESSAGE_CENTER_SETTINGS_DESCRIPTION_MULTIUSER" desc="The label to describe the settings dialog if there is more than one user.">
+ Allow notifications from the following for each user:
+ </message>
<message name="IDS_MESSAGE_CENTER_SETTINGS" desc="The menu entry or button for visiting the appropriate settings page.">
Settings...
</message>
diff --git a/ui/base/touch/touch_device_win.cc b/ui/base/touch/touch_device_win.cc
index 4eba353..c07fbe9 100644
--- a/ui/base/touch/touch_device_win.cc
+++ b/ui/base/touch/touch_device_win.cc
@@ -10,8 +10,8 @@
bool IsTouchDevicePresent() {
int value = GetSystemMetrics(SM_DIGITIZER);
- return (value & (NID_READY | NID_INTEGRATED_TOUCH)) ==
- (NID_READY | NID_INTEGRATED_TOUCH);
+ return (value & NID_READY) &&
+ ((value & NID_INTEGRATED_TOUCH) || (value & NID_EXTERNAL_TOUCH));
}
} // namespace ui
diff --git a/ui/gfx/box_f.cc b/ui/gfx/box_f.cc
new file mode 100644
index 0000000..107c5d6
--- /dev/null
+++ b/ui/gfx/box_f.cc
@@ -0,0 +1,52 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/box_f.h"
+
+#include "base/strings/stringprintf.h"
+
+namespace gfx {
+
+std::string BoxF::ToString() const {
+ return base::StringPrintf("%s %fx%fx%f",
+ origin().ToString().c_str(),
+ width_,
+ height_,
+ depth_);
+}
+
+bool BoxF::IsEmpty() const {
+ return (width_ == 0 && height_ == 0) ||
+ (width_ == 0 && depth_ == 0) ||
+ (height_ == 0 && depth_ == 0);
+}
+
+void BoxF::Union(const BoxF& box) {
+ if (IsEmpty()) {
+ *this = box;
+ return;
+ }
+ if (box.IsEmpty())
+ return;
+
+ float min_x = std::min(x(), box.x());
+ float min_y = std::min(y(), box.y());
+ float min_z = std::min(z(), box.z());
+ float max_x = std::max(right(), box.right());
+ float max_y = std::max(bottom(), box.bottom());
+ float max_z = std::max(front(), box.front());
+
+ origin_.SetPoint(min_x, min_y, min_z);
+ width_ = max_x - min_x;
+ height_ = max_y - min_y;
+ depth_ = max_z - min_z;
+}
+
+BoxF UnionBoxes(const BoxF& a, const BoxF& b) {
+ BoxF result = a;
+ result.Union(b);
+ return result;
+}
+
+} // namespace gfx
diff --git a/ui/gfx/box_f.h b/ui/gfx/box_f.h
new file mode 100644
index 0000000..01063b1
--- /dev/null
+++ b/ui/gfx/box_f.h
@@ -0,0 +1,142 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_BOX_F_H_
+#define UI_GFX_BOX_F_H_
+
+#include "ui/gfx/point3_f.h"
+#include "ui/gfx/vector3d_f.h"
+
+namespace gfx {
+
+// A 3d version of gfx::RectF, with the positive z-axis pointed towards
+// the camera.
+class UI_EXPORT BoxF {
+ public:
+ BoxF()
+ : width_(0.f),
+ height_(0.f),
+ depth_(0.f) {}
+
+ BoxF(float width, float height, float depth)
+ : width_(width < 0 ? 0 : width),
+ height_(height < 0 ? 0 : height),
+ depth_(depth < 0 ? 0 : depth) {}
+
+ BoxF(float x, float y, float z, float width, float height, float depth)
+ : origin_(x, y, z),
+ width_(width < 0 ? 0 : width),
+ height_(height < 0 ? 0 : height),
+ depth_(depth < 0 ? 0 : depth) {}
+
+ BoxF(const Point3F& origin, float width, float height, float depth)
+ : origin_(origin),
+ width_(width < 0 ? 0 : width),
+ height_(height < 0 ? 0 : height),
+ depth_(depth < 0 ? 0 : depth) {}
+
+ ~BoxF() {}
+
+ // Scales all three axes by the given scale.
+ void Scale(float scale) {
+ Scale(scale, scale, scale);
+ }
+
+ // Scales each axis by the corresponding given scale.
+ void Scale(float x_scale, float y_scale, float z_scale) {
+ origin_.Scale(x_scale, y_scale, z_scale);
+ set_size(width_ * x_scale, height_ * y_scale, depth_ * z_scale);
+ }
+
+ // Moves the box by the specified distance in each dimension.
+ void operator+=(const Vector3dF& offset) {
+ origin_ += offset;
+ }
+
+ // Returns true if the box has no interior points.
+ bool IsEmpty() const;
+
+ // Computes the union of this box with the given box. The union is the
+ // smallest box that contains both boxes.
+ void Union(const BoxF& box);
+
+ std::string ToString() const;
+
+ float x() const { return origin_.x(); }
+ void set_x(float x) { origin_.set_x(x); }
+
+ float y() const { return origin_.y(); }
+ void set_y(float y) { origin_.set_y(y); }
+
+ float z() const { return origin_.z(); }
+ void set_z(float z) { origin_.set_z(z); }
+
+ float width() const { return width_; }
+ void set_width(float width) { width_ = width < 0 ? 0 : width; }
+
+ float height() const { return height_; }
+ void set_height(float height) { height_ = height < 0 ? 0 : height; }
+
+ float depth() const { return depth_; }
+ void set_depth(float depth) { depth_ = depth < 0 ? 0 : depth; }
+
+ float right() const { return x() + width(); }
+ float bottom() const { return y() + height(); }
+ float front() const { return z() + depth(); }
+
+ void set_size(float width, float height, float depth) {
+ width_ = width < 0 ? 0 : width;
+ height_ = height < 0 ? 0 : height;
+ depth_ = depth < 0 ? 0 : depth;
+ }
+
+ const Point3F& origin() const { return origin_; }
+ void set_origin(const Point3F& origin) { origin_ = origin; }
+
+ private:
+ Point3F origin_;
+ float width_;
+ float height_;
+ float depth_;
+};
+
+UI_EXPORT BoxF UnionBoxes(const BoxF& a, const BoxF& b);
+
+inline BoxF ScaleBox(const BoxF& b,
+ float x_scale,
+ float y_scale,
+ float z_scale) {
+ return BoxF(b.x() * x_scale,
+ b.y() * y_scale,
+ b.z() * z_scale,
+ b.width() * x_scale,
+ b.height() * y_scale,
+ b.depth() * z_scale);
+}
+
+inline BoxF ScaleBox(const BoxF& b, float scale) {
+ return ScaleBox(b, scale, scale, scale);
+}
+
+inline bool operator==(const BoxF& a, const BoxF& b) {
+ return a.origin() == b.origin() && a.width() == b.width() &&
+ a.height() == b.height() && a.depth() == b.depth();
+}
+
+inline bool operator!=(const BoxF& a, const BoxF& b) {
+ return !(a == b);
+}
+
+inline BoxF operator+(const BoxF& b, const Vector3dF& v) {
+ return BoxF(b.x() + v.x(),
+ b.y() + v.y(),
+ b.z() + v.z(),
+ b.width(),
+ b.height(),
+ b.depth());
+}
+
+} // namespace gfx
+
+#endif // UI_GFX_BOX_F_H_
diff --git a/ui/gfx/box_unittest.cc b/ui/gfx/box_unittest.cc
new file mode 100644
index 0000000..0e944ec
--- /dev/null
+++ b/ui/gfx/box_unittest.cc
@@ -0,0 +1,143 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/box_f.h"
+
+namespace gfx {
+
+TEST(BoxTest, Constructors) {
+ EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 0.f).ToString(),
+ BoxF().ToString());
+ EXPECT_EQ(BoxF(0.f, 0.f, 0.f, -3.f, -5.f, -7.f).ToString(),
+ BoxF().ToString());
+
+ EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 3.f, 5.f, 7.f).ToString(),
+ BoxF(3.f, 5.f, 7.f).ToString());
+ EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 0.f).ToString(),
+ BoxF(-3.f, -5.f, -7.f).ToString());
+
+ EXPECT_EQ(BoxF(2.f, 4.f, 6.f, 3.f, 5.f, 7.f).ToString(),
+ BoxF(Point3F(2.f, 4.f, 6.f), 3.f, 5.f, 7.f).ToString());
+ EXPECT_EQ(BoxF(2.f, 4.f, 6.f, 0.f, 0.f, 0.f).ToString(),
+ BoxF(Point3F(2.f, 4.f, 6.f), -3.f, -5.f, -7.f).ToString());
+}
+
+TEST(BoxTest, IsEmpty) {
+ EXPECT_TRUE(BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 0.f).IsEmpty());
+ EXPECT_TRUE(BoxF(1.f, 2.f, 3.f, 0.f, 0.f, 0.f).IsEmpty());
+
+ EXPECT_TRUE(BoxF(0.f, 0.f, 0.f, 2.f, 0.f, 0.f).IsEmpty());
+ EXPECT_TRUE(BoxF(1.f, 2.f, 3.f, 2.f, 0.f, 0.f).IsEmpty());
+ EXPECT_TRUE(BoxF(0.f, 0.f, 0.f, 0.f, 2.f, 0.f).IsEmpty());
+ EXPECT_TRUE(BoxF(1.f, 2.f, 3.f, 0.f, 2.f, 0.f).IsEmpty());
+ EXPECT_TRUE(BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 2.f).IsEmpty());
+ EXPECT_TRUE(BoxF(1.f, 2.f, 3.f, 0.f, 0.f, 2.f).IsEmpty());
+
+ EXPECT_FALSE(BoxF(0.f, 0.f, 0.f, 0.f, 2.f, 2.f).IsEmpty());
+ EXPECT_FALSE(BoxF(1.f, 2.f, 3.f, 0.f, 2.f, 2.f).IsEmpty());
+ EXPECT_FALSE(BoxF(0.f, 0.f, 0.f, 2.f, 0.f, 2.f).IsEmpty());
+ EXPECT_FALSE(BoxF(1.f, 2.f, 3.f, 2.f, 0.f, 2.f).IsEmpty());
+ EXPECT_FALSE(BoxF(0.f, 0.f, 0.f, 2.f, 2.f, 0.f).IsEmpty());
+ EXPECT_FALSE(BoxF(1.f, 2.f, 3.f, 2.f, 2.f, 0.f).IsEmpty());
+
+ EXPECT_FALSE(BoxF(0.f, 0.f, 0.f, 2.f, 2.f, 2.f).IsEmpty());
+ EXPECT_FALSE(BoxF(1.f, 2.f, 3.f, 2.f, 2.f, 2.f).IsEmpty());
+}
+
+TEST(BoxTest, Union) {
+ BoxF empty_box;
+ BoxF box1(0.f, 0.f, 0.f, 1.f, 1.f, 1.f);
+ BoxF box2(0.f, 0.f, 0.f, 4.f, 6.f, 8.f);
+ BoxF box3(3.f, 4.f, 5.f, 6.f, 4.f, 0.f);
+
+ EXPECT_EQ(empty_box.ToString(), UnionBoxes(empty_box, empty_box).ToString());
+ EXPECT_EQ(box1.ToString(), UnionBoxes(empty_box, box1).ToString());
+ EXPECT_EQ(box1.ToString(), UnionBoxes(box1, empty_box).ToString());
+ EXPECT_EQ(box2.ToString(), UnionBoxes(empty_box, box2).ToString());
+ EXPECT_EQ(box2.ToString(), UnionBoxes(box2, empty_box).ToString());
+ EXPECT_EQ(box3.ToString(), UnionBoxes(empty_box, box3).ToString());
+ EXPECT_EQ(box3.ToString(), UnionBoxes(box3, empty_box).ToString());
+
+ // box_1 is contained in box_2
+ EXPECT_EQ(box2.ToString(), UnionBoxes(box1, box2).ToString());
+ EXPECT_EQ(box2.ToString(), UnionBoxes(box2, box1).ToString());
+
+ // box_1 and box_3 are disjoint
+ EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 9.f, 8.f, 5.f).ToString(),
+ UnionBoxes(box1, box3).ToString());
+ EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 9.f, 8.f, 5.f).ToString(),
+ UnionBoxes(box3, box1).ToString());
+
+ // box_2 and box_3 intersect, but neither contains the other
+ EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 9.f, 8.f, 8.f).ToString(),
+ UnionBoxes(box2, box3).ToString());
+ EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 9.f, 8.f, 8.f).ToString(),
+ UnionBoxes(box3, box2).ToString());
+}
+
+TEST(BoxTest, Scale) {
+ BoxF box1(2.f, 3.f, 4.f, 5.f, 6.f, 7.f);
+
+ EXPECT_EQ(BoxF().ToString(), ScaleBox(box1, 0.f).ToString());
+ EXPECT_EQ(box1.ToString(), ScaleBox(box1, 1.f).ToString());
+ EXPECT_EQ(BoxF(4.f, 12.f, 24.f, 10.f, 24.f, 42.f).ToString(),
+ ScaleBox(box1, 2.f, 4.f, 6.f).ToString());
+
+ BoxF box2 = box1;
+ box2.Scale(0.f);
+ EXPECT_EQ(BoxF().ToString(), box2.ToString());
+
+ box2 = box1;
+ box2.Scale(1.f);
+ EXPECT_EQ(box1.ToString(), box2.ToString());
+
+ box2.Scale(2.f, 4.f, 6.f);
+ EXPECT_EQ(BoxF(4.f, 12.f, 24.f, 10.f, 24.f, 42.f).ToString(),
+ box2.ToString());
+}
+
+TEST(BoxTest, Equals) {
+ EXPECT_TRUE(BoxF() == BoxF());
+ EXPECT_TRUE(BoxF(2.f, 3.f, 4.f, 6.f, 8.f, 10.f) ==
+ BoxF(2.f, 3.f, 4.f, 6.f, 8.f, 10.f));
+ EXPECT_FALSE(BoxF() == BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 1.f));
+ EXPECT_FALSE(BoxF() == BoxF(0.f, 0.f, 0.f, 0.f, 1.f, 0.f));
+ EXPECT_FALSE(BoxF() == BoxF(0.f, 0.f, 0.f, 1.f, 0.f, 0.f));
+ EXPECT_FALSE(BoxF() == BoxF(0.f, 0.f, 1.f, 0.f, 0.f, 0.f));
+ EXPECT_FALSE(BoxF() == BoxF(0.f, 1.f, 0.f, 0.f, 0.f, 0.f));
+ EXPECT_FALSE(BoxF() == BoxF(1.f, 0.f, 0.f, 0.f, 0.f, 0.f));
+}
+
+TEST(BoxTest, NotEquals) {
+ EXPECT_FALSE(BoxF() != BoxF());
+ EXPECT_FALSE(BoxF(2.f, 3.f, 4.f, 6.f, 8.f, 10.f) !=
+ BoxF(2.f, 3.f, 4.f, 6.f, 8.f, 10.f));
+ EXPECT_TRUE(BoxF() != BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 1.f));
+ EXPECT_TRUE(BoxF() != BoxF(0.f, 0.f, 0.f, 0.f, 1.f, 0.f));
+ EXPECT_TRUE(BoxF() != BoxF(0.f, 0.f, 0.f, 1.f, 0.f, 0.f));
+ EXPECT_TRUE(BoxF() != BoxF(0.f, 0.f, 1.f, 0.f, 0.f, 0.f));
+ EXPECT_TRUE(BoxF() != BoxF(0.f, 1.f, 0.f, 0.f, 0.f, 0.f));
+ EXPECT_TRUE(BoxF() != BoxF(1.f, 0.f, 0.f, 0.f, 0.f, 0.f));
+}
+
+
+TEST(BoxTest, Offset) {
+ BoxF box1(2.f, 3.f, 4.f, 5.f, 6.f, 7.f);
+
+ EXPECT_EQ(box1.ToString(), (box1 + Vector3dF(0.f, 0.f, 0.f)).ToString());
+ EXPECT_EQ(BoxF(3.f, 1.f, 0.f, 5.f, 6.f, 7.f).ToString(),
+ (box1 + Vector3dF(1.f, -2.f, -4.f)).ToString());
+
+ BoxF box2 = box1;
+ box2 += Vector3dF(0.f, 0.f, 0.f);
+ EXPECT_EQ(box1.ToString(), box2.ToString());
+
+ box2 += Vector3dF(1.f, -2.f, -4.f);
+ EXPECT_EQ(BoxF(3.f, 1.f, 0.f, 5.f, 6.f, 7.f).ToString(),
+ box2.ToString());
+}
+
+} // namespace gfx
diff --git a/ui/gfx/font_list.cc b/ui/gfx/font_list.cc
index cb6cc97..e01483a 100644
--- a/ui/gfx/font_list.cc
+++ b/ui/gfx/font_list.cc
@@ -70,37 +70,60 @@
namespace gfx {
-FontList::FontList() : common_height_(-1), common_baseline_(-1) {
+FontList::FontList()
+ : common_height_(-1),
+ common_baseline_(-1),
+ font_style_(-1),
+ font_size_(-1) {
fonts_.push_back(Font());
}
FontList::FontList(const std::string& font_description_string)
: font_description_string_(font_description_string),
common_height_(-1),
- common_baseline_(-1) {
+ common_baseline_(-1),
+ font_style_(-1),
+ font_size_(-1) {
DCHECK(!font_description_string.empty());
// DCHECK description string ends with "px" for size in pixel.
DCHECK(EndsWith(font_description_string, "px", true));
}
+FontList::FontList(const std::vector<std::string>& font_names,
+ int font_style,
+ int font_size)
+ : font_description_string_(BuildFontDescription(font_names, font_style,
+ font_size)),
+ common_height_(-1),
+ common_baseline_(-1),
+ font_style_(font_style),
+ font_size_(font_size) {
+ DCHECK(!font_names.empty());
+ DCHECK(!font_names[0].empty());
+}
+
FontList::FontList(const std::vector<Font>& fonts)
: fonts_(fonts),
common_height_(-1),
- common_baseline_(-1) {
+ common_baseline_(-1),
+ font_style_(-1),
+ font_size_(-1) {
DCHECK(!fonts.empty());
+ font_style_ = fonts[0].GetStyle();
+ font_size_ = fonts[0].GetFontSize();
if (DCHECK_IS_ON()) {
- int style = fonts[0].GetStyle();
- int size = fonts[0].GetFontSize();
for (size_t i = 1; i < fonts.size(); ++i) {
- DCHECK_EQ(fonts[i].GetStyle(), style);
- DCHECK_EQ(fonts[i].GetFontSize(), size);
+ DCHECK_EQ(fonts[i].GetStyle(), font_style_);
+ DCHECK_EQ(fonts[i].GetFontSize(), font_size_);
}
}
}
FontList::FontList(const Font& font)
: common_height_(-1),
- common_baseline_(-1) {
+ common_baseline_(-1),
+ font_style_(-1),
+ font_size_(-1) {
fonts_.push_back(font);
}
@@ -108,89 +131,74 @@
}
FontList FontList::DeriveFontList(int font_style) const {
- // If there is a font vector, derive from that.
- if (!fonts_.empty()) {
- std::vector<Font> fonts = fonts_;
- for (size_t i = 0; i < fonts.size(); ++i)
- fonts[i] = fonts[i].DeriveFont(0, font_style);
- return FontList(fonts);
- }
-
- // Otherwise, parse the font description string to derive from it.
- std::vector<std::string> font_names;
- int old_style;
- int font_size;
- ParseFontDescriptionString(font_description_string_, &font_names,
- &old_style, &font_size);
- return FontList(BuildFontDescription(font_names, font_style, font_size));
+ return DeriveFontListWithSizeDeltaAndStyle(0, font_style);
}
FontList FontList::DeriveFontListWithSize(int size) const {
DCHECK_GT(size, 0);
+ return DeriveFontListWithSizeDeltaAndStyle(size - GetFontSize(),
+ GetFontStyle());
+}
+FontList FontList::DeriveFontListWithSizeDelta(int size_delta) const {
+ return DeriveFontListWithSizeDeltaAndStyle(size_delta, GetFontStyle());
+}
+
+FontList FontList::DeriveFontListWithSizeDeltaAndStyle(int size_delta,
+ int style) const {
// If there is a font vector, derive from that.
- int old_size = 0;
if (!fonts_.empty()) {
- old_size = fonts_[0].GetFontSize();
- if (old_size == size)
- return FontList(fonts_);
-
std::vector<Font> fonts = fonts_;
for (size_t i = 0; i < fonts.size(); ++i)
- fonts[i] = fonts[i].DeriveFont(size - old_size);
+ fonts[i] = fonts[i].DeriveFont(size_delta, style);
return FontList(fonts);
}
// Otherwise, parse the font description string to derive from it.
std::vector<std::string> font_names;
- int font_style = 0;
+ int old_size;
+ int old_style;
ParseFontDescriptionString(font_description_string_, &font_names,
- &font_style, &old_size);
-
- if (old_size == size)
- return FontList(font_description_string_);
-
- return FontList(BuildFontDescription(font_names, font_style, size));
+ &old_style, &old_size);
+ int size = old_size + size_delta;
+ DCHECK_GT(size, 0);
+ return FontList(font_names, style, size);
}
int FontList::GetHeight() const {
- if (common_height_ < 0) {
- int ascent = 0;
- int descent = 0;
- const std::vector<Font>& fonts = GetFonts();
- for (std::vector<Font>::const_iterator i = fonts.begin();
- i != fonts.end(); ++i) {
- ascent = std::max(ascent, i->GetBaseline());
- descent = std::max(descent, i->GetHeight() - i->GetBaseline());
- }
- common_height_ = ascent + descent;
- }
+ if (common_height_ == -1)
+ CacheCommonFontHeightAndBaseline();
return common_height_;
}
int FontList::GetBaseline() const {
- if (common_baseline_ < 0) {
- int baseline = 0;
- const std::vector<Font>& fonts = GetFonts();
- for (std::vector<Font>::const_iterator i = fonts.begin();
- i != fonts.end(); ++i) {
- baseline = std::max(baseline, i->GetBaseline());
- }
- common_baseline_ = baseline;
- }
+ if (common_baseline_ == -1)
+ CacheCommonFontHeightAndBaseline();
return common_baseline_;
}
-int FontList::GetFontStyle() const {
- if (!fonts_.empty())
- return fonts_[0].GetStyle();
+int FontList::GetStringWidth(const base::string16& text) const {
+ // Rely on the primary font metrics for the time being.
+ // TODO(yukishiino): Not only the first font, all the fonts in the list should
+ // be taken into account to compute the pixels needed to display |text|.
+ // Also this method, including one in Font class, should be deprecated and
+ // client code should call Canvas::GetStringWidth(text, font_list) directly.
+ // Our plan is as follows:
+ // 1. Introduce the FontList version of Canvas::GetStringWidth().
+ // 2. Make client code call Canvas::GetStringWidth().
+ // 3. Retire {Font,FontList}::GetStringWidth().
+ return GetPrimaryFont().GetStringWidth(text);
+}
- std::vector<std::string> font_names;
- int font_style;
- int font_size;
- ParseFontDescriptionString(font_description_string_, &font_names,
- &font_style, &font_size);
- return font_style;
+int FontList::GetExpectedTextWidth(int length) const {
+ // Rely on the primary font metrics for the time being.
+ return GetPrimaryFont().GetExpectedTextWidth(length);
+}
+
+int FontList::GetFontStyle() const {
+ if (font_style_ == -1)
+ CacheFontStyleAndSize();
+ return font_style_;
}
const std::string& FontList::GetFontDescriptionString() const {
@@ -209,15 +217,9 @@
}
int FontList::GetFontSize() const {
- if (!fonts_.empty())
- return fonts_[0].GetFontSize();
-
- std::vector<std::string> font_names;
- int font_style;
- int font_size;
- ParseFontDescriptionString(font_description_string_, &font_names,
- &font_style, &font_size);
- return font_size;
+ if (font_size_ == -1)
+ CacheFontStyleAndSize();
+ return font_size_;
}
const std::vector<Font>& FontList::GetFonts() const {
@@ -225,18 +227,16 @@
DCHECK(!font_description_string_.empty());
std::vector<std::string> font_names;
- int font_style;
- int font_size;
ParseFontDescriptionString(font_description_string_, &font_names,
- &font_style, &font_size);
+ &font_style_, &font_size_);
for (size_t i = 0; i < font_names.size(); ++i) {
DCHECK(!font_names[i].empty());
- Font font(font_names[i], font_size);
- if (font_style == Font::NORMAL)
+ Font font(font_names[i], font_size_);
+ if (font_style_ == Font::NORMAL)
fonts_.push_back(font);
else
- fonts_.push_back(font.DeriveFont(0, font_style));
+ fonts_.push_back(font.DeriveFont(0, font_style_));
}
}
return fonts_;
@@ -246,4 +246,28 @@
return GetFonts()[0];
}
+void FontList::CacheCommonFontHeightAndBaseline() const {
+ int ascent = 0;
+ int descent = 0;
+ const std::vector<Font>& fonts = GetFonts();
+ for (std::vector<Font>::const_iterator i = fonts.begin();
+ i != fonts.end(); ++i) {
+ ascent = std::max(ascent, i->GetBaseline());
+ descent = std::max(descent, i->GetHeight() - i->GetBaseline());
+ }
+ common_height_ = ascent + descent;
+ common_baseline_ = ascent;
+}
+
+void FontList::CacheFontStyleAndSize() const {
+ if (!fonts_.empty()) {
+ font_style_ = fonts_[0].GetStyle();
+ font_size_ = fonts_[0].GetFontSize();
+ } else {
+ std::vector<std::string> font_names;
+ ParseFontDescriptionString(font_description_string_, &font_names,
+ &font_style_, &font_size_);
+ }
+}
+
} // namespace gfx
diff --git a/ui/gfx/font_list.h b/ui/gfx/font_list.h
index 8c1d0f3..22be912 100644
--- a/ui/gfx/font_list.h
+++ b/ui/gfx/font_list.h
@@ -41,6 +41,11 @@
// size.
explicit FontList(const std::string& font_description_string);
+ // Creates a font list from font names, styles and size.
+ FontList(const std::vector<std::string>& font_names,
+ int font_style,
+ int font_size);
+
// Creates a font list from a Font vector.
// All fonts in this vector should have the same style and size.
explicit FontList(const std::vector<Font>& fonts);
@@ -57,6 +62,17 @@
// given font |size| in pixels.
FontList DeriveFontListWithSize(int size) const;
+ // Returns a new FontList with the same font names and style but resized.
+ // |size_delta| is the size in pixels to add to the current font size.
+ FontList DeriveFontListWithSizeDelta(int size_delta) const;
+
+ // Returns a new FontList with the same font names but resized and the given
+ // style. |size_delta| is the size in pixels to add to the current font size.
+ // |font_style| specifies the new style, which is a bitmask of the values:
+ // Font::BOLD, Font::ITALIC and Font::UNDERLINE.
+ FontList DeriveFontListWithSizeDeltaAndStyle(int size_delta,
+ int font_style) const;
+
// Returns the height of this font list, which is max(ascent) + max(descent)
// for all the fonts in the font list.
int GetHeight() const;
@@ -65,6 +81,14 @@
// fonts in the font list.
int GetBaseline() const;
+ // Returns the number of horizontal pixels needed to display |text|.
+ int GetStringWidth(const base::string16& text) const;
+
+ // Returns the expected number of horizontal pixels needed to display the
+ // specified length of characters. Call GetStringWidth() to retrieve the
+ // actual number.
+ int GetExpectedTextWidth(int length) const;
+
// Returns the |gfx::Font::FontStyle| style flags for this font list.
int GetFontStyle() const;
@@ -83,6 +107,13 @@
const Font& GetPrimaryFont() const;
private:
+ // Extracts common font height and baseline into |common_height_| and
+ // |common_baseline_|.
+ void CacheCommonFontHeightAndBaseline() const;
+
+ // Extracts font style and size into |font_style_| and |font_size_|.
+ void CacheFontStyleAndSize() const;
+
// A vector of Font. If FontList is constructed with font description string,
// |fonts_| is not initialized during construction. Instead, it is computed
// lazily when user asked to get the font vector.
@@ -99,6 +130,10 @@
// The cached common height and baseline of the fonts in the font list.
mutable int common_height_;
mutable int common_baseline_;
+
+ // Cached font style and size.
+ mutable int font_style_;
+ mutable int font_size_;
};
} // namespace gfx
diff --git a/ui/gfx/font_list_unittest.cc b/ui/gfx/font_list_unittest.cc
index 170f6e8..a62a13d 100644
--- a/ui/gfx/font_list_unittest.cc
+++ b/ui/gfx/font_list_unittest.cc
@@ -33,16 +33,27 @@
TEST(FontListTest, FontDescString_FromDescString) {
// Test init from font name style size string.
FontList font_list = FontList("Droid Sans serif, Sans serif, 10px");
- const std::string& font_str = font_list.GetFontDescriptionString();
- EXPECT_EQ("Droid Sans serif, Sans serif, 10px", font_str);
+ EXPECT_EQ("Droid Sans serif, Sans serif, 10px",
+ font_list.GetFontDescriptionString());
+}
+
+TEST(FontListTest, FontDescString_FromFontNamesStyleAndSize) {
+ // Test init from font names, style and size.
+ std::vector<std::string> font_names;
+ font_names.push_back("Arial");
+ font_names.push_back("Droid Sans serif");
+ int font_style = Font::BOLD | Font::ITALIC;
+ int font_size = 11;
+ FontList font_list = FontList(font_names, font_style, font_size);
+ EXPECT_EQ("Arial,Droid Sans serif,Bold Italic 11px",
+ font_list.GetFontDescriptionString());
}
TEST(FontListTest, FontDescString_FromFont) {
// Test init from Font.
Font font("Arial", 8);
FontList font_list = FontList(font);
- const std::string& font_str = font_list.GetFontDescriptionString();
- EXPECT_EQ("Arial,8px", font_str);
+ EXPECT_EQ("Arial,8px", font_list.GetFontDescriptionString());
}
TEST(FontListTest, FontDescString_FromFontWithNonNormalStyle) {
@@ -63,8 +74,7 @@
fonts.push_back(font.DeriveFont(0, Font::BOLD));
fonts.push_back(font_1.DeriveFont(-2, Font::BOLD));
FontList font_list = FontList(fonts);
- const std::string& font_str = font_list.GetFontDescriptionString();
- EXPECT_EQ("Arial,Sans serif,Bold 8px", font_str);
+ EXPECT_EQ("Arial,Sans serif,Bold 8px", font_list.GetFontDescriptionString());
}
TEST(FontListTest, Fonts_FromDescString) {
@@ -233,6 +243,52 @@
EXPECT_EQ("Sans serif|5", FontToString(derived_fonts[1]));
}
+TEST(FontListTest, FontDescString_DeriveFontListWithSizeDelta) {
+ FontList font_list = FontList("Arial,Sans serif,Bold 18px");
+
+ FontList derived = font_list.DeriveFontListWithSizeDelta(-8);
+ EXPECT_EQ("Arial,Sans serif,Bold 10px",
+ derived.GetFontDescriptionString());
+}
+
+TEST(FontListTest, Fonts_DeriveFontListWithSizeDelta) {
+ std::vector<Font> fonts;
+ fonts.push_back(gfx::Font("Arial", 18).DeriveFont(0, Font::ITALIC));
+ fonts.push_back(gfx::Font("Sans serif", 18).DeriveFont(0, Font::ITALIC));
+ FontList font_list = FontList(fonts);
+
+ FontList derived = font_list.DeriveFontListWithSizeDelta(-5);
+ const std::vector<Font>& derived_fonts = derived.GetFonts();
+
+ EXPECT_EQ(2U, derived_fonts.size());
+ EXPECT_EQ("Arial|13|italic", FontToString(derived_fonts[0]));
+ EXPECT_EQ("Sans serif|13|italic", FontToString(derived_fonts[1]));
+}
+
+TEST(FontListTest, FontDescString_DeriveFontListWithSizeDeltaAndStyle) {
+ FontList font_list = FontList("Arial,Sans serif,Bold Italic 8px");
+
+ FontList derived =
+ font_list.DeriveFontListWithSizeDeltaAndStyle(10, Font::ITALIC);
+ EXPECT_EQ("Arial,Sans serif,Italic 18px",
+ derived.GetFontDescriptionString());
+}
+
+TEST(FontListTest, Fonts_DeriveFontListWithSizeDeltaAndStyle) {
+ std::vector<Font> fonts;
+ fonts.push_back(gfx::Font("Arial", 8));
+ fonts.push_back(gfx::Font("Sans serif", 8));
+ FontList font_list = FontList(fonts);
+
+ FontList derived =
+ font_list.DeriveFontListWithSizeDeltaAndStyle(5, Font::BOLD);
+ const std::vector<Font>& derived_fonts = derived.GetFonts();
+
+ EXPECT_EQ(2U, derived_fonts.size());
+ EXPECT_EQ("Arial|13|bold", FontToString(derived_fonts[0]));
+ EXPECT_EQ("Sans serif|13|bold", FontToString(derived_fonts[1]));
+}
+
TEST(FontListTest, Fonts_GetHeight_GetBaseline) {
// If a font list has only one font, the height and baseline must be the same.
Font font1("Arial", 16);
diff --git a/ui/gfx/point3_f.h b/ui/gfx/point3_f.h
index 6c45a7d..8c700df 100644
--- a/ui/gfx/point3_f.h
+++ b/ui/gfx/point3_f.h
@@ -24,6 +24,14 @@
~Point3F() {}
+ void Scale(float scale) {
+ Scale(scale, scale, scale);
+ }
+
+ void Scale(float x_scale, float y_scale, float z_scale) {
+ SetPoint(x() * x_scale, y() * y_scale, z() * z_scale);
+ }
+
float x() const { return x_; }
float y() const { return y_; }
float z() const { return z_; }
@@ -38,6 +46,20 @@
z_ = z;
}
+ // Offset the point by the given vector.
+ void operator+=(const Vector3dF& v) {
+ x_ += v.x();
+ y_ += v.y();
+ z_ += v.z();
+ }
+
+ // Offset the point by the given vector's inverse.
+ void operator-=(const Vector3dF& v) {
+ x_ -= v.x();
+ y_ -= v.y();
+ z_ -= v.z();
+ }
+
// Returns the squared euclidean distance between two points.
float SquaredDistanceTo(const Point3F& other) const {
float dx = x_ - other.x_;
@@ -82,6 +104,17 @@
return Point3F(offset.x(), offset.y(), offset.z());
}
+inline Point3F ScalePoint(const Point3F& p,
+ float x_scale,
+ float y_scale,
+ float z_scale) {
+ return Point3F(p.x() * x_scale, p.y() * y_scale, p.z() * z_scale);
+}
+
+inline Point3F ScalePoint(const Point3F& p, float scale) {
+ return ScalePoint(p, scale, scale, scale);
+}
+
} // namespace gfx
#endif // UI_GFX_POINT3_F_H_
diff --git a/ui/gfx/point3_unittest.cc b/ui/gfx/point3_unittest.cc
index 3de4f12..735ffd5 100644
--- a/ui/gfx/point3_unittest.cc
+++ b/ui/gfx/point3_unittest.cc
@@ -30,6 +30,12 @@
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i)
EXPECT_EQ(tests[i].expected.ToString(),
tests[i].actual.ToString());
+
+ a += v1;
+ EXPECT_EQ(Point3F(4.7f, 1.9f, 12.5f).ToString(), a.ToString());
+
+ a -= v2;
+ EXPECT_EQ(Point3F(12.8f, 0.7f, 9.2f).ToString(), a.ToString());
}
TEST(Point3Test, VectorFromPoints) {
@@ -40,4 +46,25 @@
EXPECT_EQ((b - a).ToString(), v1.ToString());
}
+TEST(Point3Test, Scale) {
+ EXPECT_EQ(Point3F().ToString(), ScalePoint(Point3F(), 2.f).ToString());
+ EXPECT_EQ(Point3F().ToString(),
+ ScalePoint(Point3F(), 2.f, 2.f, 2.f).ToString());
+
+ EXPECT_EQ(Point3F(2.f, -2.f, 4.f).ToString(),
+ ScalePoint(Point3F(1.f, -1.f, 2.f), 2.f).ToString());
+ EXPECT_EQ(Point3F(2.f, -3.f, 8.f).ToString(),
+ ScalePoint(Point3F(1.f, -1.f, 2.f), 2.f, 3.f, 4.f).ToString());
+
+ Point3F zero;
+ zero.Scale(2.f);
+ zero.Scale(6.f, 3.f, 1.5f);
+ EXPECT_EQ(Point3F().ToString(), zero.ToString());
+
+ Point3F point(1.f, -1.f, 2.f);
+ point.Scale(2.f);
+ point.Scale(6.f, 3.f, 1.5f);
+ EXPECT_EQ(Point3F(12.f, -6.f, 6.f).ToString(), point.ToString());
+}
+
} // namespace gfx
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 39d3eed..1fcf18c 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -661,15 +661,27 @@
canvas->FillRect(GetCursorBounds(position, true), cursor_color_);
}
-void RenderText::DrawSelectedText(Canvas* canvas) {
+void RenderText::DrawSelectedTextForDrag(Canvas* canvas) {
EnsureLayout();
const std::vector<Rect> sel = GetSubstringBounds(selection());
+
+ // Override the selection color with black, and force the background to be
+ // transparent so that it's rendered without subpixel antialiasing.
+ const bool saved_background_is_transparent = background_is_transparent();
+ const SkColor saved_selection_color = selection_color();
+ set_background_is_transparent(true);
+ set_selection_color(SK_ColorBLACK);
+
for (size_t i = 0; i < sel.size(); ++i) {
canvas->Save();
canvas->ClipRect(sel[i]);
DrawVisualText(canvas);
canvas->Restore();
}
+
+ // Restore saved transparency and selection color.
+ set_selection_color(saved_selection_color);
+ set_background_is_transparent(saved_background_is_transparent);
}
Rect RenderText::GetCursorBounds(const SelectionModel& caret,
diff --git a/ui/gfx/render_text.h b/ui/gfx/render_text.h
index 8a25d13..3427740 100644
--- a/ui/gfx/render_text.h
+++ b/ui/gfx/render_text.h
@@ -300,8 +300,9 @@
// Draws a cursor at |position|.
void DrawCursor(Canvas* canvas, const SelectionModel& position);
- // Draw the selected text without a cursor or selection highlight.
- void DrawSelectedText(Canvas* canvas);
+ // Draw the selected text without a cursor or selection highlight. Subpixel
+ // antialiasing is disabled and foreground color is forced to black.
+ void DrawSelectedTextForDrag(Canvas* canvas);
// Gets the SelectionModel from a visual point in local coordinates.
virtual SelectionModel FindCursorPosition(const Point& point) = 0;
diff --git a/ui/gl/gl.target.darwin-arm.mk b/ui/gl/gl.target.darwin-arm.mk
index 3433b8a..a0c95dd 100644
--- a/ui/gl/gl.target.darwin-arm.mk
+++ b/ui/gl/gl.target.darwin-arm.mk
@@ -195,6 +195,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
@@ -311,6 +312,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/gl/gl.target.darwin-mips.mk b/ui/gl/gl.target.darwin-mips.mk
index 3869ca8..67cc9ee 100644
--- a/ui/gl/gl.target.darwin-mips.mk
+++ b/ui/gl/gl.target.darwin-mips.mk
@@ -194,6 +194,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
@@ -309,6 +310,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/gl/gl.target.darwin-x86.mk b/ui/gl/gl.target.darwin-x86.mk
index 9baa74a..01f345e 100644
--- a/ui/gl/gl.target.darwin-x86.mk
+++ b/ui/gl/gl.target.darwin-x86.mk
@@ -197,6 +197,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -315,6 +316,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/gl/gl.target.linux-arm.mk b/ui/gl/gl.target.linux-arm.mk
index 3433b8a..a0c95dd 100644
--- a/ui/gl/gl.target.linux-arm.mk
+++ b/ui/gl/gl.target.linux-arm.mk
@@ -195,6 +195,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
@@ -311,6 +312,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/gl/gl.target.linux-mips.mk b/ui/gl/gl.target.linux-mips.mk
index 3869ca8..67cc9ee 100644
--- a/ui/gl/gl.target.linux-mips.mk
+++ b/ui/gl/gl.target.linux-mips.mk
@@ -194,6 +194,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
@@ -309,6 +310,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/gl/gl.target.linux-x86.mk b/ui/gl/gl.target.linux-x86.mk
index 9baa74a..01f345e 100644
--- a/ui/gl/gl.target.linux-x86.mk
+++ b/ui/gl/gl.target.linux-x86.mk
@@ -197,6 +197,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -315,6 +316,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/gl/vsync_provider.h b/ui/gl/vsync_provider.h
index f76cacc..b9cef7a 100644
--- a/ui/gl/vsync_provider.h
+++ b/ui/gl/vsync_provider.h
@@ -10,10 +10,11 @@
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/time/time.h"
+#include "ui/gl/gl_export.h"
namespace gfx {
-class VSyncProvider {
+class GL_EXPORT VSyncProvider {
public:
VSyncProvider();
virtual ~VSyncProvider();
diff --git a/ui/keyboard/keyboard_controller_unittest.cc b/ui/keyboard/keyboard_controller_unittest.cc
index b0b4001..49c695a 100644
--- a/ui/keyboard/keyboard_controller_unittest.cc
+++ b/ui/keyboard/keyboard_controller_unittest.cc
@@ -123,6 +123,9 @@
virtual ui::TextInputType GetTextInputType() const OVERRIDE {
return type_;
}
+ virtual ui::TextInputMode GetTextInputMode() const OVERRIDE {
+ return ui::TEXT_INPUT_MODE_DEFAULT;
+ }
virtual bool CanComposeInline() const OVERRIDE { return false; }
virtual gfx::Rect GetCaretBounds() OVERRIDE { return gfx::Rect(); }
@@ -170,6 +173,7 @@
}
virtual void TearDown() OVERRIDE {
+ focus_controller_.reset();
aura_test_helper_->TearDown();
}
diff --git a/ui/keyboard/keyboard_util.cc b/ui/keyboard/keyboard_util.cc
index 076eacf..1579068 100644
--- a/ui/keyboard/keyboard_util.cc
+++ b/ui/keyboard/keyboard_util.cc
@@ -64,6 +64,45 @@
return true;
}
+// TODO(varunjain): It would be cleaner to have something in the
+// ui::TextInputClient interface, say MoveCaretInDirection(). The code in
+// here would get the ui::InputMethod from the root_window, and the
+// ui::TextInputClient from that (see above in InsertText()).
+bool MoveCursor(int swipe_direction,
+ int modifier_flags,
+ aura::RootWindow* root_window) {
+ if (!root_window)
+ return false;
+ ui::KeyboardCode codex = ui::VKEY_UNKNOWN;
+ ui::KeyboardCode codey = ui::VKEY_UNKNOWN;
+ if (swipe_direction & kCursorMoveRight)
+ codex = ui::VKEY_RIGHT;
+ else if (swipe_direction & kCursorMoveLeft)
+ codex = ui::VKEY_LEFT;
+
+ if (swipe_direction & kCursorMoveUp)
+ codey = ui::VKEY_UP;
+ else if (swipe_direction & kCursorMoveDown)
+ codey = ui::VKEY_DOWN;
+
+ // First deal with the x movement.
+ if (codex != ui::VKEY_UNKNOWN) {
+ ui::KeyEvent press_event(ui::ET_KEY_PRESSED, codex, modifier_flags, 0);
+ root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&press_event);
+ ui::KeyEvent release_event(ui::ET_KEY_RELEASED, codex, modifier_flags, 0);
+ root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&release_event);
+ }
+
+ // Then deal with the y movement.
+ if (codey != ui::VKEY_UNKNOWN) {
+ ui::KeyEvent press_event(ui::ET_KEY_PRESSED, codey, modifier_flags, 0);
+ root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&press_event);
+ ui::KeyEvent release_event(ui::ET_KEY_RELEASED, codey, modifier_flags, 0);
+ root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&release_event);
+ }
+ return true;
+}
+
const GritResourceMap* GetKeyboardExtensionResources(size_t* size) {
// This looks a lot like the contents of a resource map; however it is
// necessary to have a custom path for the extension path, so the resource
diff --git a/ui/keyboard/keyboard_util.h b/ui/keyboard/keyboard_util.h
index 0fc60ff..7d46433 100644
--- a/ui/keyboard/keyboard_util.h
+++ b/ui/keyboard/keyboard_util.h
@@ -17,6 +17,14 @@
namespace keyboard {
+// Enumeration of swipe directions.
+enum CursorMoveDirection {
+ kCursorMoveRight = 0x01,
+ kCursorMoveLeft = 0x02,
+ kCursorMoveUp = 0x04,
+ kCursorMoveDown = 0x08
+};
+
// Returns true if the virtual keyboard is enabled.
KEYBOARD_EXPORT bool IsKeyboardEnabled();
@@ -27,6 +35,12 @@
KEYBOARD_EXPORT bool InsertText(const base::string16& text,
aura::RootWindow* root_window);
+// Move cursor when swipe on the virtualkeyboard. Returns true if cursor was
+// successfully moved according to |swipe_direction|.
+KEYBOARD_EXPORT bool MoveCursor(int swipe_direction,
+ int modifier_flags,
+ aura::RootWindow* root_window);
+
// Get the list of keyboard resources. |size| is populated with the number of
// resources in the returned array.
KEYBOARD_EXPORT const GritResourceMap* GetKeyboardExtensionResources(
diff --git a/ui/keyboard/resources/api_adapter.js b/ui/keyboard/resources/api_adapter.js
index cd64f57..eb95e35 100644
--- a/ui/keyboard/resources/api_adapter.js
+++ b/ui/keyboard/resources/api_adapter.js
@@ -11,3 +11,8 @@
function insertText(text) {
chrome.experimental.input.virtualKeyboard.insertText(text, logIfError);
}
+
+function MoveCursor(swipe_direction, swipe_flags) {
+ chrome.experimental.input.virtualKeyboard.moveCursor(swipe_direction,
+ swipe_flags);
+}
diff --git a/ui/keyboard/resources/elements/kb-key.html b/ui/keyboard/resources/elements/kb-key.html
index b8bbd4d..fc366bb 100644
--- a/ui/keyboard/resources/elements/kb-key.html
+++ b/ui/keyboard/resources/elements/kb-key.html
@@ -40,6 +40,7 @@
detail.nextKeyset = this.keysetRules.dbl[NEXT_KEYSET - OFFSET];
}
this.fire('enable-dbl', detail);
+ this.fire('enable-sel');
}
});
</script>
diff --git a/ui/keyboard/resources/elements/kb-keyboard.html b/ui/keyboard/resources/elements/kb-keyboard.html
index d21edf0..f4efb31 100644
--- a/ui/keyboard/resources/elements/kb-keyboard.html
+++ b/ui/keyboard/resources/elements/kb-keyboard.html
@@ -6,6 +6,7 @@
<polymer-element name="kb-keyboard" on-key-over="keyOver" on-key-up="keyUp"
on-key-down="keyDown" on-key-longpress="keyLongpress" on-pointerup="up"
+ on-pointerdown="down" on-enable-sel="enableSel"
on-enable-dbl="enableDbl" attributes="keyset layout rows">
<template>
<style>
@@ -60,6 +61,7 @@
* A structure to track the currently repeating key on the keyboard.
*/
var repeatKey = {
+
/**
* The timer for the delay before repeating behaviour begins.
* @type {number|undefined}
@@ -90,14 +92,97 @@
}
};
+ /**
+ * The minimum movement interval needed to trigger cursor move on
+ * horizontal and vertical way.
+ * @const
+ * @type {number}
+ */
+ var MIN_SWIPE_DIST = 30;
+
+ /**
+ * The flags constants when shift is on. It is according to the EventFlags
+ * in event_constants.h in chromium c++ code.
+ * @const
+ * @type {number}
+ * TODO(zyaozhujun): Might add more flags here according to the defination
+ * in EventFlags.
+ */
+ var SHIFT = 2;
+
+ /**
+ * The boolean to decide if it is swipe in process or finished.
+ * @const
+ * @type {boolean}
+ */
+ var swipeInProgress = false;
+
+ /**
+ * The enumeration of swipe directions.
+ * @const
+ * @type {Enum}
+ */
+ var SWIPE_DIRECTION = {
+ RIGHT: 0x1,
+ LEFT: 0x2,
+ UP: 0x4,
+ DOWN: 0x8
+ };
+
+ /**
+ * A structure to track the current swipe status.
+ */
+ var swipeStatus = {
+
+ /**
+ * The count of horizontal and vertical movement.
+ * @type {number}
+ */
+ offset_x : 0,
+ offset_y : 0,
+
+ /**
+ * Last touch coordinate.
+ * @type {number}
+ */
+ pre_x : 0,
+ pre_y : 0,
+
+ /**
+ * The flag of current modifier key.
+ * @type {number}
+ */
+ swipeFlags : 0,
+
+ /**
+ * Current swipe direction.
+ * @type {number}
+ */
+ swipeDirection : 0,
+
+ /**
+ * Reset all the values when swipe finished.
+ */
+ resetAll: function() {
+ this.offset_x = 0;
+ this.offset_y = 0;
+ this.pre_x = 0;
+ this.pre_y = 0;
+ this.swipeFlags = 0;
+ this.swipeDirection = 0;
+ }
+ };
+
Polymer('kb-keyboard', {
lastPressedKey: null,
voiceInput_: null,
dblDetail_: null,
dblTimer_: null,
+ swipeHandler: null,
ready: function() {
this.voiceInput_ = new VoiceInput(this);
+ this.swipeHandler = this.onSwipeUpdate.bind(this);
},
/**
@@ -121,6 +206,48 @@
},
/**
+ * This function is bound to swipeHandler. And swipeHandler handle
+ * the pointermove event after pointerdown event happened.
+ * @para {PointerEvent} event.
+ */
+ onSwipeUpdate: function(event) {
+ swipeStatus.offset_x += event.screenX - swipeStatus.pre_x;
+ swipeStatus.offset_y += event.screenY - swipeStatus.pre_y;
+ if (Math.abs(swipeStatus.offset_x) > MIN_SWIPE_DIST ||
+ Math.abs(swipeStatus.offset_y) > MIN_SWIPE_DIST) {
+ swipeInProgress = true;
+ this.lastPressedKey.classList.remove('active');
+ }
+ if (swipeStatus.offset_x > MIN_SWIPE_DIST) {
+ swipeStatus.swipeDirection |= SWIPE_DIRECTION.RIGHT;
+ swipeStatus.offset_x = 0;
+ }
+ else if (swipeStatus.offset_x < -MIN_SWIPE_DIST) {
+ swipeStatus.swipeDirection |= SWIPE_DIRECTION.LEFT;
+ swipeStatus.offset_x = 0;
+ }
+ // Swipe vertically only when the swipe reaches the gradient of 45
+ // degree. This can also be larger.
+ if (Math.abs(event.screenY - swipeStatus.pre_y) >
+ Math.abs(event.screenX - swipeStatus.pre_x)) {
+ if (swipeStatus.offset_y > MIN_SWIPE_DIST) {
+ swipeStatus.swipeDirection |= SWIPE_DIRECTION.DOWN;
+ swipeStatus.offset_y = 0;
+ }
+ else if (swipeStatus.offset_y < -MIN_SWIPE_DIST) {
+ swipeStatus.swipeDirection |= SWIPE_DIRECTION.UP;
+ swipeStatus.offset_y = 0;
+ }
+ }
+ if (swipeStatus.swipeDirection) {
+ MoveCursor(swipeStatus.swipeDirection, swipeStatus.swipeFlags);
+ swipeStatus.swipeDirection = 0;
+ }
+ swipeStatus.pre_x = event.screenX;
+ swipeStatus.pre_y = event.screenY;
+ },
+
+ /**
* Handles key-down event that is sent by kb-key-base.
* @param {CustomEvent} event The key-down event dispatched by
* kb-key-base.
@@ -173,12 +300,34 @@
},
/**
+ * Enable the selection while swipe.
+ * @param {CustomEvent} event The enable-dbl event dispatched by
+ * kb-shift-key.
+ */
+ enableSel: function(event) {
+ swipeStatus.swipeFlags = SHIFT;
+ },
+
+ /**
+ * Handles pointerdown event. This is used for swipe selection process.
+ * to get the start pre_x and pre_y. And also add a pointermove handler
+ * to start handling the swipe selection event.
+ * @param {PointerEvent} event The pointerup event that received by
+ * kb-keyboard.
+ */
+ down: function(event) {
+ swipeStatus.pre_x = event.screenX;
+ swipeStatus.pre_y = event.screenY;
+ this.addEventListener("pointermove", this.swipeHandler, false);
+ },
+
+ /**
* Handles pointerup event. This is used for double tap/click events.
* @param {PointerEvent} event The pointerup event that bubbled to
* kb-keyboard.
*/
up: function(event) {
- if(this.dblDetail_) {
+ if (this.dblDetail_) {
this.dblDetail_.clickCount++;
if (this.dblDetail_.clickCount == 2) {
this.keyset = this.dblDetail_.toKeyset;
@@ -188,6 +337,18 @@
this.dblDetail_ = null;
}
}
+
+ // TODO(zyaozhujun): There are some edge cases to deal with later.
+ // (for instance, what if a second finger trigger a down and up
+ // event sequence while swiping).
+ // When pointer up from the screen, a swipe selection session finished,
+ // all the data should be reset to prepare for the next session.
+ if (swipeInProgress) {
+ swipeInProgress = false;
+ swipeStatus.resetAll();
+ }
+ // Remove the pointermove event hander here.
+ this.removeEventListener('pointermove', this.swipeHandler, false);
},
/**
@@ -198,7 +359,8 @@
keyUp: function(event, detail) {
if (this.skipEvent(detail))
return;
-
+ if (swipeInProgress)
+ return;
this.lastPressedKey.classList.remove('active');
if (this.lastPressedKey != event.target)
return;
@@ -226,6 +388,7 @@
switch(char) {
case 'Invalid':
case 'Shift':
+ swipeStatus.swipeFlags = 0;
return;
case 'Microphone':
this.voiceInput_.onDown();
@@ -273,7 +436,7 @@
this.selectDefaultKeyset();
} else {
console.error('Unable to find layout ' + this.layout);
- }
+ }
}
},
diff --git a/ui/message_center/cocoa/notification_controller.mm b/ui/message_center/cocoa/notification_controller.mm
index 4a36ee6..965ba42 100644
--- a/ui/message_center/cocoa/notification_controller.mm
+++ b/ui/message_center/cocoa/notification_controller.mm
@@ -459,6 +459,18 @@
listFrame.origin.y += NSHeight(frame);
progressBarFrame.origin.y += NSHeight(frame);
+ // Make sure that there is a minimum amount of spacing below the icon and
+ // the edge of the frame.
+ CGFloat bottomDelta = NSHeight(rootFrame) - NSHeight([icon_ frame]);
+ if (bottomDelta > 0 && bottomDelta < message_center::kIconBottomPadding) {
+ CGFloat bottomAdjust = message_center::kIconBottomPadding - bottomDelta;
+ rootFrame.size.height += bottomAdjust;
+ titleFrame.origin.y += bottomAdjust;
+ messageFrame.origin.y += bottomAdjust;
+ listFrame.origin.y += bottomAdjust;
+ progressBarFrame.origin.y += bottomAdjust;
+ }
+
[[self view] setFrame:rootFrame];
[title_ setFrame:titleFrame];
[message_ setFrame:messageFrame];
diff --git a/ui/message_center/cocoa/settings_controller.h b/ui/message_center/cocoa/settings_controller.h
index 380ae14..7bce5ab 100644
--- a/ui/message_center/cocoa/settings_controller.h
+++ b/ui/message_center/cocoa/settings_controller.h
@@ -13,6 +13,7 @@
#include "ui/message_center/notifier_settings.h"
@class MCSettingsController;
+@class MCTrayViewController;
namespace message_center {
@@ -43,6 +44,7 @@
@private
scoped_ptr<message_center::NotifierSettingsObserverMac> observer_;
message_center::NotifierSettingsProvider* provider_;
+ MCTrayViewController* trayViewController_; // Weak. Owns us.
// The "Settings" text at the top.
base::scoped_nsobject<NSTextField> settingsText_;
@@ -50,6 +52,9 @@
// The smaller text below the "Settings" text.
base::scoped_nsobject<NSTextField> detailsText_;
+ // The profile switcher.
+ base::scoped_nsobject<NSPopUpButton> groupDropDownButton_;
+
// Container for all the checkboxes.
base::scoped_nsobject<NSScrollView> scrollView_;
@@ -57,13 +62,15 @@
}
// Designated initializer.
-- (id)initWithProvider:(message_center::NotifierSettingsProvider*)provider;
+- (id)initWithProvider:(message_center::NotifierSettingsProvider*)provider
+ trayViewController:(MCTrayViewController*)trayViewController;
@end
// Testing API /////////////////////////////////////////////////////////////////
@interface MCSettingsController (TestingAPI)
+- (NSPopUpButton*)groupDropDownButton;
- (NSScrollView*)scrollView;
@end
diff --git a/ui/message_center/cocoa/settings_controller.mm b/ui/message_center/cocoa/settings_controller.mm
index f34f9f0..8865dd9 100644
--- a/ui/message_center/cocoa/settings_controller.mm
+++ b/ui/message_center/cocoa/settings_controller.mm
@@ -99,6 +99,12 @@
// Returns the NSButton corresponding to the checkbox for |notifiers_[index]|.
- (NSButton*)buttonForNotifierAtIndex:(size_t)index;
+
+// Update the contents view.
+- (void)updateView;
+
+// Handler for the notifier group dropdown menu.
+- (void)notifierGroupSelectionChanged:(id)sender;
@end
namespace message_center {
@@ -110,16 +116,20 @@
[settings_controller_ setIcon:icon.AsNSImage() forNotifierId:notifier_id];
}
-void NotifierSettingsObserverMac::NotifierGroupChanged() {}
+void NotifierSettingsObserverMac::NotifierGroupChanged() {
+ [settings_controller_ updateView];
+}
} // namespace message_center
@implementation MCSettingsController
-- (id)initWithProvider:(message_center::NotifierSettingsProvider*)provider {
+- (id)initWithProvider:(message_center::NotifierSettingsProvider*)provider
+ trayViewController:(MCTrayViewController*)trayViewController {
if ((self = [super initWithNibName:nil bundle:nil])) {
observer_.reset(new message_center::NotifierSettingsObserverMac(self));
provider_ = provider;
+ trayViewController_ = trayViewController;
provider_->AddObserver(observer_.get());
}
return self;
@@ -142,6 +152,11 @@
return label;
}
+- (void)updateView {
+ notifiers_.clear();
+ [trayViewController_ updateSettings];
+}
+
- (void)loadView {
DCHECK(notifiers_.empty());
provider_->GetNotifierList(¬ifiers_);
@@ -187,8 +202,10 @@
[detailsText_ setFont:
[NSFont messageFontOfSize:message_center::kMessageFontSize]];
+ size_t groupCount = provider_->GetNotifierGroupCount();
[detailsText_ setStringValue:l10n_util::GetNSString(
- IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION)];
+ groupCount > 1 ? IDS_MESSAGE_CENTER_SETTINGS_DESCRIPTION_MULTIUSER
+ : IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION)];
[detailsText_ sizeToFit];
subheaderFrame = [detailsText_ frame];
subheaderFrame.origin.y =
@@ -196,6 +213,39 @@
NSHeight(subheaderFrame);
[[self view] addSubview:detailsText_];
+ // Profile switcher is only needed for more than one profile.
+ NSRect dropDownButtonFrame = subheaderFrame;
+ if (groupCount > 1) {
+ dropDownButtonFrame = NSMakeRect(
+ kMarginWidth, kMarginWidth, NSWidth(fullFrame), NSHeight(fullFrame));
+ groupDropDownButton_.reset(
+ [[NSPopUpButton alloc] initWithFrame:dropDownButtonFrame
+ pullsDown:YES]);
+ [groupDropDownButton_ setAction:@selector(notifierGroupSelectionChanged:)];
+ [groupDropDownButton_ setTarget:self];
+ // Add a dummy item for pull-down.
+ [groupDropDownButton_ addItemWithTitle:@""];
+ string16 title;
+ for (size_t i = 0; i < groupCount; ++i) {
+ const message_center::NotifierGroup& group =
+ provider_->GetNotifierGroupAt(i);
+ string16 item = group.login_info.empty() ? group.name : group.login_info;
+ [groupDropDownButton_ addItemWithTitle:base::SysUTF16ToNSString(item)];
+ if (provider_->IsNotifierGroupActiveAt(i)) {
+ title = item;
+ [[groupDropDownButton_ lastItem] setState:NSOnState];
+ }
+ }
+ [groupDropDownButton_ setTitle:base::SysUTF16ToNSString(title)];
+ [groupDropDownButton_ sizeToFit];
+ dropDownButtonFrame = [groupDropDownButton_ frame];
+ dropDownButtonFrame.origin.y =
+ NSMinY(subheaderFrame) - message_center::kTextTopPadding -
+ NSHeight(dropDownButtonFrame);
+ dropDownButtonFrame.size.width = NSWidth(fullFrame) - 2 * kMarginWidth;
+ [[self view] addSubview:groupDropDownButton_];
+ }
+
// Document view for the notifier settings.
CGFloat y = 0;
NSRect documentFrame = NSMakeRect(0, 0, NSWidth(fullFrame), 0);
@@ -233,7 +283,7 @@
NSRect scrollFrame = documentFrame;
scrollFrame.origin.y = kMarginWidth;
CGFloat remainingHeight =
- NSMinY(subheaderFrame) - message_center::kTextTopPadding -
+ NSMinY(dropDownButtonFrame) - message_center::kTextTopPadding -
NSMinY(scrollFrame);
if (NSHeight(documentFrame) < remainingHeight) {
@@ -241,6 +291,7 @@
CGFloat delta = remainingHeight - NSHeight(documentFrame);
headerFrame.origin.y -= delta;
subheaderFrame.origin.y -= delta;
+ dropDownButtonFrame.origin.y -= delta;
fullFrame.size.height -= delta;
} else {
scrollFrame.size.height = remainingHeight;
@@ -266,6 +317,7 @@
[[self view] addSubview:scrollView_];
[settingsText_ setFrame:headerFrame];
[detailsText_ setFrame:subheaderFrame];
+ [groupDropDownButton_ setFrame:dropDownButtonFrame];
}
- (void)checkboxClicked:(id)sender {
@@ -275,6 +327,10 @@
// Testing API /////////////////////////////////////////////////////////////////
+- (NSPopUpButton*)groupDropDownButton {
+ return groupDropDownButton_;
+}
+
- (NSScrollView*)scrollView {
return scrollView_;
}
@@ -305,4 +361,11 @@
return base::mac::ObjCCastStrict<NSButton>(view);
}
+- (void)notifierGroupSelectionChanged:(id)sender {
+ DCHECK_EQ(groupDropDownButton_.get(), sender);
+ NSPopUpButton* button = static_cast<NSPopUpButton*>(sender);
+ // The first item is a dummy item.
+ provider_->SwitchToNotifierGroup([button indexOfSelectedItem] - 1);
+}
+
@end
diff --git a/ui/message_center/cocoa/settings_controller_unittest.mm b/ui/message_center/cocoa/settings_controller_unittest.mm
index d317c31..2e4a491 100644
--- a/ui/message_center/cocoa/settings_controller_unittest.mm
+++ b/ui/message_center/cocoa/settings_controller_unittest.mm
@@ -9,6 +9,12 @@
#include "ui/message_center/fake_notifier_settings_provider.h"
@implementation MCSettingsController (TestingInterface)
+- (NSInteger)profileSwitcherListCount {
+ // Subtract the dummy item.
+ return [self groupDropDownButton] ?
+ [[self groupDropDownButton] numberOfItems] - 1 : 0;
+}
+
- (NSUInteger)scrollViewItemCount {
return [[[[self scrollView] documentView] subviews] count];
}
@@ -26,6 +32,14 @@
namespace {
+NotifierGroup* NewGroup(const std::string& name,
+ const std::string& login_info) {
+ return new NotifierGroup(gfx::Image(),
+ base::UTF8ToUTF16(name),
+ base::UTF8ToUTF16(login_info),
+ true);
+}
+
Notifier* NewNotifier(const std::string& id,
const std::string& title,
bool enabled) {
@@ -44,7 +58,8 @@
FakeNotifierSettingsProvider provider(notifiers);
base::scoped_nsobject<MCSettingsController> controller(
- [[MCSettingsController alloc] initWithProvider:&provider]);
+ [[MCSettingsController alloc] initWithProvider:&provider
+ trayViewController:nil]);
[controller view];
EXPECT_EQ(notifiers.size(), [controller scrollViewItemCount]);
@@ -59,7 +74,8 @@
FakeNotifierSettingsProvider provider(notifiers);
base::scoped_nsobject<MCSettingsController> controller(
- [[MCSettingsController alloc] initWithProvider:&provider]);
+ [[MCSettingsController alloc] initWithProvider:&provider
+ trayViewController:nil]);
[controller view];
NSButton* toggleSecond = [controller bottomMostButton];
@@ -75,4 +91,40 @@
EXPECT_EQ(1, provider.closed_called_count());
}
+TEST_F(CocoaTest, SingleProfile) {
+ // Notifiers are owned by settings controller.
+ std::vector<Notifier*> notifiers;
+ notifiers.push_back(NewNotifier("id", "title", /*enabled=*/true));
+ notifiers.push_back(NewNotifier("id2", "other title", /*enabled=*/false));
+
+ FakeNotifierSettingsProvider provider(notifiers);
+
+ base::scoped_nsobject<MCSettingsController> controller(
+ [[MCSettingsController alloc] initWithProvider:&provider
+ trayViewController:nil]);
+ [controller view];
+
+ EXPECT_EQ(0, [controller profileSwitcherListCount]);
+}
+
+TEST_F(CocoaTest, MultiProfile) {
+ FakeNotifierSettingsProvider provider;
+ std::vector<Notifier*> group1_notifiers;
+ group1_notifiers.push_back(NewNotifier("id", "title", /*enabled=*/true));
+ group1_notifiers.push_back(NewNotifier("id2", "title2", /*enabled=*/false));
+ provider.AddGroup(NewGroup("Group1", "GroupId1"), group1_notifiers);
+ std::vector<Notifier*> group2_notifiers;
+ group2_notifiers.push_back(NewNotifier("id3", "title3", /*enabled=*/true));
+ group2_notifiers.push_back(NewNotifier("id4", "title4", /*enabled=*/false));
+ group2_notifiers.push_back(NewNotifier("id5", "title5", /*enabled=*/false));
+ provider.AddGroup(NewGroup("Group2", "GroupId2"), group2_notifiers);
+
+ base::scoped_nsobject<MCSettingsController> controller(
+ [[MCSettingsController alloc] initWithProvider:&provider
+ trayViewController:nil]);
+ [controller view];
+
+ EXPECT_EQ(2, [controller profileSwitcherListCount]);
+}
+
} // namespace message_center
diff --git a/ui/message_center/cocoa/tray_view_controller.h b/ui/message_center/cocoa/tray_view_controller.h
index 76ce518..e1e9ca2 100644
--- a/ui/message_center/cocoa/tray_view_controller.h
+++ b/ui/message_center/cocoa/tray_view_controller.h
@@ -125,6 +125,10 @@
// Action for the settings button.
- (void)showSettings:(id)sender;
+// Updates the settings dialog in response to contents change due to something
+// like selecting a different profile.
+- (void)updateSettings;
+
// Hides the settings dialog if it's open.
- (void)hideSettings:(id)sender;
diff --git a/ui/message_center/cocoa/tray_view_controller.mm b/ui/message_center/cocoa/tray_view_controller.mm
index 45cb1a4..cf49a95 100644
--- a/ui/message_center/cocoa/tray_view_controller.mm
+++ b/ui/message_center/cocoa/tray_view_controller.mm
@@ -273,7 +273,8 @@
message_center::NotifierSettingsProvider* provider =
messageCenter_->GetNotifierSettingsProvider();
settingsController_.reset(
- [[MCSettingsController alloc] initWithProvider:provider]);
+ [[MCSettingsController alloc] initWithProvider:provider
+ trayViewController:self]);
[[self view] addSubview:[settingsController_ view]];
@@ -291,6 +292,17 @@
[self updateTrayViewAndWindow];
}
+- (void)updateSettings {
+ // TODO(jianli): This class should not be calling -loadView, but instead
+ // should just observe a resize notification.
+ // (http://crbug.com/270251)
+ [[settingsController_ view] removeFromSuperview];
+ [settingsController_ loadView];
+ [[self view] addSubview:[settingsController_ view]];
+
+ [self updateTrayViewAndWindow];
+}
+
- (void)hideSettings:(id)sender {
[scrollView_ setHidden:NO];
diff --git a/ui/message_center/fake_notifier_settings_provider.cc b/ui/message_center/fake_notifier_settings_provider.cc
index 66b193b..d8054ca 100644
--- a/ui/message_center/fake_notifier_settings_provider.cc
+++ b/ui/message_center/fake_notifier_settings_provider.cc
@@ -9,36 +9,62 @@
namespace message_center {
+FakeNotifierSettingsProvider::NotifierGroupItem::NotifierGroupItem() {
+}
+
+FakeNotifierSettingsProvider::NotifierGroupItem::~NotifierGroupItem() {
+}
+
+FakeNotifierSettingsProvider::FakeNotifierSettingsProvider() {
+}
+
FakeNotifierSettingsProvider::FakeNotifierSettingsProvider(
const std::vector<Notifier*>& notifiers)
- : notifiers_(notifiers),
- notifier_group_(gfx::Image(),
- UTF8ToUTF16("Fake name"),
- UTF8ToUTF16("fake@email.com"),
- true),
- closed_called_count_(0) {}
+ : closed_called_count_(0),
+ active_item_index_(0) {
+ NotifierGroupItem item;
+ item.group = new NotifierGroup(gfx::Image(),
+ UTF8ToUTF16("Fake name"),
+ UTF8ToUTF16("fake@email.com"),
+ true);
+ item.notifiers = notifiers;
+ items_.push_back(item);
+}
-FakeNotifierSettingsProvider::~FakeNotifierSettingsProvider() {}
+FakeNotifierSettingsProvider::~FakeNotifierSettingsProvider() {
+ for (size_t i = 0; i < items_.size(); ++i) {
+ delete items_[i].group;
+ }
+}
-size_t FakeNotifierSettingsProvider::GetNotifierGroupCount() const { return 1; }
+size_t FakeNotifierSettingsProvider::GetNotifierGroupCount() const {
+ return items_.size();
+}
const message_center::NotifierGroup&
FakeNotifierSettingsProvider::GetNotifierGroupAt(size_t index) const {
- return notifier_group_;
+ return *(items_[index].group);
}
-void FakeNotifierSettingsProvider::SwitchToNotifierGroup(size_t index) {}
+bool FakeNotifierSettingsProvider::IsNotifierGroupActiveAt(
+ size_t index) const {
+ return active_item_index_ == index;
+}
+
+void FakeNotifierSettingsProvider::SwitchToNotifierGroup(size_t index) {
+ active_item_index_ = index;
+}
const message_center::NotifierGroup&
FakeNotifierSettingsProvider::GetActiveNotifierGroup() const {
- return notifier_group_;
+ return *(items_[active_item_index_].group);
}
void FakeNotifierSettingsProvider::GetNotifierList(
std::vector<Notifier*>* notifiers) {
notifiers->clear();
- for (size_t i = 0; i < notifiers_.size(); ++i)
- notifiers->push_back(notifiers_[i]);
+ for (size_t i = 0; i < items_[active_item_index_].notifiers.size(); ++i)
+ notifiers->push_back(items_[active_item_index_].notifiers[i]);
}
void FakeNotifierSettingsProvider::SetNotifierEnabled(const Notifier& notifier,
@@ -62,6 +88,14 @@
return enabled_[¬ifier];
}
+void FakeNotifierSettingsProvider::AddGroup(
+ NotifierGroup* group, const std::vector<Notifier*>& notifiers) {
+ NotifierGroupItem item;
+ item.group = group;
+ item.notifiers = notifiers;
+ items_.push_back(item);
+}
+
int FakeNotifierSettingsProvider::closed_called_count() {
return closed_called_count_;
}
diff --git a/ui/message_center/fake_notifier_settings_provider.h b/ui/message_center/fake_notifier_settings_provider.h
index f2c5cd7..85348f7 100644
--- a/ui/message_center/fake_notifier_settings_provider.h
+++ b/ui/message_center/fake_notifier_settings_provider.h
@@ -13,12 +13,14 @@
// notifiers and records which callbacks were called. For use in tests.
class FakeNotifierSettingsProvider : public NotifierSettingsProvider {
public:
+ FakeNotifierSettingsProvider();
FakeNotifierSettingsProvider(const std::vector<Notifier*>& notifiers);
virtual ~FakeNotifierSettingsProvider();
virtual size_t GetNotifierGroupCount() const OVERRIDE;
virtual const message_center::NotifierGroup& GetNotifierGroupAt(
size_t index) const OVERRIDE;
+ virtual bool IsNotifierGroupActiveAt(size_t index) const OVERRIDE;
virtual void SwitchToNotifierGroup(size_t index) OVERRIDE;
virtual const message_center::NotifierGroup& GetActiveNotifierGroup() const
OVERRIDE;
@@ -35,11 +37,21 @@
bool WasEnabled(const Notifier& notifier);
int closed_called_count();
+ void AddGroup(NotifierGroup* group, const std::vector<Notifier*>& notifiers);
+
private:
- std::vector<Notifier*> notifiers_;
+ struct NotifierGroupItem {
+ NotifierGroup* group;
+ std::vector<Notifier*> notifiers;
+
+ NotifierGroupItem();
+ ~NotifierGroupItem();
+ };
+
std::map<const Notifier*, bool> enabled_;
- const NotifierGroup notifier_group_;
+ std::vector<NotifierGroupItem> items_;
int closed_called_count_;
+ size_t active_item_index_;
};
} // namespace message_center
diff --git a/ui/message_center/message_center_impl.cc b/ui/message_center/message_center_impl.cc
index 9d73327..c1d0179 100644
--- a/ui/message_center/message_center_impl.cc
+++ b/ui/message_center/message_center_impl.cc
@@ -313,6 +313,11 @@
if (!HasNotification(id))
return;
+ NotificationDelegate* delegate =
+ notification_list_->GetNotificationDelegate(id);
+ if (delegate)
+ delegate->Close(by_user);
+
// In many cases |id| is a reference to an existing notification instance
// but the instance can be destructed in RemoveNotification(). Hence
// copies the id explicitly here.
diff --git a/ui/message_center/message_center_style.cc b/ui/message_center/message_center_style.cc
index 5c8d066..0289a96 100644
--- a/ui/message_center/message_center_style.cc
+++ b/ui/message_center/message_center_style.cc
@@ -31,6 +31,7 @@
const int kNotificationWidth = 360;
const int kIconToTextPadding = 16;
const int kTextTopPadding = 12;
+const int kIconBottomPadding = 16;
// Text sizes.
const int kTitleFontSize = 14;
diff --git a/ui/message_center/message_center_style.h b/ui/message_center/message_center_style.h
index 222a61d..1235363 100644
--- a/ui/message_center/message_center_style.h
+++ b/ui/message_center/message_center_style.h
@@ -39,6 +39,8 @@
extern const int kControlButtonSize; // Square size of close & expand buttons.
extern const int kIconToTextPadding; // H space between icon & title/message.
extern const int kTextTopPadding; // V space between text elements.
+extern const int kIconBottomPadding; // Minimum non-zero V space between icon
+ // and frame.
// Text sizes.
extern const int kTitleFontSize; // For title only.
diff --git a/ui/message_center/notifier_settings.h b/ui/message_center/notifier_settings.h
index 05fc7fe..b8771a3 100644
--- a/ui/message_center/notifier_settings.h
+++ b/ui/message_center/notifier_settings.h
@@ -142,6 +142,9 @@
virtual const message_center::NotifierGroup& GetNotifierGroupAt(
size_t index) const = 0;
+ // Returns true if the notifier group at |index| is active.
+ virtual bool IsNotifierGroupActiveAt(size_t index) const = 0;
+
// Informs the settings provider that further requests to GetNotifierList
// should return notifiers for the specified notifier group.
virtual void SwitchToNotifierGroup(size_t index) = 0;
diff --git a/ui/message_center/views/message_center_button_bar.cc b/ui/message_center/views/message_center_button_bar.cc
index b436bf3..b6ebd81 100644
--- a/ui/message_center/views/message_center_button_bar.cc
+++ b/ui/message_center/views/message_center_button_bar.cc
@@ -29,8 +29,8 @@
namespace {
const int kButtonSize = 40;
-const int kChevronMargin = 4;
-const int kFooterLeftMargin = 17;
+const int kChevronWidth = 8;
+const int kFooterLeftMargin = 20;
const int kFooterRightMargin = 14;
} // namespace
@@ -43,6 +43,7 @@
int hover_id,
int pressed_id,
int text_id);
+ void set_size(gfx::Size size) { size_ = size; }
protected:
// Overridden from views::View:
@@ -50,6 +51,8 @@
virtual void OnPaintFocusBorder(gfx::Canvas* canvas) OVERRIDE;
private:
+ gfx::Size size_;
+
DISALLOW_COPY_AND_ASSIGN(NotificationCenterButton);
};
@@ -59,21 +62,21 @@
int hover_id,
int pressed_id,
int text_id)
- : views::ToggleImageButton(listener) {
+ : views::ToggleImageButton(listener), size_(kButtonSize, kButtonSize) {
ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
SetImage(STATE_NORMAL, resource_bundle.GetImageSkiaNamed(normal_id));
SetImage(STATE_HOVERED, resource_bundle.GetImageSkiaNamed(hover_id));
SetImage(STATE_PRESSED, resource_bundle.GetImageSkiaNamed(pressed_id));
SetImageAlignment(views::ImageButton::ALIGN_CENTER,
views::ImageButton::ALIGN_MIDDLE);
- SetTooltipText(resource_bundle.GetLocalizedString(text_id));
+ if (text_id)
+ SetTooltipText(resource_bundle.GetLocalizedString(text_id));
+
set_focusable(true);
set_request_focus_on_press(false);
}
-gfx::Size NotificationCenterButton::GetPreferredSize() {
- return gfx::Size(kButtonSize, kButtonSize);
-}
+gfx::Size NotificationCenterButton::GetPreferredSize() { return size_; }
void NotificationCenterButton::OnPaintFocusBorder(gfx::Canvas* canvas) {
if (HasFocus() && (focusable() || IsAccessibilityFocusable())) {
@@ -91,22 +94,42 @@
bool settings_initially_visible)
: message_center_view_(message_center_view),
message_center_(message_center),
+ title_arrow_(NULL),
+ notification_label_(NULL),
+ button_container_(NULL),
close_all_button_(NULL),
+ settings_button_(NULL),
quiet_mode_button_(NULL) {
if (get_use_acceleration_when_possible())
SetPaintToLayer(true);
set_background(
views::Background::CreateSolidBackground(kMessageCenterBackgroundColor));
- views::Label* notification_label = new views::Label(
- l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_FOOTER_TITLE));
- notification_label->SetAutoColorReadabilityEnabled(false);
- notification_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- notification_label->SetEnabledColor(kRegularTextColor);
- AddChildView(notification_label);
+ ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
- views::View* button_container = new views::View;
- button_container->SetLayoutManager(
+ title_arrow_ = new NotificationCenterButton(this,
+ IDR_NOTIFICATION_ARROW,
+ IDR_NOTIFICATION_ARROW_HOVER,
+ IDR_NOTIFICATION_ARROW_PRESSED,
+ 0);
+ title_arrow_->set_size(gfx::Size(kChevronWidth, kButtonSize));
+
+ // Keyboardists can use the gear button to switch modes.
+ title_arrow_->set_focusable(false);
+ AddChildView(title_arrow_);
+
+ gfx::Font notification_label_font =
+ ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont);
+ notification_label_ = new views::Label(
+ l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_FOOTER_TITLE),
+ notification_label_font);
+ notification_label_->SetAutoColorReadabilityEnabled(false);
+ notification_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ notification_label_->SetEnabledColor(kRegularTextColor);
+ AddChildView(notification_label_);
+
+ button_container_ = new views::View;
+ button_container_->SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
quiet_mode_button_ = new NotificationCenterButton(
this,
@@ -114,7 +137,6 @@
IDR_NOTIFICATION_DO_NOT_DISTURB_HOVER,
IDR_NOTIFICATION_DO_NOT_DISTURB_PRESSED,
IDS_MESSAGE_CENTER_QUIET_MODE_BUTTON_TOOLTIP);
- ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
quiet_mode_button_->SetToggledImage(
views::Button::STATE_NORMAL,
resource_bundle.GetImageSkiaNamed(
@@ -128,7 +150,7 @@
resource_bundle.GetImageSkiaNamed(
IDR_NOTIFICATION_DO_NOT_DISTURB_PRESSED));
quiet_mode_button_->SetToggled(message_center->IsQuietMode());
- button_container->AddChildView(quiet_mode_button_);
+ button_container_->AddChildView(quiet_mode_button_);
close_all_button_ =
new NotificationCenterButton(this,
@@ -136,15 +158,21 @@
IDR_NOTIFICATION_CLEAR_ALL_HOVER,
IDR_NOTIFICATION_CLEAR_ALL_PRESSED,
IDS_MESSAGE_CENTER_CLEAR_ALL);
- button_container->AddChildView(close_all_button_);
+ button_container_->AddChildView(close_all_button_);
settings_button_ =
new NotificationCenterButton(this,
IDR_NOTIFICATION_SETTINGS,
IDR_NOTIFICATION_SETTINGS_HOVER,
IDR_NOTIFICATION_SETTINGS_PRESSED,
IDS_MESSAGE_CENTER_SETTINGS_BUTTON_LABEL);
- button_container->AddChildView(settings_button_);
+ button_container_->AddChildView(settings_button_);
+ SetCloseAllButtonEnabled(!settings_initially_visible);
+ SetBackArrowVisible(settings_initially_visible);
+ ViewVisibilityChanged();
+}
+
+void MessageCenterButtonBar::ViewVisibilityChanged() {
gfx::ImageSkia* settings_image =
ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
IDR_NOTIFICATION_SETTINGS);
@@ -154,21 +182,42 @@
layout->SetInsets(
0, kFooterLeftMargin, 0, std::max(0, kFooterRightMargin - image_margin));
views::ColumnSet* column = layout->AddColumnSet(0);
- column->AddColumn(views::GridLayout::FILL,
- views::GridLayout::FILL,
- 1.0f,
- views::GridLayout::USE_PREF,
- 0,
- 0);
+ if (title_arrow_->visible()) {
+ // Column for the left-arrow used to back out of settings.
+ column->AddColumn(views::GridLayout::LEADING,
+ views::GridLayout::CENTER,
+ 0.0f,
+ views::GridLayout::USE_PREF,
+ 0,
+ 0);
+
+ column->AddPaddingColumn(0.0f, 10);
+ }
+
+ // Column for the label "Notifications".
column->AddColumn(views::GridLayout::LEADING,
- views::GridLayout::FILL,
- 0,
+ views::GridLayout::CENTER,
+ 0.0f,
views::GridLayout::USE_PREF,
0,
0);
+
+ // Fills in the remaining space between "Notifications" and buttons.
+ column->AddPaddingColumn(1.0f, image_margin);
+
+ // The button area column.
+ column->AddColumn(views::GridLayout::LEADING,
+ views::GridLayout::CENTER,
+ 0.0f,
+ views::GridLayout::USE_PREF,
+ 0,
+ 0);
+
layout->StartRow(0, 0);
- layout->AddView(notification_label);
- layout->AddView(button_container);
+ if (title_arrow_->visible())
+ layout->AddView(title_arrow_);
+ layout->AddView(notification_label_);
+ layout->AddView(button_container_);
}
MessageCenterButtonBar::~MessageCenterButtonBar() {}
@@ -180,9 +229,16 @@
quiet_mode_button_->SetEnabled(enabled);
}
-void MessageCenterButtonBar::SetCloseAllButtonVisible(bool visible) {
+void MessageCenterButtonBar::SetCloseAllButtonEnabled(bool enabled) {
if (close_all_button_)
- close_all_button_->SetVisible(visible);
+ close_all_button_->SetEnabled(enabled);
+}
+
+void MessageCenterButtonBar::SetBackArrowVisible(bool visible) {
+ if (title_arrow_)
+ title_arrow_->SetVisible(visible);
+ ViewVisibilityChanged();
+ Layout();
}
void MessageCenterButtonBar::ChildVisibilityChanged(views::View* child) {
@@ -193,7 +249,7 @@
const ui::Event& event) {
if (sender == close_all_button_) {
message_center_view()->ClearAllNotifications();
- } else if (sender == settings_button_) {
+ } else if (sender == settings_button_ || sender == title_arrow_) {
MessageCenterView* center_view = message_center_view();
center_view->SetSettingsVisible(!center_view->settings_visible());
} else if (sender == quiet_mode_button_) {
diff --git a/ui/message_center/views/message_center_button_bar.h b/ui/message_center/views/message_center_button_bar.h
index 72b30c9..950e25e 100644
--- a/ui/message_center/views/message_center_button_bar.h
+++ b/ui/message_center/views/message_center_button_bar.h
@@ -6,6 +6,7 @@
#define UI_MESSAGE_CENTER_VIEWS_MESSAGE_CENTER_BUTTON_BAR_H_
#include "ui/views/controls/button/button.h"
+#include "ui/views/controls/button/image_button.h"
#include "ui/views/view.h"
namespace views {
@@ -37,9 +38,16 @@
virtual void SetAllButtonsEnabled(bool enabled);
// Sometimes we shouldn't see the close-all button.
- void SetCloseAllButtonVisible(bool visible);
+ void SetCloseAllButtonEnabled(bool enabled);
+
+ // Sometimes we shouldn't see the back arrow (not in settings).
+ void SetBackArrowVisible(bool visible);
private:
+ // Updates the layout manager which can have differing configuration
+ // depending on the visibilty of different parts of the button bar.
+ void ViewVisibilityChanged();
+
// Overridden from views::View:
virtual void ChildVisibilityChanged(views::View* child) OVERRIDE;
@@ -56,6 +64,9 @@
MessageCenter* message_center_; // Weak reference.
// Sub-views of the button bar.
+ NotificationCenterButton* title_arrow_;
+ views::Label* notification_label_;
+ views::View* button_container_;
views::Button* close_all_button_;
NotificationCenterButton* settings_button_;
NotificationCenterButton* quiet_mode_button_;
diff --git a/ui/message_center/views/message_center_view.cc b/ui/message_center/views/message_center_view.cc
index 9f0d2fd..95c2cc3 100644
--- a/ui/message_center/views/message_center_view.cc
+++ b/ui/message_center/views/message_center_view.cc
@@ -611,12 +611,6 @@
initially_settings_visible);
const int button_height = button_bar_->GetPreferredSize().height();
- button_bar_->set_border(views::Border::CreateSolidSidedBorder(
- top_down_ ? 0 : kButtonBarBorderThickness,
- 0,
- top_down_ ? kButtonBarBorderThickness : 0,
- 0,
- kFooterDelimiterColor));
scroller_ =
new BoundedScrollView(kMinScrollViewHeight, max_height - button_height);
@@ -715,8 +709,9 @@
settings_transition_animation_->set_delegate(this);
settings_transition_animation_->set_continuous(false);
settings_transition_animation_->Start();
-}
+ button_bar_->SetBackArrowVisible(visible);
+}
void MessageCenterView::ClearAllNotifications() {
if (is_closing_)
@@ -730,6 +725,7 @@
void MessageCenterView::OnAllNotificationsCleared() {
scroller_->SetEnabled(true);
button_bar_->SetAllButtonsEnabled(true);
+ button_bar_->SetCloseAllButtonEnabled(false);
message_center_->RemoveAllNotifications(true); // Action by user.
}
@@ -776,6 +772,26 @@
width(),
height() - button_height);
+ bool is_scrollable = false;
+ if (scroller_->visible())
+ is_scrollable = scroller_->height() < message_list_view_->height();
+ else
+ is_scrollable = settings_view_->IsScrollable();
+
+ if (is_scrollable && !button_bar_->border()) {
+ // Draw separator line on the top of the button bar if it is on the bottom
+ // or draw it at the bottom if the bar is on the top.
+ button_bar_->set_border(views::Border::CreateSolidSidedBorder(
+ top_down_ ? 0 : 1,
+ 0,
+ top_down_ ? 1 : 0,
+ 0,
+ kFooterDelimiterColor));
+ button_bar_->SchedulePaint();
+ } else if (!is_scrollable && button_bar_->border()) {
+ button_bar_->set_border(NULL);
+ button_bar_->SchedulePaint();
+ }
button_bar_->SetBounds(0,
top_down_ ? 0 : height() - button_height,
width(),
@@ -971,7 +987,7 @@
bool no_message_views = message_views_.empty();
no_notifications_message_view_->SetVisible(no_message_views);
- button_bar_->SetCloseAllButtonVisible(!no_message_views);
+ button_bar_->SetCloseAllButtonEnabled(!no_message_views);
scroller_->set_focusable(!no_message_views);
scroller_->InvalidateLayout();
diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc
index e829bee..abfc1ef 100644
--- a/ui/message_center/views/notification_view.cc
+++ b/ui/message_center/views/notification_view.cc
@@ -35,7 +35,6 @@
// Dimensions.
const int kIconSize = message_center::kNotificationIconSize;
const int kLegacyIconSize = 40;
-const int kIconBottomPadding = 16;
const int kTextLeftPadding = kIconSize + message_center::kIconToTextPadding;
const int kTextBottomPadding = 12;
const int kTextRightPadding = 23;
@@ -607,7 +606,8 @@
// Adjust the height to make sure there is at least 16px of space below the
// icon if there is any space there (<http://crbug.com/232966>).
if (content_height > kIconSize)
- content_height = std::max(content_height, kIconSize + kIconBottomPadding);
+ content_height = std::max(content_height,
+ kIconSize + message_center::kIconBottomPadding);
return content_height + GetInsets().height();
}
diff --git a/ui/message_center/views/notifier_settings_view.cc b/ui/message_center/views/notifier_settings_view.cc
index b97bc84..b4e1884 100644
--- a/ui/message_center/views/notifier_settings_view.cc
+++ b/ui/message_center/views/notifier_settings_view.cc
@@ -19,7 +19,6 @@
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
-#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/size.h"
#include "ui/message_center/message_center_style.h"
#include "ui/message_center/views/message_center_view.h"
@@ -27,6 +26,7 @@
#include "ui/views/border.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/button/custom_button.h"
+#include "ui/views/controls/button/label_button_border.h"
#include "ui/views/controls/button/menu_button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
@@ -34,6 +34,7 @@
#include "ui/views/controls/scroll_view.h"
#include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/fill_layout.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/widget/widget.h"
@@ -43,11 +44,28 @@
namespace message_center {
namespace {
-
-const int kSpaceInButtonComponents = 16;
-const int kMarginWidth = 16;
-const int kMinimumWindowWidth = 320;
+const int kButtonPainterInsets = 5;
+// We really want the margin to be 20px, but various views are padded by
+// whitespace.
+const int kDesiredMargin = 20;
+// The MenuButton has 2px whitespace built-in.
+const int kMenuButtonInnateMargin = 2;
+const int kMinimumHorizontalMargin = kDesiredMargin - kMenuButtonInnateMargin;
+// The EntryViews' leftmost view is a checkbox with 1px whitespace built in, so
+// the margin for entry views should be one less than the target margin.
+const int kCheckboxInnateMargin = 1;
+const int kEntryMargin = kDesiredMargin - kCheckboxInnateMargin;
+const int kMenuButtonLeftPadding = 12;
+const int kMenuButtonRightPadding = 13;
+const int kMenuButtonVerticalPadding = 9;
+const int kMenuWhitespaceOffset = 2;
const int kMinimumWindowHeight = 480;
+const int kMinimumWindowWidth = 320;
+const int kSettingsTitleBottomMargin = 12;
+const int kSettingsTitleTopMargin = 15;
+const int kSpaceInButtonComponents = 16;
+const int kTitleVerticalMargin = 1;
+const int kTitleElementSpacing = 10;
const int kEntryHeight = kMinimumWindowHeight / 10;
// The view to guarantee the 48px height and place the contents at the
@@ -80,10 +98,10 @@
void EntryView::Layout() {
DCHECK_EQ(1, child_count());
views::View* content = child_at(0);
- int content_width = width() - kMarginWidth * 2;
+ int content_width = width() - kEntryMargin * 2;
int content_height = content->GetHeightForWidth(content_width);
int y = std::max((height() - content_height) / 2, 0);
- content->SetBounds(kMarginWidth, y, content_width, content_height);
+ content->SetBounds(kEntryMargin, y, content_width, content_height);
}
gfx::Size EntryView::GetPreferredSize() {
@@ -120,6 +138,40 @@
} // namespace
+// NotifierGroupMenuButtonBorder ///////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+class NotifierGroupMenuButtonBorder : public views::TextButtonDefaultBorder {
+ public:
+ NotifierGroupMenuButtonBorder();
+
+ private:
+ virtual ~NotifierGroupMenuButtonBorder();
+};
+
+NotifierGroupMenuButtonBorder::NotifierGroupMenuButtonBorder()
+ : views::TextButtonDefaultBorder() {
+ ui::ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+
+ gfx::Insets insets(kButtonPainterInsets,
+ kButtonPainterInsets,
+ kButtonPainterInsets,
+ kButtonPainterInsets);
+
+ set_normal_painter(views::Painter::CreateImagePainter(
+ *rb.GetImageSkiaNamed(IDR_BUTTON_NORMAL), insets));
+ set_hot_painter(views::Painter::CreateImagePainter(
+ *rb.GetImageSkiaNamed(IDR_BUTTON_HOVER), insets));
+ set_pushed_painter(views::Painter::CreateImagePainter(
+ *rb.GetImageSkiaNamed(IDR_BUTTON_PRESSED), insets));
+
+ SetInsets(gfx::Insets(kMenuButtonVerticalPadding,
+ kMenuButtonLeftPadding,
+ kMenuButtonVerticalPadding,
+ kMenuButtonRightPadding));
+}
+
+NotifierGroupMenuButtonBorder::~NotifierGroupMenuButtonBorder() {}
+
// NotifierGroupMenuModel //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
class NotifierGroupMenuModel : public ui::SimpleMenuModel,
@@ -152,21 +204,18 @@
const NotifierGroup& group =
notifier_settings_provider_->GetNotifierGroupAt(i);
- AddItem(i, group.login_info.empty() ? group.name : group.login_info);
-
- gfx::ImageSkia resized_icon = gfx::ImageSkiaOperations::CreateResizedImage(
- *group.icon.ToImageSkia(),
- skia::ImageOperations::RESIZE_BETTER,
- gfx::Size(kSettingsIconSize, kSettingsIconSize));
-
- SetIcon(i, gfx::Image(resized_icon));
+ AddCheckItem(i, group.login_info.empty() ? group.name : group.login_info);
}
}
NotifierGroupMenuModel::~NotifierGroupMenuModel() {}
bool NotifierGroupMenuModel::IsCommandIdChecked(int command_id) const {
- return false;
+ // If there's no provider, assume only one notifier group - the active one.
+ if (!notifier_settings_provider_)
+ return true;
+
+ return notifier_settings_provider_->IsNotifierGroupActiveAt(command_id);
}
bool NotifierGroupMenuModel::IsCommandIdEnabled(int command_id) const {
@@ -268,7 +317,11 @@
};
NotifierSettingsView::NotifierSettingsView(NotifierSettingsProvider* provider)
- : provider_(provider) {
+ : title_arrow_(NULL),
+ title_label_(NULL),
+ notifier_group_selector_(NULL),
+ scroller_(NULL),
+ provider_(provider) {
// |provider_| may be NULL in tests.
if (provider_)
provider_->AddObserver(this);
@@ -280,39 +333,20 @@
if (get_use_acceleration_when_possible())
SetPaintToLayer(true);
- ResourceBundle& bundle = ResourceBundle::GetSharedInstance();
-
- views::View* title_container = new views::View;
- // The title_arrow and title_label aren't aligned well in Windows for the
- // horizontal BoxLayout. That's why GridLayout with vertical alignment is
- // used here.
- views::GridLayout* title_layout = new views::GridLayout(title_container);
- title_container->SetLayoutManager(title_layout);
- views::ColumnSet* columns = title_layout->AddColumnSet(0);
- columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
- 0, views::GridLayout::USE_PREF, 0, 0);
- columns->AddPaddingColumn(0, kMarginWidth);
- columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
- 1, views::GridLayout::USE_PREF, 0, 0);
- title_arrow_ = new views::ImageButton(this);
- title_arrow_->SetImage(views::Button::STATE_NORMAL, bundle.GetImageSkiaNamed(
- IDR_NOTIFICATION_ARROW));
- title_arrow_->SetImage(views::Button::STATE_HOVERED, bundle.GetImageSkiaNamed(
- IDR_NOTIFICATION_ARROW_HOVER));
- title_arrow_->SetImage(views::Button::STATE_PRESSED, bundle.GetImageSkiaNamed(
- IDR_NOTIFICATION_ARROW_PRESSED));
gfx::Font title_font =
ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont);
- views::Label* title_label = new views::Label(
+ title_label_ = new views::Label(
l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_SETTINGS_BUTTON_LABEL),
title_font);
- title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- title_label->SetMultiLine(true);
- title_layout->StartRow(0, 0);
- title_layout->AddView(title_arrow_);
- title_layout->AddView(title_label);
- title_entry_ = new EntryView(title_container);
- AddChildView(title_entry_);
+ title_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ title_label_->SetMultiLine(true);
+ title_label_->set_border(
+ views::Border::CreateEmptyBorder(kSettingsTitleTopMargin,
+ kDesiredMargin,
+ kSettingsTitleBottomMargin,
+ kDesiredMargin));
+
+ AddChildView(title_label_);
scroller_ = new views::ScrollView();
scroller_->SetVerticalScrollBar(new views::OverlayScrollBar(false));
@@ -364,11 +398,24 @@
views::View* contents_title_view = new views::View();
contents_title_view->SetLayoutManager(
- new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 5));
- views::Label* top_label = new views::Label(l10n_util::GetStringUTF16(
- IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION));
+ new views::BoxLayout(views::BoxLayout::kVertical,
+ kMinimumHorizontalMargin,
+ kTitleVerticalMargin,
+ kTitleElementSpacing));
+
+ bool need_account_switcher =
+ provider_ && provider_->GetNotifierGroupCount() > 1;
+ int top_label_resource_id =
+ need_account_switcher ? IDS_MESSAGE_CENTER_SETTINGS_DESCRIPTION_MULTIUSER
+ : IDS_MESSAGE_CENTER_SETTINGS_DIALOG_DESCRIPTION;
+
+ views::Label* top_label =
+ new views::Label(l10n_util::GetStringUTF16(top_label_resource_id));
+
top_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
top_label->SetMultiLine(true);
+ top_label->set_border(views::Border::CreateEmptyBorder(
+ 0, kMenuButtonInnateMargin, 0, kMenuButtonInnateMargin));
contents_title_view->AddChildView(top_label);
string16 notifier_group_text;
@@ -379,10 +426,17 @@
: active_group.login_info;
}
- views::View* notifier_group_selector =
- new views::MenuButton(NULL, notifier_group_text, this, true);
- contents_title_view->AddChildView(notifier_group_selector);
- contents_view->AddChildView(new EntryView(contents_title_view));
+ if (need_account_switcher) {
+ notifier_group_selector_ =
+ new views::MenuButton(NULL, notifier_group_text, this, true);
+ notifier_group_selector_->set_border(new NotifierGroupMenuButtonBorder);
+ notifier_group_selector_->set_focus_border(NULL);
+ notifier_group_selector_->set_animate_on_state_change(false);
+ notifier_group_selector_->set_focusable(true);
+ contents_title_view->AddChildView(notifier_group_selector_);
+ }
+
+ contents_view->AddChildView(contents_title_view);
for (size_t i = 0; i < notifiers.size(); ++i) {
NotifierButton* button = new NotifierButton(notifiers[i], this);
@@ -391,6 +445,7 @@
contents_view->AddChildView(entry);
buttons_.insert(button);
}
+
scroller_->SetContents(contents_view);
contents_view->SetBoundsRect(gfx::Rect(contents_view->GetPreferredSize()));
@@ -398,8 +453,8 @@
}
void NotifierSettingsView::Layout() {
- int title_height = title_entry_->GetHeightForWidth(width());
- title_entry_->SetBounds(0, 0, width(), title_height);
+ int title_height = title_label_->GetHeightForWidth(width());
+ title_label_->SetBounds(0, 0, width(), title_height);
views::View* contents_view = scroller_->contents();
int content_width = width();
@@ -414,8 +469,8 @@
gfx::Size NotifierSettingsView::GetMinimumSize() {
gfx::Size size(kMinimumWindowWidth, kMinimumWindowHeight);
- int total_height = title_entry_->GetPreferredSize().height() +
- scroller_->contents()->GetPreferredSize().height();
+ int total_height = title_label_->GetPreferredSize().height() +
+ scroller_->contents()->GetPreferredSize().height();
if (total_height > kMinimumWindowHeight)
size.Enlarge(scroller_->GetScrollBarWidth(), 0);
return size;
@@ -424,7 +479,7 @@
gfx::Size NotifierSettingsView::GetPreferredSize() {
gfx::Size preferred_size;
std::vector<gfx::Size> child_sizes;
- gfx::Size title_size = title_entry_->GetPreferredSize();
+ gfx::Size title_size = title_label_->GetPreferredSize();
gfx::Size content_size = scroller_->contents()->GetPreferredSize();
return gfx::Size(std::max(title_size.width(), content_size.width()),
title_size.height() + content_size.height());
@@ -467,10 +522,13 @@
notifier_group_menu_model_.reset(new NotifierGroupMenuModel(provider_));
notifier_group_menu_runner_.reset(
new views::MenuRunner(notifier_group_menu_model_.get()));
+ gfx::Rect menu_anchor = source->GetBoundsInScreen();
+ menu_anchor.Inset(
+ gfx::Insets(0, kMenuWhitespaceOffset, 0, kMenuWhitespaceOffset));
if (views::MenuRunner::MENU_DELETED ==
notifier_group_menu_runner_->RunMenuAt(GetWidget(),
- NULL,
- source->GetBoundsInScreen(),
+ notifier_group_selector_,
+ menu_anchor,
views::MenuItemView::BUBBLE_ABOVE,
ui::MENU_SOURCE_MOUSE,
views::MenuRunner::CONTEXT_MENU))
diff --git a/ui/message_center/views/notifier_settings_view.h b/ui/message_center/views/notifier_settings_view.h
index 6fc5b58..5e64ab9 100644
--- a/ui/message_center/views/notifier_settings_view.h
+++ b/ui/message_center/views/notifier_settings_view.h
@@ -16,6 +16,8 @@
#include "ui/views/view.h"
namespace views {
+class Label;
+class MenuButton;
class MenuRunner;
}
@@ -64,7 +66,8 @@
const gfx::Point& point) OVERRIDE;
views::ImageButton* title_arrow_;
- views::View* title_entry_;
+ views::Label* title_label_;
+ views::MenuButton* notifier_group_selector_;
views::ScrollView* scroller_;
NotifierSettingsProvider* provider_;
std::set<NotifierButton*> buttons_;
diff --git a/ui/message_center/views/toast_contents_view.cc b/ui/message_center/views/toast_contents_view.cc
index bb4b7d8..b7dae98 100644
--- a/ui/message_center/views/toast_contents_view.cc
+++ b/ui/message_center/views/toast_contents_view.cc
@@ -84,10 +84,15 @@
}
void ToastContentsView::SetContents(MessageView* view) {
+ bool already_has_contents = child_count() > 0;
RemoveAllChildViews(true);
AddChildView(view);
preferred_size_ = GetToastSizeForView(view);
Layout();
+ // If it has the contents already, this invocation means an update of the
+ // popup toast, and the new contents should be read through a11y feature.
+ if (already_has_contents)
+ NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_FOCUS, false);
}
void ToastContentsView::RevealWithAnimation(gfx::Point origin) {
diff --git a/ui/native_theme/native_theme.target.darwin-arm.mk b/ui/native_theme/native_theme.target.darwin-arm.mk
index 167c94e..74f5245 100644
--- a/ui/native_theme/native_theme.target.darwin-arm.mk
+++ b/ui/native_theme/native_theme.target.darwin-arm.mk
@@ -88,6 +88,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -196,6 +197,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/native_theme/native_theme.target.darwin-mips.mk b/ui/native_theme/native_theme.target.darwin-mips.mk
index 5e7b61c..8594dde 100644
--- a/ui/native_theme/native_theme.target.darwin-mips.mk
+++ b/ui/native_theme/native_theme.target.darwin-mips.mk
@@ -87,6 +87,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -194,6 +195,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/native_theme/native_theme.target.darwin-x86.mk b/ui/native_theme/native_theme.target.darwin-x86.mk
index a0fc1ae..48d6d7a 100644
--- a/ui/native_theme/native_theme.target.darwin-x86.mk
+++ b/ui/native_theme/native_theme.target.darwin-x86.mk
@@ -90,6 +90,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -200,6 +201,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/ui/native_theme/native_theme.target.linux-arm.mk b/ui/native_theme/native_theme.target.linux-arm.mk
index 167c94e..74f5245 100644
--- a/ui/native_theme/native_theme.target.linux-arm.mk
+++ b/ui/native_theme/native_theme.target.linux-arm.mk
@@ -88,6 +88,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -196,6 +197,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/native_theme/native_theme.target.linux-mips.mk b/ui/native_theme/native_theme.target.linux-mips.mk
index 5e7b61c..8594dde 100644
--- a/ui/native_theme/native_theme.target.linux-mips.mk
+++ b/ui/native_theme/native_theme.target.linux-mips.mk
@@ -87,6 +87,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -194,6 +195,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/native_theme/native_theme.target.linux-x86.mk b/ui/native_theme/native_theme.target.linux-x86.mk
index a0fc1ae..48d6d7a 100644
--- a/ui/native_theme/native_theme.target.linux-x86.mk
+++ b/ui/native_theme/native_theme.target.linux-x86.mk
@@ -90,6 +90,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -200,6 +201,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/ui/resources/default_100_percent/common/app_list_tools_hover.png b/ui/resources/default_100_percent/common/app_list_tools_hover.png
index 8a230fa..984b603 100644
--- a/ui/resources/default_100_percent/common/app_list_tools_hover.png
+++ b/ui/resources/default_100_percent/common/app_list_tools_hover.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/app_list_tools_normal.png b/ui/resources/default_100_percent/common/app_list_tools_normal.png
index 99b300e..53653d0 100644
--- a/ui/resources/default_100_percent/common/app_list_tools_normal.png
+++ b/ui/resources/default_100_percent/common/app_list_tools_normal.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/app_list_tools_pressed.png b/ui/resources/default_100_percent/common/app_list_tools_pressed.png
index f439821..6a460a5 100644
--- a/ui/resources/default_100_percent/common/app_list_tools_pressed.png
+++ b/ui/resources/default_100_percent/common/app_list_tools_pressed.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/app_list_tools_hover.png b/ui/resources/default_200_percent/common/app_list_tools_hover.png
index fdff0e2..3db04e8 100644
--- a/ui/resources/default_200_percent/common/app_list_tools_hover.png
+++ b/ui/resources/default_200_percent/common/app_list_tools_hover.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/app_list_tools_normal.png b/ui/resources/default_200_percent/common/app_list_tools_normal.png
index 5200f2a..9a8c506 100644
--- a/ui/resources/default_200_percent/common/app_list_tools_normal.png
+++ b/ui/resources/default_200_percent/common/app_list_tools_normal.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/app_list_tools_pressed.png b/ui/resources/default_200_percent/common/app_list_tools_pressed.png
index ec107e8..089cdba 100644
--- a/ui/resources/default_200_percent/common/app_list_tools_pressed.png
+++ b/ui/resources/default_200_percent/common/app_list_tools_pressed.png
Binary files differ
diff --git a/ui/shell_dialogs.target.darwin-arm.mk b/ui/shell_dialogs.target.darwin-arm.mk
index ba77732..b6c6e59 100644
--- a/ui/shell_dialogs.target.darwin-arm.mk
+++ b/ui/shell_dialogs.target.darwin-arm.mk
@@ -92,6 +92,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -203,6 +204,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/shell_dialogs.target.darwin-mips.mk b/ui/shell_dialogs.target.darwin-mips.mk
index 9aa7cde..271b265 100644
--- a/ui/shell_dialogs.target.darwin-mips.mk
+++ b/ui/shell_dialogs.target.darwin-mips.mk
@@ -91,6 +91,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -201,6 +202,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/shell_dialogs.target.darwin-x86.mk b/ui/shell_dialogs.target.darwin-x86.mk
index a16792b..5159909 100644
--- a/ui/shell_dialogs.target.darwin-x86.mk
+++ b/ui/shell_dialogs.target.darwin-x86.mk
@@ -94,6 +94,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -207,6 +208,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/ui/shell_dialogs.target.linux-arm.mk b/ui/shell_dialogs.target.linux-arm.mk
index ba77732..b6c6e59 100644
--- a/ui/shell_dialogs.target.linux-arm.mk
+++ b/ui/shell_dialogs.target.linux-arm.mk
@@ -92,6 +92,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -203,6 +204,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/shell_dialogs.target.linux-mips.mk b/ui/shell_dialogs.target.linux-mips.mk
index 9aa7cde..271b265 100644
--- a/ui/shell_dialogs.target.linux-mips.mk
+++ b/ui/shell_dialogs.target.linux-mips.mk
@@ -91,6 +91,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -201,6 +202,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/shell_dialogs.target.linux-x86.mk b/ui/shell_dialogs.target.linux-x86.mk
index a16792b..5159909 100644
--- a/ui/shell_dialogs.target.linux-x86.mk
+++ b/ui/shell_dialogs.target.linux-x86.mk
@@ -94,6 +94,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -207,6 +208,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/ui/snapshot/snapshot.target.darwin-arm.mk b/ui/snapshot/snapshot.target.darwin-arm.mk
index 2d904ea..eeea992 100644
--- a/ui/snapshot/snapshot.target.darwin-arm.mk
+++ b/ui/snapshot/snapshot.target.darwin-arm.mk
@@ -83,6 +83,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -191,6 +192,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/snapshot/snapshot.target.darwin-mips.mk b/ui/snapshot/snapshot.target.darwin-mips.mk
index 0b4e165..9334e6a 100644
--- a/ui/snapshot/snapshot.target.darwin-mips.mk
+++ b/ui/snapshot/snapshot.target.darwin-mips.mk
@@ -82,6 +82,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -189,6 +190,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/snapshot/snapshot.target.darwin-x86.mk b/ui/snapshot/snapshot.target.darwin-x86.mk
index cb10e9a..6796eb7 100644
--- a/ui/snapshot/snapshot.target.darwin-x86.mk
+++ b/ui/snapshot/snapshot.target.darwin-x86.mk
@@ -85,6 +85,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -195,6 +196,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/ui/snapshot/snapshot.target.linux-arm.mk b/ui/snapshot/snapshot.target.linux-arm.mk
index 2d904ea..eeea992 100644
--- a/ui/snapshot/snapshot.target.linux-arm.mk
+++ b/ui/snapshot/snapshot.target.linux-arm.mk
@@ -83,6 +83,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -191,6 +192,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/snapshot/snapshot.target.linux-mips.mk b/ui/snapshot/snapshot.target.linux-mips.mk
index 0b4e165..9334e6a 100644
--- a/ui/snapshot/snapshot.target.linux-mips.mk
+++ b/ui/snapshot/snapshot.target.linux-mips.mk
@@ -82,6 +82,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -189,6 +190,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/snapshot/snapshot.target.linux-x86.mk b/ui/snapshot/snapshot.target.linux-x86.mk
index cb10e9a..6796eb7 100644
--- a/ui/snapshot/snapshot.target.linux-x86.mk
+++ b/ui/snapshot/snapshot.target.linux-x86.mk
@@ -85,6 +85,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -195,6 +196,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/ui/surface/surface.target.darwin-arm.mk b/ui/surface/surface.target.darwin-arm.mk
index 3f569ec..597a400 100644
--- a/ui/surface/surface.target.darwin-arm.mk
+++ b/ui/surface/surface.target.darwin-arm.mk
@@ -88,6 +88,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
@@ -202,6 +203,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/surface/surface.target.darwin-mips.mk b/ui/surface/surface.target.darwin-mips.mk
index 821abeb..50836ab 100644
--- a/ui/surface/surface.target.darwin-mips.mk
+++ b/ui/surface/surface.target.darwin-mips.mk
@@ -87,6 +87,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
@@ -200,6 +201,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/surface/surface.target.darwin-x86.mk b/ui/surface/surface.target.darwin-x86.mk
index bab9f0a..e0f8727 100644
--- a/ui/surface/surface.target.darwin-x86.mk
+++ b/ui/surface/surface.target.darwin-x86.mk
@@ -90,6 +90,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -206,6 +207,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/surface/surface.target.linux-arm.mk b/ui/surface/surface.target.linux-arm.mk
index 3f569ec..597a400 100644
--- a/ui/surface/surface.target.linux-arm.mk
+++ b/ui/surface/surface.target.linux-arm.mk
@@ -88,6 +88,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
@@ -202,6 +203,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/surface/surface.target.linux-mips.mk b/ui/surface/surface.target.linux-mips.mk
index 821abeb..50836ab 100644
--- a/ui/surface/surface.target.linux-mips.mk
+++ b/ui/surface/surface.target.linux-mips.mk
@@ -87,6 +87,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
@@ -200,6 +201,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/ui/surface/surface.target.linux-x86.mk b/ui/surface/surface.target.linux-x86.mk
index bab9f0a..e0f8727 100644
--- a/ui/surface/surface.target.linux-x86.mk
+++ b/ui/surface/surface.target.linux-x86.mk
@@ -90,6 +90,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
@@ -206,6 +207,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/ui/ui.gyp b/ui/ui.gyp
index e17d242..2aa50d4 100644
--- a/ui/ui.gyp
+++ b/ui/ui.gyp
@@ -412,6 +412,8 @@
'gfx/android/java_bitmap.h',
'gfx/blit.cc',
'gfx/blit.h',
+ 'gfx/box_f.cc',
+ 'gfx/box_f.h',
'gfx/break_list.h',
'gfx/canvas.cc',
'gfx/canvas.h',
diff --git a/ui/ui.target.darwin-arm.mk b/ui/ui.target.darwin-arm.mk
index f3e940a..dfe1e1a 100644
--- a/ui/ui.target.darwin-arm.mk
+++ b/ui/ui.target.darwin-arm.mk
@@ -89,6 +89,7 @@
ui/gfx/android/device_display_info.cc \
ui/gfx/android/java_bitmap.cc \
ui/gfx/blit.cc \
+ ui/gfx/box_f.cc \
ui/gfx/canvas.cc \
ui/gfx/canvas_android.cc \
ui/gfx/codec/jpeg_codec.cc \
@@ -207,6 +208,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
@@ -324,6 +326,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
diff --git a/ui/ui.target.darwin-mips.mk b/ui/ui.target.darwin-mips.mk
index 7a521ee..01a6fa8 100644
--- a/ui/ui.target.darwin-mips.mk
+++ b/ui/ui.target.darwin-mips.mk
@@ -89,6 +89,7 @@
ui/gfx/android/device_display_info.cc \
ui/gfx/android/java_bitmap.cc \
ui/gfx/blit.cc \
+ ui/gfx/box_f.cc \
ui/gfx/canvas.cc \
ui/gfx/canvas_android.cc \
ui/gfx/codec/jpeg_codec.cc \
@@ -206,6 +207,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
@@ -322,6 +324,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
diff --git a/ui/ui.target.darwin-x86.mk b/ui/ui.target.darwin-x86.mk
index 9c93235..0eba80b 100644
--- a/ui/ui.target.darwin-x86.mk
+++ b/ui/ui.target.darwin-x86.mk
@@ -89,6 +89,7 @@
ui/gfx/android/device_display_info.cc \
ui/gfx/android/java_bitmap.cc \
ui/gfx/blit.cc \
+ ui/gfx/box_f.cc \
ui/gfx/canvas.cc \
ui/gfx/canvas_android.cc \
ui/gfx/codec/jpeg_codec.cc \
@@ -208,6 +209,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
@@ -327,6 +329,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
diff --git a/ui/ui.target.linux-arm.mk b/ui/ui.target.linux-arm.mk
index f3e940a..dfe1e1a 100644
--- a/ui/ui.target.linux-arm.mk
+++ b/ui/ui.target.linux-arm.mk
@@ -89,6 +89,7 @@
ui/gfx/android/device_display_info.cc \
ui/gfx/android/java_bitmap.cc \
ui/gfx/blit.cc \
+ ui/gfx/box_f.cc \
ui/gfx/canvas.cc \
ui/gfx/canvas_android.cc \
ui/gfx/codec/jpeg_codec.cc \
@@ -207,6 +208,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
@@ -324,6 +326,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
diff --git a/ui/ui.target.linux-mips.mk b/ui/ui.target.linux-mips.mk
index 7a521ee..01a6fa8 100644
--- a/ui/ui.target.linux-mips.mk
+++ b/ui/ui.target.linux-mips.mk
@@ -89,6 +89,7 @@
ui/gfx/android/device_display_info.cc \
ui/gfx/android/java_bitmap.cc \
ui/gfx/blit.cc \
+ ui/gfx/box_f.cc \
ui/gfx/canvas.cc \
ui/gfx/canvas_android.cc \
ui/gfx/codec/jpeg_codec.cc \
@@ -206,6 +207,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
@@ -322,6 +324,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
diff --git a/ui/ui.target.linux-x86.mk b/ui/ui.target.linux-x86.mk
index 9c93235..0eba80b 100644
--- a/ui/ui.target.linux-x86.mk
+++ b/ui/ui.target.linux-x86.mk
@@ -89,6 +89,7 @@
ui/gfx/android/device_display_info.cc \
ui/gfx/android/java_bitmap.cc \
ui/gfx/blit.cc \
+ ui/gfx/box_f.cc \
ui/gfx/canvas.cc \
ui/gfx/canvas_android.cc \
ui/gfx/codec/jpeg_codec.cc \
@@ -208,6 +209,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
@@ -327,6 +329,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DCHROME_PNG_WRITE_SUPPORT' \
'-DPNG_USER_CONFIG' \
diff --git a/ui/ui_unittests.gypi b/ui/ui_unittests.gypi
index dc46a55..e62af93 100644
--- a/ui/ui_unittests.gypi
+++ b/ui/ui_unittests.gypi
@@ -108,6 +108,7 @@
'base/resource/data_pack_unittest.cc',
'base/resource/resource_bundle_unittest.cc',
'base/text/text_elider_unittest.cc',
+ 'gfx/box_unittest.cc',
'gfx/codec/png_codec_unittest.cc',
'gfx/color_utils_unittest.cc',
'gfx/display_unittest.cc',
diff --git a/ui/views/bubble/bubble_border.cc b/ui/views/bubble/bubble_border.cc
index 8b9a612..3c9a320 100644
--- a/ui/views/bubble/bubble_border.cc
+++ b/ui/views/bubble/bubble_border.cc
@@ -157,12 +157,13 @@
const int min_with_arrow_thickness = images_->border_thickness +
std::max(images_->arrow_thickness + images_->border_interior_thickness,
images_->border_thickness);
- if (is_arrow_on_horizontal(arrow_))
- size.SetToMax(gfx::Size(min_with_arrow_width, min_with_arrow_thickness));
- else if (has_arrow(arrow_))
- size.SetToMax(gfx::Size(min_with_arrow_thickness, min_with_arrow_width));
- else
+ // Only take arrow image sizes into account when the bubble tip is shown.
+ if (arrow_paint_type_ == PAINT_TRANSPARENT || !has_arrow(arrow_))
size.SetToMax(gfx::Size(min, min));
+ else if (is_arrow_on_horizontal(arrow_))
+ size.SetToMax(gfx::Size(min_with_arrow_width, min_with_arrow_thickness));
+ else
+ size.SetToMax(gfx::Size(min_with_arrow_thickness, min_with_arrow_width));
int x = anchor_rect.x();
int y = anchor_rect.y();
diff --git a/ui/views/bubble/bubble_border_unittest.cc b/ui/views/bubble/bubble_border_unittest.cc
index cb49030..b8838f6 100644
--- a/ui/views/bubble/bubble_border_unittest.cc
+++ b/ui/views/bubble/bubble_border_unittest.cc
@@ -202,4 +202,39 @@
EXPECT_FALSE(BubbleBorder::is_arrow_at_center(BubbleBorder::FLOAT));
}
+TEST_F(BubbleBorderTest, TestMinimalSize) {
+ gfx::Rect anchor = gfx::Rect(100, 100, 20, 20);
+ gfx::Size contents = gfx::Size(10, 10);
+ BubbleBorder b1(BubbleBorder::RIGHT_TOP, BubbleBorder::NO_SHADOW, 0);
+
+ // The height should be much bigger then the requested size + border and
+ // padding since it needs to be able to include the tip bitmap.
+ gfx::Rect visible_tip_1 = b1.GetBounds(anchor, contents);
+ EXPECT_GE(visible_tip_1.height(), 30);
+ EXPECT_LE(visible_tip_1.width(), 30);
+
+ // With the tip being invisible the height should now be much smaller.
+ b1.set_paint_arrow(BubbleBorder::PAINT_TRANSPARENT);
+ gfx::Rect invisible_tip_1 = b1.GetBounds(anchor, contents);
+ EXPECT_LE(invisible_tip_1.height(), 30);
+ EXPECT_LE(invisible_tip_1.width(), 30);
+
+ // When the orientation of the tip changes, the above mentioned tests need to
+ // be reverse for width and height.
+ BubbleBorder b2(BubbleBorder::TOP_RIGHT, BubbleBorder::NO_SHADOW, 0);
+
+ // The width should be much bigger then the requested size + border and
+ // padding since it needs to be able to include the tip bitmap.
+ gfx::Rect visible_tip_2 = b2.GetBounds(anchor, contents);
+ EXPECT_GE(visible_tip_2.width(), 30);
+ EXPECT_LE(visible_tip_2.height(), 30);
+
+ // With the tip being invisible the width should now be much smaller.
+ b2.set_paint_arrow(BubbleBorder::PAINT_TRANSPARENT);
+ gfx::Rect invisible_tip_2 = b2.GetBounds(anchor, contents);
+ EXPECT_LE(invisible_tip_2.width(), 30);
+ EXPECT_LE(invisible_tip_2.height(), 30);
+}
+
+
} // namespace views
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc
index 94d99d2..2bd579d 100644
--- a/ui/views/bubble/bubble_frame_view.cc
+++ b/ui/views/bubble/bubble_frame_view.cc
@@ -54,6 +54,11 @@
// static
const char BubbleFrameView::kViewClassName[] = "BubbleFrameView";
+// static
+gfx::Insets BubbleFrameView::GetTitleInsets() {
+ return gfx::Insets(kTitleTopInset, kTitleLeftInset, kTitleBottomInset, 0);
+}
+
BubbleFrameView::BubbleFrameView(const gfx::Insets& content_margins)
: bubble_border_(NULL),
content_margins_(content_margins),
diff --git a/ui/views/bubble/bubble_frame_view.h b/ui/views/bubble/bubble_frame_view.h
index e39b538..7dc4596 100644
--- a/ui/views/bubble/bubble_frame_view.h
+++ b/ui/views/bubble/bubble_frame_view.h
@@ -25,6 +25,10 @@
// Internal class name.
static const char kViewClassName[];
+ // Insets to make bubble contents align horizontal with the bubble title.
+ // NOTE: this does not take into account whether a title actually exists.
+ static gfx::Insets GetTitleInsets();
+
explicit BubbleFrameView(const gfx::Insets& content_margins);
virtual ~BubbleFrameView();
diff --git a/ui/views/bubble/tray_bubble_view.cc b/ui/views/bubble/tray_bubble_view.cc
index 76a2d42..0d8accd 100644
--- a/ui/views/bubble/tray_bubble_view.cc
+++ b/ui/views/bubble/tray_bubble_view.cc
@@ -33,10 +33,10 @@
// The new theme adjusts the menus / bubbles to be flush with the shelf when
// there is no bubble. These are the offsets which need to be applied.
-const int kArrowOffsetTopBottom = 5;
+const int kArrowOffsetTopBottom = 4;
const int kArrowOffsetLeft = 9;
const int kArrowOffsetRight = -5;
-const int kOffsetLeftRightForTopBottomOrientation = 2;
+const int kOffsetLeftRightForTopBottomOrientation = 5;
} // namespace
@@ -86,8 +86,6 @@
return rect;
}
- // TODO(skuhne): With shelf LR alignment, arrow-less messages get
- // automatically offsetted from an open status menu which needs addressing.
gfx::Size border_size(contents_size);
gfx::Insets insets = GetInsets();
border_size.Enlarge(insets.width(), insets.height());
diff --git a/ui/views/controls/button/button_dropdown.cc b/ui/views/controls/button/button_dropdown.cc
index 32ee4f4..9a699ea 100644
--- a/ui/views/controls/button/button_dropdown.cc
+++ b/ui/views/controls/button/button_dropdown.cc
@@ -12,6 +12,8 @@
#include "ui/base/accessibility/accessible_view_state.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/menu_model.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/screen.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_model_adapter.h"
#include "ui/views/controls/menu/menu_runner.h"
@@ -172,6 +174,14 @@
#if defined(OS_WIN)
int left_bound = GetSystemMetrics(SM_XVIRTUALSCREEN);
+#elif defined(OS_CHROMEOS)
+ // A window won't overlap between displays on ChromeOS.
+ // Use the left bound of the display on which
+ // the menu button exists.
+ gfx::NativeView view = GetWidget()->GetNativeView();
+ gfx::Display display = gfx::Screen::GetScreenFor(
+ view)->GetDisplayNearestWindow(view);
+ int left_bound = display.bounds().x();
#else
int left_bound = 0;
NOTIMPLEMENTED();
diff --git a/ui/views/controls/button/text_button.cc b/ui/views/controls/button/text_button.cc
index aba3941..a02d6b2 100644
--- a/ui/views/controls/button/text_button.cc
+++ b/ui/views/controls/button/text_button.cc
@@ -481,7 +481,7 @@
#if defined(OS_WIN)
// TODO(erg): Either port DrawStringWithHalo to linux or find an
// alternative here.
- canvas->DrawStringWithHalo(text_, font_, text_color, color_highlight_,
+ canvas->DrawStringWithHalo(text_, font_, SK_ColorBLACK, SK_ColorWHITE,
text_bounds.x(), text_bounds.y(), text_bounds.width(),
text_bounds.height(), draw_string_flags);
#else
diff --git a/ui/views/controls/prefix_selector.cc b/ui/views/controls/prefix_selector.cc
index 12208c0..6d6e080 100644
--- a/ui/views/controls/prefix_selector.cc
+++ b/ui/views/controls/prefix_selector.cc
@@ -63,6 +63,10 @@
return ui::TEXT_INPUT_TYPE_TEXT;
}
+ui::TextInputMode PrefixSelector::GetTextInputMode() const {
+ return ui::TEXT_INPUT_MODE_DEFAULT;
+}
+
bool PrefixSelector::CanComposeInline() const {
return false;
}
diff --git a/ui/views/controls/prefix_selector.h b/ui/views/controls/prefix_selector.h
index b587f77..629c306 100644
--- a/ui/views/controls/prefix_selector.h
+++ b/ui/views/controls/prefix_selector.h
@@ -33,6 +33,7 @@
virtual void InsertChar(char16 ch, int flags) OVERRIDE;
virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
virtual ui::TextInputType GetTextInputType() const OVERRIDE;
+ virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
virtual bool CanComposeInline() const OVERRIDE;
virtual gfx::Rect GetCaretBounds() OVERRIDE;
virtual bool GetCompositionCharacterBounds(uint32 index,
diff --git a/ui/views/controls/textfield/native_textfield_views.cc b/ui/views/controls/textfield/native_textfield_views.cc
index 2ac35aa..14831ba 100644
--- a/ui/views/controls/textfield/native_textfield_views.cc
+++ b/ui/views/controls/textfield/native_textfield_views.cc
@@ -457,7 +457,7 @@
data->SetString(GetSelectedText());
scoped_ptr<gfx::Canvas> canvas(
views::GetCanvasForDragImage(textfield_->GetWidget(), size()));
- GetRenderText()->DrawSelectedText(canvas.get());
+ GetRenderText()->DrawSelectedTextForDrag(canvas.get());
drag_utils::SetDragImageOnDataObject(*canvas, size(),
press_pt.OffsetFromOrigin(),
data);
@@ -959,6 +959,10 @@
return textfield_->GetTextInputType();
}
+ui::TextInputMode NativeTextfieldViews::GetTextInputMode() const {
+ return ui::TEXT_INPUT_MODE_DEFAULT;
+}
+
bool NativeTextfieldViews::CanComposeInline() const {
return true;
}
@@ -1409,7 +1413,10 @@
base::TimeDelta time_delta = event.time_stamp() - last_click_time_;
if (time_delta.InMilliseconds() <= GetDoubleClickInterval() &&
!ExceededDragThresholdFromLastClickLocation(event)) {
- aggregated_clicks_ = (aggregated_clicks_ + 1) % 3;
+ // Upon clicking after a triple click, the count should go back to double
+ // click and alternate between double and triple. This assignment maps
+ // 0 to 1, 1 to 2, 2 to 1.
+ aggregated_clicks_ = (aggregated_clicks_ % 2) + 1;
} else {
aggregated_clicks_ = 0;
}
diff --git a/ui/views/controls/textfield/native_textfield_views.h b/ui/views/controls/textfield/native_textfield_views.h
index 98ca71e..3230fb4 100644
--- a/ui/views/controls/textfield/native_textfield_views.h
+++ b/ui/views/controls/textfield/native_textfield_views.h
@@ -185,6 +185,7 @@
virtual void InsertChar(char16 ch, int flags) OVERRIDE;
virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
virtual ui::TextInputType GetTextInputType() const OVERRIDE;
+ virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
virtual bool CanComposeInline() const OVERRIDE;
virtual gfx::Rect GetCaretBounds() OVERRIDE;
virtual bool GetCompositionCharacterBounds(uint32 index,
diff --git a/ui/views/controls/textfield/native_textfield_views_unittest.cc b/ui/views/controls/textfield/native_textfield_views_unittest.cc
index a56905c..adaac20 100644
--- a/ui/views/controls/textfield/native_textfield_views_unittest.cc
+++ b/ui/views/controls/textfield/native_textfield_views_unittest.cc
@@ -816,10 +816,10 @@
textfield_view_->OnMouseReleased(release);
EXPECT_STR_EQ("hello world", textfield_->GetSelectedText());
- // Another click should reset back to single click.
+ // Another click should reset back to double click.
textfield_view_->OnMousePressed(click);
textfield_view_->OnMouseReleased(release);
- EXPECT_TRUE(textfield_->GetSelectedText().empty());
+ EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
}
TEST_F(NativeTextfieldViewsTest, DragToSelect) {
diff --git a/ui/views/ime/input_method_bridge.cc b/ui/views/ime/input_method_bridge.cc
index 34f6e1b..5507647 100644
--- a/ui/views/ime/input_method_bridge.cc
+++ b/ui/views/ime/input_method_bridge.cc
@@ -147,6 +147,11 @@
return client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE;
}
+ui::TextInputMode InputMethodBridge::GetTextInputMode() const {
+ TextInputClient* client = GetTextInputClient();
+ return client ? client->GetTextInputMode() : ui::TEXT_INPUT_MODE_DEFAULT;
+}
+
bool InputMethodBridge::CanComposeInline() const {
TextInputClient* client = GetTextInputClient();
return client ? client->CanComposeInline() : true;
diff --git a/ui/views/ime/input_method_bridge.h b/ui/views/ime/input_method_bridge.h
index 9eace28..03ea567 100644
--- a/ui/views/ime/input_method_bridge.h
+++ b/ui/views/ime/input_method_bridge.h
@@ -58,6 +58,7 @@
virtual void InsertChar(char16 ch, int flags) OVERRIDE;
virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
virtual ui::TextInputType GetTextInputType() const OVERRIDE;
+ virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
virtual bool CanComposeInline() const OVERRIDE;
virtual gfx::Rect GetCaretBounds() OVERRIDE;
virtual bool GetCompositionCharacterBounds(uint32 index,
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 0df5cf4..1870e11 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
@@ -19,7 +19,6 @@
#include "ui/base/x/selection_utils.h"
#include "ui/base/x/x11_util.h"
#include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
-#include "ui/views/widget/desktop_aura/desktop_root_window_host_x11.h"
using aura::client::DragDropDelegate;
using ui::OSExchangeData;
@@ -367,13 +366,11 @@
///////////////////////////////////////////////////////////////////////////////
DesktopDragDropClientAuraX11::DesktopDragDropClientAuraX11(
- views::DesktopRootWindowHostX11* root_window_host,
aura::RootWindow* root_window,
views::DesktopNativeCursorManager* cursor_manager,
Display* xdisplay,
::Window xwindow)
: move_loop_(this),
- root_window_host_(root_window_host),
root_window_(root_window),
xdisplay_(xdisplay),
xwindow_(xwindow),
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
index b473a98..2dee730 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
@@ -45,7 +45,6 @@
namespace views {
class DesktopNativeCursorManager;
-class DesktopRootWindowHostX11;
// Implements drag and drop on X11 for aura. On one side, this class takes raw
// X11 events forwarded from DesktopRootWindowHostLinux, while on the other, it
@@ -56,7 +55,6 @@
public X11WholeScreenMoveLoopDelegate {
public:
DesktopDragDropClientAuraX11(
- views::DesktopRootWindowHostX11* root_window_host,
aura::RootWindow* root_window,
views::DesktopNativeCursorManager* cursor_manager,
Display* xdisplay,
@@ -156,7 +154,6 @@
// X11WholeScreenMoveLoopDelegate interface.
X11WholeScreenMoveLoop move_loop_;
- views::DesktopRootWindowHostX11* root_window_host_;
aura::RootWindow* root_window_;
Display* xdisplay_;
diff --git a/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc b/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
index ee83e26..159ffc1 100644
--- a/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
@@ -390,14 +390,9 @@
void DesktopRootWindowHostWin::SetInactiveRenderingDisabled(
bool disable_inactive) {
- // We call DefWindowProc of WM_NCACTIVATE to paint the caption as active or
- // inactive. This is safe with the only sideeffect being the
- // WM_GETTEXT message which is sent by DefWindowProc to get the text to be
- // displayed on the caption.
- ::DefWindowProc(message_handler_->hwnd(),
- WM_NCACTIVATE,
- !!disable_inactive,
- 0);
+ // Force the non-client area (most notably the title bar) to paint as either
+ // active or inactive, depending on the input.
+ SendMessage(message_handler_->hwnd(), WM_NCACTIVATE, !!disable_inactive, 0);
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc b/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc
index b9656a6..8c4ba7c 100644
--- a/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc
@@ -159,7 +159,23 @@
void DesktopRootWindowHostX11::HandleNativeWidgetActivationChanged(
bool active) {
+ if (active)
+ root_window_host_delegate_->OnHostActivated();
native_widget_delegate_->OnNativeWidgetActivationChanged(active);
+ // If we're not active we need to deactivate the corresponding aura::Window.
+ // This way if a child widget is active it gets correctly deactivated (child
+ // widgets don't get native desktop activation changes, only aura activation
+ // changes).
+ if (!active) {
+ aura::client::ActivationClient* activation_client =
+ aura::client::GetActivationClient(root_window_);
+ if (activation_client) {
+ aura::Window* active_window = activation_client->GetActiveWindow();
+ if (active_window)
+ activation_client->DeactivateWindow(active_window);
+ }
+ }
+
native_widget_delegate_->AsWidget()->GetRootView()->SchedulePaint();
}
@@ -930,7 +946,7 @@
desktop_native_widget_aura_->InstallInputMethodEventFilter(root_window_);
drag_drop_client_.reset(new DesktopDragDropClientAuraX11(
- this, root_window_, desktop_native_cursor_manager, xdisplay_, xwindow_));
+ root_window_, desktop_native_cursor_manager, xdisplay_, xwindow_));
aura::client::SetDragDropClient(root_window_, drag_drop_client_.get());
// TODO(erg): Unify this code once the other consumer goes away.
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index 9e14f20..8c9ad02 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -443,8 +443,8 @@
void NativeWidgetAura::ShowMaximizedWithBounds(
const gfx::Rect& restored_bounds) {
- ShowWithWindowState(ui::SHOW_STATE_MAXIMIZED);
SetRestoreBounds(window_, restored_bounds);
+ ShowWithWindowState(ui::SHOW_STATE_MAXIMIZED);
}
void NativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) {
diff --git a/ui/views/window/non_client_view.h b/ui/views/window/non_client_view.h
index e5be44e..d430578 100644
--- a/ui/views/window/non_client_view.h
+++ b/ui/views/window/non_client_view.h
@@ -107,7 +107,7 @@
// +- views::Widget ------------------------------------+
// | +- views::RootView ------------------------------+ |
// | | +- views::NonClientView ---------------------+ | |
-// | | | +- views::NonClientFrameView subclas ---+ | | |
+// | | | +- views::NonClientFrameView subclass ---+ | | |
// | | | | | | | |
// | | | | << all painting and event receiving >> | | | |
// | | | | << of the non-client areas of a >> | | | |
diff --git a/ui/webui/resources/css/overlay.css b/ui/webui/resources/css/overlay.css
index 7086d54..af47453 100644
--- a/ui/webui/resources/css/overlay.css
+++ b/ui/webui/resources/css/overlay.css
@@ -167,3 +167,13 @@
background-color: rgba(0, 0, 0, 0.5);
}
</if>
+
+.gray-bottom-bar {
+ background-color: #f5f5f5;
+ border-color: #e7e7e7;
+ border-top-style: solid;
+ border-width: 1px;
+ color: #888;
+ display: -webkit-box;
+ padding: 14px 17px;
+}
diff --git a/ui/webui/resources/js/cr/ui/focus_outline_manager.js b/ui/webui/resources/js/cr/ui/focus_outline_manager.js
index fd106c2..5fdbb5d 100644
--- a/ui/webui/resources/js/cr/ui/focus_outline_manager.js
+++ b/ui/webui/resources/js/cr/ui/focus_outline_manager.js
@@ -45,19 +45,13 @@
}, true);
}
- /**
- * The class name to set on the document element.
- * @const
- */
- FocusOutlineManager.CLASS_NAME = CLASS_NAME;
-
FocusOutlineManager.prototype = {
/**
* Whether focus change is triggered by TAB key.
* @type {boolean}
* @private
*/
- focusByKeyboard_: false,
+ focusByKeyboard_: true,
/**
* Whether the focus outline should be visible.
diff --git a/ui/webui/resources/js/cr/ui/list.js b/ui/webui/resources/js/cr/ui/list.js
index 2f7ced9..52f2896 100644
--- a/ui/webui/resources/js/cr/ui/list.js
+++ b/ui/webui/resources/js/cr/ui/list.js
@@ -515,13 +515,15 @@
// When the blur event happens we do not know who is getting focus so we
// delay this a bit until we know if the new focus node is outside the
// list.
+ // We need 51 msec delay because InlineEditableList sets focus after
+ // 50 msec.
var list = this;
var doc = e.target.ownerDocument;
window.setTimeout(function() {
var activeElement = doc.activeElement;
- if (activeElement != doc.body && !list.contains(activeElement))
+ if (!list.contains(activeElement))
list.hasElementFocus = false;
- });
+ }, 51);
},
/**
diff --git a/url/third_party/mozilla/LICENSE.txt b/url/third_party/mozilla/LICENSE.txt
new file mode 100644
index 0000000..ac40837
--- /dev/null
+++ b/url/third_party/mozilla/LICENSE.txt
@@ -0,0 +1,65 @@
+Copyright 2007, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------------------------------------------------------------------
+
+The file url_parse.cc is based on nsURLParsers.cc from Mozilla. This file is
+licensed separately as follows:
+
+The contents of this file are subject to the Mozilla Public License Version
+1.1 (the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+for the specific language governing rights and limitations under the
+License.
+
+The Original Code is mozilla.org code.
+
+The Initial Developer of the Original Code is
+Netscape Communications Corporation.
+Portions created by the Initial Developer are Copyright (C) 1998
+the Initial Developer. All Rights Reserved.
+
+Contributor(s):
+ Darin Fisher (original author)
+
+Alternatively, the contents of this file may be used under the terms of
+either the GNU General Public License Version 2 or later (the "GPL"), or
+the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+in which case the provisions of the GPL or the LGPL are applicable instead
+of those above. If you wish to allow use of your version of this file only
+under the terms of either the GPL or the LGPL, and not to allow others to
+use your version of this file under the terms of the MPL, indicate your
+decision by deleting the provisions above and replace them with the notice
+and other provisions required by the GPL or the LGPL. If you do not delete
+the provisions above, a recipient may use your version of this file under
+the terms of any one of the MPL, the GPL or the LGPL.
diff --git a/url/third_party/mozilla/README.chromium b/url/third_party/mozilla/README.chromium
new file mode 100644
index 0000000..ef396d3
--- /dev/null
+++ b/url/third_party/mozilla/README.chromium
@@ -0,0 +1,8 @@
+Name: url_parse
+URL: http://mxr.mozilla.org/comm-central/source/mozilla/netwerk/base/src/nsURLParsers.cpp
+License: BSD and MPL 1.1/GPL 2.0/LGPL 2.1
+License File: LICENSE.txt
+
+Description:
+
+The file url_parse.cc is based on nsURLParsers.cc from Mozilla.
diff --git a/url/url_parse.cc b/url/third_party/mozilla/url_parse.cc
similarity index 99%
rename from url/url_parse.cc
rename to url/third_party/mozilla/url_parse.cc
index 0d9c6dd..52c6196 100644
--- a/url/url_parse.cc
+++ b/url/third_party/mozilla/url_parse.cc
@@ -34,7 +34,7 @@
*
* ***** END LICENSE BLOCK ***** */
-#include "url/url_parse.h"
+#include "url/third_party/mozilla/url_parse.h"
#include <stdlib.h>
diff --git a/url/third_party/mozilla/url_parse.h b/url/third_party/mozilla/url_parse.h
new file mode 100644
index 0000000..fd974f8
--- /dev/null
+++ b/url/third_party/mozilla/url_parse.h
@@ -0,0 +1,361 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef URL_THIRD_PARTY_MOZILLA_URL_PARSE_H_
+#define URL_THIRD_PARTY_MOZILLA_URL_PARSE_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/strings/string16.h"
+#include "url/url_export.h"
+
+namespace url_parse {
+
+// Deprecated, but WebKit/WebCore/platform/KURLGooglePrivate.h and
+// KURLGoogle.cpp still rely on this type.
+typedef base::char16 UTF16Char;
+
+// Component ------------------------------------------------------------------
+
+// Represents a substring for URL parsing.
+struct Component {
+ Component() : begin(0), len(-1) {}
+
+ // Normal constructor: takes an offset and a length.
+ Component(int b, int l) : begin(b), len(l) {}
+
+ int end() const {
+ return begin + len;
+ }
+
+ // Returns true if this component is valid, meaning the length is given. Even
+ // valid components may be empty to record the fact that they exist.
+ bool is_valid() const {
+ return (len != -1);
+ }
+
+ // Returns true if the given component is specified on false, the component
+ // is either empty or invalid.
+ bool is_nonempty() const {
+ return (len > 0);
+ }
+
+ void reset() {
+ begin = 0;
+ len = -1;
+ }
+
+ bool operator==(const Component& other) const {
+ return begin == other.begin && len == other.len;
+ }
+
+ int begin; // Byte offset in the string of this component.
+ int len; // Will be -1 if the component is unspecified.
+};
+
+// Helper that returns a component created with the given begin and ending
+// points. The ending point is non-inclusive.
+inline Component MakeRange(int begin, int end) {
+ return Component(begin, end - begin);
+}
+
+// Parsed ---------------------------------------------------------------------
+
+// A structure that holds the identified parts of an input URL. This structure
+// does NOT store the URL itself. The caller will have to store the URL text
+// and its corresponding Parsed structure separately.
+//
+// Typical usage would be:
+//
+// url_parse::Parsed parsed;
+// url_parse::Component scheme;
+// if (!url_parse::ExtractScheme(url, url_len, &scheme))
+// return I_CAN_NOT_FIND_THE_SCHEME_DUDE;
+//
+// if (IsStandardScheme(url, scheme)) // Not provided by this component
+// url_parseParseStandardURL(url, url_len, &parsed);
+// else if (IsFileURL(url, scheme)) // Not provided by this component
+// url_parse::ParseFileURL(url, url_len, &parsed);
+// else
+// url_parse::ParsePathURL(url, url_len, &parsed);
+//
+struct URL_EXPORT Parsed {
+ // Identifies different components.
+ enum ComponentType {
+ SCHEME,
+ USERNAME,
+ PASSWORD,
+ HOST,
+ PORT,
+ PATH,
+ QUERY,
+ REF,
+ };
+
+ // The default constructor is sufficient for the components, but inner_parsed_
+ // requires special handling.
+ Parsed();
+ Parsed(const Parsed&);
+ Parsed& operator=(const Parsed&);
+ ~Parsed();
+
+ // Returns the length of the URL (the end of the last component).
+ //
+ // Note that for some invalid, non-canonical URLs, this may not be the length
+ // of the string. For example "http://": the parsed structure will only
+ // contain an entry for the four-character scheme, and it doesn't know about
+ // the "://". For all other last-components, it will return the real length.
+ int Length() const;
+
+ // Returns the number of characters before the given component if it exists,
+ // or where the component would be if it did exist. This will return the
+ // string length if the component would be appended to the end.
+ //
+ // Note that this can get a little funny for the port, query, and ref
+ // components which have a delimiter that is not counted as part of the
+ // component. The |include_delimiter| flag controls if you want this counted
+ // as part of the component or not when the component exists.
+ //
+ // This example shows the difference between the two flags for two of these
+ // delimited components that is present (the port and query) and one that
+ // isn't (the reference). The components that this flag affects are marked
+ // with a *.
+ // 0 1 2
+ // 012345678901234567890
+ // Example input: http://foo:80/?query
+ // include_delim=true, ...=false ("<-" indicates different)
+ // SCHEME: 0 0
+ // USERNAME: 5 5
+ // PASSWORD: 5 5
+ // HOST: 7 7
+ // *PORT: 10 11 <-
+ // PATH: 13 13
+ // *QUERY: 14 15 <-
+ // *REF: 20 20
+ //
+ int CountCharactersBefore(ComponentType type, bool include_delimiter) const;
+
+ // Scheme without the colon: "http://foo"/ would have a scheme of "http".
+ // The length will be -1 if no scheme is specified ("foo.com"), or 0 if there
+ // is a colon but no scheme (":foo"). Note that the scheme is not guaranteed
+ // to start at the beginning of the string if there are preceeding whitespace
+ // or control characters.
+ Component scheme;
+
+ // Username. Specified in URLs with an @ sign before the host. See |password|
+ Component username;
+
+ // Password. The length will be -1 if unspecified, 0 if specified but empty.
+ // Not all URLs with a username have a password, as in "http://me@host/".
+ // The password is separated form the username with a colon, as in
+ // "http://me:secret@host/"
+ Component password;
+
+ // Host name.
+ Component host;
+
+ // Port number.
+ Component port;
+
+ // Path, this is everything following the host name. Length will be -1 if
+ // unspecified. This includes the preceeding slash, so the path on
+ // http://www.google.com/asdf" is "/asdf". As a result, it is impossible to
+ // have a 0 length path, it will be -1 in cases like "http://host?foo".
+ // Note that we treat backslashes the same as slashes.
+ Component path;
+
+ // Stuff between the ? and the # after the path. This does not include the
+ // preceeding ? character. Length will be -1 if unspecified, 0 if there is
+ // a question mark but no query string.
+ Component query;
+
+ // Indicated by a #, this is everything following the hash sign (not
+ // including it). If there are multiple hash signs, we'll use the last one.
+ // Length will be -1 if there is no hash sign, or 0 if there is one but
+ // nothing follows it.
+ Component ref;
+
+ // This is used for nested URL types, currently only filesystem. If you
+ // parse a filesystem URL, the resulting Parsed will have a nested
+ // inner_parsed_ to hold the parsed inner URL's component information.
+ // For all other url types [including the inner URL], it will be NULL.
+ Parsed* inner_parsed() const {
+ return inner_parsed_;
+ }
+
+ void set_inner_parsed(const Parsed& inner_parsed) {
+ if (!inner_parsed_)
+ inner_parsed_ = new Parsed(inner_parsed);
+ else
+ *inner_parsed_ = inner_parsed;
+ }
+
+ void clear_inner_parsed() {
+ if (inner_parsed_) {
+ delete inner_parsed_;
+ inner_parsed_ = NULL;
+ }
+ }
+
+ private:
+ Parsed* inner_parsed_; // This object is owned and managed by this struct.
+};
+
+// Initialization functions ---------------------------------------------------
+//
+// These functions parse the given URL, filling in all of the structure's
+// components. These functions can not fail, they will always do their best
+// at interpreting the input given.
+//
+// The string length of the URL MUST be specified, we do not check for NULLs
+// at any point in the process, and will actually handle embedded NULLs.
+//
+// IMPORTANT: These functions do NOT hang on to the given pointer or copy it
+// in any way. See the comment above the struct.
+//
+// The 8-bit versions require UTF-8 encoding.
+
+// StandardURL is for when the scheme is known to be one that has an
+// authority (host) like "http". This function will not handle weird ones
+// like "about:" and "javascript:", or do the right thing for "file:" URLs.
+URL_EXPORT void ParseStandardURL(const char* url,
+ int url_len,
+ Parsed* parsed);
+URL_EXPORT void ParseStandardURL(const base::char16* url,
+ int url_len,
+ Parsed* parsed);
+
+// PathURL is for when the scheme is known not to have an authority (host)
+// section but that aren't file URLs either. The scheme is parsed, and
+// everything after the scheme is considered as the path. This is used for
+// things like "about:" and "javascript:"
+URL_EXPORT void ParsePathURL(const char* url, int url_len, Parsed* parsed);
+URL_EXPORT void ParsePathURL(const base::char16* url,
+ int url_len,
+ Parsed* parsed);
+
+// FileURL is for file URLs. There are some special rules for interpreting
+// these.
+URL_EXPORT void ParseFileURL(const char* url, int url_len, Parsed* parsed);
+URL_EXPORT void ParseFileURL(const base::char16* url,
+ int url_len,
+ Parsed* parsed);
+
+// Filesystem URLs are structured differently than other URLs.
+URL_EXPORT void ParseFileSystemURL(const char* url,
+ int url_len,
+ Parsed* parsed);
+URL_EXPORT void ParseFileSystemURL(const base::char16* url,
+ int url_len,
+ Parsed* parsed);
+
+// MailtoURL is for mailto: urls. They are made up scheme,path,query
+URL_EXPORT void ParseMailtoURL(const char* url, int url_len, Parsed* parsed);
+URL_EXPORT void ParseMailtoURL(const base::char16* url,
+ int url_len,
+ Parsed* parsed);
+
+// Helper functions -----------------------------------------------------------
+
+// Locates the scheme according to the URL parser's rules. This function is
+// designed so the caller can find the scheme and call the correct Init*
+// function according to their known scheme types.
+//
+// It also does not perform any validation on the scheme.
+//
+// This function will return true if the scheme is found and will put the
+// scheme's range into *scheme. False means no scheme could be found. Note
+// that a URL beginning with a colon has a scheme, but it is empty, so this
+// function will return true but *scheme will = (0,0).
+//
+// The scheme is found by skipping spaces and control characters at the
+// beginning, and taking everything from there to the first colon to be the
+// scheme. The character at scheme.end() will be the colon (we may enhance
+// this to handle full width colons or something, so don't count on the
+// actual character value). The character at scheme.end()+1 will be the
+// beginning of the rest of the URL, be it the authority or the path (or the
+// end of the string).
+//
+// The 8-bit version requires UTF-8 encoding.
+URL_EXPORT bool ExtractScheme(const char* url,
+ int url_len,
+ Component* scheme);
+URL_EXPORT bool ExtractScheme(const base::char16* url,
+ int url_len,
+ Component* scheme);
+
+// Returns true if ch is a character that terminates the authority segment
+// of a URL.
+URL_EXPORT bool IsAuthorityTerminator(base::char16 ch);
+
+// Does a best effort parse of input |spec|, in range |auth|. If a particular
+// component is not found, it will be set to invalid.
+URL_EXPORT void ParseAuthority(const char* spec,
+ const Component& auth,
+ Component* username,
+ Component* password,
+ Component* hostname,
+ Component* port_num);
+URL_EXPORT void ParseAuthority(const base::char16* spec,
+ const Component& auth,
+ Component* username,
+ Component* password,
+ Component* hostname,
+ Component* port_num);
+
+// Computes the integer port value from the given port component. The port
+// component should have been identified by one of the init functions on
+// |Parsed| for the given input url.
+//
+// The return value will be a positive integer between 0 and 64K, or one of
+// the two special values below.
+enum SpecialPort { PORT_UNSPECIFIED = -1, PORT_INVALID = -2 };
+URL_EXPORT int ParsePort(const char* url, const Component& port);
+URL_EXPORT int ParsePort(const base::char16* url, const Component& port);
+
+// Extracts the range of the file name in the given url. The path must
+// already have been computed by the parse function, and the matching URL
+// and extracted path are provided to this function. The filename is
+// defined as being everything from the last slash/backslash of the path
+// to the end of the path.
+//
+// The file name will be empty if the path is empty or there is nothing
+// following the last slash.
+//
+// The 8-bit version requires UTF-8 encoding.
+URL_EXPORT void ExtractFileName(const char* url,
+ const Component& path,
+ Component* file_name);
+URL_EXPORT void ExtractFileName(const base::char16* url,
+ const Component& path,
+ Component* file_name);
+
+// Extract the first key/value from the range defined by |*query|. Updates
+// |*query| to start at the end of the extracted key/value pair. This is
+// designed for use in a loop: you can keep calling it with the same query
+// object and it will iterate over all items in the query.
+//
+// Some key/value pairs may have the key, the value, or both be empty (for
+// example, the query string "?&"). These will be returned. Note that an empty
+// last parameter "foo.com?" or foo.com?a&" will not be returned, this case
+// is the same as "done."
+//
+// The initial query component should not include the '?' (this is the default
+// for parsed URLs).
+//
+// If no key/value are found |*key| and |*value| will be unchanged and it will
+// return false.
+URL_EXPORT bool ExtractQueryKeyValue(const char* url,
+ Component* query,
+ Component* key,
+ Component* value);
+URL_EXPORT bool ExtractQueryKeyValue(const base::char16* url,
+ Component* query,
+ Component* key,
+ Component* value);
+
+} // namespace url_parse
+
+#endif // URL_THIRD_PARTY_MOZILLA_URL_PARSE_H_
diff --git a/url/url.gyp b/url/url.gyp
index a9a1a19..fe4d5fd 100644
--- a/url/url.gyp
+++ b/url/url.gyp
@@ -22,6 +22,8 @@
'sources': [
'gurl.cc',
'gurl.h',
+ 'third_party/mozilla/url_parse.cc',
+ 'third_party/mozilla/url_parse.h',
'url_canon.h',
'url_canon_etc.cc',
'url_canon_filesystemurl.cc',
@@ -42,8 +44,6 @@
'url_canon_stdstring.h',
'url_canon_stdurl.cc',
'url_file.h',
- 'url_parse.cc',
- 'url_parse.h',
'url_parse_file.cc',
'url_parse_internal.h',
'url_util.cc',
diff --git a/url/url_lib.target.darwin-arm.mk b/url/url_lib.target.darwin-arm.mk
index 0f359f5..30e0c4b 100644
--- a/url/url_lib.target.darwin-arm.mk
+++ b/url/url_lib.target.darwin-arm.mk
@@ -27,6 +27,7 @@
LOCAL_SRC_FILES := \
url/gurl.cc \
+ url/third_party/mozilla/url_parse.cc \
url/url_canon_etc.cc \
url/url_canon_filesystemurl.cc \
url/url_canon_fileurl.cc \
@@ -40,7 +41,6 @@
url/url_canon_query.cc \
url/url_canon_relative.cc \
url/url_canon_stdurl.cc \
- url/url_parse.cc \
url/url_parse_file.cc \
url/url_util.cc
diff --git a/url/url_lib.target.darwin-mips.mk b/url/url_lib.target.darwin-mips.mk
index 7801c4f..2e0a4b0 100644
--- a/url/url_lib.target.darwin-mips.mk
+++ b/url/url_lib.target.darwin-mips.mk
@@ -27,6 +27,7 @@
LOCAL_SRC_FILES := \
url/gurl.cc \
+ url/third_party/mozilla/url_parse.cc \
url/url_canon_etc.cc \
url/url_canon_filesystemurl.cc \
url/url_canon_fileurl.cc \
@@ -40,7 +41,6 @@
url/url_canon_query.cc \
url/url_canon_relative.cc \
url/url_canon_stdurl.cc \
- url/url_parse.cc \
url/url_parse_file.cc \
url/url_util.cc
diff --git a/url/url_lib.target.darwin-x86.mk b/url/url_lib.target.darwin-x86.mk
index b530406..c864096 100644
--- a/url/url_lib.target.darwin-x86.mk
+++ b/url/url_lib.target.darwin-x86.mk
@@ -27,6 +27,7 @@
LOCAL_SRC_FILES := \
url/gurl.cc \
+ url/third_party/mozilla/url_parse.cc \
url/url_canon_etc.cc \
url/url_canon_filesystemurl.cc \
url/url_canon_fileurl.cc \
@@ -40,7 +41,6 @@
url/url_canon_query.cc \
url/url_canon_relative.cc \
url/url_canon_stdurl.cc \
- url/url_parse.cc \
url/url_parse_file.cc \
url/url_util.cc
diff --git a/url/url_lib.target.linux-arm.mk b/url/url_lib.target.linux-arm.mk
index 0f359f5..30e0c4b 100644
--- a/url/url_lib.target.linux-arm.mk
+++ b/url/url_lib.target.linux-arm.mk
@@ -27,6 +27,7 @@
LOCAL_SRC_FILES := \
url/gurl.cc \
+ url/third_party/mozilla/url_parse.cc \
url/url_canon_etc.cc \
url/url_canon_filesystemurl.cc \
url/url_canon_fileurl.cc \
@@ -40,7 +41,6 @@
url/url_canon_query.cc \
url/url_canon_relative.cc \
url/url_canon_stdurl.cc \
- url/url_parse.cc \
url/url_parse_file.cc \
url/url_util.cc
diff --git a/url/url_lib.target.linux-mips.mk b/url/url_lib.target.linux-mips.mk
index 7801c4f..2e0a4b0 100644
--- a/url/url_lib.target.linux-mips.mk
+++ b/url/url_lib.target.linux-mips.mk
@@ -27,6 +27,7 @@
LOCAL_SRC_FILES := \
url/gurl.cc \
+ url/third_party/mozilla/url_parse.cc \
url/url_canon_etc.cc \
url/url_canon_filesystemurl.cc \
url/url_canon_fileurl.cc \
@@ -40,7 +41,6 @@
url/url_canon_query.cc \
url/url_canon_relative.cc \
url/url_canon_stdurl.cc \
- url/url_parse.cc \
url/url_parse_file.cc \
url/url_util.cc
diff --git a/url/url_lib.target.linux-x86.mk b/url/url_lib.target.linux-x86.mk
index b530406..c864096 100644
--- a/url/url_lib.target.linux-x86.mk
+++ b/url/url_lib.target.linux-x86.mk
@@ -27,6 +27,7 @@
LOCAL_SRC_FILES := \
url/gurl.cc \
+ url/third_party/mozilla/url_parse.cc \
url/url_canon_etc.cc \
url/url_canon_filesystemurl.cc \
url/url_canon_fileurl.cc \
@@ -40,7 +41,6 @@
url/url_canon_query.cc \
url/url_canon_relative.cc \
url/url_canon_stdurl.cc \
- url/url_parse.cc \
url/url_parse_file.cc \
url/url_util.cc
diff --git a/url/url_parse.h b/url/url_parse.h
index 21033dd..3b9c546 100644
--- a/url/url_parse.h
+++ b/url/url_parse.h
@@ -5,357 +5,7 @@
#ifndef URL_URL_PARSE_H_
#define URL_URL_PARSE_H_
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/strings/string16.h"
-#include "url/url_export.h"
-
-namespace url_parse {
-
-// Deprecated, but WebKit/WebCore/platform/KURLGooglePrivate.h and
-// KURLGoogle.cpp still rely on this type.
-typedef base::char16 UTF16Char;
-
-// Component ------------------------------------------------------------------
-
-// Represents a substring for URL parsing.
-struct Component {
- Component() : begin(0), len(-1) {}
-
- // Normal constructor: takes an offset and a length.
- Component(int b, int l) : begin(b), len(l) {}
-
- int end() const {
- return begin + len;
- }
-
- // Returns true if this component is valid, meaning the length is given. Even
- // valid components may be empty to record the fact that they exist.
- bool is_valid() const {
- return (len != -1);
- }
-
- // Returns true if the given component is specified on false, the component
- // is either empty or invalid.
- bool is_nonempty() const {
- return (len > 0);
- }
-
- void reset() {
- begin = 0;
- len = -1;
- }
-
- bool operator==(const Component& other) const {
- return begin == other.begin && len == other.len;
- }
-
- int begin; // Byte offset in the string of this component.
- int len; // Will be -1 if the component is unspecified.
-};
-
-// Helper that returns a component created with the given begin and ending
-// points. The ending point is non-inclusive.
-inline Component MakeRange(int begin, int end) {
- return Component(begin, end - begin);
-}
-
-// Parsed ---------------------------------------------------------------------
-
-// A structure that holds the identified parts of an input URL. This structure
-// does NOT store the URL itself. The caller will have to store the URL text
-// and its corresponding Parsed structure separately.
-//
-// Typical usage would be:
-//
-// url_parse::Parsed parsed;
-// url_parse::Component scheme;
-// if (!url_parse::ExtractScheme(url, url_len, &scheme))
-// return I_CAN_NOT_FIND_THE_SCHEME_DUDE;
-//
-// if (IsStandardScheme(url, scheme)) // Not provided by this component
-// url_parseParseStandardURL(url, url_len, &parsed);
-// else if (IsFileURL(url, scheme)) // Not provided by this component
-// url_parse::ParseFileURL(url, url_len, &parsed);
-// else
-// url_parse::ParsePathURL(url, url_len, &parsed);
-//
-struct URL_EXPORT Parsed {
- // Identifies different components.
- enum ComponentType {
- SCHEME,
- USERNAME,
- PASSWORD,
- HOST,
- PORT,
- PATH,
- QUERY,
- REF,
- };
-
- // The default constructor is sufficient for the components, but inner_parsed_
- // requires special handling.
- Parsed();
- Parsed(const Parsed&);
- Parsed& operator=(const Parsed&);
- ~Parsed();
-
- // Returns the length of the URL (the end of the last component).
- //
- // Note that for some invalid, non-canonical URLs, this may not be the length
- // of the string. For example "http://": the parsed structure will only
- // contain an entry for the four-character scheme, and it doesn't know about
- // the "://". For all other last-components, it will return the real length.
- int Length() const;
-
- // Returns the number of characters before the given component if it exists,
- // or where the component would be if it did exist. This will return the
- // string length if the component would be appended to the end.
- //
- // Note that this can get a little funny for the port, query, and ref
- // components which have a delimiter that is not counted as part of the
- // component. The |include_delimiter| flag controls if you want this counted
- // as part of the component or not when the component exists.
- //
- // This example shows the difference between the two flags for two of these
- // delimited components that is present (the port and query) and one that
- // isn't (the reference). The components that this flag affects are marked
- // with a *.
- // 0 1 2
- // 012345678901234567890
- // Example input: http://foo:80/?query
- // include_delim=true, ...=false ("<-" indicates different)
- // SCHEME: 0 0
- // USERNAME: 5 5
- // PASSWORD: 5 5
- // HOST: 7 7
- // *PORT: 10 11 <-
- // PATH: 13 13
- // *QUERY: 14 15 <-
- // *REF: 20 20
- //
- int CountCharactersBefore(ComponentType type, bool include_delimiter) const;
-
- // Scheme without the colon: "http://foo"/ would have a scheme of "http".
- // The length will be -1 if no scheme is specified ("foo.com"), or 0 if there
- // is a colon but no scheme (":foo"). Note that the scheme is not guaranteed
- // to start at the beginning of the string if there are preceeding whitespace
- // or control characters.
- Component scheme;
-
- // Username. Specified in URLs with an @ sign before the host. See |password|
- Component username;
-
- // Password. The length will be -1 if unspecified, 0 if specified but empty.
- // Not all URLs with a username have a password, as in "http://me@host/".
- // The password is separated form the username with a colon, as in
- // "http://me:secret@host/"
- Component password;
-
- // Host name.
- Component host;
-
- // Port number.
- Component port;
-
- // Path, this is everything following the host name. Length will be -1 if
- // unspecified. This includes the preceeding slash, so the path on
- // http://www.google.com/asdf" is "/asdf". As a result, it is impossible to
- // have a 0 length path, it will be -1 in cases like "http://host?foo".
- // Note that we treat backslashes the same as slashes.
- Component path;
-
- // Stuff between the ? and the # after the path. This does not include the
- // preceeding ? character. Length will be -1 if unspecified, 0 if there is
- // a question mark but no query string.
- Component query;
-
- // Indicated by a #, this is everything following the hash sign (not
- // including it). If there are multiple hash signs, we'll use the last one.
- // Length will be -1 if there is no hash sign, or 0 if there is one but
- // nothing follows it.
- Component ref;
-
- // This is used for nested URL types, currently only filesystem. If you
- // parse a filesystem URL, the resulting Parsed will have a nested
- // inner_parsed_ to hold the parsed inner URL's component information.
- // For all other url types [including the inner URL], it will be NULL.
- Parsed* inner_parsed() const {
- return inner_parsed_;
- }
-
- void set_inner_parsed(const Parsed& inner_parsed) {
- if (!inner_parsed_)
- inner_parsed_ = new Parsed(inner_parsed);
- else
- *inner_parsed_ = inner_parsed;
- }
-
- void clear_inner_parsed() {
- if (inner_parsed_) {
- delete inner_parsed_;
- inner_parsed_ = NULL;
- }
- }
-
- private:
- Parsed* inner_parsed_; // This object is owned and managed by this struct.
-};
-
-// Initialization functions ---------------------------------------------------
-//
-// These functions parse the given URL, filling in all of the structure's
-// components. These functions can not fail, they will always do their best
-// at interpreting the input given.
-//
-// The string length of the URL MUST be specified, we do not check for NULLs
-// at any point in the process, and will actually handle embedded NULLs.
-//
-// IMPORTANT: These functions do NOT hang on to the given pointer or copy it
-// in any way. See the comment above the struct.
-//
-// The 8-bit versions require UTF-8 encoding.
-
-// StandardURL is for when the scheme is known to be one that has an
-// authority (host) like "http". This function will not handle weird ones
-// like "about:" and "javascript:", or do the right thing for "file:" URLs.
-URL_EXPORT void ParseStandardURL(const char* url,
- int url_len,
- Parsed* parsed);
-URL_EXPORT void ParseStandardURL(const base::char16* url,
- int url_len,
- Parsed* parsed);
-
-// PathURL is for when the scheme is known not to have an authority (host)
-// section but that aren't file URLs either. The scheme is parsed, and
-// everything after the scheme is considered as the path. This is used for
-// things like "about:" and "javascript:"
-URL_EXPORT void ParsePathURL(const char* url, int url_len, Parsed* parsed);
-URL_EXPORT void ParsePathURL(const base::char16* url,
- int url_len,
- Parsed* parsed);
-
-// FileURL is for file URLs. There are some special rules for interpreting
-// these.
-URL_EXPORT void ParseFileURL(const char* url, int url_len, Parsed* parsed);
-URL_EXPORT void ParseFileURL(const base::char16* url,
- int url_len,
- Parsed* parsed);
-
-// Filesystem URLs are structured differently than other URLs.
-URL_EXPORT void ParseFileSystemURL(const char* url,
- int url_len,
- Parsed* parsed);
-URL_EXPORT void ParseFileSystemURL(const base::char16* url,
- int url_len,
- Parsed* parsed);
-
-// MailtoURL is for mailto: urls. They are made up scheme,path,query
-URL_EXPORT void ParseMailtoURL(const char* url, int url_len, Parsed* parsed);
-URL_EXPORT void ParseMailtoURL(const base::char16* url,
- int url_len,
- Parsed* parsed);
-
-// Helper functions -----------------------------------------------------------
-
-// Locates the scheme according to the URL parser's rules. This function is
-// designed so the caller can find the scheme and call the correct Init*
-// function according to their known scheme types.
-//
-// It also does not perform any validation on the scheme.
-//
-// This function will return true if the scheme is found and will put the
-// scheme's range into *scheme. False means no scheme could be found. Note
-// that a URL beginning with a colon has a scheme, but it is empty, so this
-// function will return true but *scheme will = (0,0).
-//
-// The scheme is found by skipping spaces and control characters at the
-// beginning, and taking everything from there to the first colon to be the
-// scheme. The character at scheme.end() will be the colon (we may enhance
-// this to handle full width colons or something, so don't count on the
-// actual character value). The character at scheme.end()+1 will be the
-// beginning of the rest of the URL, be it the authority or the path (or the
-// end of the string).
-//
-// The 8-bit version requires UTF-8 encoding.
-URL_EXPORT bool ExtractScheme(const char* url,
- int url_len,
- Component* scheme);
-URL_EXPORT bool ExtractScheme(const base::char16* url,
- int url_len,
- Component* scheme);
-
-// Returns true if ch is a character that terminates the authority segment
-// of a URL.
-URL_EXPORT bool IsAuthorityTerminator(base::char16 ch);
-
-// Does a best effort parse of input |spec|, in range |auth|. If a particular
-// component is not found, it will be set to invalid.
-URL_EXPORT void ParseAuthority(const char* spec,
- const Component& auth,
- Component* username,
- Component* password,
- Component* hostname,
- Component* port_num);
-URL_EXPORT void ParseAuthority(const base::char16* spec,
- const Component& auth,
- Component* username,
- Component* password,
- Component* hostname,
- Component* port_num);
-
-// Computes the integer port value from the given port component. The port
-// component should have been identified by one of the init functions on
-// |Parsed| for the given input url.
-//
-// The return value will be a positive integer between 0 and 64K, or one of
-// the two special values below.
-enum SpecialPort { PORT_UNSPECIFIED = -1, PORT_INVALID = -2 };
-URL_EXPORT int ParsePort(const char* url, const Component& port);
-URL_EXPORT int ParsePort(const base::char16* url, const Component& port);
-
-// Extracts the range of the file name in the given url. The path must
-// already have been computed by the parse function, and the matching URL
-// and extracted path are provided to this function. The filename is
-// defined as being everything from the last slash/backslash of the path
-// to the end of the path.
-//
-// The file name will be empty if the path is empty or there is nothing
-// following the last slash.
-//
-// The 8-bit version requires UTF-8 encoding.
-URL_EXPORT void ExtractFileName(const char* url,
- const Component& path,
- Component* file_name);
-URL_EXPORT void ExtractFileName(const base::char16* url,
- const Component& path,
- Component* file_name);
-
-// Extract the first key/value from the range defined by |*query|. Updates
-// |*query| to start at the end of the extracted key/value pair. This is
-// designed for use in a loop: you can keep calling it with the same query
-// object and it will iterate over all items in the query.
-//
-// Some key/value pairs may have the key, the value, or both be empty (for
-// example, the query string "?&"). These will be returned. Note that an empty
-// last parameter "foo.com?" or foo.com?a&" will not be returned, this case
-// is the same as "done."
-//
-// The initial query component should not include the '?' (this is the default
-// for parsed URLs).
-//
-// If no key/value are found |*key| and |*value| will be unchanged and it will
-// return false.
-URL_EXPORT bool ExtractQueryKeyValue(const char* url,
- Component* query,
- Component* key,
- Component* value);
-URL_EXPORT bool ExtractQueryKeyValue(const base::char16* url,
- Component* query,
- Component* key,
- Component* value);
-
-} // namespace url_parse
+// TODO(tfarina): Remove this file when the callers are updated.
+#include "url/third_party/mozilla/url_parse.h"
#endif // URL_URL_PARSE_H_
diff --git a/webkit/DEPS b/webkit/DEPS
index fb09b7c..4571d4c 100644
--- a/webkit/DEPS
+++ b/webkit/DEPS
@@ -37,7 +37,6 @@
"+ui/base/keycodes",
# TODO(brettw) - review these; move up if it's ok, or remove the dependency
- "+crypto",
"+net",
"+third_party/npapi/bindings",
diff --git a/webkit/browser/fileapi/copy_or_move_operation_delegate.cc b/webkit/browser/fileapi/copy_or_move_operation_delegate.cc
index 15e222d..da1ef97 100644
--- a/webkit/browser/fileapi/copy_or_move_operation_delegate.cc
+++ b/webkit/browser/fileapi/copy_or_move_operation_delegate.cc
@@ -26,7 +26,8 @@
src_root_(src_root),
dest_root_(dest_root),
operation_type_(operation_type),
- callback_(callback) {
+ callback_(callback),
+ weak_factory_(this) {
same_file_system_ = src_root_.IsInSameFileSystem(dest_root_);
}
@@ -56,7 +57,7 @@
// First try to copy/move it as a file.
CopyOrMoveFile(URLPair(src_root_, dest_root_),
base::Bind(&CopyOrMoveOperationDelegate::DidTryCopyOrMoveFile,
- AsWeakPtr()));
+ weak_factory_.GetWeakPtr()));
}
void CopyOrMoveOperationDelegate::ProcessFile(const FileSystemURL& src_url,
@@ -90,7 +91,7 @@
operation_runner()->RemoveDirectory(
dest_root_,
base::Bind(&CopyOrMoveOperationDelegate::DidTryRemoveDestRoot,
- AsWeakPtr()));
+ weak_factory_.GetWeakPtr()));
}
void CopyOrMoveOperationDelegate::DidTryRemoveDestRoot(
@@ -112,7 +113,7 @@
StartRecursiveOperation(
src_root_,
base::Bind(&CopyOrMoveOperationDelegate::DidFinishRecursiveCopyDir,
- AsWeakPtr(), src_root_, callback_));
+ weak_factory_.GetWeakPtr(), src_root_, callback_));
}
void CopyOrMoveOperationDelegate::CopyOrMoveFile(
@@ -132,12 +133,12 @@
// Perform CreateSnapshotFile, CopyInForeignFile and then calls
// copy_callback which removes the source file if operation_type == MOVE.
StatusCallback copy_callback =
- base::Bind(&CopyOrMoveOperationDelegate::DidFinishCopy, AsWeakPtr(),
- url_pair, callback);
+ base::Bind(&CopyOrMoveOperationDelegate::DidFinishCopy,
+ weak_factory_.GetWeakPtr(), url_pair, callback);
operation_runner()->CreateSnapshotFile(
url_pair.src,
- base::Bind(&CopyOrMoveOperationDelegate::DidCreateSnapshot, AsWeakPtr(),
- url_pair, copy_callback));
+ base::Bind(&CopyOrMoveOperationDelegate::DidCreateSnapshot,
+ weak_factory_.GetWeakPtr(), url_pair, copy_callback));
}
void CopyOrMoveOperationDelegate::DidCreateSnapshot(
@@ -172,7 +173,8 @@
validator_.reset(
factory->CreateCopyOrMoveFileValidator(url_pair.src, platform_path));
validator_->StartPreWriteValidation(
- base::Bind(&CopyOrMoveOperationDelegate::DidValidateFile, AsWeakPtr(),
+ base::Bind(&CopyOrMoveOperationDelegate::DidValidateFile,
+ weak_factory_.GetWeakPtr(),
url_pair.dest, callback, file_info, platform_path));
}
@@ -206,7 +208,7 @@
operation_runner()->Remove(
src, true /* recursive */,
base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove,
- AsWeakPtr(), callback));
+ weak_factory_.GetWeakPtr(), callback));
}
void CopyOrMoveOperationDelegate::DidFinishCopy(
@@ -231,7 +233,7 @@
operation_runner()->CreateSnapshotFile(
url_pair.dest,
base::Bind(&CopyOrMoveOperationDelegate::DoPostWriteValidation,
- AsWeakPtr(), url_pair, callback));
+ weak_factory_.GetWeakPtr(), url_pair, callback));
}
void CopyOrMoveOperationDelegate::DoPostWriteValidation(
@@ -245,7 +247,7 @@
operation_runner()->Remove(
url_pair.dest, true,
base::Bind(&CopyOrMoveOperationDelegate::DidRemoveDestForError,
- AsWeakPtr(), error, callback));
+ weak_factory_.GetWeakPtr(), error, callback));
return;
}
@@ -255,7 +257,7 @@
validator_->StartPostWriteValidation(
platform_path,
base::Bind(&CopyOrMoveOperationDelegate::DidPostWriteValidation,
- AsWeakPtr(), url_pair, callback, file_ref));
+ weak_factory_.GetWeakPtr(), url_pair, callback, file_ref));
}
// |file_ref| is unused; it is passed here to make sure the reference is
@@ -269,7 +271,7 @@
operation_runner()->Remove(
url_pair.dest, true,
base::Bind(&CopyOrMoveOperationDelegate::DidRemoveDestForError,
- AsWeakPtr(), error, callback));
+ weak_factory_.GetWeakPtr(), error, callback));
return;
}
@@ -284,7 +286,7 @@
operation_runner()->Remove(
url_pair.src, true /* recursive */,
base::Bind(&CopyOrMoveOperationDelegate::DidRemoveSourceForMove,
- AsWeakPtr(), callback));
+ weak_factory_.GetWeakPtr(), callback));
}
void CopyOrMoveOperationDelegate::DidRemoveSourceForMove(
diff --git a/webkit/browser/fileapi/copy_or_move_operation_delegate.h b/webkit/browser/fileapi/copy_or_move_operation_delegate.h
index 3c40cae..ceceb97 100644
--- a/webkit/browser/fileapi/copy_or_move_operation_delegate.h
+++ b/webkit/browser/fileapi/copy_or_move_operation_delegate.h
@@ -21,8 +21,7 @@
// A delegate class for recursive copy or move operations.
class CopyOrMoveOperationDelegate
- : public RecursiveOperationDelegate,
- public base::SupportsWeakPtr<CopyOrMoveOperationDelegate> {
+ : public RecursiveOperationDelegate {
public:
enum OperationType {
OPERATION_COPY,
@@ -45,8 +44,6 @@
virtual void ProcessDirectory(const FileSystemURL& url,
const StatusCallback& callback) OVERRIDE;
- using base::SupportsWeakPtr<CopyOrMoveOperationDelegate>::AsWeakPtr;
-
private:
struct URLPair {
URLPair(const FileSystemURL& src, const FileSystemURL& dest)
@@ -115,6 +112,8 @@
scoped_ptr<CopyOrMoveFileValidator> validator_;
+ base::WeakPtrFactory<CopyOrMoveOperationDelegate> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(CopyOrMoveOperationDelegate);
};
diff --git a/webkit/browser/fileapi/file_system_operation_impl_unittest.cc b/webkit/browser/fileapi/file_system_operation_impl_unittest.cc
index 846335c..083fdeb 100644
--- a/webkit/browser/fileapi/file_system_operation_impl_unittest.cc
+++ b/webkit/browser/fileapi/file_system_operation_impl_unittest.cc
@@ -47,11 +47,11 @@
// Test class for FileSystemOperationImpl.
class FileSystemOperationImplTest
- : public testing::Test,
- public base::SupportsWeakPtr<FileSystemOperationImplTest> {
+ : public testing::Test {
public:
FileSystemOperationImplTest()
- : status_(kFileOperationStatusNotSet) {}
+ : status_(kFileOperationStatusNotSet),
+ weak_factory_(this) {}
protected:
virtual void SetUp() OVERRIDE {
@@ -165,23 +165,24 @@
// Callbacks for recording test results.
FileSystemOperation::StatusCallback RecordStatusCallback() {
- return base::Bind(&FileSystemOperationImplTest::DidFinish, AsWeakPtr());
+ return base::Bind(&FileSystemOperationImplTest::DidFinish,
+ weak_factory_.GetWeakPtr());
}
FileSystemOperation::ReadDirectoryCallback
RecordReadDirectoryCallback() {
return base::Bind(&FileSystemOperationImplTest::DidReadDirectory,
- AsWeakPtr());
+ weak_factory_.GetWeakPtr());
}
FileSystemOperation::GetMetadataCallback RecordMetadataCallback() {
return base::Bind(&FileSystemOperationImplTest::DidGetMetadata,
- AsWeakPtr());
+ weak_factory_.GetWeakPtr());
}
FileSystemOperation::SnapshotFileCallback RecordSnapshotFileCallback() {
return base::Bind(&FileSystemOperationImplTest::DidCreateSnapshotFile,
- AsWeakPtr());
+ weak_factory_.GetWeakPtr());
}
void DidFinish(base::PlatformFileError status) {
@@ -287,6 +288,8 @@
MockFileChangeObserver change_observer_;
ChangeObserverList change_observers_;
+ base::WeakPtrFactory<FileSystemOperationImplTest> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImplTest);
};
diff --git a/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc b/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc
index 88a48d8..d8ecc28 100644
--- a/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc
+++ b/webkit/browser/fileapi/file_system_operation_impl_write_unittest.cc
@@ -48,15 +48,15 @@
} // namespace
class FileSystemOperationImplWriteTest
- : public testing::Test,
- public base::SupportsWeakPtr<FileSystemOperationImplWriteTest> {
+ : public testing::Test {
public:
FileSystemOperationImplWriteTest()
: loop_(base::MessageLoop::TYPE_IO),
status_(base::PLATFORM_FILE_OK),
cancel_status_(base::PLATFORM_FILE_ERROR_FAILED),
bytes_written_(0),
- complete_(false) {
+ complete_(false),
+ weak_factory_(this) {
change_observers_ = MockFileChangeObserver::CreateList(&change_observer_);
}
@@ -118,12 +118,12 @@
// Callback function for recording test results.
FileSystemOperation::WriteCallback RecordWriteCallback() {
return base::Bind(&FileSystemOperationImplWriteTest::DidWrite,
- AsWeakPtr());
+ weak_factory_.GetWeakPtr());
}
FileSystemOperation::StatusCallback RecordCancelCallback() {
return base::Bind(&FileSystemOperationImplWriteTest::DidCancel,
- AsWeakPtr());
+ weak_factory_.GetWeakPtr());
}
void DidWrite(base::PlatformFileError status, int64 bytes, bool complete) {
@@ -168,6 +168,8 @@
MockFileChangeObserver change_observer_;
ChangeObserverList change_observers_;
+ base::WeakPtrFactory<FileSystemOperationImplWriteTest> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(FileSystemOperationImplWriteTest);
};
diff --git a/webkit/browser/fileapi/file_writer_delegate.cc b/webkit/browser/fileapi/file_writer_delegate.cc
index 48f1770..7a0094e 100644
--- a/webkit/browser/fileapi/file_writer_delegate.cc
+++ b/webkit/browser/fileapi/file_writer_delegate.cc
@@ -46,7 +46,8 @@
bytes_written_backlog_(0),
bytes_written_(0),
bytes_read_(0),
- io_buffer_(new net::IOBufferWithSize(kReadBufSize)) {
+ io_buffer_(new net::IOBufferWithSize(kReadBufSize)),
+ weak_factory_(this) {
}
FileWriterDelegate::~FileWriterDelegate() {
@@ -67,7 +68,8 @@
}
const int status = file_stream_writer_->Cancel(
- base::Bind(&FileWriterDelegate::OnWriteCancelled, AsWeakPtr()));
+ base::Bind(&FileWriterDelegate::OnWriteCancelled,
+ weak_factory_.GetWeakPtr()));
// Return true to finish immediately if we have no pending writes.
// Otherwise we'll do the final cleanup in the Cancel callback.
if (status != net::ERR_IO_PENDING) {
@@ -129,7 +131,7 @@
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&FileWriterDelegate::OnDataReceived,
- AsWeakPtr(), bytes_read_));
+ weak_factory_.GetWeakPtr(), bytes_read_));
} else if (!request_->status().is_io_pending()) {
OnError(base::PLATFORM_FILE_ERROR_FAILED);
}
@@ -155,12 +157,12 @@
file_stream_writer_->Write(cursor_.get(),
static_cast<int>(bytes_to_write),
base::Bind(&FileWriterDelegate::OnDataWritten,
- AsWeakPtr()));
+ weak_factory_.GetWeakPtr()));
if (write_response > 0) {
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&FileWriterDelegate::OnDataWritten,
- AsWeakPtr(), write_response));
+ weak_factory_.GetWeakPtr(), write_response));
} else if (net::ERR_IO_PENDING != write_response) {
OnError(NetErrorToPlatformFileError(write_response));
}
@@ -230,7 +232,7 @@
int bytes_written,
WriteProgressStatus progress_status) {
int flush_error = file_stream_writer_->Flush(
- base::Bind(&FileWriterDelegate::OnFlushed, AsWeakPtr(),
+ base::Bind(&FileWriterDelegate::OnFlushed, weak_factory_.GetWeakPtr(),
error, bytes_written, progress_status));
if (flush_error != net::ERR_IO_PENDING)
OnFlushed(error, bytes_written, progress_status, flush_error);
diff --git a/webkit/browser/fileapi/file_writer_delegate.h b/webkit/browser/fileapi/file_writer_delegate.h
index e6e53cf..ae63e7f 100644
--- a/webkit/browser/fileapi/file_writer_delegate.h
+++ b/webkit/browser/fileapi/file_writer_delegate.h
@@ -20,8 +20,7 @@
class FileStreamWriter;
class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileWriterDelegate
- : public net::URLRequest::Delegate,
- public base::SupportsWeakPtr<FileWriterDelegate> {
+ : public net::URLRequest::Delegate {
public:
enum WriteProgressStatus {
SUCCESS_IO_PENDING,
@@ -93,6 +92,10 @@
scoped_refptr<net::IOBufferWithSize> io_buffer_;
scoped_refptr<net::DrainableIOBuffer> cursor_;
scoped_ptr<net::URLRequest> request_;
+
+ base::WeakPtrFactory<FileWriterDelegate> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileWriterDelegate);
};
} // namespace fileapi
diff --git a/webkit/browser/fileapi/remove_operation_delegate.cc b/webkit/browser/fileapi/remove_operation_delegate.cc
index a639e98..fcd9ba9 100644
--- a/webkit/browser/fileapi/remove_operation_delegate.cc
+++ b/webkit/browser/fileapi/remove_operation_delegate.cc
@@ -16,20 +16,22 @@
const StatusCallback& callback)
: RecursiveOperationDelegate(file_system_context),
url_(url),
- callback_(callback) {
+ callback_(callback),
+ weak_factory_(this) {
}
RemoveOperationDelegate::~RemoveOperationDelegate() {}
void RemoveOperationDelegate::Run() {
operation_runner()->RemoveFile(url_, base::Bind(
- &RemoveOperationDelegate::DidTryRemoveFile, AsWeakPtr()));
+ &RemoveOperationDelegate::DidTryRemoveFile, weak_factory_.GetWeakPtr()));
}
void RemoveOperationDelegate::RunRecursively() {
StartRecursiveOperation(
url_,
- base::Bind(&RemoveOperationDelegate::RemoveNextDirectory, AsWeakPtr()));
+ base::Bind(&RemoveOperationDelegate::RemoveNextDirectory,
+ weak_factory_.GetWeakPtr()));
}
void RemoveOperationDelegate::ProcessFile(const FileSystemURL& url,
@@ -40,7 +42,8 @@
to_remove_directories_.pop();
}
operation_runner()->RemoveFile(url, base::Bind(
- &RemoveOperationDelegate::DidRemoveFile, AsWeakPtr(), callback));
+ &RemoveOperationDelegate::DidRemoveFile,
+ weak_factory_.GetWeakPtr(), callback));
}
void RemoveOperationDelegate::ProcessDirectory(const FileSystemURL& url,
@@ -79,7 +82,7 @@
to_remove_directories_.pop();
operation_runner()->RemoveDirectory(url, base::Bind(
&RemoveOperationDelegate::RemoveNextDirectory,
- AsWeakPtr()));
+ weak_factory_.GetWeakPtr()));
}
} // namespace fileapi
diff --git a/webkit/browser/fileapi/remove_operation_delegate.h b/webkit/browser/fileapi/remove_operation_delegate.h
index 4657cff..ef9e1a0 100644
--- a/webkit/browser/fileapi/remove_operation_delegate.h
+++ b/webkit/browser/fileapi/remove_operation_delegate.h
@@ -12,8 +12,7 @@
namespace fileapi {
class RemoveOperationDelegate
- : public RecursiveOperationDelegate,
- public base::SupportsWeakPtr<RemoveOperationDelegate> {
+ : public RecursiveOperationDelegate {
public:
RemoveOperationDelegate(FileSystemContext* file_system_context,
const FileSystemURL& url,
@@ -28,8 +27,6 @@
virtual void ProcessDirectory(const FileSystemURL& url,
const StatusCallback& callback) OVERRIDE;
- using base::SupportsWeakPtr<RemoveOperationDelegate>::AsWeakPtr;
-
private:
void DidTryRemoveFile(base::PlatformFileError error);
void DidRemoveFile(const StatusCallback& callback,
@@ -41,6 +38,8 @@
std::stack<FileSystemURL> to_remove_directories_;
+ base::WeakPtrFactory<RemoveOperationDelegate> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(RemoveOperationDelegate);
};
diff --git a/webkit/common/gpu/webkit_gpu.target.darwin-arm.mk b/webkit/common/gpu/webkit_gpu.target.darwin-arm.mk
index c560512..822ad0c 100644
--- a/webkit/common/gpu/webkit_gpu.target.darwin-arm.mk
+++ b/webkit/common/gpu/webkit_gpu.target.darwin-arm.mk
@@ -94,6 +94,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
@@ -210,6 +211,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/webkit/common/gpu/webkit_gpu.target.darwin-mips.mk b/webkit/common/gpu/webkit_gpu.target.darwin-mips.mk
index 9ca7067..93fc07b 100644
--- a/webkit/common/gpu/webkit_gpu.target.darwin-mips.mk
+++ b/webkit/common/gpu/webkit_gpu.target.darwin-mips.mk
@@ -94,6 +94,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
@@ -210,6 +211,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/webkit/common/gpu/webkit_gpu.target.darwin-x86.mk b/webkit/common/gpu/webkit_gpu.target.darwin-x86.mk
index 227272c..cf7e31c 100644
--- a/webkit/common/gpu/webkit_gpu.target.darwin-x86.mk
+++ b/webkit/common/gpu/webkit_gpu.target.darwin-x86.mk
@@ -96,6 +96,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
@@ -214,6 +215,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
diff --git a/webkit/common/gpu/webkit_gpu.target.linux-arm.mk b/webkit/common/gpu/webkit_gpu.target.linux-arm.mk
index c560512..822ad0c 100644
--- a/webkit/common/gpu/webkit_gpu.target.linux-arm.mk
+++ b/webkit/common/gpu/webkit_gpu.target.linux-arm.mk
@@ -94,6 +94,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
@@ -210,6 +211,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/webkit/common/gpu/webkit_gpu.target.linux-mips.mk b/webkit/common/gpu/webkit_gpu.target.linux-mips.mk
index 9ca7067..93fc07b 100644
--- a/webkit/common/gpu/webkit_gpu.target.linux-mips.mk
+++ b/webkit/common/gpu/webkit_gpu.target.linux-mips.mk
@@ -94,6 +94,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
@@ -210,6 +211,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DPOSIX_AVOID_MMAP' \
'-DU_USING_ICU_NAMESPACE=0' \
diff --git a/webkit/common/gpu/webkit_gpu.target.linux-x86.mk b/webkit/common/gpu/webkit_gpu.target.linux-x86.mk
index 227272c..cf7e31c 100644
--- a/webkit/common/gpu/webkit_gpu.target.linux-x86.mk
+++ b/webkit/common/gpu/webkit_gpu.target.linux-x86.mk
@@ -96,6 +96,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
@@ -214,6 +215,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
diff --git a/webkit/common/plugins/ppapi/OWNERS b/webkit/common/plugins/ppapi/OWNERS
deleted file mode 100644
index d24c4ea..0000000
--- a/webkit/common/plugins/ppapi/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-brettw@chromium.org
-bbudge@chromium.org
-dmichael@chromium.org
-piman@chromium.org
-raymes@chromium.org
-yzshen@chromium.org
diff --git a/webkit/common/plugins/ppapi/ppapi_utils.h b/webkit/common/plugins/ppapi/ppapi_utils.h
deleted file mode 100644
index 849bac9..0000000
--- a/webkit/common/plugins/ppapi/ppapi_utils.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// 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_PLUGINS_PPAPI_PPAPI_UTILS_H_
-#define WEBKIT_COMMON_PLUGINS_PPAPI_PPAPI_UTILS_H_
-
-namespace webkit {
-namespace ppapi {
-
-// Returns true if the interface name passed in is supported by the
-// browser.
-bool IsSupportedPepperInterface(const char* name);
-
-} // namespace ppapi
-} // namespace webkit
-
-#endif // WEBKIT_COMMON_PLUGINS_PPAPI_PPAPI_UTILS_H_
-
-
diff --git a/webkit/common/webkit_common.target.darwin-arm.mk b/webkit/common/webkit_common.target.darwin-arm.mk
index 7ceb7ad..67e9a0f 100644
--- a/webkit/common/webkit_common.target.darwin-arm.mk
+++ b/webkit/common/webkit_common.target.darwin-arm.mk
@@ -93,6 +93,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -204,6 +205,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/common/webkit_common.target.darwin-mips.mk b/webkit/common/webkit_common.target.darwin-mips.mk
index 46c3b0d..2c22851 100644
--- a/webkit/common/webkit_common.target.darwin-mips.mk
+++ b/webkit/common/webkit_common.target.darwin-mips.mk
@@ -92,6 +92,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -202,6 +203,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/common/webkit_common.target.darwin-x86.mk b/webkit/common/webkit_common.target.darwin-x86.mk
index a199c81..25c463a 100644
--- a/webkit/common/webkit_common.target.darwin-x86.mk
+++ b/webkit/common/webkit_common.target.darwin-x86.mk
@@ -94,6 +94,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -207,6 +208,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/common/webkit_common.target.linux-arm.mk b/webkit/common/webkit_common.target.linux-arm.mk
index 7ceb7ad..67e9a0f 100644
--- a/webkit/common/webkit_common.target.linux-arm.mk
+++ b/webkit/common/webkit_common.target.linux-arm.mk
@@ -93,6 +93,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -204,6 +205,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/common/webkit_common.target.linux-mips.mk b/webkit/common/webkit_common.target.linux-mips.mk
index 46c3b0d..2c22851 100644
--- a/webkit/common/webkit_common.target.linux-mips.mk
+++ b/webkit/common/webkit_common.target.linux-mips.mk
@@ -92,6 +92,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -202,6 +203,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/common/webkit_common.target.linux-x86.mk b/webkit/common/webkit_common.target.linux-x86.mk
index a199c81..25c463a 100644
--- a/webkit/common/webkit_common.target.linux-x86.mk
+++ b/webkit/common/webkit_common.target.linux-x86.mk
@@ -94,6 +94,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -207,6 +208,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi
index 3400cea..adbd54d 100644
--- a/webkit/glue/webkit_glue.gypi
+++ b/webkit/glue/webkit_glue.gypi
@@ -31,7 +31,6 @@
'<(DEPTH)/v8/tools/gyp/v8.gyp:v8',
'<(DEPTH)/webkit/common/user_agent/webkit_user_agent.gyp:user_agent',
'<(DEPTH)/webkit/common/webkit_common.gyp:webkit_common',
- '<(DEPTH)/webkit/plugins/webkit_plugins.gyp:plugins_common',
],
'include_dirs': [
@@ -123,6 +122,7 @@
'WEBKIT_GLUE_IMPLEMENTATION',
],
'dependencies': [
+ '<(DEPTH)/base/base.gyp:base',
'<(DEPTH)/base/base.gyp:base_i18n',
'<(DEPTH)/base/base.gyp:base_static',
'<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
@@ -141,13 +141,11 @@
'<(DEPTH)/v8/tools/gyp/v8.gyp:v8',
'<(DEPTH)/webkit/common/user_agent/webkit_user_agent.gyp:user_agent',
'<(DEPTH)/webkit/common/webkit_common.gyp:webkit_common',
- '<(DEPTH)/webkit/plugins/webkit_plugins.gyp:plugins_common',
'<(DEPTH)/webkit/renderer/compositor_bindings/compositor_bindings.gyp:webkit_compositor_support',
'<(DEPTH)/webkit/storage_browser.gyp:webkit_storage_browser',
'<(DEPTH)/webkit/storage_common.gyp:webkit_storage_common',
'<(DEPTH)/webkit/webkit_resources.gyp:webkit_resources',
'<(DEPTH)/webkit/webkit_resources.gyp:webkit_strings',
- 'plugins',
],
'include_dirs': [
'<(INTERMEDIATE_DIR)',
diff --git a/webkit/plugins/OWNERS b/webkit/plugins/OWNERS
deleted file mode 100644
index b47b3b2..0000000
--- a/webkit/plugins/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-jam@chromium.org
diff --git a/webkit/plugins/plugin_constants.cc b/webkit/plugins/plugin_constants.cc
deleted file mode 100644
index 52d5aa2..0000000
--- a/webkit/plugins/plugin_constants.cc
+++ /dev/null
@@ -1,17 +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 "webkit/plugins/plugin_constants.h"
-
-const char kFlashPluginName[] = "Shockwave Flash";
-const char kFlashPluginSwfMimeType[] = "application/x-shockwave-flash";
-const char kFlashPluginSwfExtension[] = "swf";
-const char kFlashPluginSwfDescription[] = "Shockwave Flash";
-const char kFlashPluginSplMimeType[] = "application/futuresplash";
-const char kFlashPluginSplExtension[] = "spl";
-const char kFlashPluginSplDescription[] = "FutureSplash Player";
-
-const uint16 kMaxPluginSideLength = 1 << 15;
-// 8m pixels.
-const uint32 kMaxPluginSize = 8 << 20;
diff --git a/webkit/plugins/plugin_constants.h b/webkit/plugins/plugin_constants.h
deleted file mode 100644
index 6792fb3..0000000
--- a/webkit/plugins/plugin_constants.h
+++ /dev/null
@@ -1,24 +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 WEBKIT_PLUGINS_PLUGIN_CONSTANTS_H_
-#define WEBKIT_PLUGINS_PLUGIN_CONSTANTS_H_
-
-#include "base/basictypes.h"
-
-extern const char kFlashPluginName[];
-extern const char kFlashPluginSwfMimeType[];
-extern const char kFlashPluginSwfExtension[];
-extern const char kFlashPluginSwfDescription[];
-extern const char kFlashPluginSplMimeType[];
-extern const char kFlashPluginSplExtension[];
-extern const char kFlashPluginSplDescription[];
-
-// The maximum plugin width and height.
-extern const uint16 kMaxPluginSideLength;
-// The maximum plugin size, defined as the number of pixels occupied by the
-// plugin.
-extern const uint32 kMaxPluginSize;
-
-#endif // WEBKIT_PLUGINS_PLUGIN_CONSTANTS_H_
diff --git a/webkit/plugins/plugin_switches.cc b/webkit/plugins/plugin_switches.cc
deleted file mode 100644
index 563b844..0000000
--- a/webkit/plugins/plugin_switches.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2010 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 "webkit/plugins/plugin_switches.h"
-
-namespace switches {
-
-// Dumps extra logging about plugin loading to the log file.
-const char kDebugPluginLoading[] = "debug-plugin-loading";
-
-// Disable Pepper3D.
-const char kDisablePepper3d[] = "disable-pepper-3d";
-
-// "Command-line" arguments for the PPAPI Flash; used for debugging options.
-const char kPpapiFlashArgs[] = "ppapi-flash-args";
-
-} // namespace switches
diff --git a/webkit/plugins/plugin_switches.h b/webkit/plugins/plugin_switches.h
deleted file mode 100644
index 6ba76cd..0000000
--- a/webkit/plugins/plugin_switches.h
+++ /dev/null
@@ -1,18 +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.
-
-#ifndef WEBKIT_PLUGINS_PLUGIN_SWITCHES_H_
-#define WEBKIT_PLUGINS_PLUGIN_SWITCHES_H_
-
-#include "build/build_config.h"
-
-namespace switches {
-
-extern const char kDebugPluginLoading[];
-extern const char kDisablePepper3d[];
-extern const char kPpapiFlashArgs[];
-
-} // namespace switches
-
-#endif // WEBKIT_PLUGINS_PLUGIN_SWITCHES_H_
diff --git a/webkit/plugins/plugins_common.target.darwin-arm.mk b/webkit/plugins/plugins_common.target.darwin-arm.mk
deleted file mode 100644
index 9b324e9..0000000
--- a/webkit/plugins/plugins_common.target.darwin-arm.mk
+++ /dev/null
@@ -1,276 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_plugins_plugins_common_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
- $(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- webkit/plugins/plugin_constants.cc \
- webkit/plugins/plugin_switches.cc \
- webkit/common/plugins/ppapi/ppapi_utils.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-format \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DPOSIX_AVOID_MMAP' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH) \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wno-deprecated \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-format \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DPOSIX_AVOID_MMAP' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH) \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wno-deprecated \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -Wl,-z,relro \
- -Wl,-z,now \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--icf=safe \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -Wl,-z,relro \
- -Wl,-z,now \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--icf=safe \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- ui_ui_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: webkit_plugins_plugins_common_gyp
-
-# Alias gyp target name.
-.PHONY: plugins_common
-plugins_common: webkit_plugins_plugins_common_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/plugins/plugins_common.target.darwin-mips.mk b/webkit/plugins/plugins_common.target.darwin-mips.mk
deleted file mode 100644
index aee20e4..0000000
--- a/webkit/plugins/plugins_common.target.darwin-mips.mk
+++ /dev/null
@@ -1,272 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_plugins_plugins_common_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
- $(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- webkit/plugins/plugin_constants.cc \
- webkit/plugins/plugin_switches.cc \
- webkit/common/plugins/ppapi/ppapi_utils.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-format \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DPOSIX_AVOID_MMAP' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH) \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wno-deprecated \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-format \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DPOSIX_AVOID_MMAP' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH) \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wno-deprecated \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -EL \
- -Wl,--no-keep-memory \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -EL \
- -Wl,--no-keep-memory \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- ui_ui_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: webkit_plugins_plugins_common_gyp
-
-# Alias gyp target name.
-.PHONY: plugins_common
-plugins_common: webkit_plugins_plugins_common_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/plugins/plugins_common.target.darwin-x86.mk b/webkit/plugins/plugins_common.target.darwin-x86.mk
deleted file mode 100644
index 580ac45..0000000
--- a/webkit/plugins/plugins_common.target.darwin-x86.mk
+++ /dev/null
@@ -1,274 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_plugins_plugins_common_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
- $(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- webkit/plugins/plugin_constants.cc \
- webkit/plugins/plugin_switches.cc \
- webkit/common/plugins/ppapi/ppapi_utils.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- --param=ssp-buffer-size=4 \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-format \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -fno-stack-protector \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH) \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wno-deprecated \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- --param=ssp-buffer-size=4 \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-format \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -fno-stack-protector \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer \
- -fno-unwind-tables \
- -fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH) \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wno-deprecated \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -m32 \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -m32 \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- ui_ui_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: webkit_plugins_plugins_common_gyp
-
-# Alias gyp target name.
-.PHONY: plugins_common
-plugins_common: webkit_plugins_plugins_common_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/plugins/plugins_common.target.linux-arm.mk b/webkit/plugins/plugins_common.target.linux-arm.mk
deleted file mode 100644
index 9b324e9..0000000
--- a/webkit/plugins/plugins_common.target.linux-arm.mk
+++ /dev/null
@@ -1,276 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_plugins_plugins_common_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
- $(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- webkit/plugins/plugin_constants.cc \
- webkit/plugins/plugin_switches.cc \
- webkit/common/plugins/ppapi/ppapi_utils.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-format \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DPOSIX_AVOID_MMAP' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH) \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wno-deprecated \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-format \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DPOSIX_AVOID_MMAP' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH) \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wno-deprecated \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -Wl,-z,relro \
- -Wl,-z,now \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--icf=safe \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -Wl,-z,relro \
- -Wl,-z,now \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--icf=safe \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- ui_ui_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: webkit_plugins_plugins_common_gyp
-
-# Alias gyp target name.
-.PHONY: plugins_common
-plugins_common: webkit_plugins_plugins_common_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/plugins/plugins_common.target.linux-mips.mk b/webkit/plugins/plugins_common.target.linux-mips.mk
deleted file mode 100644
index aee20e4..0000000
--- a/webkit/plugins/plugins_common.target.linux-mips.mk
+++ /dev/null
@@ -1,272 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_plugins_plugins_common_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
- $(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- webkit/plugins/plugin_constants.cc \
- webkit/plugins/plugin_switches.cc \
- webkit/common/plugins/ppapi/ppapi_utils.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-format \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DPOSIX_AVOID_MMAP' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH) \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wno-deprecated \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-format \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DPOSIX_AVOID_MMAP' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH) \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wno-deprecated \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -EL \
- -Wl,--no-keep-memory \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -EL \
- -Wl,--no-keep-memory \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- ui_ui_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: webkit_plugins_plugins_common_gyp
-
-# Alias gyp target name.
-.PHONY: plugins_common
-plugins_common: webkit_plugins_plugins_common_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/plugins/plugins_common.target.linux-x86.mk b/webkit/plugins/plugins_common.target.linux-x86.mk
deleted file mode 100644
index 580ac45..0000000
--- a/webkit/plugins/plugins_common.target.linux-x86.mk
+++ /dev/null
@@ -1,274 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_plugins_plugins_common_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
- $(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- webkit/plugins/plugin_constants.cc \
- webkit/plugins/plugin_switches.cc \
- webkit/common/plugins/ppapi/ppapi_utils.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- --param=ssp-buffer-size=4 \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-format \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -fno-stack-protector \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH) \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wno-deprecated \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- --param=ssp-buffer-size=4 \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-format \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -fno-stack-protector \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer \
- -fno-unwind-tables \
- -fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH) \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wno-deprecated \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -m32 \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -m32 \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- ui_ui_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: webkit_plugins_plugins_common_gyp
-
-# Alias gyp target name.
-.PHONY: plugins_common
-plugins_common: webkit_plugins_plugins_common_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/plugins/sad_plugin.h b/webkit/plugins/sad_plugin.h
deleted file mode 100644
index d4ae546..0000000
--- a/webkit/plugins/sad_plugin.h
+++ /dev/null
@@ -1,27 +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.
-
-#ifndef WEBKIT_PLUGINS_SAD_PLUGIN_H_
-#define WEBKIT_PLUGINS_SAD_PLUGIN_H_
-
-#include "third_party/WebKit/public/platform/WebCanvas.h"
-#include "webkit/plugins/webkit_plugins_export.h"
-
-class SkBitmap;
-
-namespace gfx {
-class Rect;
-}
-
-namespace webkit {
-
-// Paints the sad plugin to the given canvas for the given plugin bounds. This
-// is used by both the NPAPI and the PPAPI out-of-process plugin impls.
-WEBKIT_PLUGINS_EXPORT void PaintSadPlugin(WebKit::WebCanvas* canvas,
- const gfx::Rect& plugin_rect,
- const SkBitmap& sad_plugin_bitmap);
-
-} // namespace
-
-#endif // WEBKIT_PLUGINS_SAD_PLUGIN_H_
diff --git a/webkit/plugins/webkit_plugins.gyp b/webkit/plugins/webkit_plugins.gyp
deleted file mode 100644
index 18fb10d..0000000
--- a/webkit/plugins/webkit_plugins.gyp
+++ /dev/null
@@ -1,55 +0,0 @@
-# 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.
-
-{
- 'targets': [
- {
- 'target_name': 'plugins_common',
- 'type': 'static_library',
- 'defines': [
- 'WEBKIT_PLUGINS_IMPLEMENTATION',
- ],
- 'include_dirs': [
- '<(INTERMEDIATE_DIR)',
- '<(SHARED_INTERMEDIATE_DIR)/ui',
- ],
- 'dependencies': [
- '<(DEPTH)/base/base.gyp:base_i18n',
- '<(DEPTH)/base/base.gyp:base',
- '<(DEPTH)/base/base.gyp:base_static',
- '<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
- '<(DEPTH)/net/net.gyp:net',
- '<(DEPTH)/ui/ui.gyp:ui',
- '<(DEPTH)/ui/ui.gyp:ui_resources',
- ],
- 'sources': [
- '../plugins/plugin_constants.cc',
- '../plugins/plugin_constants.h',
- '../plugins/plugin_switches.cc',
- '../plugins/plugin_switches.h',
- '../common/plugins/ppapi/ppapi_utils.cc',
- '../common/plugins/ppapi/ppapi_utils.h',
- ],
- 'conditions': [
- ['toolkit_uses_gtk == 1', {
- 'dependencies': [
- '<(DEPTH)/build/linux/system.gyp:gtk',
- ],
- 'sources/': [['exclude', '_x11\\.cc$']],
- }],
- ['OS!="win"', {
- 'sources/': [['exclude', '_win\\.cc$']],
- }, { # else: OS=="win"
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- 'msvs_disabled_warnings': [ 4800, 4267 ],
- 'sources/': [['exclude', '_posix\\.cc$']],
- 'include_dirs': [
- '<(DEPTH)/third_party/wtl/include',
- ],
- }],
- ],
- },
- ],
-}
-
diff --git a/webkit/plugins/webkit_plugins.gypi b/webkit/plugins/webkit_plugins.gypi
deleted file mode 100644
index 8cc2648..0000000
--- a/webkit/plugins/webkit_plugins.gypi
+++ /dev/null
@@ -1,55 +0,0 @@
-# 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.
-
-{
- 'targets': [
- {
- 'target_name': 'plugins',
- 'type': '<(component)',
- 'defines': [
- 'WEBKIT_PLUGINS_IMPLEMENTATION',
- ],
- 'include_dirs': [
- '<(INTERMEDIATE_DIR)',
- '<(SHARED_INTERMEDIATE_DIR)/webkit',
- '<(SHARED_INTERMEDIATE_DIR)/ui',
- ],
- 'dependencies': [
- '<(DEPTH)/base/base.gyp:base',
- '<(DEPTH)/base/base.gyp:base_i18n',
- '<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
- '<(DEPTH)/gpu/gpu.gyp:command_buffer_common',
- '<(DEPTH)/gpu/gpu.gyp:gles2_c_lib',
- '<(DEPTH)/gpu/gpu.gyp:gles2_implementation',
- '<(DEPTH)/media/media.gyp:media',
- '<(DEPTH)/media/media.gyp:shared_memory_support',
- '<(DEPTH)/net/net.gyp:net',
- '<(DEPTH)/ppapi/ppapi.gyp:ppapi_c',
- '<(DEPTH)/ppapi/ppapi_internal.gyp:ppapi_shared',
- '<(DEPTH)/printing/printing.gyp:printing',
- '<(DEPTH)/skia/skia.gyp:skia',
- '<(DEPTH)/third_party/WebKit/public/blink.gyp:blink',
- '<(DEPTH)/ui/gl/gl.gyp:gl',
- '<(DEPTH)/ui/ui.gyp:ui',
- '<(DEPTH)/ui/ui.gyp:ui_resources',
- '<(DEPTH)/url/url.gyp:url_lib',
- '<(DEPTH)/v8/tools/gyp/v8.gyp:v8',
- '<(DEPTH)/webkit/common/user_agent/webkit_user_agent.gyp:user_agent',
- '<(DEPTH)/webkit/common/webkit_common.gyp:webkit_common',
- '<(DEPTH)/webkit/plugins/webkit_plugins.gyp:plugins_common',
- '<(DEPTH)/webkit/renderer/compositor_bindings/compositor_bindings.gyp:webkit_compositor_support',
- '<(DEPTH)/webkit/storage_common.gyp:webkit_storage_common',
- 'glue_child',
- ],
- 'sources': [
- # This list contains all .h, .cc, and .mm files in glue except for
- # those in the test subdirectory and those with unittest in in their
- # names.
- '../plugins/sad_plugin.cc',
- '../plugins/sad_plugin.h',
- '../plugins/webkit_plugins_export.h',
- ],
- },
- ]
-}
diff --git a/webkit/plugins/webkit_plugins_export.h b/webkit/plugins/webkit_plugins_export.h
deleted file mode 100644
index 387d5e4..0000000
--- a/webkit/plugins/webkit_plugins_export.h
+++ /dev/null
@@ -1,29 +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 WEBKIT_PLUGINS_WEBKIT_PLUGINS_EXPORT_H_
-#define WEBKIT_PLUGINS_WEBKIT_PLUGINS_EXPORT_H_
-
-#if defined(COMPONENT_BUILD)
-#if defined(WIN32)
-
-#if defined(WEBKIT_PLUGINS_IMPLEMENTATION)
-#define WEBKIT_PLUGINS_EXPORT __declspec(dllexport)
-#else
-#define WEBKIT_PLUGINS_EXPORT __declspec(dllimport)
-#endif // defined(WEBKIT_PLUGINS_IMPLEMENTATION)
-
-#else // defined(WIN32)
-#if defined(WEBKIT_PLUGINS_IMPLEMENTATION)
-#define WEBKIT_PLUGINS_EXPORT __attribute__((visibility("default")))
-#else
-#define WEBKIT_PLUGINS_EXPORT
-#endif
-#endif
-
-#else // defined(COMPONENT_BUILD)
-#define WEBKIT_PLUGINS_EXPORT
-#endif
-
-#endif // WEBKIT_PLUGINS_WEBKIT_PLUGINS_EXPORT_H_
diff --git a/webkit/renderer/appcache/appcache_frontend_impl.h b/webkit/renderer/appcache/appcache_frontend_impl.h
deleted file mode 100644
index 42ba745..0000000
--- a/webkit/renderer/appcache/appcache_frontend_impl.h
+++ /dev/null
@@ -1,37 +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.
-
-#ifndef WEBKIT_RENDERER_APPCACHE_APPCACHE_FRONTEND_IMPL_H_
-#define WEBKIT_RENDERER_APPCACHE_APPCACHE_FRONTEND_IMPL_H_
-
-#include <string>
-#include <vector>
-
-#include "webkit/common/appcache/appcache_interfaces.h"
-#include "webkit/renderer/webkit_storage_renderer_export.h"
-
-namespace appcache {
-
-class WEBKIT_STORAGE_RENDERER_EXPORT AppCacheFrontendImpl
- : public AppCacheFrontend {
- public:
- virtual void OnCacheSelected(
- int host_id, const appcache::AppCacheInfo& info) OVERRIDE;
- virtual void OnStatusChanged(const std::vector<int>& host_ids,
- Status status) OVERRIDE;
- virtual void OnEventRaised(const std::vector<int>& host_ids,
- EventID event_id) OVERRIDE;
- virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
- const GURL& url,
- int num_total, int num_complete) OVERRIDE;
- virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
- const std::string& message) OVERRIDE;
- virtual void OnLogMessage(int host_id, LogLevel log_level,
- const std::string& message) OVERRIDE;
- virtual void OnContentBlocked(int host_id, const GURL& manifest_url) OVERRIDE;
-};
-
-} // namespace
-
-#endif // WEBKIT_RENDERER_APPCACHE_APPCACHE_FRONTEND_IMPL_H_
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-arm.mk b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-arm.mk
index c4663a0..f9398e9 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-arm.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-arm.mk
@@ -102,6 +102,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DPOSIX_AVOID_MMAP' \
'-D__STDC_CONSTANT_MACROS' \
@@ -216,6 +217,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DPOSIX_AVOID_MMAP' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-mips.mk b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-mips.mk
index 2d5eb70..9362b4c 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-mips.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-mips.mk
@@ -101,6 +101,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DPOSIX_AVOID_MMAP' \
'-D__STDC_CONSTANT_MACROS' \
@@ -214,6 +215,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DPOSIX_AVOID_MMAP' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-x86.mk b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-x86.mk
index 9fe67e9..3ffef57 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-x86.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-x86.mk
@@ -104,6 +104,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -220,6 +221,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-arm.mk b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-arm.mk
index c4663a0..f9398e9 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-arm.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-arm.mk
@@ -102,6 +102,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DPOSIX_AVOID_MMAP' \
'-D__STDC_CONSTANT_MACROS' \
@@ -216,6 +217,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DPOSIX_AVOID_MMAP' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-mips.mk b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-mips.mk
index 2d5eb70..9362b4c 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-mips.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-mips.mk
@@ -101,6 +101,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DPOSIX_AVOID_MMAP' \
'-D__STDC_CONSTANT_MACROS' \
@@ -214,6 +215,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DPOSIX_AVOID_MMAP' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-x86.mk b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-x86.mk
index 9fe67e9..3ffef57 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-x86.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-x86.mk
@@ -104,6 +104,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -220,6 +221,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-arm.mk b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-arm.mk
index b031ec9..07c01dd 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-arm.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-arm.mk
@@ -81,6 +81,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -187,6 +188,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-mips.mk b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-mips.mk
index 1dfda10..35d8f22 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-mips.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-mips.mk
@@ -80,6 +80,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -185,6 +186,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-x86.mk b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-x86.mk
index 3515dbb..068afeb 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-x86.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-x86.mk
@@ -83,6 +83,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -192,6 +193,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-arm.mk b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-arm.mk
index b031ec9..07c01dd 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-arm.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-arm.mk
@@ -81,6 +81,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -187,6 +188,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-mips.mk b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-mips.mk
index 1dfda10..35d8f22 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-mips.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-mips.mk
@@ -80,6 +80,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -185,6 +186,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-x86.mk b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-x86.mk
index 3515dbb..068afeb 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-x86.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-x86.mk
@@ -83,6 +83,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -192,6 +193,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
diff --git a/webkit/renderer/media/DEPS b/webkit/renderer/media/DEPS
deleted file mode 100644
index c3a5b96..0000000
--- a/webkit/renderer/media/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+media",
-]
diff --git a/webkit/renderer/media/OWNERS b/webkit/renderer/media/OWNERS
deleted file mode 100644
index 679494d..0000000
--- a/webkit/renderer/media/OWNERS
+++ /dev/null
@@ -1,9 +0,0 @@
-acolwell@chromium.org
-dalecurtis@chromium.org
-ddorwin@chromium.org
-fischman@chromium.org
-scherkus@chromium.org
-shadi@chromium.org
-vrk@chromium.org
-xhwang@chromium.org
-wjia@chromium.org
diff --git a/webkit/renderer/media/crypto/ppapi/DEPS b/webkit/renderer/media/crypto/ppapi/DEPS
deleted file mode 100644
index 00317f1..0000000
--- a/webkit/renderer/media/crypto/ppapi/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- "+ppapi",
- "+third_party/libvpx",
-]
diff --git a/webkit/renderer/webkit_renderer.target.darwin-arm.mk b/webkit/renderer/webkit_renderer.target.darwin-arm.mk
index 2f627be..6239808 100644
--- a/webkit/renderer/webkit_renderer.target.darwin-arm.mk
+++ b/webkit/renderer/webkit_renderer.target.darwin-arm.mk
@@ -92,6 +92,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -207,6 +208,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/renderer/webkit_renderer.target.darwin-mips.mk b/webkit/renderer/webkit_renderer.target.darwin-mips.mk
index edae01d..cb0a2f7 100644
--- a/webkit/renderer/webkit_renderer.target.darwin-mips.mk
+++ b/webkit/renderer/webkit_renderer.target.darwin-mips.mk
@@ -92,6 +92,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -207,6 +208,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/renderer/webkit_renderer.target.darwin-x86.mk b/webkit/renderer/webkit_renderer.target.darwin-x86.mk
index 0b06f75..f07b99d 100644
--- a/webkit/renderer/webkit_renderer.target.darwin-x86.mk
+++ b/webkit/renderer/webkit_renderer.target.darwin-x86.mk
@@ -93,6 +93,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -210,6 +211,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/renderer/webkit_renderer.target.linux-arm.mk b/webkit/renderer/webkit_renderer.target.linux-arm.mk
index 2f627be..6239808 100644
--- a/webkit/renderer/webkit_renderer.target.linux-arm.mk
+++ b/webkit/renderer/webkit_renderer.target.linux-arm.mk
@@ -92,6 +92,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -207,6 +208,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/renderer/webkit_renderer.target.linux-mips.mk b/webkit/renderer/webkit_renderer.target.linux-mips.mk
index edae01d..cb0a2f7 100644
--- a/webkit/renderer/webkit_renderer.target.linux-mips.mk
+++ b/webkit/renderer/webkit_renderer.target.linux-mips.mk
@@ -92,6 +92,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -207,6 +208,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/renderer/webkit_renderer.target.linux-x86.mk b/webkit/renderer/webkit_renderer.target.linux-x86.mk
index 0b06f75..f07b99d 100644
--- a/webkit/renderer/webkit_renderer.target.linux-x86.mk
+++ b/webkit/renderer/webkit_renderer.target.linux-x86.mk
@@ -93,6 +93,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -210,6 +211,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/storage_renderer.gyp b/webkit/storage_renderer.gyp
index b2a17aa..dc406e2 100644
--- a/webkit/storage_renderer.gyp
+++ b/webkit/storage_renderer.gyp
@@ -19,10 +19,6 @@
'defines': ['WEBKIT_STORAGE_RENDERER_IMPLEMENTATION'],
'sources': [
'renderer/webkit_storage_renderer_export.h',
- 'renderer/appcache/appcache_frontend_impl.cc',
- 'renderer/appcache/appcache_frontend_impl.h',
- 'renderer/appcache/web_application_cache_host_impl.cc',
- 'renderer/appcache/web_application_cache_host_impl.h',
'renderer/fileapi/webfilewriter_base.cc',
'renderer/fileapi/webfilewriter_base.h',
],
diff --git a/webkit/support/glue.target.darwin-arm.mk b/webkit/support/glue.target.darwin-arm.mk
index e2f96a0..503fc46 100644
--- a/webkit/support/glue.target.darwin-arm.mk
+++ b/webkit/support/glue.target.darwin-arm.mk
@@ -102,6 +102,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
@@ -231,6 +232,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/support/glue.target.darwin-mips.mk b/webkit/support/glue.target.darwin-mips.mk
index 47c264d..af15923 100644
--- a/webkit/support/glue.target.darwin-mips.mk
+++ b/webkit/support/glue.target.darwin-mips.mk
@@ -101,6 +101,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
@@ -229,6 +230,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/support/glue.target.darwin-x86.mk b/webkit/support/glue.target.darwin-x86.mk
index 5cc61e1..ba3135c 100644
--- a/webkit/support/glue.target.darwin-x86.mk
+++ b/webkit/support/glue.target.darwin-x86.mk
@@ -103,6 +103,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
@@ -234,6 +235,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/support/glue.target.linux-arm.mk b/webkit/support/glue.target.linux-arm.mk
index e2f96a0..503fc46 100644
--- a/webkit/support/glue.target.linux-arm.mk
+++ b/webkit/support/glue.target.linux-arm.mk
@@ -102,6 +102,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
@@ -231,6 +232,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/support/glue.target.linux-mips.mk b/webkit/support/glue.target.linux-mips.mk
index 47c264d..af15923 100644
--- a/webkit/support/glue.target.linux-mips.mk
+++ b/webkit/support/glue.target.linux-mips.mk
@@ -101,6 +101,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
@@ -229,6 +230,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/support/glue.target.linux-x86.mk b/webkit/support/glue.target.linux-x86.mk
index 5cc61e1..ba3135c 100644
--- a/webkit/support/glue.target.linux-x86.mk
+++ b/webkit/support/glue.target.linux-x86.mk
@@ -103,6 +103,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
@@ -234,6 +235,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DMESA_EGL_NO_X11_HEADERS' \
'-D__STDC_CONSTANT_MACROS' \
diff --git a/webkit/support/glue_child.target.darwin-arm.mk b/webkit/support/glue_child.target.darwin-arm.mk
index 896b6b8..35dbc20 100644
--- a/webkit/support/glue_child.target.darwin-arm.mk
+++ b/webkit/support/glue_child.target.darwin-arm.mk
@@ -109,6 +109,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -230,6 +231,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/support/glue_child.target.darwin-mips.mk b/webkit/support/glue_child.target.darwin-mips.mk
index 7fdefb2..a0f2206 100644
--- a/webkit/support/glue_child.target.darwin-mips.mk
+++ b/webkit/support/glue_child.target.darwin-mips.mk
@@ -108,6 +108,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -228,6 +229,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/support/glue_child.target.darwin-x86.mk b/webkit/support/glue_child.target.darwin-x86.mk
index bd57c82..d836937 100644
--- a/webkit/support/glue_child.target.darwin-x86.mk
+++ b/webkit/support/glue_child.target.darwin-x86.mk
@@ -110,6 +110,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -233,6 +234,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/support/glue_child.target.linux-arm.mk b/webkit/support/glue_child.target.linux-arm.mk
index 896b6b8..35dbc20 100644
--- a/webkit/support/glue_child.target.linux-arm.mk
+++ b/webkit/support/glue_child.target.linux-arm.mk
@@ -109,6 +109,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -230,6 +231,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/support/glue_child.target.linux-mips.mk b/webkit/support/glue_child.target.linux-mips.mk
index 7fdefb2..a0f2206 100644
--- a/webkit/support/glue_child.target.linux-mips.mk
+++ b/webkit/support/glue_child.target.linux-mips.mk
@@ -108,6 +108,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -228,6 +229,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/support/glue_child.target.linux-x86.mk b/webkit/support/glue_child.target.linux-x86.mk
index bd57c82..d836937 100644
--- a/webkit/support/glue_child.target.linux-x86.mk
+++ b/webkit/support/glue_child.target.linux-x86.mk
@@ -110,6 +110,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
@@ -233,6 +234,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
diff --git a/webkit/support/plugins.target.darwin-arm.mk b/webkit/support/plugins.target.darwin-arm.mk
deleted file mode 100644
index a75476b..0000000
--- a/webkit/support/plugins.target.darwin-arm.mk
+++ /dev/null
@@ -1,359 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_support_plugins_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
- $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
- $(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
- $(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- webkit/plugins/sad_plugin.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -Wno-narrowing \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-unknown-pragmas \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DMEDIA_DISABLE_LIBVPX' \
- '-DPOSIX_AVOID_MMAP' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DMESA_EGL_NO_X11_HEADERS' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/webkit \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(LOCAL_PATH)/third_party/WebKit \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(gyp_shared_intermediate_dir)/ui/gl \
- $(LOCAL_PATH)/third_party/mesa/src/include \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -Wno-narrowing \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -Wno-narrowing \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-unknown-pragmas \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DMEDIA_DISABLE_LIBVPX' \
- '-DPOSIX_AVOID_MMAP' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DMESA_EGL_NO_X11_HEADERS' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/webkit \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(LOCAL_PATH)/third_party/WebKit \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(gyp_shared_intermediate_dir)/ui/gl \
- $(LOCAL_PATH)/third_party/mesa/src/include \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -Wno-narrowing \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -Wl,-z,relro \
- -Wl,-z,now \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--icf=safe \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -Wl,-z,relro \
- -Wl,-z,now \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--icf=safe \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- skia_skia_library_gyp \
- ui_gl_gl_gyp \
- ui_ui_gyp \
- webkit_support_glue_child_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: webkit_support_plugins_gyp
-
-# Alias gyp target name.
-.PHONY: plugins
-plugins: webkit_support_plugins_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/support/plugins.target.darwin-mips.mk b/webkit/support/plugins.target.darwin-mips.mk
deleted file mode 100644
index 7761ce3..0000000
--- a/webkit/support/plugins.target.darwin-mips.mk
+++ /dev/null
@@ -1,353 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_support_plugins_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
- $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
- $(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
- $(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- webkit/plugins/sad_plugin.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -Wno-narrowing \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-unknown-pragmas \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DMEDIA_DISABLE_LIBVPX' \
- '-DPOSIX_AVOID_MMAP' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DMESA_EGL_NO_X11_HEADERS' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/webkit \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(LOCAL_PATH)/third_party/WebKit \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(gyp_shared_intermediate_dir)/ui/gl \
- $(LOCAL_PATH)/third_party/mesa/src/include \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -Wno-narrowing \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -Wno-narrowing \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-unknown-pragmas \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DMEDIA_DISABLE_LIBVPX' \
- '-DPOSIX_AVOID_MMAP' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DMESA_EGL_NO_X11_HEADERS' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/webkit \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(LOCAL_PATH)/third_party/WebKit \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(gyp_shared_intermediate_dir)/ui/gl \
- $(LOCAL_PATH)/third_party/mesa/src/include \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -Wno-narrowing \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -EL \
- -Wl,--no-keep-memory \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -EL \
- -Wl,--no-keep-memory \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- skia_skia_library_gyp \
- ui_gl_gl_gyp \
- ui_ui_gyp \
- webkit_support_glue_child_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: webkit_support_plugins_gyp
-
-# Alias gyp target name.
-.PHONY: plugins
-plugins: webkit_support_plugins_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/support/plugins.target.darwin-x86.mk b/webkit/support/plugins.target.darwin-x86.mk
deleted file mode 100644
index 00061ee..0000000
--- a/webkit/support/plugins.target.darwin-x86.mk
+++ /dev/null
@@ -1,357 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_support_plugins_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
- $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
- $(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
- $(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- webkit/plugins/sad_plugin.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -Wno-narrowing \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-unknown-pragmas \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -fno-stack-protector \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DMEDIA_DISABLE_LIBVPX' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DMESA_EGL_NO_X11_HEADERS' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/webkit \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(LOCAL_PATH)/third_party/WebKit \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(gyp_shared_intermediate_dir)/ui/gl \
- $(LOCAL_PATH)/third_party/mesa/src/include \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -Wno-narrowing \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -Wno-narrowing \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-unknown-pragmas \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -fno-stack-protector \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer \
- -fno-unwind-tables \
- -fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DMEDIA_DISABLE_LIBVPX' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DMESA_EGL_NO_X11_HEADERS' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/webkit \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(LOCAL_PATH)/third_party/WebKit \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(gyp_shared_intermediate_dir)/ui/gl \
- $(LOCAL_PATH)/third_party/mesa/src/include \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -Wno-narrowing \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -m32 \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -m32 \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- skia_skia_library_gyp \
- ui_gl_gl_gyp \
- ui_ui_gyp \
- webkit_support_glue_child_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: webkit_support_plugins_gyp
-
-# Alias gyp target name.
-.PHONY: plugins
-plugins: webkit_support_plugins_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/support/plugins.target.linux-arm.mk b/webkit/support/plugins.target.linux-arm.mk
deleted file mode 100644
index a75476b..0000000
--- a/webkit/support/plugins.target.linux-arm.mk
+++ /dev/null
@@ -1,359 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_support_plugins_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
- $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
- $(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
- $(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- webkit/plugins/sad_plugin.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -Wno-narrowing \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-unknown-pragmas \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DMEDIA_DISABLE_LIBVPX' \
- '-DPOSIX_AVOID_MMAP' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DMESA_EGL_NO_X11_HEADERS' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/webkit \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(LOCAL_PATH)/third_party/WebKit \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(gyp_shared_intermediate_dir)/ui/gl \
- $(LOCAL_PATH)/third_party/mesa/src/include \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -Wno-narrowing \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -Wno-narrowing \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-unknown-pragmas \
- -fno-tree-sra \
- -fuse-ld=gold \
- -Wno-psabi \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DMEDIA_DISABLE_LIBVPX' \
- '-DPOSIX_AVOID_MMAP' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DMESA_EGL_NO_X11_HEADERS' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/webkit \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(LOCAL_PATH)/third_party/WebKit \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(gyp_shared_intermediate_dir)/ui/gl \
- $(LOCAL_PATH)/third_party/mesa/src/include \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -Wno-narrowing \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-abi \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -Wl,-z,relro \
- -Wl,-z,now \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--icf=safe \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -Wl,-z,relro \
- -Wl,-z,now \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--icf=safe \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- skia_skia_library_gyp \
- ui_gl_gl_gyp \
- ui_ui_gyp \
- webkit_support_glue_child_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: webkit_support_plugins_gyp
-
-# Alias gyp target name.
-.PHONY: plugins
-plugins: webkit_support_plugins_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/support/plugins.target.linux-mips.mk b/webkit/support/plugins.target.linux-mips.mk
deleted file mode 100644
index 7761ce3..0000000
--- a/webkit/support/plugins.target.linux-mips.mk
+++ /dev/null
@@ -1,353 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_support_plugins_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
- $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
- $(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
- $(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- webkit/plugins/sad_plugin.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -Wno-narrowing \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-unknown-pragmas \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DMEDIA_DISABLE_LIBVPX' \
- '-DPOSIX_AVOID_MMAP' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DMESA_EGL_NO_X11_HEADERS' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/webkit \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(LOCAL_PATH)/third_party/WebKit \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(gyp_shared_intermediate_dir)/ui/gl \
- $(LOCAL_PATH)/third_party/mesa/src/include \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -Wno-narrowing \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -Wno-narrowing \
- -fstack-protector \
- --param=ssp-buffer-size=4 \
- \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-unknown-pragmas \
- -EL \
- -mhard-float \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fstack-protector \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DMEDIA_DISABLE_LIBVPX' \
- '-DPOSIX_AVOID_MMAP' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DMESA_EGL_NO_X11_HEADERS' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/webkit \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(LOCAL_PATH)/third_party/WebKit \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(gyp_shared_intermediate_dir)/ui/gl \
- $(LOCAL_PATH)/third_party/mesa/src/include \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -Wno-narrowing \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-uninitialized \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -EL \
- -Wl,--no-keep-memory \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -EL \
- -Wl,--no-keep-memory \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- skia_skia_library_gyp \
- ui_gl_gl_gyp \
- ui_ui_gyp \
- webkit_support_glue_child_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: webkit_support_plugins_gyp
-
-# Alias gyp target name.
-.PHONY: plugins
-plugins: webkit_support_plugins_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/support/plugins.target.linux-x86.mk b/webkit/support/plugins.target.linux-x86.mk
deleted file mode 100644
index 00061ee..0000000
--- a/webkit/support/plugins.target.linux-x86.mk
+++ /dev/null
@@ -1,357 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-LOCAL_MODULE := webkit_support_plugins_gyp
-LOCAL_MODULE_SUFFIX := .a
-LOCAL_MODULE_TAGS := optional
-gyp_intermediate_dir := $(call local-intermediates-dir)
-gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
-
-# Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES := \
- $(call intermediates-dir-for,GYP,ppapi_ppapi_c_gyp)/ppapi_c.stamp \
- $(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
- $(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
- $(call intermediates-dir-for,STATIC_LIBRARIES,ui_ui_gyp)/ui_ui_gyp.a \
- $(call intermediates-dir-for,GYP,ui_ui_resources_gyp)/ui_resources.stamp \
- $(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
- $(call intermediates-dir-for,STATIC_LIBRARIES,webkit_support_glue_child_gyp)/webkit_support_glue_child_gyp.a
-
-GYP_GENERATED_OUTPUTS :=
-
-# Make sure our deps and generated files are built first.
-LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
-
-LOCAL_CPP_EXTENSION := .cc
-LOCAL_GENERATED_SOURCES :=
-
-GYP_COPIED_SOURCE_ORIGIN_DIRS :=
-
-LOCAL_SRC_FILES := \
- webkit/plugins/sad_plugin.cc
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Debug := \
- -Wno-narrowing \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-unknown-pragmas \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -fno-stack-protector \
- -Os \
- -g \
- -fomit-frame-pointer \
- -fdata-sections \
- -ffunction-sections
-
-MY_DEFS_Debug := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DMEDIA_DISABLE_LIBVPX' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DMESA_EGL_NO_X11_HEADERS' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
- '-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
- '-D_DEBUG'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Debug := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/webkit \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(LOCAL_PATH)/third_party/WebKit \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(gyp_shared_intermediate_dir)/ui/gl \
- $(LOCAL_PATH)/third_party/mesa/src/include \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Debug := \
- -Wno-narrowing \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-# Flags passed to both C and C++ files.
-MY_CFLAGS_Release := \
- -Wno-narrowing \
- --param=ssp-buffer-size=4 \
- -Werror \
- -fno-exceptions \
- -fno-strict-aliasing \
- -Wall \
- -Wno-unused-parameter \
- -Wno-missing-field-initializers \
- -fvisibility=hidden \
- -pipe \
- -fPIC \
- -Wno-unknown-pragmas \
- -m32 \
- -mmmx \
- -march=pentium4 \
- -msse2 \
- -mfpmath=sse \
- -fuse-ld=gold \
- -ffunction-sections \
- -funwind-tables \
- -g \
- -fno-short-enums \
- -finline-limit=64 \
- -Wa,--noexecstack \
- -U_FORTIFY_SOURCE \
- -Wno-extra \
- -Wno-ignored-qualifiers \
- -Wno-type-limits \
- -Wno-address \
- -Wno-format-security \
- -Wno-return-type \
- -Wno-sequence-point \
- -fno-stack-protector \
- -Os \
- -fno-ident \
- -fdata-sections \
- -ffunction-sections \
- -fomit-frame-pointer \
- -fno-unwind-tables \
- -fno-asynchronous-unwind-tables
-
-MY_DEFS_Release := \
- '-DANGLE_DX11' \
- '-D_FILE_OFFSET_BITS=64' \
- '-DNO_TCMALLOC' \
- '-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
- '-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DDISABLE_NACL' \
- '-DCHROMIUM_BUILD' \
- '-DUSE_LIBJPEG_TURBO=1' \
- '-DUSE_PROPRIETARY_CODECS' \
- '-DENABLE_CONFIGURATION_POLICY' \
- '-DENABLE_GPU=1' \
- '-DUSE_OPENSSL=1' \
- '-DENABLE_EGLIMAGE=1' \
- '-DWEBKIT_PLUGINS_IMPLEMENTATION' \
- '-DMEDIA_DISABLE_LIBVPX' \
- '-DSK_ENABLE_INST_COUNT=0' \
- '-DSK_SUPPORT_GPU=1' \
- '-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
- '-DSK_BUILD_FOR_ANDROID' \
- '-DUSE_CHROMIUM_SKIA' \
- '-DSK_USE_POSIX_THREADS' \
- '-DU_USING_ICU_NAMESPACE=0' \
- '-DMESA_EGL_NO_X11_HEADERS' \
- '-D__STDC_CONSTANT_MACROS' \
- '-D__STDC_FORMAT_MACROS' \
- '-DANDROID' \
- '-D__GNU_SOURCE=1' \
- '-DUSE_STLPORT=1' \
- '-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
- '-DCHROME_BUILD_ID=""' \
- '-DNDEBUG' \
- '-DNVALGRIND' \
- '-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
- '-D_FORTIFY_SOURCE=2'
-
-
-# Include paths placed before CFLAGS/CPPFLAGS
-LOCAL_C_INCLUDES_Release := \
- $(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
- $(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
- $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
- $(gyp_intermediate_dir) \
- $(gyp_shared_intermediate_dir)/webkit \
- $(gyp_shared_intermediate_dir)/ui \
- $(LOCAL_PATH)/third_party/khronos \
- $(LOCAL_PATH)/gpu \
- $(LOCAL_PATH) \
- $(LOCAL_PATH)/third_party/skia/src/core \
- $(LOCAL_PATH)/skia/config \
- $(LOCAL_PATH)/third_party/skia/include/config \
- $(LOCAL_PATH)/third_party/skia/include/core \
- $(LOCAL_PATH)/third_party/skia/include/effects \
- $(LOCAL_PATH)/third_party/skia/include/pdf \
- $(LOCAL_PATH)/third_party/skia/include/gpu \
- $(LOCAL_PATH)/third_party/skia/include/gpu/gl \
- $(LOCAL_PATH)/third_party/skia/include/lazy \
- $(LOCAL_PATH)/third_party/skia/include/pathops \
- $(LOCAL_PATH)/third_party/skia/include/pipe \
- $(LOCAL_PATH)/third_party/skia/include/ports \
- $(LOCAL_PATH)/third_party/skia/include/utils \
- $(LOCAL_PATH)/skia/ext \
- $(LOCAL_PATH)/third_party/WebKit \
- $(PWD)/external/icu4c/common \
- $(PWD)/external/icu4c/i18n \
- $(LOCAL_PATH)/third_party/npapi \
- $(LOCAL_PATH)/third_party/npapi/bindings \
- $(gyp_shared_intermediate_dir)/ui/gl \
- $(LOCAL_PATH)/third_party/mesa/src/include \
- $(gyp_shared_intermediate_dir)/ui/ui_resources \
- $(LOCAL_PATH)/v8/include \
- $(PWD)/frameworks/wilhelm/include \
- $(PWD)/bionic \
- $(PWD)/external/stlport/stlport
-
-
-# Flags passed to only C++ (and not C) files.
-LOCAL_CPPFLAGS_Release := \
- -Wno-narrowing \
- -fno-rtti \
- -fno-threadsafe-statics \
- -fvisibility-inlines-hidden \
- -Wsign-compare \
- -Wno-error=c++0x-compat \
- -Wno-non-virtual-dtor \
- -Wno-sign-promo \
- -Wno-non-virtual-dtor
-
-
-LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
-LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
-LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
-### Rules for final target.
-
-LOCAL_LDFLAGS_Debug := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -m32 \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,--gc-sections \
- -Wl,-O1 \
- -Wl,--as-needed
-
-
-LOCAL_LDFLAGS_Release := \
- -Wl,-z,now \
- -Wl,-z,relro \
- -Wl,-z,noexecstack \
- -fPIC \
- -m32 \
- -fuse-ld=gold \
- -nostdlib \
- -Wl,--no-undefined \
- -Wl,--exclude-libs=ALL \
- -Wl,-O1 \
- -Wl,--as-needed \
- -Wl,--gc-sections
-
-
-LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
-
-LOCAL_STATIC_LIBRARIES := \
- skia_skia_library_gyp \
- ui_gl_gl_gyp \
- ui_ui_gyp \
- webkit_support_glue_child_gyp
-
-# Enable grouping to fix circular references
-LOCAL_GROUP_STATIC_LIBRARIES := true
-
-LOCAL_SHARED_LIBRARIES := \
- libstlport \
- libdl
-
-# Add target alias to "gyp_all_modules" target.
-.PHONY: gyp_all_modules
-gyp_all_modules: webkit_support_plugins_gyp
-
-# Alias gyp target name.
-.PHONY: plugins
-plugins: webkit_support_plugins_gyp
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/support/test_webkit_platform_support.cc b/webkit/support/test_webkit_platform_support.cc
index 6eecfed..5156568 100644
--- a/webkit/support/test_webkit_platform_support.cc
+++ b/webkit/support/test_webkit_platform_support.cc
@@ -34,7 +34,6 @@
#include "webkit/common/gpu/webgraphicscontext3d_provider_impl.h"
#include "webkit/glue/simple_webmimeregistry_impl.h"
#include "webkit/glue/webkit_glue.h"
-#include "webkit/renderer/appcache/web_application_cache_host_impl.h"
#include "webkit/renderer/compositor_bindings/web_compositor_support_impl.h"
#include "webkit/support/gc_extension.h"
#include "webkit/support/mock_webclipboard_impl.h"
diff --git a/webkit/support/webkit_support.gyp b/webkit/support/webkit_support.gyp
index 7e39747..5bbf80a 100644
--- a/webkit/support/webkit_support.gyp
+++ b/webkit/support/webkit_support.gyp
@@ -11,8 +11,6 @@
'includes': [
'../../build/win_precompile.gypi',
'../glue/webkit_glue.gypi',
- '../plugins/webkit_plugins.gypi',
- '../renderer/media/webkit_media.gypi',
'webkit_support.gypi',
],
}],
diff --git a/webkit/support/webkit_support.gypi b/webkit/support/webkit_support.gypi
index bf1a35e..25d9de1 100644
--- a/webkit/support/webkit_support.gypi
+++ b/webkit/support/webkit_support.gypi
@@ -34,7 +34,6 @@
'<(DEPTH)/webkit/storage_renderer.gyp:webkit_storage_renderer',
'glue',
'glue_child',
- 'plugins',
'webkit_support_common',
],
'include_dirs': [
@@ -98,7 +97,6 @@
'variables': { 'enable_wexit_time_destructors': 1, },
'dependencies': [
'<(DEPTH)/base/base.gyp:base',
- '<(DEPTH)/crypto/crypto.gyp:crypto',
'<(DEPTH)/net/net.gyp:net',
'<(DEPTH)/skia/skia.gyp:skia',
'<(DEPTH)/third_party/zlib/zlib.gyp:zlib',
diff --git a/webkit/webkit_storage_browser.target.darwin-arm.mk b/webkit/webkit_storage_browser.target.darwin-arm.mk
index 349d8bc..4ca2850 100644
--- a/webkit/webkit_storage_browser.target.darwin-arm.mk
+++ b/webkit/webkit_storage_browser.target.darwin-arm.mk
@@ -163,6 +163,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -282,6 +283,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_browser.target.darwin-mips.mk b/webkit/webkit_storage_browser.target.darwin-mips.mk
index 223f22b..550f873 100644
--- a/webkit/webkit_storage_browser.target.darwin-mips.mk
+++ b/webkit/webkit_storage_browser.target.darwin-mips.mk
@@ -163,6 +163,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -282,6 +283,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_browser.target.darwin-x86.mk b/webkit/webkit_storage_browser.target.darwin-x86.mk
index 9c2fe20..c38c105 100644
--- a/webkit/webkit_storage_browser.target.darwin-x86.mk
+++ b/webkit/webkit_storage_browser.target.darwin-x86.mk
@@ -164,6 +164,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -285,6 +286,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_browser.target.linux-arm.mk b/webkit/webkit_storage_browser.target.linux-arm.mk
index 349d8bc..4ca2850 100644
--- a/webkit/webkit_storage_browser.target.linux-arm.mk
+++ b/webkit/webkit_storage_browser.target.linux-arm.mk
@@ -163,6 +163,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -282,6 +283,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_browser.target.linux-mips.mk b/webkit/webkit_storage_browser.target.linux-mips.mk
index 223f22b..550f873 100644
--- a/webkit/webkit_storage_browser.target.linux-mips.mk
+++ b/webkit/webkit_storage_browser.target.linux-mips.mk
@@ -163,6 +163,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -282,6 +283,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_browser.target.linux-x86.mk b/webkit/webkit_storage_browser.target.linux-x86.mk
index 9c2fe20..c38c105 100644
--- a/webkit/webkit_storage_browser.target.linux-x86.mk
+++ b/webkit/webkit_storage_browser.target.linux-x86.mk
@@ -164,6 +164,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -285,6 +286,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_renderer.target.darwin-arm.mk b/webkit/webkit_storage_renderer.target.darwin-arm.mk
index cf6a55a..ccf4621 100644
--- a/webkit/webkit_storage_renderer.target.darwin-arm.mk
+++ b/webkit/webkit_storage_renderer.target.darwin-arm.mk
@@ -25,8 +25,6 @@
GYP_COPIED_SOURCE_ORIGIN_DIRS :=
LOCAL_SRC_FILES := \
- webkit/renderer/appcache/appcache_frontend_impl.cc \
- webkit/renderer/appcache/web_application_cache_host_impl.cc \
webkit/renderer/fileapi/webfilewriter_base.cc
@@ -87,6 +85,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -201,6 +200,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_renderer.target.darwin-mips.mk b/webkit/webkit_storage_renderer.target.darwin-mips.mk
index 464a0dc..5680461 100644
--- a/webkit/webkit_storage_renderer.target.darwin-mips.mk
+++ b/webkit/webkit_storage_renderer.target.darwin-mips.mk
@@ -25,8 +25,6 @@
GYP_COPIED_SOURCE_ORIGIN_DIRS :=
LOCAL_SRC_FILES := \
- webkit/renderer/appcache/appcache_frontend_impl.cc \
- webkit/renderer/appcache/web_application_cache_host_impl.cc \
webkit/renderer/fileapi/webfilewriter_base.cc
@@ -87,6 +85,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -201,6 +200,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_renderer.target.darwin-x86.mk b/webkit/webkit_storage_renderer.target.darwin-x86.mk
index e15e6ec..b37d229 100644
--- a/webkit/webkit_storage_renderer.target.darwin-x86.mk
+++ b/webkit/webkit_storage_renderer.target.darwin-x86.mk
@@ -25,8 +25,6 @@
GYP_COPIED_SOURCE_ORIGIN_DIRS :=
LOCAL_SRC_FILES := \
- webkit/renderer/appcache/appcache_frontend_impl.cc \
- webkit/renderer/appcache/web_application_cache_host_impl.cc \
webkit/renderer/fileapi/webfilewriter_base.cc
@@ -89,6 +87,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -206,6 +205,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_renderer.target.linux-arm.mk b/webkit/webkit_storage_renderer.target.linux-arm.mk
index cf6a55a..ccf4621 100644
--- a/webkit/webkit_storage_renderer.target.linux-arm.mk
+++ b/webkit/webkit_storage_renderer.target.linux-arm.mk
@@ -25,8 +25,6 @@
GYP_COPIED_SOURCE_ORIGIN_DIRS :=
LOCAL_SRC_FILES := \
- webkit/renderer/appcache/appcache_frontend_impl.cc \
- webkit/renderer/appcache/web_application_cache_host_impl.cc \
webkit/renderer/fileapi/webfilewriter_base.cc
@@ -87,6 +85,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -201,6 +200,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_renderer.target.linux-mips.mk b/webkit/webkit_storage_renderer.target.linux-mips.mk
index 464a0dc..5680461 100644
--- a/webkit/webkit_storage_renderer.target.linux-mips.mk
+++ b/webkit/webkit_storage_renderer.target.linux-mips.mk
@@ -25,8 +25,6 @@
GYP_COPIED_SOURCE_ORIGIN_DIRS :=
LOCAL_SRC_FILES := \
- webkit/renderer/appcache/appcache_frontend_impl.cc \
- webkit/renderer/appcache/web_application_cache_host_impl.cc \
webkit/renderer/fileapi/webfilewriter_base.cc
@@ -87,6 +85,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -201,6 +200,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
diff --git a/webkit/webkit_storage_renderer.target.linux-x86.mk b/webkit/webkit_storage_renderer.target.linux-x86.mk
index e15e6ec..b37d229 100644
--- a/webkit/webkit_storage_renderer.target.linux-x86.mk
+++ b/webkit/webkit_storage_renderer.target.linux-x86.mk
@@ -25,8 +25,6 @@
GYP_COPIED_SOURCE_ORIGIN_DIRS :=
LOCAL_SRC_FILES := \
- webkit/renderer/appcache/appcache_frontend_impl.cc \
- webkit/renderer/appcache/web_application_cache_host_impl.cc \
webkit/renderer/fileapi/webfilewriter_base.cc
@@ -89,6 +87,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \
@@ -206,6 +205,7 @@
'-DSK_BUILD_FOR_ANDROID' \
'-DUSE_CHROMIUM_SKIA' \
'-DSK_USE_POSIX_THREADS' \
+ '-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
'-DU_USING_ICU_NAMESPACE=0' \
'-DANDROID' \
'-D__GNU_SOURCE=1' \